mirror of git://gcc.gnu.org/git/gcc.git
				
				
				
			
		
			
				
	
	
		
			818 lines
		
	
	
		
			29 KiB
		
	
	
	
		
			Java
		
	
	
	
			
		
		
	
	
			818 lines
		
	
	
		
			29 KiB
		
	
	
	
		
			Java
		
	
	
	
| /* ManagementFactory.java - Factory for obtaining system beans.
 | |
|    Copyright (C) 2006 Free Software Foundation
 | |
| 
 | |
| This file is part of GNU Classpath.
 | |
| 
 | |
| GNU Classpath is free software; you can redistribute it and/or modify
 | |
| it under the terms of the GNU General Public License as published by
 | |
| the Free Software Foundation; either version 2, or (at your option)
 | |
| any later version.
 | |
| 
 | |
| GNU Classpath is distributed in the hope that it will be useful, but
 | |
| WITHOUT ANY WARRANTY; without even the implied warranty of
 | |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 | |
| General Public License for more details.
 | |
| 
 | |
| You should have received a copy of the GNU General Public License
 | |
| along with GNU Classpath; see the file COPYING.  If not, write to the
 | |
| Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 | |
| 02110-1301 USA.
 | |
| 
 | |
| Linking this library statically or dynamically with other modules is
 | |
| making a combined work based on this library.  Thus, the terms and
 | |
| conditions of the GNU General Public License cover the whole
 | |
| combination.
 | |
| 
 | |
| As a special exception, the copyright holders of this library give you
 | |
| permission to link this library with independent modules to produce an
 | |
| executable, regardless of the license terms of these independent
 | |
| modules, and to copy and distribute the resulting executable under
 | |
| terms of your choice, provided that you also meet, for each linked
 | |
| independent module, the terms and conditions of the license of that
 | |
| module.  An independent module is a module which is not derived from
 | |
| or based on this library.  If you modify this library, you may extend
 | |
| this exception to your version of the library, but you are not
 | |
| obligated to do so.  If you do not wish to do so, delete this
 | |
| exception statement from your version. */
 | |
| 
 | |
| package java.lang.management;
 | |
| 
 | |
| import gnu.classpath.SystemProperties;
 | |
| 
 | |
| import gnu.java.lang.management.ClassLoadingMXBeanImpl;
 | |
| import gnu.java.lang.management.CompilationMXBeanImpl;
 | |
| import gnu.java.lang.management.GarbageCollectorMXBeanImpl;
 | |
| import gnu.java.lang.management.OperatingSystemMXBeanImpl;
 | |
| import gnu.java.lang.management.MemoryMXBeanImpl;
 | |
| import gnu.java.lang.management.MemoryManagerMXBeanImpl;
 | |
| import gnu.java.lang.management.MemoryPoolMXBeanImpl;
 | |
| import gnu.java.lang.management.RuntimeMXBeanImpl;
 | |
| import gnu.java.lang.management.ThreadMXBeanImpl;
 | |
| 
 | |
| import java.io.IOException;
 | |
| 
 | |
| import java.lang.reflect.InvocationHandler;
 | |
| import java.lang.reflect.Method;
 | |
| import java.lang.reflect.Proxy;
 | |
| 
 | |
| import java.util.ArrayList;
 | |
| import java.util.HashMap;
 | |
| import java.util.Iterator;
 | |
| import java.util.List;
 | |
| import java.util.Map;
 | |
| 
 | |
| import java.util.logging.LogManager;
 | |
| 
 | |
| import javax.management.Attribute;
 | |
| import javax.management.InstanceAlreadyExistsException;
 | |
| import javax.management.MBeanRegistrationException;
 | |
| import javax.management.MBeanServer;
 | |
| import javax.management.MBeanServerConnection;
 | |
| import javax.management.MBeanServerFactory;
 | |
| import javax.management.MalformedObjectNameException;
 | |
| import javax.management.NotCompliantMBeanException;
 | |
| import javax.management.NotificationEmitter;
 | |
| import javax.management.NotificationFilter;
 | |
| import javax.management.NotificationListener;
 | |
| import javax.management.ObjectName;
 | |
| 
 | |
| import javax.management.openmbean.CompositeData;
 | |
| import javax.management.openmbean.TabularData;
 | |
| 
 | |
