1237 lines · 50.6 KB · Java
RawDownload
/* * Copyright (c) 2002, 2008, 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 static com.sun.jmx.defaults.JmxProperties.MISC_LOGGER;import com.sun.jmx.mbeanserver.DescriptorCache;import com.sun.jmx.mbeanserver.Introspector;import com.sun.jmx.mbeanserver.MBeanSupport;import com.sun.jmx.mbeanserver.MXBeanSupport;import com.sun.jmx.mbeanserver.StandardMBeanSupport;import com.sun.jmx.mbeanserver.Util; import java.security.AccessController;import java.security.PrivilegedAction;import java.util.HashMap;import java.util.Map;import java.util.WeakHashMap;import java.util.logging.Level;import javax.management.openmbean.OpenMBeanAttributeInfo;import javax.management.openmbean.OpenMBeanAttributeInfoSupport;import javax.management.openmbean.OpenMBeanConstructorInfo;import javax.management.openmbean.OpenMBeanConstructorInfoSupport;import javax.management.openmbean.OpenMBeanOperationInfo;import javax.management.openmbean.OpenMBeanOperationInfoSupport;import javax.management.openmbean.OpenMBeanParameterInfo;import javax.management.openmbean.OpenMBeanParameterInfoSupport; /** * <p>An MBean whose management interface is determined by reflection * on a Java interface.</p> * * <p>This class brings more flexibility to the notion of Management * Interface in the use of Standard MBeans.  Straightforward use of * the patterns for Standard MBeans described in the JMX Specification * means that there is a fixed relationship between the implementation * class of an MBean and its management interface (i.e., if the * implementation class is Thing, the management interface must be * ThingMBean).  This class makes it possible to keep the convenience * of specifying the management interface with a Java interface, * without requiring that there be any naming relationship between the * implementation and interface classes.</p> * * <p>By making a DynamicMBean out of an MBean, this class makes * it possible to select any interface implemented by the MBean as its * management interface, provided that it complies with JMX patterns * (i.e., attributes defined by getter/setter etc...).</p> * * <p> This class also provides hooks that make it possible to supply * custom descriptions and names for the {@link MBeanInfo} returned by * the DynamicMBean interface.</p> * * <p>Using this class, an MBean can be created with any * implementation class name <i>Impl</i> and with a management * interface defined (as for current Standard MBeans) by any interface * <i>Intf</i>, in one of two general ways:</p> * * <ul> * * <li>Using the public constructor *     {@link #StandardMBean(java.lang.Object, java.lang.Class, boolean) *     StandardMBean(impl,interface)}: *     <pre> *     MBeanServer mbs; *     ... *     Impl impl = new Impl(...); *     StandardMBean mbean = new StandardMBean(impl, Intf.class, false); *     mbs.registerMBean(mbean, objectName); *     </pre></li> * * <li>Subclassing StandardMBean: *     <pre> *     public class Impl extends StandardMBean implements Intf { *        public Impl() { *          super(Intf.class, false); *       } *       // implement methods of Intf *     } * *     [...] * *     MBeanServer mbs; *     .... *     Impl impl = new Impl(); *     mbs.registerMBean(impl, objectName); *     </pre></li> * * </ul> * * <p>In either case, the class <i>Impl</i> must implement the * interface <i>Intf</i>.</p> * * <p>Standard MBeans based on the naming relationship between * implementation and interface classes are of course still * available.</p> * * <p>This class may also be used to construct MXBeans.  The usage * is exactly the same as for Standard MBeans except that in the * examples above, the {@code false} parameter to the constructor or * {@code super(...)} invocation is instead {@code true}.</p> * * @since 1.5 */public class StandardMBean implements DynamicMBean, MBeanRegistration {     private final static DescriptorCache descriptors =        DescriptorCache.getInstance(JMX.proof);     /**     * The DynamicMBean that wraps the MXBean or Standard MBean implementation.     **/    private volatile MBeanSupport<?> mbean;     /**     * The cached MBeanInfo.     **/    private volatile MBeanInfo cachedMBeanInfo;     /**     * Make a DynamicMBean out of <var>implementation</var>, using the     * specified <var>mbeanInterface</var> class.     * @param implementation The implementation of this MBean.     *        If <code>null</code>, and null implementation is allowed,     *        then the implementation is assumed to be <var>this</var>.     * @param mbeanInterface The Management Interface exported by this     *        MBean's implementation. If <code>null</code>, then this     *        object will use standard JMX design pattern to determine     *        the management interface associated with the given     *        implementation.     * @param nullImplementationAllowed <code>true</code> if a null     *        implementation is allowed. If null implementation is allowed,     *        and a null implementation is passed, then the implementation     *        is assumed to be <var>this</var>.     * @exception IllegalArgumentException if the given     *    <var>implementation</var> is null, and null is not allowed.     **/    private <T> void construct(T implementation, Class<T> mbeanInterface,                               boolean nullImplementationAllowed,                               boolean isMXBean)                               throws NotCompliantMBeanException {        if (implementation == null) {            // Have to use (T)this rather than mbeanInterface.cast(this)            // because mbeanInterface might be null.            if (nullImplementationAllowed)                implementation = Util.<T>cast(this);            else throw new IllegalArgumentException("implementation is null");        }        if (isMXBean) {            if (mbeanInterface == null) {                mbeanInterface = Util.cast(Introspector.getMXBeanInterface(                        implementation.getClass()));            }            this.mbean = new MXBeanSupport(implementation, mbeanInterface);        } else {            if (mbeanInterface == null) {                mbeanInterface = Util.cast(Introspector.getStandardMBeanInterface(                        implementation.getClass()));            }            this.mbean =                    new StandardMBeanSupport(implementation, mbeanInterface);        }    }     /**     * <p>Make a DynamicMBean out of the object     * <var>implementation</var>, using the specified     * <var>mbeanInterface</var> class.</p>     *     * @param implementation The implementation of this MBean.     * @param mbeanInterface The Management Interface exported by this     *        MBean's implementation. If <code>null</code>, then this     *        object will use standard JMX design pattern to determine     *        the management interface associated with the given     *        implementation.     * @param <T> Allows the compiler to check     * that {@code implementation} does indeed implement the class     * described by {@code mbeanInterface}.  The compiler can only     * check this if {@code mbeanInterface} is a class literal such     * as {@code MyMBean.class}.     *     * @exception IllegalArgumentException if the given     *    <var>implementation</var> is null.     * @exception NotCompliantMBeanException if the <var>mbeanInterface</var>     *    does not follow JMX design patterns for Management Interfaces, or     *    if the given <var>implementation</var> does not implement the     *    specified interface.     **/    public <T> StandardMBean(T implementation, Class<T> mbeanInterface)        throws NotCompliantMBeanException {        construct(implementation, mbeanInterface, false, false);    }     /**     * <p>Make a DynamicMBean out of <var>this</var>, using the specified     * <var>mbeanInterface</var> class.</p>     *     * <p>Calls {@link #StandardMBean(java.lang.Object, java.lang.Class)     *       this(this,mbeanInterface)}.     * This constructor is reserved to subclasses.</p>     *     * @param mbeanInterface The Management Interface exported by this     *        MBean.     *     * @exception NotCompliantMBeanException if the <var>mbeanInterface</var>     *    does not follow JMX design patterns for Management Interfaces, or     *    if <var>this</var> does not implement the specified interface.     **/    protected StandardMBean(Class<?> mbeanInterface)        throws NotCompliantMBeanException {        construct(null, mbeanInterface, true, false);    }     /**     * <p>Make a DynamicMBean out of the object     * <var>implementation</var>, using the specified     * <var>mbeanInterface</var> class, and choosing whether the     * resultant MBean is an MXBean.  This constructor can be used     * to make either Standard MBeans or MXBeans.  Unlike the     * constructor {@link #StandardMBean(Object, Class)}, it     * does not throw NotCompliantMBeanException.</p>     *     * @param implementation The implementation of this MBean.     * @param mbeanInterface The Management Interface exported by this     *        MBean's implementation. If <code>null</code>, then this     *        object will use standard JMX design pattern to determine     *        the management interface associated with the given     *        implementation.     * @param isMXBean If true, the {@code mbeanInterface} parameter     * names an MXBean interface and the resultant MBean is an MXBean.     * @param <T> Allows the compiler to check     * that {@code implementation} does indeed implement the class     * described by {@code mbeanInterface}.  The compiler can only     * check this if {@code mbeanInterface} is a class literal such     * as {@code MyMBean.class}.     *     * @exception IllegalArgumentException if the given     *    <var>implementation</var> is null, or if the <var>mbeanInterface</var>     *    does not follow JMX design patterns for Management Interfaces, or     *    if the given <var>implementation</var> does not implement the     *    specified interface.     *     * @since 1.6     **/    public <T> StandardMBean(T implementation, Class<T> mbeanInterface,                             boolean isMXBean) {        try {            construct(implementation, mbeanInterface, false, isMXBean);        } catch (NotCompliantMBeanException e) {            throw new IllegalArgumentException(e);        }    }     /**     * <p>Make a DynamicMBean out of <var>this</var>, using the specified     * <var>mbeanInterface</var> class, and choosing whether the resulting     * MBean is an MXBean.  This constructor can be used     * to make either Standard MBeans or MXBeans.  Unlike the     * constructor {@link #StandardMBean(Object, Class)}, it     * does not throw NotCompliantMBeanException.</p>     *     * <p>Calls {@link #StandardMBean(java.lang.Object, java.lang.Class, boolean)     *       this(this, mbeanInterface, isMXBean)}.     * This constructor is reserved to subclasses.</p>     *     * @param mbeanInterface The Management Interface exported by this     *        MBean.     * @param isMXBean If true, the {@code mbeanInterface} parameter     * names an MXBean interface and the resultant MBean is an MXBean.     *     * @exception IllegalArgumentException if the <var>mbeanInterface</var>     *    does not follow JMX design patterns for Management Interfaces, or     *    if <var>this</var> does not implement the specified interface.     *     * @since 1.6     **/    protected StandardMBean(Class<?> mbeanInterface, boolean isMXBean) {        try {            construct(null, mbeanInterface, true, isMXBean);        } catch (NotCompliantMBeanException e) {            throw new IllegalArgumentException(e);        }    }     /**     * <p>Replace the implementation object wrapped in this object.</p>     *     * @param implementation The new implementation of this Standard MBean     * (or MXBean). The <code>implementation</code> object must implement     * the Standard MBean (or MXBean) interface that was supplied when this     * <code>StandardMBean</code> was constructed.     *     * @exception IllegalArgumentException if the given     * <var>implementation</var> is null.     *     * @exception NotCompliantMBeanException if the given     * <var>implementation</var> does not implement the     * Standard MBean (or MXBean) interface that was     * supplied at construction.     *     * @see #getImplementation     **/    public void setImplementation(Object implementation)        throws NotCompliantMBeanException {         if (implementation == null)            throw new IllegalArgumentException("implementation is null");         if (isMXBean()) {            this.mbean = new MXBeanSupport(implementation,                    Util.<Class<Object>>cast(getMBeanInterface()));        } else {            this.mbean = new StandardMBeanSupport(implementation,                    Util.<Class<Object>>cast(getMBeanInterface()));        }    }     /**     * Get the implementation of this Standard MBean (or MXBean).     * @return The implementation of this Standard MBean (or MXBean).     *     * @see #setImplementation     **/    public Object getImplementation() {        return mbean.getResource();    }     /**     * Get the Management Interface of this Standard MBean (or MXBean).     * @return The management interface of this Standard MBean (or MXBean).     **/    public final Class<?> getMBeanInterface() {        return mbean.getMBeanInterface();    }     /**     * Get the class of the implementation of this Standard MBean (or MXBean).     * @return The class of the implementation of this Standard MBean (or MXBean).     **/    public Class<?> getImplementationClass() {        return mbean.getResource().getClass();    }     // ------------------------------------------------------------------    // From the DynamicMBean interface.    // ------------------------------------------------------------------    public Object getAttribute(String attribute)        throws AttributeNotFoundException,               MBeanException,               ReflectionException {        return mbean.getAttribute(attribute);    }     // ------------------------------------------------------------------    // From the DynamicMBean interface.    // ------------------------------------------------------------------    public void setAttribute(Attribute attribute)        throws AttributeNotFoundException,               InvalidAttributeValueException,               MBeanException,               ReflectionException {        mbean.setAttribute(attribute);    }     // ------------------------------------------------------------------    // From the DynamicMBean interface.    // ------------------------------------------------------------------    public AttributeList getAttributes(String[] attributes) {        return mbean.getAttributes(attributes);    }     // ------------------------------------------------------------------    // From the DynamicMBean interface.    // ------------------------------------------------------------------    public AttributeList setAttributes(AttributeList attributes) {        return mbean.setAttributes(attributes);    }     // ------------------------------------------------------------------    // From the DynamicMBean interface.    // ------------------------------------------------------------------    public Object invoke(String actionName, Object params[], String signature[])            throws MBeanException, ReflectionException {        return mbean.invoke(actionName, params, signature);    }     /**     * Get the {@link MBeanInfo} for this MBean.     * <p>     * This method implements     * {@link javax.management.DynamicMBean#getMBeanInfo()     *   DynamicMBean.getMBeanInfo()}.     * <p>     * This method first calls {@link #getCachedMBeanInfo()} in order to     * retrieve the cached MBeanInfo for this MBean, if any. If the     * MBeanInfo returned by {@link #getCachedMBeanInfo()} is not null,     * then it is returned.<br>     * Otherwise, this method builds a default MBeanInfo for this MBean,     * using the Management Interface specified for this MBean.     * <p>     * While building the MBeanInfo, this method calls the customization     * hooks that make it possible for subclasses to supply their custom     * descriptions, parameter names, etc...<br>     * Finally, it calls {@link #cacheMBeanInfo(javax.management.MBeanInfo)     * cacheMBeanInfo()} in order to cache the new MBeanInfo.     * @return The cached MBeanInfo for that MBean, if not null, or a     *         newly built MBeanInfo if none was cached.     **/    public MBeanInfo getMBeanInfo() {        try {            final MBeanInfo cached = getCachedMBeanInfo();            if (cached != null) return cached;        } catch (RuntimeException x) {            if (MISC_LOGGER.isLoggable(Level.FINEST)) {                MISC_LOGGER.logp(Level.FINEST,                        MBeanServerFactory.class.getName(), "getMBeanInfo",                        "Failed to get cached MBeanInfo", x);            }        }         if (MISC_LOGGER.isLoggable(Level.FINER)) {            MISC_LOGGER.logp(Level.FINER,                    MBeanServerFactory.class.getName(), "getMBeanInfo",                    "Building MBeanInfo for " +                    getImplementationClass().getName());        }         MBeanSupport<?> msupport = mbean;        final MBeanInfo bi = msupport.getMBeanInfo();        final Object impl = msupport.getResource();         final boolean immutableInfo = immutableInfo(this.getClass());         final String                  cname = getClassName(bi);        final String                  text  = getDescription(bi);        final MBeanConstructorInfo[]  ctors = getConstructors(bi,impl);        final MBeanAttributeInfo[]    attrs = getAttributes(bi);        final MBeanOperationInfo[]    ops   = getOperations(bi);        final MBeanNotificationInfo[] ntfs  = getNotifications(bi);        final Descriptor              desc  = getDescriptor(bi, immutableInfo);         final MBeanInfo nmbi = new MBeanInfo(                cname, text, attrs, ctors, ops, ntfs, desc);        try {            cacheMBeanInfo(nmbi);        } catch (RuntimeException x) {            if (MISC_LOGGER.isLoggable(Level.FINEST)) {                MISC_LOGGER.logp(Level.FINEST,                        MBeanServerFactory.class.getName(), "getMBeanInfo",                        "Failed to cache MBeanInfo", x);            }        }         return nmbi;    }     /**     * Customization hook:     * Get the className that will be used in the MBeanInfo returned by     * this MBean.     * <br>     * Subclasses may redefine this method in order to supply their     * custom class name.  The default implementation returns     * {@link MBeanInfo#getClassName() info.getClassName()}.     * @param info The default MBeanInfo derived by reflection.     * @return the class name for the new MBeanInfo.     **/    protected String getClassName(MBeanInfo info) {        if (info == null) return getImplementationClass().getName();        return info.getClassName();    }     /**     * Customization hook:     * Get the description that will be used in the MBeanInfo returned by     * this MBean.     * <br>     * Subclasses may redefine this method in order to supply their     * custom MBean description.  The default implementation returns

Lines 1–500 of 1237.