summaryrefslogtreecommitdiff
path: root/libjava/classpath/java/lang/management/ManagementFactory.java
diff options
context:
space:
mode:
authorupstream source tree <ports@midipix.org>2015-03-15 20:14:05 -0400
committerupstream source tree <ports@midipix.org>2015-03-15 20:14:05 -0400
commit554fd8c5195424bdbcabf5de30fdc183aba391bd (patch)
tree976dc5ab7fddf506dadce60ae936f43f58787092 /libjava/classpath/java/lang/management/ManagementFactory.java
downloadcbb-gcc-4.6.4-554fd8c5195424bdbcabf5de30fdc183aba391bd.tar.bz2
cbb-gcc-4.6.4-554fd8c5195424bdbcabf5de30fdc183aba391bd.tar.xz
obtained gcc-4.6.4.tar.bz2 from upstream website;upstream
verified gcc-4.6.4.tar.bz2.sig; imported gcc-4.6.4 source tree from verified upstream tarball. downloading a git-generated archive based on the 'upstream' tag should provide you with a source tree that is binary identical to the one extracted from the above tarball. if you have obtained the source via the command 'git clone', however, do note that line-endings of files in your working directory might differ from line-endings of the respective files in the upstream repository.
Diffstat (limited to 'libjava/classpath/java/lang/management/ManagementFactory.java')
-rw-r--r--libjava/classpath/java/lang/management/ManagementFactory.java817
1 files changed, 817 insertions, 0 deletions
diff --git a/libjava/classpath/java/lang/management/ManagementFactory.java b/libjava/classpath/java/lang/management/ManagementFactory.java
new file mode 100644
index 000000000..c054f5dd9
--- /dev/null
+++ b/libjava/classpath/java/lang/management/ManagementFactory.java
@@ -0,0 +1,817 @@
+/* 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;
+ }
+
+ }
+}