| /**
 | |
|  * <p>
 | |
|  * Provides access to the system's management beans via a series
 | |
|  * of static methods.
 | |
|  * </p>
 | |
|  * <p>
 | |
|  * An instance of a system management bean can be obtained by
 | |
|  * using one of the following methods:
 | |
|  * </p>
 | |
|  * <ol>
 | |
|  * <li>Calling the appropriate static method of this factory.
 | |
|  * </li>
 | |
|  * <li>Using the platform {@link javax.management.MBeanServer}
 | |
|  * to access the beans locally, or an
 | |
|  * {@link javax.management.MBeanServerConnection} for remote
 | |
|  * access.  The attributes and operations use the limited
 | |
|  * range of data types specified below.</li>
 | |
|  * </ol>
 | |
|  * <h2>Open Data Types</h2>
 | |
|  * <p>
 | |
|  * The data types used by the management beans are restricted
 | |
|  * to <emph>open</emph> data types to aid interoperability.  This
 | |
|  * allows the beans to be accessed remotely, including from non-Java
 | |
|  * clients.  Below is a table which lists the types used by the beans
 | |
|  * on the left, and the types they are converted to when returned via
 | |
|  * a bean server on the right.  Type information is provided for each
 | |
|  * bean by obtaining its instance of {@link javax.management.MBeanInfo}.
 | |
|  * </p>
 | |
|  * <table>
 | |
|  * <th><td>Data Type Used</td><td>Data Type Returned</td></th>
 | |
|  * <tr>
 | |
|  * <td>Primitive types (<code>int</code>, <code>char</code>, etc.)</td>
 | |
|  * <td>Same</td>
 | |
|  * </tr><tr>
 | |
|  * <td>Wrapper classes ({@link{java.lang.Integer},
 | |
|  * @link{java.lang.Character}, etc.)</td>
 | |
|  * <td>Same</td>
 | |
|  * </tr><tr>
 | |
|  * <td>An {@link java.lang.Enum}</td>
 | |
|  * <td>The <code>name</code> of the enumeration constant</td>
 | |
|  * </tr><tr>
 | |
|  * <td>An array of type <code>E</code></td>
 | |
|  * <td>An array of the same dimensions with this mapping applied
 | |
|  * to <code>E</code>.</td>
 | |
|  * </tr><tr>
 | |
|  * <td>A class with `getter' methods and a
 | |
|  * <code>from({@link javax.management.openmbean.CompositeData})</code>
 | |
|  * method.</td>
 | |
|  * <td>The equivalent {@link javax.management.openmbean.CompositeData}
 | |
|  * instance, specified by the <code>from</code> method.</td>
 | |
|  * </tr><tr>
 | |
|  * <td>A map with keys of type <code>K</code> and values of
 | |
|  * type <code>V</code>.</td>
 | |
|  * <td>A {@link javax.management.openmbean.TabularData} instance,
 | |
|  * with the row type containing two items, <code>"key"</code> and
 | |
|  * <code>"value"</code> with the types <code>K</code> and <code>V</code>
 | |
|  * respectively (with translation applied).</td>
 | |
|  * </tr><tr>
 | |
|  * <td>A list of type <code>E</code>.</td>
 | |
|  * <td>An array with this mapping applied to <code>E</code>.</td>
 | |
|  * </tr></table>
 | |
|  *
 | |
|  * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
 | |
|  * @since 1.5
 | |
|  */
 | |
| public class ManagementFactory
 | |
