summaryrefslogtreecommitdiff
path: root/javax
diff options
context:
space:
mode:
authorAndrew John Hughes <gnu_andrew@member.fsf.org>2007-03-05 00:22:40 +0000
committerAndrew John Hughes <gnu_andrew@member.fsf.org>2007-03-05 00:22:40 +0000
commit5e7d7af8305ec32c022fd21d117638b3fa569d32 (patch)
treefd6b9c77d1d67a78854998a050b1e31cb31401c7 /javax
parent8755402234c333b689b541a32a66bbd759460635 (diff)
downloadclasspath-5e7d7af8305ec32c022fd21d117638b3fa569d32.tar.gz
2007-03-05 Andrew John Hughs <gnu_andrew@member.fsf.org>
* gnu/java/lang/management/BeanImpl.java: Reference the new Translator class. (translate(String)): Moved to Translator. * gnu/javax/management/Translator.java: New file. * javax/management/JMX.java: Likewise. * javax/management/MBeanServerInvocationHandler.java: Likewise. * javax/management/MXBean.java: Likewise. * javax/management/ObjectName.java: (ObjectName(String)): Catch a key without a value. * javax/management/StandardMBean.java: (StandardMBean(Class<?>)): Handle MXBeans. (StandardMBean(Object, Class<?>)): Likewise. (invoke(String,Object[],String[])): Disallow calling attribute methods and handle null signatures. (setAttribute(Attribute)): Search for mutators with the appropriate signature. * javax/management/openmbean/OpenType.java: Add generic typing. (ALLOWED_CLASSNAMES_LIST): New field.
Diffstat (limited to 'javax')
-rw-r--r--javax/management/JMX.java342
-rw-r--r--javax/management/MBeanServerInvocationHandler.java400
-rw-r--r--javax/management/MXBean.java82
-rw-r--r--javax/management/ObjectName.java3
-rw-r--r--javax/management/StandardMBean.java79
-rw-r--r--javax/management/openmbean/OpenType.java16
6 files changed, 897 insertions, 25 deletions
diff --git a/javax/management/JMX.java b/javax/management/JMX.java
new file mode 100644
index 000000000..fb3bd2b66
--- /dev/null
+++ b/javax/management/JMX.java
@@ -0,0 +1,342 @@
+/* JMX.java -- Static methods pertaining to the management API.
+ Copyright (C) 2007 Free Software Foundation, Inc.
+
+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 javax.management;
+
+import java.lang.reflect.Proxy;
+
+/**
+ * Common static methods pertaining to the management
+ * API. There are no instances of this class.
+ *
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ * @since 1.6
+ */
+public class JMX
+{
+
+ /**
+ * The name of the defaultValue field.
+ */
+ public static final String DEFAULT_VALUE_FIELD = "defaultValue";
+
+ /**
+ * The name of the immutableInfo field.
+ */
+ public static final String IMMUTABLE_INFO_FIELD = "immutableInfo";
+
+ /**
+ * The name of the interfaceClassName field.
+ */
+ public static final String INTERFACE_CLASS_NAME_FIELD = "interfaceClassName";
+
+ /**
+ * The name of the legalValues field.
+ */
+ public static final String LEGAL_VALUES_FIELD = "legalValues";
+
+ /**
+ * The name of the maxValue field.
+ */
+ public static final String MAX_VALUE_FIELD = "maxValue";
+
+ /**
+ * The name of the minValue field.
+ */
+ public static final String MIN_VALUE_FIELD = "minValue";
+
+ /**
+ * The name of the mxbean field.
+ */
+ public static final String MXBEAN_FIELD = "mxbean";
+
+ /**
+ * The name of the openType field.
+ */
+ public static final String OPEN_TYPE_FIELD = "openType";
+
+ /**
+ * The name of the originalType field.
+ */
+ public static final String ORIGINAL_TYPE_FIELD = "originalType";
+
+ /**
+ * Prevent instance creation.
+ */
+ private JMX()
+ {
+ }
+
+ /**
+ * <p>
+ * Returns true if the given class represents an {@link MXBean}
+ * interface. An interface is an {@link MXBean interface} if:
+ * </p>
+ * <ul>
+ * <li>It is annotated with {@code @MXBean} or
+ * {@code @MXBean(true)}</li>.
+ * <li>Its name ends in {@code "MXBean"} and it does not
+ * have an {@link MXBean} annotation.</li>
+ * </ul>
+ *
+ * @param iface the interface class that is to be checked
+ * for {@link MXBean} status.
+ * @return true if the interface represents an {@link MXBean}.
+ * @throws NullPointerException if {@code iface} is {@code null}.
+ */
+ public static boolean isMXBeanInterface(Class<?> iface)
+ {
+ MXBean annotation = iface.getAnnotation(MXBean.class);
+ if (annotation != null)
+ return annotation.value();
+ return iface.getName().endsWith("MXBean");
+ }
+
+ /**
+ * <p>
+ * Returns a proxy for a standard management bean, using
+ * the specified connection to access the named implementation.
+ * To create a proxy for the bean, {@code SomethingMBean}, a call to
+ * {@code JMX.newMBeanProxy(server, name, SomethingMBean.class)}
+ * is made, where {@code server} is a local or remote management
+ * server, and {@code name} is the registered {@link ObjectName}
+ * of the implementation of {@code SomethingMBean} to use.
+ * </p>
+ * <p>
+ * The proxy redirects calls to the methods of the interface,
+ * {@link SomethingMBean}, to the appropriate methods of the
+ * management server. If {@link SomethingMBean} is specified
+ * as follows:
+ * </p>
+ * <pre>
+ * public interface SomethingMBean
+ * {
+ * String getName();
+ * void setName(String name);
+ * void doStuff();
+ * }
+ * </pre>
+ * <p>
+ * The proxy created above will provide these three methods
+ * using an instance of {@link MBeanServerInvocationHandler}.
+ * The two methods, {@code getName} and {@code setName} define
+ * an attribute, {@code Name}, so a call to {@code getName()}
+ * will return the value of {@code server.getAttribute(name,
+ * "Name")}, while {@code setName(newName)} will result in a
+ * call to {@code server.setAttribute(name, new Attribute("Name",
+ * newName))}. Finally, {@code doStuff()}, as an operation,
+ * will cause the proxy to call {@link MBeanServer#invoke(ObjectName,
+ * String, Object[], String[])} as
+ * {@code server.invoke(name, "doStuff", null, null)}.
+ * </p>
+ * <p>
+ * Calling this method is equivalent to calling
+ * {@link #newMBeanProxy(MBeanServerConnection, ObjectName, Class,
+ * boolean)}.
+ * </p>
+ *
+ * @param conn the server connection over which to forward calls to
+ * the bean.
+ * @param name the registered name of the bean to use to implement
+ * the given interface.
+ * @param iface the interface to provide a proxy for.
+ * @return a proxy implementing the specified interface using calls
+ * to the methods of the bean registered with the supplied
+ * server using the given name.
+ * @see #newMBeanProxy(MBeanServerConnection, ObjectName, Class,
+ * boolean)
+ */
+ public static <T> T newMBeanProxy(MBeanServerConnection conn,
+ ObjectName name, Class<T> iface)
+ {
+ return newMBeanProxy(conn, name, iface, false);
+ }
+
+ /**
+ * Returns a proxy for a standard management bean, using
+ * the specified connection to access the named implementation,
+ * as with {@link #newMBeanProxy(MBeanServerConnection, ObjectName,
+ * Class)}. In addition, the proxy returned by this method will
+ * also implement {@link NotificationEmitter} if {@code bcast} is
+ * true, under the assumption that the implementation referenced by
+ * {@code name} implements this interface. Calls to the methods of
+ * {@link NotificationEmitter} will be forwarded to the bean
+ * implementation via the appropriate server methods.
+ *
+ * @param conn the server connection over which to forward calls to
+ * the bean.
+ * @param name the registered name of the bean to use to implement
+ * the given interface.
+ * @param iface the interface to provide a proxy for.
+ * @param bcast true if the proxy should implement
+ * {@link NotificationEmitter}.
+ * @return a proxy implementing the specified interface using calls
+ * to the methods of the bean registered with the supplied
+ * server using the given name.
+ * @see #newMBeanProxy(MBeanServerConnection, ObjectName, Class)
+ */
+ public static <T> T newMBeanProxy(MBeanServerConnection conn,
+ ObjectName name, Class<T> iface,
+ boolean bcast)
+ {
+ return MBeanServerInvocationHandler.newProxyInstance(conn, name,
+ iface, bcast);
+ }
+
+ /**
+ * <p>
+ * Returns a proxy for a {@link MXBean}, using the specified
+ * connection to access the named implementation.
+ * To create a proxy for the bean, {@code SomethingMXBean}, a call to
+ * {@code JMX.newMXBeanProxy(server, name, SomethingMXBean.class)}
+ * is made, where {@code server} is a local or remote management
+ * server, and {@code name} is the registered {@link ObjectName}
+ * of the implementation of {@code SomethingMBean} to use.
+ * </p>
+ * <p>
+ * The proxy redirects calls to the methods of the interface,
+ * {@link SomethingMXBean}, to the appropriate methods of the
+ * management server with appropriate conversion between
+ * Java and open types, according to the MXBean rules. If
+ * {@link SomethingMXBean} is specified as follows:
+ * </p>
+ * <pre>
+ * public interface SomethingMXBean
+ * {
+ * String getName();
+ * void setName(String name);
+ * List<Double> getStatistics();
+ * void setStatistics(List<Double> statistics);
+ * List<Double> getNamedStatistics(String, Map<String,Integer>);
+ * }
+ * </pre>
+ * <p>
+ * The proxy created above will provide these five methods
+ * using an instance of {@link MBeanServerInvocationHandler}.
+ * The two methods, {@code getName} and {@code setName} define
+ * an attribute, {@code Name}, so a call to {@code getName()}
+ * will return the value of {@code server.getAttribute(name,
+ * "Name")}, while {@code setName(newName)} will result in a
+ * call to {@code server.setAttribute(name, new Attribute("Name",
+ * newName))}. As this uses a simple type, {@link String}, no
+ * conversion is necessary.
+ * </p>
+ * <p>
+ * The two methods, {@code getStatistics} and {@code setStatistics}
+ * similarly define another attribute, {@code Statistics}. Calling
+ * {@code getStatistics()} will cause a call to the server to be
+ * made as before, {@code server.getAttribute(name, "Statistics")}.
+ * However, the type of the return value from this call will be
+ * an array of {@link Double} objects, as per the {@link MXBean}
+ * rules. The proxy converts this back in to a {@link java.util.List}
+ * of {@link Double} objects before returning it.
+ * </p>
+ * <p>
+ * The same process is applied in reverse for
+ * {@code setStatistics(newStats)}. The list is converted into
+ * an appropriate array before the call to
+ * {@link MBeanServerConnection#setAttribute(ObjectName, Attribute)}
+ * is made. Finally, a call to {@code getNamedStatistics} will require
+ * both a Java to open type conversion on the arguments, and then
+ * an open type to Java conversion of the return value. Thus, a proxy
+ * enables an {@link MXBean} to be used in cases where the appropriate
+ * Java types are available and the user wishes to access the bean
+ * using the types directly defined in its interface, just as with
+ * standard management beans.
+ * </p>
+ * <p>
+ * Calling this method is equivalent to calling
+ * {@link #newMXBeanProxy(MBeanServerConnection, ObjectName, Class,
+ * boolean)}.
+ * </p>
+ *
+ * @param conn the server connection over which to forward calls to
+ * the bean.
+ * @param name the registered name of the bean to use to implement
+ * the given interface.
+ * @param iface the interface to provide a proxy for.
+ * @return a proxy implementing the specified interface using calls
+ * to the methods of the bean registered with the supplied
+ * server using the given name.
+ * @see #newMXBeanProxy(MBeanServerConnection, ObjectName, Class,
+ * boolean)
+ */
+ public static <T> T newMXBeanProxy(MBeanServerConnection conn,
+ ObjectName name, Class<T> iface)
+ {
+ return newMBeanProxy(conn, name, iface, false);
+ }
+
+ /**
+ * Returns a proxy for a {@link MXBean}, using
+ * the specified connection to access the named implementation,
+ * as with {@link #newMXBeanProxy(MBeanServerConnection, ObjectName,
+ * Class)}. In addition, the proxy returned by this method will
+ * also implement {@link NotificationEmitter} if {@code bcast} is
+ * true, under the assumption that the implementation referenced by
+ * {@code name} implements this interface. Calls to the methods of
+ * {@link NotificationEmitter} will be forwarded to the bean
+ * implementation via the appropriate server methods.
+ *
+ * @param conn the server connection over which to forward calls to
+ * the bean.
+ * @param name the registered name of the bean to use to implement
+ * the given interface.
+ * @param iface the interface to provide a proxy for.
+ * @param bcast true if the proxy should implement
+ * {@link NotificationEmitter}.
+ * @return a proxy implementing the specified interface using calls
+ * to the methods of the bean registered with the supplied
+ * server using the given name.
+ * @see #newMXBeanProxy(MBeanServerConnection, ObjectName, Class)
+ */
+ public static <T> T newMXBeanProxy(MBeanServerConnection conn,
+ ObjectName name, Class<T> iface,
+ boolean bcast)
+ {
+ if (bcast)
+ return (T) Proxy.newProxyInstance(iface.getClassLoader(),
+ new Class[] { iface,
+ NotificationEmitter.class },
+ new MBeanServerInvocationHandler(conn,name,true));
+ else
+ return (T) Proxy.newProxyInstance(iface.getClassLoader(),
+ new Class[] { iface },
+ new MBeanServerInvocationHandler(conn,name,true));
+ }
+
+}
diff --git a/javax/management/MBeanServerInvocationHandler.java b/javax/management/MBeanServerInvocationHandler.java
new file mode 100644
index 000000000..948996764
--- /dev/null
+++ b/javax/management/MBeanServerInvocationHandler.java
@@ -0,0 +1,400 @@
+/* MBeanServerInvocationHandler.java -- Provides a proxy for a bean.
+ Copyright (C) 2007 Free Software Foundation, Inc.
+
+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 javax.management;
+
+import gnu.javax.management.Translator;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+
+/**
+ * <p>
+ * Provides a proxy for a management bean. The methods
+ * of the given interface are fulfilled by redirecting the
+ * calls over an {@link MBeanServerConnection} to the bean
+ * specified by the supplied {@link ObjectName}.
+ * </p>
+ * <p>
+ * The {@link java.lang.reflect.InvocationHandler} also makes
+ * provision for {@link MXBean}s by providing type conversion
+ * according to the rules defined for these beans. The input
+ * parameters are converted to their equivalent open type before
+ * calling the method, and then the return value is converted
+ * back from its open type to the appropriate Java type. For
+ * example, a method that takes an {@link Enum} as input and
+ * returns a {@link java.util.List} will have the input value
+ * converted from an {@link Enum} to a {@link String}, while
+ * the return value will be converted from its return type
+ * (an appropriately typed array) to a {@link java.util.List}.
+ * </p>
+ * <p>
+ * The proxy has special cases for the {@link Object#equals(Object)},
+ * {@link Object#hashCode()} and {@link Object#toString()} methods.
+ * Unless they are specified explictly by the interface, the
+ * following behaviour is provided for these methods by the proxy:
+ * </p>
+ * <ul>
+ * <li><code>equals(Object)</code> returns true if the other object
+ * is an {@link MBeanServerInvocationHandler} with the same
+ * {@link MBeanServerConnection} and {@link ObjectName}. If an
+ * interface class was specified on construction for one of the
+ * proxies, then the same class must have also been specified
+ * for the other.</li>
+ * <li><code>hashCode()</code> returns the same value for
+ * equivalent proxies.</li>
+ * <li><code>toString()</code> returns a textual representation
+ * of the proxy.</li>
+ * </ul>
+ *
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ * @since 1.5
+ */
+public class MBeanServerInvocationHandler
+ implements InvocationHandler
+{
+
+ /**
+ * The connection used to make the calls.
+ */
+ private MBeanServerConnection conn;
+
+ /**
+ * The name of the bean to perform operations on.
+ */
+ private ObjectName name;
+
+ /**
+ * True if this proxy is for an {@link MXBean}.
+ */
+ private boolean mxBean;
+
+ /**
+ * The interface class associated with the bean.
+ */
+ private Class<?> iface;
+
+ /**
+ * Constructs a new {@link MBeanServerInvocationHandler}
+ * which forwards methods to the supplied bean via the
+ * given {@link MBeanServerConnection}. This constructor
+ * is used in preference to
+ * {@link JMX#newMBeanProxy(MBeanServerConnection, ObjectName,
+ * Class<T>)} if you wish to make your own call to
+ * {@link java.lang.reflect.Proxy#newInstance(ClassLoader,
+ * Class[], java.lang.reflect.InvocationHandler)} with
+ * a different {@link ClassLoader}. Calling this constructor
+ * is equivalent to <code>MBeanServerInvocationHandler(conn,
+ * name, false)</code>. The other constructor should be used
+ * instead if the bean being proxied is an {@link MXBean}.
+ *
+ * @param conn the connection through which methods will
+ * be forwarded to the bean.
+ * @param name the name of the bean to use to provide the
+ * actual calls.
+ */
+ public MBeanServerInvocationHandler(MBeanServerConnection conn,
+ ObjectName name)
+ {
+ this(conn, name, false);
+ }
+
+ /**
+ * Constructs a new {@link MBeanServerInvocationHandler}
+ * which forwards methods to the supplied bean via the
+ * given {@link MBeanServerConnection}. This constructor
+ * is used in preference to
+ * {@link JMX#newMBeanProxy(MBeanServerConnection, ObjectName,
+ * Class<T>)} if you wish to make your own call to
+ * {@link java.lang.reflect.Proxy#newInstance(ClassLoader,
+ * Class[], java.lang.reflect.InvocationHandler)} with
+ * a different {@link ClassLoader}.
+ *
+ * @param conn the connection through which methods will
+ * be forwarded to the bean.
+ * @param name the name of the bean to use to provide the
+ * actual calls.
+ * @param mxBean true if the bean being proxied is an
+ * {@link MXBean}.
+ * @since 1.6
+ */
+ public MBeanServerInvocationHandler(MBeanServerConnection conn,
+ ObjectName name, boolean mxBean)
+ {
+ this.conn = conn;
+ this.name = name;
+ this.mxBean = mxBean;
+ }
+
+ /**
+ * Returns the connection through which the calls to the bean
+ * will be made.
+ *
+ * @return the connection being used to forward the calls to
+ * the bean.
+ * @since 1.6
+ */
+ public MBeanServerConnection getMBeanServerConnection()
+ {
+ return conn;
+ }
+
+ /**
+ * Returns the name of the bean to which method calls are made.
+ *
+ * @return the bean which provides the actual method calls.
+ * @since 1.6
+ */
+ public ObjectName getObjectName()
+ {
+ return name;
+ }
+
+ /**
+ * 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 if the bean is an {@link MXBean}.
+ *
+ * @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 mName = method.getName();
+ Class proxyClass = proxy.getClass();
+ if (mName.equals("toString"))
+ {
+ if (inInterface(mName, proxyClass))
+ return conn.invoke(name,mName,null,null);
+ else
+ return proxyClass.getName() + "[name=" + name
+ + ", conn=" + conn + "]";
+ }
+ if (mName.equals("hashCode"))
+ {
+ if (inInterface(mName, proxyClass))
+ return conn.invoke(name,mName,null,null);
+ else
+ return conn.hashCode() + name.hashCode()
+ + (iface == null ? 0 : iface.hashCode());
+ }
+ if (mName.equals("equals"))
+ {
+ if (inInterface(mName, proxyClass, Object.class))
+ return conn.invoke(name,mName,new Object[]{args[0]},
+ new String[]{"java.lang.Object"});
+ else
+ {
+ if (args[0].getClass() != proxy.getClass())
+ return false;
+ InvocationHandler ih = Proxy.getInvocationHandler(args[0]);
+ if (ih instanceof MBeanServerInvocationHandler)
+ {
+ MBeanServerInvocationHandler h =
+ (MBeanServerInvocationHandler) ih;
+ return conn.equals(h.getMBeanServerConnection())
+ && name.equals(h.getObjectName())
+ && (iface == null ? h.iface == null
+ : iface.equals(h.iface));
+ }
+ return false;
+ }
+ }
+ if (NotificationEmitter.class.isAssignableFrom(proxyClass))
+ {
+ if (mName.equals("addNotificationListener"))
+ {
+ conn.addNotificationListener(name,
+ (NotificationListener) args[0],
+ (NotificationFilter) args[1],
+ args[2]);
+ return null;
+ }
+ if (mName.equals("getNotificationInfo"))
+ return conn.getMBeanInfo(name).getNotifications();
+ if (mName.equals("removeNotificationListener"))
+ {
+ if (args.length == 1)
+ conn.removeNotificationListener(name,
+ (NotificationListener)
+ args[0]);
+ else
+ conn.removeNotificationListener(name,
+ (NotificationListener)
+ args[0],
+ (NotificationFilter)
+ args[1], args[2]);
+ return null;
+ }
+ }
+ String[] sigs;
+ if (args == null)
+ sigs = null;
+ else
+ {
+ sigs = new String[args.length];
+ for (int a = 0; a < args.length; ++a)
+ sigs[a] = args[a].getClass().getName();
+ }
+ String attrib = null;
+ if (mName.startsWith("get"))
+ attrib = mName.substring(3);
+ else if (mName.startsWith("is"))
+ attrib = mName.substring(2);
+ if (attrib != null)
+ {
+ Object val = conn.getAttribute(name, attrib);
+ if (mxBean)
+ return Translator.toJava(val, method);
+ else
+ return val;
+ }
+ else if (mName.startsWith("set"))
+ {
+ Object arg;
+ if (mxBean)
+ arg = Translator.fromJava(args, method)[0];
+ else
+ arg = args[0];
+ conn.setAttribute(name, new Attribute(mName.substring(3), arg));
+ return null;
+ }
+ if (mxBean)
+ return Translator.toJava(conn.invoke(name, mName,
+ Translator.fromJava(args,method),
+ sigs), method);
+ else
+ return conn.invoke(name, mName, args, sigs);
+ }
+
+ /**
+ * Returns true if this is a proxy for an {@link MXBean}
+ * and conversions must be applied to input parameters
+ * and return types, according to the rules for such beans.
+ *
+ * @return true if this is a proxy for an {@link MXBean}.
+ * @since 1.6
+ */
+ public boolean isMXBean()
+ {
+ return mxBean;
+ }
+
+ /**
+ * <p>
+ * Returns a proxy for the specified bean. A proxy object is created
+ * using <code>Proxy.newProxyInstance(iface.getClassLoader(),
+ * new Class[] { iface }, handler)</code>. The
+ * {@link javax.management.NotificationEmitter} class is included as the
+ * second element of the array if <code>broadcaster</code> is true.
+ * <code>handler</code> refers to the invocation handler which forwards
+ * calls to the connection, which is created by a call to
+ * <code>new MBeanServerInvocationHandler(conn, name)</code>.
+ * </p>
+ * <p>
+ * <strong>Note</strong>: use of the proxy may result in
+ * {@link java.io.IOException}s from the underlying
+ * {@link MBeanServerConnection}.
+ * As of 1.6, the use of {@link JMX#newMBeanProxy(MBeanServerConnection,
+ * ObjectName,Class)} and {@link JMX#newMBeanProxy(MBeanServerConnection,
+ * ObjectName,Class,boolean)} is preferred.
+ * </p>
+ *
+ * @param conn the server connection to use to access the bean.
+ * @param name the {@link javax.management.ObjectName} of the
+ * bean to provide a proxy for.
+ * @param iface the interface for the bean being proxied.
+ * @param broadcaster true if the proxy should implement
+ * {@link NotificationEmitter}.
+ * @return a proxy for the specified bean.
+ * @see JMX#newMBeanProxy(MBeanServerConnection,ObjectName,Class)
+ */
+ public static <T> T newProxyInstance(MBeanServerConnection conn,
+ ObjectName name, Class<T> iface,
+ boolean broadcaster)
+ {
+ if (broadcaster)
+ return (T) Proxy.newProxyInstance(iface.getClassLoader(),
+ new Class[] { iface,
+ NotificationEmitter.class },
+ new MBeanServerInvocationHandler(conn,name));
+ else
+ return (T) Proxy.newProxyInstance(iface.getClassLoader(),
+ new Class[] { iface },
+ new MBeanServerInvocationHandler(conn,name));
+ }
+
+ /**
+ * Returns true if the specified method is specified
+ * by one of the proxy's interfaces.
+ *
+ * @param name the name of the method to search for.
+ * @param proxyClass the class of the proxy.
+ * @param args the arguments to the method.
+ * @return true if one of the interfaces specifies the
+ * given method.
+ */
+ private boolean inInterface(String name, Class<?> proxyClass,
+ Class<?>... args)
+ {
+ for (Class<?> iface : proxyClass.getInterfaces())
+ {
+ try
+ {
+ iface.getMethod(name, args);
+ return true;
+ }
+ catch (NoSuchMethodException e)
+ {
+ /* Ignored; this interface doesn't specify
+ the method. */
+ }
+ }
+ return false;
+ }
+
+}
+
diff --git a/javax/management/MXBean.java b/javax/management/MXBean.java
new file mode 100644
index 000000000..7b3af541c
--- /dev/null
+++ b/javax/management/MXBean.java
@@ -0,0 +1,82 @@
+/* MXBean.java - Marks a management bean interface as an MXBean.
+ Copyright (C) 2007 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 javax.management;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+import static java.lang.annotation.ElementType.TYPE;
+
+/**
+ * <p>
+ * An annotation used to explictly mark an interface
+ * as defining (or not defining) an {@link MXBean}. By
+ * default, such beans are taken to be those whose interface
+ * has the suffix {@code "MXBean"}. The presence of this
+ * annotation overrides this intuition. The following
+ * interfaces would be classed as {@link MXBean}s:
+ * </p>
+ * <ul>
+ * <li>{@code public interface SomethingMXBean{}}</li>
+ * <li>{@code @MXBean public interface Someat{}}</li>
+ * <li>{@code @MXBean(true) public interface SomeatElse{}}</li>
+ * </ul>
+ * <p>The following would not:</p>
+ * <ul>
+ * <li>{@code public interface RandomInterface{}}</li>
+ * <li>{@code @MXBean(false) public interface SomethingMXBean{}}</li>
+ * </ul>
+ *
+ * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
+ * @since 1.6
+ */
+@Documented @Retention(RUNTIME) @Target(TYPE)
+public @interface MXBean
+{
+
+ /**
+ * Returns true if the annotated interface
+ * is an {@link MXBean}.
+ *
+ * @return true if the interface is an {@link MXBean}.
+ */
+ boolean value();
+
+}
diff --git a/javax/management/ObjectName.java b/javax/management/ObjectName.java
index 8259eab02..49d063543 100644
--- a/javax/management/ObjectName.java
+++ b/javax/management/ObjectName.java
@@ -167,6 +167,9 @@ public class ObjectName
for (int a = 0; a < pairs.length; ++a)
{
int sep = pairs[a].indexOf('=');
+ if (sep == -1)
+ throw new MalformedObjectNameException("A key must be " +
+ "followed by a value.");
String key = pairs[a].substring(0, sep);
if (properties.containsKey(key))
throw new MalformedObjectNameException("The same key occurs " +
diff --git a/javax/management/StandardMBean.java b/javax/management/StandardMBean.java
index b31436c6e..9d9bce4cf 100644
--- a/javax/management/StandardMBean.java
+++ b/javax/management/StandardMBean.java
@@ -106,10 +106,19 @@ public class StandardMBean
}
catch (ClassNotFoundException e)
{
- throw (NotCompliantMBeanException)
- (new NotCompliantMBeanException("An interface, " + className +
- "MBean, for the class " + className +
- " was not found.").initCause(e));
+ for (Class<?> nextIface : getClass().getInterfaces())
+ {
+ if (JMX.isMXBeanInterface(nextIface))
+ {
+ iface = nextIface;
+ break;
+ }
+ }
+ if (iface == null)
+ throw (NotCompliantMBeanException)
+ (new NotCompliantMBeanException("An interface for the class "
+ + className +
+ " was not found.").initCause(e));
}
}
if (!(iface.isInstance(this)))
@@ -140,18 +149,28 @@ public class StandardMBean
throw new IllegalArgumentException("The specified implementation is null.");
if (iface == null)
{
- String className = impl.getClass().getName();
+ Class<?> implClass = impl.getClass();
+ String className = implClass.getName();
try
{
this.iface = Class.forName(className + "MBean", true,
- impl.getClass().getClassLoader());
+ implClass.getClassLoader());
}
catch (ClassNotFoundException e)
{
- throw (NotCompliantMBeanException)
- (new NotCompliantMBeanException("An interface, " + className +
- "MBean, for the class " + className +
- " was not found.").initCause(e));
+ for (Class<?> nextIface : implClass.getInterfaces())
+ {
+ if (JMX.isMXBeanInterface(nextIface))
+ {
+ this.iface = nextIface;
+ break;
+ }
+ }
+ if (this.iface == null)
+ throw (NotCompliantMBeanException)
+ (new NotCompliantMBeanException("An interface for the class " +
+ className +
+ " was not found.").initCause(e));
}
}
else
@@ -753,19 +772,30 @@ public class StandardMBean
public Object invoke(String name, Object[] params, String[] signature)
throws MBeanException, ReflectionException
{
- Class[] sigTypes = new Class[signature.length];
+ if (name.startsWith("get") || name.startsWith("is") ||
+ name.startsWith("set"))
+ throw new ReflectionException(new NoSuchMethodException(),
+ "Invocation of an attribute " +
+ "method is disallowed.");
ClassLoader loader = getClass().getClassLoader();
- for (int a = 0; a < signature.length; ++a)
- try
- {
- sigTypes[a] = Class.forName(signature[a], true, loader);
- }
- catch (ClassNotFoundException e)
- {
- throw new ReflectionException(e, "The class, " + signature[a] +
- ", in the method signature " +
- "could not be loaded.");
- }
+ Class[] sigTypes;
+ if (signature != null)
+ {
+ sigTypes = new Class[signature.length];
+ for (int a = 0; a < signature.length; ++a)
+ try
+ {
+ sigTypes[a] = Class.forName(signature[a], true, loader);
+ }
+ catch (ClassNotFoundException e)
+ {
+ throw new ReflectionException(e, "The class, " + signature[a] +
+ ", in the method signature " +
+ "could not be loaded.");
+ }
+ }
+ else
+ sigTypes = null;
Method method;
try
{
@@ -826,11 +856,12 @@ public class StandardMBean
{
Method setter;
String name = attribute.getName();
+ Object val = attribute.getValue();
try
{
setter = iface.getMethod("set" +
name.substring(0, 1).toUpperCase() +
- name.substring(1), null);
+ name.substring(1), val.getClass());
}
catch (NoSuchMethodException e)
{
@@ -840,7 +871,7 @@ public class StandardMBean
}
try
{
- setter.invoke(impl, new Object[] { attribute.getValue() });
+ setter.invoke(impl, new Object[] { val });
}
catch (IllegalAccessException e)
{
diff --git a/javax/management/openmbean/OpenType.java b/javax/management/openmbean/OpenType.java
index 13c9e8a3e..2f827b59f 100644
--- a/javax/management/openmbean/OpenType.java
+++ b/javax/management/openmbean/OpenType.java
@@ -39,6 +39,9 @@ package javax.management.openmbean;
import java.io.Serializable;
+import java.util.Arrays;
+import java.util.List;
+
/**
* The superclass of all open types, which describe the
* applicable data values for open MBeans. An open type
@@ -48,7 +51,7 @@ import java.io.Serializable;
* @author Andrew John Hughes (gnu_andrew@member.fsf.org)
* @since 1.5
*/
-public abstract class OpenType
+public abstract class OpenType<T>
implements Serializable
{
@@ -76,7 +79,10 @@ public abstract class OpenType
* An array which defines the set of Java types which can be
* used as open types. Note that each type is also available
* in array form, possibly with multiple dimensions.
+ *
+ * @deprecated Use {@link ALLOWED_CLASSNAMES_LIST} instead.
*/
+ @Deprecated
public static final String[] ALLOWED_CLASSNAMES = {
"java.lang.Void",
"java.lang.Boolean",
@@ -97,6 +103,14 @@ public abstract class OpenType
};
/**
+ * A list which defines the set of Java types that may be
+ * used as open types. Note that each type is also available
+ * in array form, possibly with multiple dimensions.
+ */
+ public static final List<String> ALLOWED_CLASSNAMES_LIST =
+ Arrays.asList(ALLOWED_CLASSNAMES);
+
+ /**
* Constructs a new {@link OpenType} for the specified class
* with the given name and description. The name of the class
* must be taken from the list of {@link ALLOWED_CLASSNAMES}.