395 lines · 15.8 KB · Java
RawDownload
/* * Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation.  Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code 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 * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package javax.management; import com.sun.jmx.mbeanserver.Introspector;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Proxy; /** * Static methods from the JMX API.  There are no instances of this class. * * @since 1.6 */public class JMX {    /* Code within this package can prove that by providing this instance of     * this class.     */    static final JMX proof = new JMX();     private JMX() {}     /**     * The name of the <a href="Descriptor.html#defaultValue">{@code     * defaultValue}</a> field.     */    public static final String DEFAULT_VALUE_FIELD = "defaultValue";     /**     * The name of the <a href="Descriptor.html#immutableInfo">{@code     * immutableInfo}</a> field.     */    public static final String IMMUTABLE_INFO_FIELD = "immutableInfo";     /**     * The name of the <a href="Descriptor.html#interfaceClassName">{@code     * interfaceClassName}</a> field.     */    public static final String INTERFACE_CLASS_NAME_FIELD = "interfaceClassName";     /**     * The name of the <a href="Descriptor.html#legalValues">{@code     * legalValues}</a> field.     */    public static final String LEGAL_VALUES_FIELD = "legalValues";     /**     * The name of the <a href="Descriptor.html#maxValue">{@code     * maxValue}</a> field.     */    public static final String MAX_VALUE_FIELD = "maxValue";     /**     * The name of the <a href="Descriptor.html#minValue">{@code     * minValue}</a> field.     */    public static final String MIN_VALUE_FIELD = "minValue";     /**     * The name of the <a href="Descriptor.html#mxbean">{@code     * mxbean}</a> field.     */    public static final String MXBEAN_FIELD = "mxbean";     /**     * The name of the <a href="Descriptor.html#openType">{@code     * openType}</a> field.     */    public static final String OPEN_TYPE_FIELD = "openType";     /**     * The name of the <a href="Descriptor.html#originalType">{@code     * originalType}</a> field.     */    public static final String ORIGINAL_TYPE_FIELD = "originalType";     /**     * <p>Make a proxy for a Standard MBean in a local or remote     * MBean Server.</p>     *     * <p>If you have an MBean Server {@code mbs} containing an MBean     * with {@link ObjectName} {@code name}, and if the MBean's     * management interface is described by the Java interface     * {@code MyMBean}, you can construct a proxy for the MBean like     * this:</p>     *     * <pre>     * MyMBean proxy = JMX.newMBeanProxy(mbs, name, MyMBean.class);     * </pre>     *     * <p>Suppose, for example, {@code MyMBean} looks like this:</p>     *     * <pre>     * public interface MyMBean {     *     public String getSomeAttribute();     *     public void setSomeAttribute(String value);     *     public void someOperation(String param1, int param2);     * }     * </pre>     *     * <p>Then you can execute:</p>     *     * <ul>     *     * <li>{@code proxy.getSomeAttribute()} which will result in a     * call to {@code mbs.}{@link MBeanServerConnection#getAttribute     * getAttribute}{@code (name, "SomeAttribute")}.     *     * <li>{@code proxy.setSomeAttribute("whatever")} which will result     * in a call to {@code mbs.}{@link MBeanServerConnection#setAttribute     * setAttribute}{@code (name, new Attribute("SomeAttribute", "whatever"))}.     *     * <li>{@code proxy.someOperation("param1", 2)} which will be     * translated into a call to {@code mbs.}{@link     * MBeanServerConnection#invoke invoke}{@code (name, "someOperation", <etc>)}.     *     * </ul>     *     * <p>The object returned by this method is a     * {@link Proxy} whose {@code InvocationHandler} is an     * {@link MBeanServerInvocationHandler}.</p>     *     * <p>This method is equivalent to {@link     * #newMBeanProxy(MBeanServerConnection, ObjectName, Class,     * boolean) newMBeanProxy(connection, objectName, interfaceClass,     * false)}.</p>     *     * @param connection the MBean server to forward to.     * @param objectName the name of the MBean within     * {@code connection} to forward to.     * @param interfaceClass the management interface that the MBean     * exports, which will also be implemented by the returned proxy.     *     * @param <T> allows the compiler to know that if the {@code     * interfaceClass} parameter is {@code MyMBean.class}, for     * example, then the return type is {@code MyMBean}.     *     * @return the new proxy instance.     */    public static <T> T newMBeanProxy(MBeanServerConnection connection,                                      ObjectName objectName,                                      Class<T> interfaceClass) {        return newMBeanProxy(connection, objectName, interfaceClass, false);    }     /**     * <p>Make a proxy for a Standard MBean in a local or remote MBean     * Server that may also support the methods of {@link     * NotificationEmitter}.</p>     *     * <p>This method behaves the same as {@link     * #newMBeanProxy(MBeanServerConnection, ObjectName, Class)}, but     * additionally, if {@code notificationEmitter} is {@code     * true}, then the MBean is assumed to be a {@link     * NotificationBroadcaster} or {@link NotificationEmitter} and the     * returned proxy will implement {@link NotificationEmitter} as     * well as {@code interfaceClass}.  A call to {@link     * NotificationBroadcaster#addNotificationListener} on the proxy     * will result in a call to {@link     * MBeanServerConnection#addNotificationListener(ObjectName,     * NotificationListener, NotificationFilter, Object)}, and     * likewise for the other methods of {@link     * NotificationBroadcaster} and {@link NotificationEmitter}.</p>     *     * @param connection the MBean server to forward to.     * @param objectName the name of the MBean within     * {@code connection} to forward to.     * @param interfaceClass the management interface that the MBean     * exports, which will also be implemented by the returned proxy.     * @param notificationEmitter make the returned proxy     * implement {@link NotificationEmitter} by forwarding its methods     * via {@code connection}.     *     * @param <T> allows the compiler to know that if the {@code     * interfaceClass} parameter is {@code MyMBean.class}, for     * example, then the return type is {@code MyMBean}.     *     * @return the new proxy instance.     */    public static <T> T newMBeanProxy(MBeanServerConnection connection,                                      ObjectName objectName,                                      Class<T> interfaceClass,                                      boolean notificationEmitter) {        return MBeanServerInvocationHandler.newProxyInstance(                connection,                objectName,                interfaceClass,                notificationEmitter);    }     /**     * <p>Make a proxy for an MXBean in a local or remote     * MBean Server.</p>     *     * <p>If you have an MBean Server {@code mbs} containing an     * MXBean with {@link ObjectName} {@code name}, and if the     * MXBean's management interface is described by the Java     * interface {@code MyMXBean}, you can construct a proxy for     * the MXBean like this:</p>     *     * <pre>     * MyMXBean proxy = JMX.newMXBeanProxy(mbs, name, MyMXBean.class);     * </pre>     *     * <p>Suppose, for example, {@code MyMXBean} looks like this:</p>     *     * <pre>     * public interface MyMXBean {     *     public String getSimpleAttribute();     *     public void setSimpleAttribute(String value);     *     public {@link java.lang.management.MemoryUsage} getMappedAttribute();     *     public void setMappedAttribute(MemoryUsage memoryUsage);     *     public MemoryUsage someOperation(String param1, MemoryUsage param2);     * }     * </pre>     *     * <p>Then:</p>     *     * <ul>     *     * <li><p>{@code proxy.getSimpleAttribute()} will result in a     * call to {@code mbs.}{@link MBeanServerConnection#getAttribute     * getAttribute}{@code (name, "SimpleAttribute")}.</p>     *     * <li><p>{@code proxy.setSimpleAttribute("whatever")} will result     * in a call to {@code mbs.}{@link     * MBeanServerConnection#setAttribute setAttribute}<code>(name,     * new Attribute("SimpleAttribute", "whatever"))</code>.<p>     *     *     <p>Because {@code String} is a <em>simple type</em>, in the     *     sense of {@link javax.management.openmbean.SimpleType}, it     *     is not changed in the context of an MXBean.  The MXBean     *     proxy behaves the same as a Standard MBean proxy (see     *     {@link #newMBeanProxy(MBeanServerConnection, ObjectName,     *     Class) newMBeanProxy}) for the attribute {@code     *     SimpleAttribute}.</p>     *     * <li><p>{@code proxy.getMappedAttribute()} will result in a call     * to {@code mbs.getAttribute("MappedAttribute")}.  The MXBean     * mapping rules mean that the actual type of the attribute {@code     * MappedAttribute} will be {@link     * javax.management.openmbean.CompositeData CompositeData} and     * that is what the {@code mbs.getAttribute} call will return.     * The proxy will then convert the {@code CompositeData} back into     * the expected type {@code MemoryUsage} using the MXBean mapping     * rules.</p>     *     * <li><p>Similarly, {@code proxy.setMappedAttribute(memoryUsage)}     * will convert the {@code MemoryUsage} argument into a {@code     * CompositeData} before calling {@code mbs.setAttribute}.</p>     *     * <li><p>{@code proxy.someOperation("whatever", memoryUsage)}     * will convert the {@code MemoryUsage} argument into a {@code     * CompositeData} and call {@code mbs.invoke}.  The value returned     * by {@code mbs.invoke} will be also be a {@code CompositeData},     * and the proxy will convert this into the expected type {@code     * MemoryUsage} using the MXBean mapping rules.</p>     *     * </ul>     *     * <p>The object returned by this method is a     * {@link Proxy} whose {@code InvocationHandler} is an     * {@link MBeanServerInvocationHandler}.</p>     *     * <p>This method is equivalent to {@link     * #newMXBeanProxy(MBeanServerConnection, ObjectName, Class,     * boolean) newMXBeanProxy(connection, objectName, interfaceClass,     * false)}.</p>     *     * @param connection the MBean server to forward to.     * @param objectName the name of the MBean within     * {@code connection} to forward to.     * @param interfaceClass the MXBean interface,     * which will also be implemented by the returned proxy.     *     * @param <T> allows the compiler to know that if the {@code     * interfaceClass} parameter is {@code MyMXBean.class}, for     * example, then the return type is {@code MyMXBean}.     *     * @return the new proxy instance.     */    public static <T> T newMXBeanProxy(MBeanServerConnection connection,                                       ObjectName objectName,                                       Class<T> interfaceClass) {        return newMXBeanProxy(connection, objectName, interfaceClass, false);    }     /**     * <p>Make a proxy for an MXBean in a local or remote MBean     * Server that may also support the methods of {@link     * NotificationEmitter}.</p>     *     * <p>This method behaves the same as {@link     * #newMXBeanProxy(MBeanServerConnection, ObjectName, Class)}, but     * additionally, if {@code notificationEmitter} is {@code     * true}, then the MXBean is assumed to be a {@link     * NotificationBroadcaster} or {@link NotificationEmitter} and the     * returned proxy will implement {@link NotificationEmitter} as     * well as {@code interfaceClass}.  A call to {@link     * NotificationBroadcaster#addNotificationListener} on the proxy     * will result in a call to {@link     * MBeanServerConnection#addNotificationListener(ObjectName,     * NotificationListener, NotificationFilter, Object)}, and     * likewise for the other methods of {@link     * NotificationBroadcaster} and {@link NotificationEmitter}.</p>     *     * @param connection the MBean server to forward to.     * @param objectName the name of the MBean within     * {@code connection} to forward to.     * @param interfaceClass the MXBean interface,     * which will also be implemented by the returned proxy.     * @param notificationEmitter make the returned proxy     * implement {@link NotificationEmitter} by forwarding its methods     * via {@code connection}.     *     * @param <T> allows the compiler to know that if the {@code     * interfaceClass} parameter is {@code MyMXBean.class}, for     * example, then the return type is {@code MyMXBean}.     *     * @return the new proxy instance.     */    public static <T> T newMXBeanProxy(MBeanServerConnection connection,                                       ObjectName objectName,                                       Class<T> interfaceClass,                                       boolean notificationEmitter) {        // Check interface for MXBean compliance        //        try {            Introspector.testComplianceMXBeanInterface(interfaceClass);        } catch (NotCompliantMBeanException e) {            throw new IllegalArgumentException(e);        }        InvocationHandler handler = new MBeanServerInvocationHandler(                connection, objectName, true);        final Class<?>[] interfaces;        if (notificationEmitter) {            interfaces =                new Class<?>[] {interfaceClass, NotificationEmitter.class};        } else            interfaces = new Class<?>[] {interfaceClass};        Object proxy = Proxy.newProxyInstance(                interfaceClass.getClassLoader(),                interfaces,                handler);        return interfaceClass.cast(proxy);    }     /**     * <p>Test whether an interface is an MXBean interface.     * An interface is an MXBean interface if it is annotated     * {@link MXBean &#64;MXBean} or {@code @MXBean(true)}     * or if it does not have an {@code @MXBean} annotation     * and its name ends with "{@code MXBean}".</p>     *     * @param interfaceClass The candidate interface.     *     * @return true if {@code interfaceClass} is an interface and     * meets the conditions described.     *     * @throws NullPointerException if {@code interfaceClass} is null.     */    public static boolean isMXBeanInterface(Class<?> interfaceClass) {        if (!interfaceClass.isInterface())            return false;        MXBean a = interfaceClass.getAnnotation(MXBean.class);        if (a != null)            return a.value();        return interfaceClass.getName().endsWith("MXBean");        // We don't bother excluding the case where the name is        // exactly the string "MXBean" since that would mean there        // was no package name, which is pretty unlikely in practice.    }}