| {
 | |
| 
 | |
|   /**
 | |
|    * The object name for the class loading bean.
 | |
|    */
 | |
|   public static final String CLASS_LOADING_MXBEAN_NAME =
 | |
|     "java.lang:type=ClassLoading";
 | |
| 
 | |
|   /**
 | |
|    * The object name for the compilation bean.
 | |
|    */
 | |
|   public static final String COMPILATION_MXBEAN_NAME =
 | |
|     "java.lang:type=Compilation";
 | |
| 
 | |
|   /**
 | |
|    * The domain for the garbage collecting beans.
 | |
|    */
 | |
|   public static final String GARBAGE_COLLECTOR_MXBEAN_DOMAIN_TYPE =
 | |
|     "java.lang:type=GarbageCollector";
 | |
| 
 | |
|   /**
 | |
|    * The domain for the memory manager beans.
 | |
|    */
 | |
|   public static final String MEMORY_MANAGER_MXBEAN_DOMAIN_TYPE =
 | |
|     "java.lang:type=MemoryManager";
 | |
| 
 | |
|   /**
 | |
|    * The object name for the memory bean.
 | |
|    */
 | |
|   public static final String MEMORY_MXBEAN_NAME =
 | |
|     "java.lang:type=Memory";
 | |
| 
 | |
|   /**
 | |
|    * The domain for the memory pool beans.
 | |
|    */
 | |
|   public static final String MEMORY_POOL_MXBEAN_DOMAIN_TYPE =
 | |
|     "java.lang:type=MemoryPool";
 | |
| 
 | |
|   /**
 | |
|    * The object name for the operating system bean.
 | |
|    */
 | |
|   public static final String OPERATING_SYSTEM_MXBEAN_NAME =
 | |
|     "java.lang:type=OperatingSystem";
 | |
| 
 | |
|   /**
 | |
|    * The object name for the runtime bean.
 | |
|    */
 | |
|   public static final String RUNTIME_MXBEAN_NAME =
 | |
|     "java.lang:type=Runtime";
 | |
| 
 | |
|   /**
 | |
|    * The object name for the threading bean.
 | |
|    */
 | |
|   public static final String THREAD_MXBEAN_NAME =
 | |
|     "java.lang:type=Threading";
 | |
| 
 | |
|   /**
 | |
|    * The operating system management bean.
 | |
|    */
 | |
|   private static OperatingSystemMXBean osBean;
 | |
| 
 | |
|   /**
 | |
|    * The runtime management bean.
 | |
|    */
 | |
|   private static RuntimeMXBean runtimeBean;
 | |
| 
 | |
|   /**
 | |
|    * The class loading management bean.
 | |
|    */
 | |
|   private static ClassLoadingMXBean classLoadingBean;
 | |
| 
 | |
|   /**
 | |
|    * The thread bean.
 | |
|    */
 | |
|   private static ThreadMXBean threadBean;
 | |
| 
 | |
|   /**
 | |
|    * The memory bean.
 | |
|    */
 | |
|   private static MemoryMXBean memoryBean;
 | |
| 
 | |
|   /**
 | |
|    * The compilation bean (may remain null).
 | |
|    */
 | |
|   private static CompilationMXBean compilationBean;
 | |
| 
 | |
|   /**
 | |
|    * The platform server.
 | |
|    */
 | |
|   private static MBeanServer platformServer;
 | |
| 
 | |
|   /**
 | |
|    * Private constructor to prevent instance creation.
 | |
|    */
 | |
|   private ManagementFactory() {}
 | |
| 
 | |
|   /**
 | |
|    * Returns the operating system management bean for the
 | |
|    * operating system on which the virtual machine is running.
 | |
|    *
 | |
|    * @return an instance of {@link OperatingSystemMXBean} for
 | |
|    *         the underlying operating system.
 | |
|    */
 | |
|   public static OperatingSystemMXBean getOperatingSystemMXBean()
 | |
|   {
 | |
|     if (osBean == null)
 | |
|       try
 | |
|         {
 | |
|           osBean = new OperatingSystemMXBeanImpl();
 | |
|         }
 | |
|       catch (NotCompliantMBeanException e)
 | |
|         {
 | |
|           throw new InternalError("The GNU implementation of the " +
 | |
|                                   "operating system bean is not a " +
 | |
|                                   "compliant management bean.");
 | |
|         }
 | |
|     return osBean;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Returns the runtime management bean for the
 | |
|    * running virtual machine.
 | |
|    *
 | |
|    * @return an instance of {@link RuntimeMXBean} for
 | |
|    *         this virtual machine.
 | |
|    */
 | |
|   public static RuntimeMXBean getRuntimeMXBean()
 | |
|   {
 | |
|     if (runtimeBean == null)
 | |
|       try
 | |
|         {
 | |
|           runtimeBean = new RuntimeMXBeanImpl();
 | |
|         }
 | |
|       catch (NotCompliantMBeanException e)
 | |
|         {
 | |
|           throw new InternalError("The GNU implementation of the " +
 | |
|                                   "runtime bean is not a compliant " +
 | |
|                                   "management bean.");
 | |
|         }
 | |
|     return runtimeBean;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Returns the class loading management bean for the
 | |
|    * running virtual machine.
 | |
|    *
 | |
|    * @return an instance of {@link ClassLoadingMXBean} for
 | |
|    *         this virtual machine.
 | |
|    */
 | |
|   public static ClassLoadingMXBean getClassLoadingMXBean()
 | |
|   {
 | |
|     if (classLoadingBean == null)
 | |
|       try
 | |
|         {
 | |
|           classLoadingBean = new ClassLoadingMXBeanImpl();
 | |
|         }
 | |
|       catch (NotCompliantMBeanException e)
 | |
|         {
 | |
|           throw new InternalError("The GNU implementation of the " +
 | |
|                                   "class loading bean is not a " +
 | |
|                                   "compliant management bean.");
 | |
|         }
 | |
|     return classLoadingBean;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Returns the thread management bean for the running
 | |
|    * virtual machine.
 | |
|    *
 | |
|    * @return an instance of {@link ThreadMXBean} for
 | |
|    *         this virtual machine.
 | |
|    */
 | |
|   public static ThreadMXBean getThreadMXBean()
 | |
|   {
 | |
|     if (threadBean == null)
 | |
|       try
 | |
|         {
 | |
|           threadBean = new ThreadMXBeanImpl();
 | |
|         }
 | |
|       catch (NotCompliantMBeanException e)
 | |
|         {
 | |
|           throw new InternalError("The GNU implementation of the " +
 | |
|                                   "thread bean is not a compliant " +
 | |
|                                   "management bean.");
 | |
|         }
 | |
|     return threadBean;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Returns the memory management bean for the running
 | |
|    * virtual machine.
 | |
|    *
 | |
|    * @return an instance of {@link MemoryMXBean} for
 | |
|    *         this virtual machine.
 | |
|    */
 | |
|   public static MemoryMXBean getMemoryMXBean()
 | |
|   {
 | |
|     if (memoryBean == null)
 | |
|       try
 | |
|         {
 | |
|           memoryBean = new MemoryMXBeanImpl();
 | |
|         }
 | |
|       catch (NotCompliantMBeanException e)
 | |
|         {
 | |
|           throw new InternalError("The GNU implementation of the " +
 | |
|                                   "memory bean is not a compliant " +
 | |
|                                   "management bean.");
 | |
|         }
 | |
|     return memoryBean;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Returns the compilation bean for the running
 | |
|    * virtual machine, if supported.  Otherwise,
 | |
|    * it returns <code>null</code>.
 | |
|    *
 | |
|    * @return an instance of {@link CompilationMXBean} for
 | |
|    *         this virtual machine, or <code>null</code>
 | |
|    *         if the virtual machine doesn't include
 | |
|    *         a Just-In-Time (JIT) compiler.
 | |
|    */
 | |
|   public static CompilationMXBean getCompilationMXBean()
 | |
|   {
 | |
|     if (compilationBean == null &&
 | |
|         SystemProperties.getProperty("gnu.java.compiler.name") != null)
 | |
|       try
 | |
|         {
 | |
|           compilationBean = new CompilationMXBeanImpl();
 | |
|         }
 | |
|       catch (NotCompliantMBeanException e)
 | |
|         {
 | |
|           throw new InternalError("The GNU implementation of the " +
 | |
|                                   "compilation bean is not a compliant " +
 | |
|                                   "management bean.");
 | |
|         }
 | |
|     return compilationBean;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Returns the memory pool beans for the running
 | |
|    * virtual machine.  These may change during the course
 | |
|    * of execution.
 | |
|    *
 | |
|    * @return a list of memory pool beans, one for each pool.
 | |
|    */
 | |
|   public static List<MemoryPoolMXBean> getMemoryPoolMXBeans()
 | |
|   {
 | |
|     List<MemoryPoolMXBean> poolBeans =
 | |
|       new ArrayList<MemoryPoolMXBean>();
 | |
|     String[] names = VMManagementFactory.getMemoryPoolNames();
 | |
|     for (int a = 0; a < names.length; ++a)
 | |
|       try
 | |
|         {
 | |
|           poolBeans.add(new MemoryPoolMXBeanImpl(names[a]));
 | |
|         }
 | |
|       catch (NotCompliantMBeanException e)
 | |
|         {
 | |
|           throw new InternalError("The GNU implementation of the " +
 | |
|                                   "memory pool bean, " + a + ", is " +
 | |
|                                   "not a compliant management bean.");
 | |
|         }
 | |
|     return poolBeans;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Returns the memory manager beans for the running
 | |
|    * virtual machine.  These may change during the course
 | |
|    * of execution.
 | |
|    *
 | |
|    * @return a list of memory manager beans, one for each manager.
 | |
|    */
 | |
|   public static List<MemoryManagerMXBean> getMemoryManagerMXBeans()
 | |
|   {
 | |
|     List<MemoryManagerMXBean> managerBeans =
 | |
|       new ArrayList<MemoryManagerMXBean>();
 | |
|     String[] names = VMManagementFactory.getMemoryManagerNames();
 | |
|     for (int a = 0; a < names.length; ++a)
 | |
|       try
 | |
|         {
 | |
|           managerBeans.add(new MemoryManagerMXBeanImpl(names[a]));
 | |
|         }
 | |
|       catch (NotCompliantMBeanException e)
 | |
|         {
 | |
|           throw new InternalError("The GNU implementation of the " +
 | |
|                                   "memory manager bean, " + a + ", is " +
 | |
|                                   "not a compliant management bean.");
 | |
|         }
 | |
|     managerBeans.addAll(getGarbageCollectorMXBeans());
 | |
|     return managerBeans;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * Returns the garbage collector beans for the running
 | |
|    * virtual machine.  These may change during the course
 | |
|    * of execution.
 | |
|    *
 | |
|    * @return a list of garbage collector beans, one for each pool.
 | |
|    */
 | |
|   public static List<GarbageCollectorMXBean> getGarbageCollectorMXBeans()
 | |
|   {
 | |
|     List<GarbageCollectorMXBean> gcBeans =
 | |
|       new ArrayList<GarbageCollectorMXBean>();
 | |
|     String[] names = VMManagementFactory.getGarbageCollectorNames();
 | |
|     for (int a = 0; a < names.length; ++a)
 | |
|       try
 | |
|         {
 | |
|           gcBeans.add(new GarbageCollectorMXBeanImpl(names[a]));
 | |
|         }
 | |
|       catch (NotCompliantMBeanException e)
 | |
|         {
 | |
|           throw new InternalError("The GNU implementation of the " +
 | |
|                                   "garbage collector bean, " + a +
 | |
|                                   ", is not a compliant management " +
 | |
|                                   "bean.");
 | |
|         }
 | |
|     return gcBeans;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * <p>
 | |
|    * Returns the platform {@link javax.management.MBeanServer}.  On the
 | |
|    * first call to this method, a server instance is retrieved from
 | |
|    * the {@link javax.management.MBeanServerFactory} and each of the
 | |
|    * beans are registered with it.  Subsequent calls return the existing
 | |
|    * instance.  If the property <code>javax.management.builder.initial</code>
 | |
|    * is set, its value will be used as the name of the class which is used
 | |
|    * to provide the server instance.
 | |
|    * </p>
 | |
|    * <p>
 | |
|    * It is recommended that the platform server is used for other beans as
 | |
|    * well, in order to simplify their discovery and publication.  Name conflicts
 | |
|    * should be avoided.
 | |
|    * </p>
 | |
|    *
 | |
|    * @return the platform {@link javax.management.MBeanServer}
 | |
|    * @throws SecurityException if a security manager exists and the
 | |
|    *                           caller's permissions don't imply {@link
 | |
|    *                           MBeanServerPermission(String)}("createMBeanServer")
 | |
|    * @see javax.management.MBeanServerFactory
 | |
|    * @see javax.management.MBeanServerFactory#createMBeanServer()
 | |
|    */
 | |
|   public static MBeanServer getPlatformMBeanServer()
 | |
|   {
 | |
|     if (platformServer == null)
 | |
|       {
 | |
|         platformServer = MBeanServerFactory.createMBeanServer();
 | |
|         try
 | |
|           {
 | |
|             platformServer.registerMBean(getOperatingSystemMXBean(),
 | |
|                                          new ObjectName(OPERATING_SYSTEM_MXBEAN_NAME));
 | |
|             platformServer.registerMBean(getRuntimeMXBean(),
 | |
|                                          new ObjectName(RUNTIME_MXBEAN_NAME));
 | |
|             platformServer.registerMBean(getClassLoadingMXBean(),
 | |
|                                          new ObjectName(CLASS_LOADING_MXBEAN_NAME));
 | |
|             platformServer.registerMBean(getThreadMXBean(),
 | |
|                                          new ObjectName(THREAD_MXBEAN_NAME));
 | |
|             platformServer.registerMBean(getMemoryMXBean(),
 | |
|                                          new ObjectName(MEMORY_MXBEAN_NAME));
 | |
|             CompilationMXBean compBean = getCompilationMXBean();
 | |
|             if (compBean != null)
 | |
|               platformServer.registerMBean(compBean,
 | |
|                                            new ObjectName(COMPILATION_MXBEAN_NAME));
 | |
|             Iterator beans = getMemoryPoolMXBeans().iterator();
 | |
|             while (beans.hasNext())
 | |
|               {
 | |
|                 MemoryPoolMXBean bean = (MemoryPoolMXBean) beans.next();
 | |
|                 platformServer.registerMBean(bean,
 | |
|                                              new ObjectName(MEMORY_POOL_MXBEAN_DOMAIN_TYPE +
 | |
|                                                             ",name=" +
 | |
|                                                             bean.getName()));
 | |
|               }
 | |
|             beans = getMemoryManagerMXBeans().iterator();
 | |
|             while (beans.hasNext())
 | |
|               {
 | |
|                 MemoryManagerMXBean bean = (MemoryManagerMXBean) beans.next();
 | |
|                 platformServer.registerMBean(bean,
 | |
|                                              new ObjectName(MEMORY_MANAGER_MXBEAN_DOMAIN_TYPE +
 | |
|                                                             ",name=" +
 | |
|                                                             bean.getName()));
 | |
|               }
 | |
|             beans = getGarbageCollectorMXBeans().iterator();
 | |
|             while (beans.hasNext())
 | |
|               {
 | |
|                 GarbageCollectorMXBean bean = (GarbageCollectorMXBean) beans.next();
 | |
|                 platformServer.registerMBean(bean,
 | |
|                                              new ObjectName(GARBAGE_COLLECTOR_MXBEAN_DOMAIN_TYPE +
 | |
|                                                             ",name=" +
 | |
|                                                             bean.getName()));
 | |
|               }
 | |
|             platformServer.registerMBean(LogManager.getLoggingMXBean(),
 | |
|                                          new ObjectName(LogManager.LOGGING_MXBEAN_NAME));
 | |
|           }
 | |
|         catch (InstanceAlreadyExistsException e)
 | |
|           {
 | |
|             throw (Error)
 | |
|               (new InternalError("One of the management beans is " +
 | |
|                                  "already registered.").initCause(e));
 | |
|           }
 | |
|         catch (MBeanRegistrationException e)
 | |
|           {
 | |
|             throw (Error)
 | |
|               (new InternalError("One of the management beans' preRegister " +
 | |
|                                  "methods threw an exception.").initCause(e));
 | |
|           }
 | |
|         catch (NotCompliantMBeanException e)
 | |
|           {
 | |
|             throw (Error)
 | |
|               (new InternalError("One of the management beans is " +
 | |
|                                  "not compliant.").initCause(e));
 | |
|           }
 | |
|         catch (MalformedObjectNameException e)
 | |
|           {
 | |
|             throw (Error)
 | |
|               (new InternalError("The object name of a management bean is " +
 | |
|                                  "not compliant.").initCause(e));
 | |
|           }
 | |
|       }
 | |
|     return platformServer;
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * <p>
 | |
|    * Returns a proxy for the specified platform bean.  A proxy object is created
 | |
|    * using <code>Proxy.newProxyInstance(mxbeanInterface.getClassLoader(),
 | |
|    * new Class[] { mxbeanInterface }, handler)</code>.  The
 | |
|    * {@link javax.management.NotificationEmitter} class is also added to the
 | |
|    * array if the bean provides notifications.  <code>handler</code> refers
 | |
|    * to the invocation handler which forwards calls to the connection, and
 | |
|    * also provides translation between the Java data types used in the
 | |
|    * bean interfaces and the open data types, as specified in the description
 | |
|    * of this class.  It is this translation that makes the
 | |
|    * usual {@link javax.management.MBeanServerInvocationHandler} inappropriate
 | |
|    * for providing such a proxy.
 | |
|    * </p>
 | |
|    * <p>
 | |
|    * <strong>Note</strong>: use of the proxy may result in
 | |
|    * {@link java.io.IOException}s from the underlying {@link MBeanServerConnection}
 | |
|    * and a {@link java.io.InvalidObjectException} if enum constants
 | |
|    * used on the client and the server don't match.
 | |
|    * </p>
 | |
|    *
 | |
|    * @param connection the server connection to use to access the bean.
 | |
|    * @param mxbeanName the {@link javax.management.ObjectName} of the
 | |
|    *                   bean to provide a proxy for.
 | |
|    * @param mxbeanInterface the interface for the bean being proxied.
 | |
|    * @return a proxy for the specified bean.
 | |
|    * @throws IllegalArgumentException if <code>mxbeanName</code> is not a valid
 | |
|    *                                  {@link javax.management.ObjectName},
 | |
|    *                                  the interface and name do not match the
 | |
|    *                                  same bean, the name does not refer to a
 | |
|    *                                  platform bean or the bean is not registered
 | |
|    *                                  with the server accessed by <code>connection</code>.
 | |
|    * @throws IOException if the connection throws one.
 | |
|    */
 | |
|   public static <T> T newPlatformMXBeanProxy(MBeanServerConnection connection,
 | |
|                                              String mxbeanName,
 | |
|                                              Class<T> mxbeanInterface)
 | |
|     throws IOException
 | |
|   {
 | |
|     if (!(mxbeanName.equals(CLASS_LOADING_MXBEAN_NAME) ||
 | |
|           mxbeanName.equals(COMPILATION_MXBEAN_NAME) ||
 | |
|           mxbeanName.startsWith(GARBAGE_COLLECTOR_MXBEAN_DOMAIN_TYPE) ||
 | |
|           mxbeanName.startsWith(MEMORY_MANAGER_MXBEAN_DOMAIN_TYPE) ||
 | |
|           mxbeanName.equals(MEMORY_MXBEAN_NAME) ||
 | |
|           mxbeanName.startsWith(MEMORY_POOL_MXBEAN_DOMAIN_TYPE) ||
 | |
|           mxbeanName.equals(OPERATING_SYSTEM_MXBEAN_NAME) ||
 | |
|           mxbeanName.equals(RUNTIME_MXBEAN_NAME) ||
 | |
|           mxbeanName.equals(THREAD_MXBEAN_NAME)))
 | |
|       {
 | |
|         throw new IllegalArgumentException("The named bean, " + mxbeanName +
 | |
|                                            ", is not a platform name.");
 | |
|       }
 | |
|     if ((mxbeanName.equals(CLASS_LOADING_MXBEAN_NAME) &&
 | |
|          mxbeanInterface != ClassLoadingMXBean.class) ||
 | |
|         (mxbeanName.equals(COMPILATION_MXBEAN_NAME) &&
 | |
|          mxbeanInterface != CompilationMXBean.class) ||
 | |
|         (mxbeanName.startsWith(GARBAGE_COLLECTOR_MXBEAN_DOMAIN_TYPE) &&
 | |
|          mxbeanInterface != GarbageCollectorMXBean.class) ||
 | |
|         (mxbeanName.startsWith(MEMORY_MANAGER_MXBEAN_DOMAIN_TYPE) &&
 | |
|          mxbeanInterface != MemoryManagerMXBean.class) ||
 | |
|         (mxbeanName.equals(MEMORY_MXBEAN_NAME) &&
 | |
|          mxbeanInterface != MemoryMXBean.class) ||
 | |
|         (mxbeanName.startsWith(MEMORY_POOL_MXBEAN_DOMAIN_TYPE) &&
 | |
|          mxbeanInterface != MemoryPoolMXBean.class) ||
 | |
|         (mxbeanName.equals(OPERATING_SYSTEM_MXBEAN_NAME) &&
 | |
|          mxbeanInterface != OperatingSystemMXBean.class) ||
 | |
|         (mxbeanName.equals(RUNTIME_MXBEAN_NAME) &&
 | |
|          mxbeanInterface != RuntimeMXBean.class) ||
 | |
|         (mxbeanName.equals(THREAD_MXBEAN_NAME) &&
 | |
|          mxbeanInterface != ThreadMXBean.class))
 | |
|       throw new IllegalArgumentException("The interface, " + mxbeanInterface +
 | |
|                                          ", does not match the bean, " + mxbeanName);
 | |
|     ObjectName bean;
 | |
|     try
 | |
|       {
 | |
|         bean = new ObjectName(mxbeanName);
 | |
|       }
 | |
|     catch (MalformedObjectNameException e)
 | |
|       {
 | |
|         throw new IllegalArgumentException("The named bean is invalid.");
 | |
|       }
 | |
|     if (!(connection.isRegistered(bean)))
 | |
|       throw new IllegalArgumentException("The bean is not registered on this connection.");
 | |
|     Class[] interfaces;
 | |
|     if (mxbeanName.equals(MEMORY_MXBEAN_NAME))
 | |
|       interfaces = new Class[] { mxbeanInterface, NotificationEmitter.class };
 | |
|     else
 | |
|       interfaces = new Class[] { mxbeanInterface };
 | |
|     return (T) Proxy.newProxyInstance(mxbeanInterface.getClassLoader(),
 | |
|                                       interfaces,
 | |
|                                       new ManagementInvocationHandler(connection, bean));
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|    * This invocation handler provides method calls for a platform bean
 | |
|    * by forwarding them to a {@link MBeanServerConnection}.  Translation from
 | |
|    * Java data types to open data types is performed as specified above.
 | |
|    *
 | |
|    * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
 | |
|    * @since 1.5
 | |
|    */
 | |
|   private static class ManagementInvocationHandler
 | |
|     implements InvocationHandler
 | |
|   {
 | |
| 
 | |
|     /**
 | |
|      * The encapsulated connection.
 | |
|      */
 | |
|     private MBeanServerConnection conn;
 | |
| 
 | |
|     /**
 | |
|      * The bean being proxied.
 | |
|      */
 | |
|     private ObjectName bean;
 | |
| 
 | |
|     /**
 | |
|      * Constructs a new {@link InvocationHandler} which proxies
 | |
|      * for the specified bean using the supplied connection.
 | |
|      *
 | |
|      * @param conn the connection on which to forward method calls.
 | |
|      * @param bean the bean to proxy.
 | |
|      */
 | |
|     public ManagementInvocationHandler(MBeanServerConnection conn,
 | |
|                                        ObjectName bean)
 | |
|       throws IOException
 | |
|     {
 | |
|       this.conn = conn;
 | |
|       this.bean = bean;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Called by the proxy class whenever a method is called.  The method
 | |
|      * is emulated by retrieving an attribute from, setting an attribute on
 | |
|      * or invoking a method on the server connection as required.  Translation
 | |
|      * between the Java data types supplied as arguments to the open types used
 | |
|      * by the bean is provided, as well as translation of the return value back
 | |
|      * in to the appropriate Java type.
 | |
|      *
 | |
|      * @param proxy the proxy on which the method was called.
 | |
|      * @param method the method which was called.
 | |
|      * @param args the arguments supplied to the method.
 | |
|      * @return the return value from the method.
 | |
|      * @throws Throwable if an exception is thrown in performing the
 | |
|      *                   method emulation.
 | |
|      */
 | |
|     public Object invoke(Object proxy, Method method, Object[] args)
 | |
|       throws Throwable
 | |
|     {
 | |
|       String name = method.getName();
 | |
|       if (name.equals("toString"))
 | |
|         return "Proxy for " + bean + " using " + conn;
 | |
|       if (name.equals("addNotificationListener"))
 | |
|         {
 | |
|           conn.addNotificationListener(bean,
 | |
|                                        (NotificationListener) args[0],
 | |
|                                        (NotificationFilter) args[1],
 | |
|                                        args[2]);
 | |
|           return null;
 | |
|         }
 | |
|       if (name.equals("getNotificationInfo"))
 | |
|         return conn.getMBeanInfo(bean).getNotifications();
 | |
|       if (name.equals("removeNotificationListener"))
 | |
|         {
 | |
|           if (args.length == 1)
 | |
|             conn.removeNotificationListener(bean,
 | |
|                                             (NotificationListener)
 | |
|                                             args[0]);
 | |
|           else
 | |
|             conn.removeNotificationListener(bean,
 | |
|                                             (NotificationListener)
 | |
|                                             args[0],
 | |
|                                             (NotificationFilter)
 | |
|                                             args[1], args[2]);
 | |
|           return null;
 | |
|         }
 | |
|       String attrib = null;
 | |
|       if (name.startsWith("get"))
 | |
|         attrib = name.substring(3);
 | |
|       else if (name.startsWith("is"))
 | |
|         attrib = name.substring(2);
 | |
|       if (attrib != null)
 | |
|         return translate(conn.getAttribute(bean, attrib), method);
 | |
|       else if (name.startsWith("set"))
 | |
|         {
 | |
|           conn.setAttribute(bean, new Attribute(name.substring(3),
 | |
|                                                 args[0]));
 | |
|           return null;
 | |
|         }
 | |
|       else
 | |
|         return translate(conn.invoke(bean, name, args, null), method);
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Translates the returned open data type to the value
 | |
|      * required by the interface.
 | |
|      *
 | |
|      * @param otype the open type returned by the method call.
 | |
|      * @param method the method that was called.
 | |
|      * @return the equivalent return type required by the interface.
 | |
|      * @throws Throwable if an exception is thrown in performing the
 | |
|      *                   conversion.
 | |
|      */
 | |
|     private final Object translate(Object otype, Method method)
 | |
|       throws Throwable
 | |
|     {
 | |
|       Class<?> returnType = method.getReturnType();
 | |
|       if (returnType.isEnum())
 | |
|         {
 | |
|           String ename = (String) otype;
 | |
|           Enum[] constants = (Enum[]) returnType.getEnumConstants();
 | |
|           for (Enum c : constants)
 | |
|             if (c.name().equals(ename))
 | |
|               return c;
 | |
|         }
 | |
|       if (List.class.isAssignableFrom(returnType))
 | |
|         {
 | |
|           Object[] elems = (Object[]) otype;
 | |
|           List l = new ArrayList(elems.length);
 | |
|           for (Object elem : elems)
 | |
|             l.add(elem);
 | |
|           return l;
 | |
|         }
 | |
|       if (Map.class.isAssignableFrom(returnType))
 | |
|         {
 | |
|           TabularData data = (TabularData) otype;
 | |
|           Map m = new HashMap(data.size());
 | |
|           for (Object val : data.values())
 | |
|             {
 | |
|               CompositeData vals = (CompositeData) val;
 | |
|               m.put(vals.get("key"), vals.get("value"));
 | |
|             }
 | |
|           return m;
 | |
|         }
 | |
|       try
 | |
|         {
 | |
|           Method m = returnType.getMethod("from",
 | |
|                                           new Class[]
 | |
|             { CompositeData.class });
 | |
|           return m.invoke(null, (CompositeData) otype);
 | |
|         }
 | |
|       catch (NoSuchMethodException e)
 | |
|         {
 | |
|           /* Ignored; we expect this if this
 | |
|              isn't a from(CompositeData) class */
 | |
|         }
 | |
|       return otype;
 | |
|     }
 | |
| 
 | |
|   }
 | |
| }
 |