2881 lines · 119.3 KB · Java
RawDownload
/* * Copyright (c) 2000, 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. *//* * @author    IBM Corp. * * Copyright IBM Corp. 1999-2000.  All rights reserved. */  package javax.management.modelmbean; /* java imports */ import static com.sun.jmx.defaults.JmxProperties.MODELMBEAN_LOGGER;import java.io.FileOutputStream;import java.io.PrintStream;import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.Date;import java.util.HashMap;import java.util.HashSet;import java.util.Iterator;import java.util.logging.Level;import java.util.Map;import java.util.Set; import java.util.Vector;import javax.management.Attribute;import javax.management.AttributeChangeNotification;import javax.management.AttributeChangeNotificationFilter;import javax.management.AttributeList;import javax.management.AttributeNotFoundException;import javax.management.Descriptor;import javax.management.InstanceNotFoundException;import javax.management.InvalidAttributeValueException;import javax.management.ListenerNotFoundException;import javax.management.MBeanAttributeInfo;import javax.management.MBeanConstructorInfo;import javax.management.MBeanException;import javax.management.MBeanInfo;import javax.management.MBeanNotificationInfo;import javax.management.MBeanOperationInfo;import javax.management.MBeanRegistration;import javax.management.MBeanServer;import javax.management.MBeanServerFactory;import javax.management.Notification;import javax.management.NotificationBroadcasterSupport;import javax.management.NotificationEmitter;import javax.management.NotificationFilter;import javax.management.NotificationListener;import javax.management.ObjectName;import javax.management.ReflectionException;import javax.management.RuntimeErrorException;import javax.management.RuntimeOperationsException;import javax.management.ServiceNotFoundException;import javax.management.loading.ClassLoaderRepository; import sun.reflect.misc.MethodUtil;import sun.reflect.misc.ReflectUtil; /** * This class is the implementation of a ModelMBean. An appropriate * implementation of a ModelMBean must be shipped with every JMX Agent * and the class must be named RequiredModelMBean. * <P> * Java resources wishing to be manageable instantiate the * RequiredModelMBean using the MBeanServer's createMBean method. * The resource then sets the MBeanInfo and Descriptors for the * RequiredModelMBean instance. The attributes and operations exposed * via the ModelMBeanInfo for the ModelMBean are accessible * from MBeans, connectors/adaptors like other MBeans. Through the * Descriptors, values and methods in the managed application can be * defined and mapped to attributes and operations of the ModelMBean. * This mapping can be defined in an XML formatted file or dynamically and * programmatically at runtime. * <P> * Every RequiredModelMBean which is instantiated in the MBeanServer * becomes manageable:<br> * its attributes and operations become remotely accessible through the * connectors/adaptors connected to that MBeanServer. * <P> * A Java object cannot be registered in the MBeanServer unless it is a * JMX compliant MBean. By instantiating a RequiredModelMBean, resources * are guaranteed that the MBean is valid. * * MBeanException and RuntimeOperationsException must be thrown on every * public method.  This allows for wrapping exceptions from distributed * communications (RMI, EJB, etc.) * * @since 1.5 */ public class RequiredModelMBean    implements ModelMBean, MBeanRegistration, NotificationEmitter {     /*************************************/    /* attributes                        */    /*************************************/    ModelMBeanInfo modelMBeanInfo;     /* Notification broadcaster for any notification to be sent     * from the application through the RequiredModelMBean.  */    private NotificationBroadcasterSupport generalBroadcaster = null;     /* Notification broadcaster for attribute change notifications */    private NotificationBroadcasterSupport attributeBroadcaster = null;     /* handle, name, or reference for instance on which the actual invoke     * and operations will be executed */    private Object managedResource = null;      /* records the registering in MBeanServer */    private boolean registered = false;    private transient MBeanServer server = null;     /*************************************/    /* constructors                      */    /*************************************/     /**     * Constructs an <CODE>RequiredModelMBean</CODE> with an empty     * ModelMBeanInfo.     * <P>     * The RequiredModelMBean's MBeanInfo and Descriptors     * can be customized using the {@link #setModelMBeanInfo} method.     * After the RequiredModelMBean's MBeanInfo and Descriptors are     * customized, the RequiredModelMBean can be registered with     * the MBeanServer.     *     * @exception MBeanException Wraps a distributed communication Exception.     *     * @exception RuntimeOperationsException Wraps a {@link     * RuntimeException} during the construction of the object.     **/    public RequiredModelMBean()        throws MBeanException, RuntimeOperationsException {        if (MODELMBEAN_LOGGER.isLoggable(Level.FINER)) {            MODELMBEAN_LOGGER.logp(Level.FINER,                    RequiredModelMBean.class.getName(),                    "RequiredModelMBean()", "Entry");        }        modelMBeanInfo = createDefaultModelMBeanInfo();        if (MODELMBEAN_LOGGER.isLoggable(Level.FINER)) {            MODELMBEAN_LOGGER.logp(Level.FINER,                    RequiredModelMBean.class.getName(),                    "RequiredModelMBean()", "Exit");        }    }     /**     * Constructs a RequiredModelMBean object using ModelMBeanInfo passed in.     * As long as the RequiredModelMBean is not registered     * with the MBeanServer yet, the RequiredModelMBean's MBeanInfo and     * Descriptors can be customized using the {@link #setModelMBeanInfo}     * method.     * After the RequiredModelMBean's MBeanInfo and Descriptors are     * customized, the RequiredModelMBean can be registered with the     * MBeanServer.     *     * @param mbi The ModelMBeanInfo object to be used by the     *            RequiredModelMBean. The given ModelMBeanInfo is cloned     *            and modified as specified by {@link #setModelMBeanInfo}     *     * @exception MBeanException Wraps a distributed communication Exception.     * @exception RuntimeOperationsException Wraps an     *    {link java.lang.IllegalArgumentException}:     *          The MBeanInfo passed in parameter is null.     *     **/    public RequiredModelMBean(ModelMBeanInfo mbi)        throws MBeanException, RuntimeOperationsException {         if (MODELMBEAN_LOGGER.isLoggable(Level.FINER)) {            MODELMBEAN_LOGGER.logp(Level.FINER,                    RequiredModelMBean.class.getName(),                    "RequiredModelMBean(MBeanInfo)", "Entry");        }        setModelMBeanInfo(mbi);         if (MODELMBEAN_LOGGER.isLoggable(Level.FINER)) {            MODELMBEAN_LOGGER.logp(Level.FINER,                    RequiredModelMBean.class.getName(),                    "RequiredModelMBean(MBeanInfo)", "Exit");        }    }      /*************************************/    /* initializers                      */    /*************************************/     /**     * Initializes a ModelMBean object using ModelMBeanInfo passed in.     * This method makes it possible to set a customized ModelMBeanInfo on     * the ModelMBean as long as it is not registered with the MBeanServer.     * <br>     * Once the ModelMBean's ModelMBeanInfo (with Descriptors) are     * customized and set on the ModelMBean, the  ModelMBean be     * registered with the MBeanServer.     * <P>     * If the ModelMBean is currently registered, this method throws     * a {@link javax.management.RuntimeOperationsException} wrapping an     * {@link IllegalStateException}     * <P>     * If the given <var>inModelMBeanInfo</var> does not contain any     * {@link ModelMBeanNotificationInfo} for the <code>GENERIC</code>     * or <code>ATTRIBUTE_CHANGE</code> notifications, then the     * RequiredModelMBean will supply its own default     * {@link ModelMBeanNotificationInfo ModelMBeanNotificationInfo}s for     * those missing notifications.     *     * @param mbi The ModelMBeanInfo object to be used     *        by the ModelMBean.     *     * @exception MBeanException Wraps a distributed communication     *        Exception.     * @exception RuntimeOperationsException     * <ul><li>Wraps an {@link IllegalArgumentException} if     *         the MBeanInfo passed in parameter is null.</li>     *     <li>Wraps an {@link IllegalStateException} if the ModelMBean     *         is currently registered in the MBeanServer.</li>     * </ul>     *     **/    public void setModelMBeanInfo(ModelMBeanInfo mbi)        throws MBeanException, RuntimeOperationsException {         if (MODELMBEAN_LOGGER.isLoggable(Level.FINER)) {            MODELMBEAN_LOGGER.logp(Level.FINER,                    RequiredModelMBean.class.getName(),                "setModelMBeanInfo(ModelMBeanInfo)","Entry");        }         if (mbi == null) {            if (MODELMBEAN_LOGGER.isLoggable(Level.FINER)) {                MODELMBEAN_LOGGER.logp(Level.FINER,                        RequiredModelMBean.class.getName(),                    "setModelMBeanInfo(ModelMBeanInfo)",                    "ModelMBeanInfo is null: Raising exception.");            }            final RuntimeException x = new                IllegalArgumentException("ModelMBeanInfo must not be null");            final String exceptionText =                "Exception occurred trying to initialize the " +                "ModelMBeanInfo of the RequiredModelMBean";            throw new RuntimeOperationsException(x,exceptionText);        }         if (registered) {            if (MODELMBEAN_LOGGER.isLoggable(Level.FINER)) {                MODELMBEAN_LOGGER.logp(Level.FINER,                        RequiredModelMBean.class.getName(),                    "setModelMBeanInfo(ModelMBeanInfo)",                    "RequiredMBean is registered: Raising exception.");            }            final String exceptionText =                "Exception occurred trying to set the " +                "ModelMBeanInfo of the RequiredModelMBean";            final RuntimeException x = new IllegalStateException(             "cannot call setModelMBeanInfo while ModelMBean is registered");            throw new RuntimeOperationsException(x,exceptionText);        }         if (MODELMBEAN_LOGGER.isLoggable(Level.FINER)) {            MODELMBEAN_LOGGER.logp(Level.FINER,                    RequiredModelMBean.class.getName(),                "setModelMBeanInfo(ModelMBeanInfo)",                "Setting ModelMBeanInfo to " + printModelMBeanInfo(mbi));            MODELMBEAN_LOGGER.logp(Level.FINER,                    RequiredModelMBean.class.getName(),                "setModelMBeanInfo(ModelMBeanInfo)",                "ModelMBeanInfo notifications has " +                (mbi.getNotifications()).length + " elements");        }         modelMBeanInfo = (ModelMBeanInfo)mbi.clone();         if (MODELMBEAN_LOGGER.isLoggable(Level.FINER)) {            MODELMBEAN_LOGGER.logp(Level.FINER,                    RequiredModelMBean.class.getName(),                "setModelMBeanInfo(ModelMBeanInfo)","set mbeanInfo to: "+                 printModelMBeanInfo(modelMBeanInfo));            MODELMBEAN_LOGGER.logp(Level.FINER,                    RequiredModelMBean.class.getName(),                "setModelMBeanInfo(ModelMBeanInfo)","Exit");        }    }      /**     * Sets the instance handle of the object against which to     * execute all methods in this ModelMBean management interface     * (MBeanInfo and Descriptors).     *     * @param mr Object that is the managed resource     * @param mr_type The type of reference for the managed resource.     *     <br>Can be: "ObjectReference", "Handle", "IOR", "EJBHandle",     *         or "RMIReference".     *     <br>In this implementation only "ObjectReference" is supported.     *     * @exception MBeanException The initializer of the object has     *            thrown an exception.     * @exception InstanceNotFoundException The managed resource     *            object could not be found     * @exception InvalidTargetObjectTypeException The managed     *            resource type should be "ObjectReference".     * @exception RuntimeOperationsException Wraps a {@link     *            RuntimeException} when setting the resource.     **/    public void setManagedResource(Object mr, String mr_type)        throws MBeanException, RuntimeOperationsException,               InstanceNotFoundException, InvalidTargetObjectTypeException {        if (MODELMBEAN_LOGGER.isLoggable(Level.FINER)) {            MODELMBEAN_LOGGER.logp(Level.FINER,                    RequiredModelMBean.class.getName(),                "setManagedResource(Object,String)","Entry");        }         // check that the mr_type is supported by this JMXAgent        // only "objectReference" is supported        if ((mr_type == null) ||            (! mr_type.equalsIgnoreCase("objectReference"))) {            if (MODELMBEAN_LOGGER.isLoggable(Level.FINER)) {                MODELMBEAN_LOGGER.logp(Level.FINER,                        RequiredModelMBean.class.getName(),                    "setManagedResource(Object,String)",                    "Managed Resouce Type is not supported: " + mr_type);            }            throw new InvalidTargetObjectTypeException(mr_type);        }         if (MODELMBEAN_LOGGER.isLoggable(Level.FINER)) {            MODELMBEAN_LOGGER.logp(Level.FINER,                    RequiredModelMBean.class.getName(),                "setManagedResource(Object,String)",                "Managed Resouce is valid");        }        managedResource = mr;         if (MODELMBEAN_LOGGER.isLoggable(Level.FINER)) {            MODELMBEAN_LOGGER.logp(Level.FINER,                    RequiredModelMBean.class.getName(),                "setManagedResource(Object, String)", "Exit");        }    }     /**     * <p>Instantiates this MBean instance with the data found for     * the MBean in the persistent store.  The data loaded could include     * attribute and operation values.</p>     *     * <p>This method should be called during construction or     * initialization of this instance, and before the MBean is     * registered with the MBeanServer.</p>     *     * <p>If the implementation of this class does not support     * persistence, an {@link MBeanException} wrapping a {@link     * ServiceNotFoundException} is thrown.</p>     *     * @exception MBeanException Wraps another exception, or     * persistence is not supported     * @exception RuntimeOperationsException Wraps exceptions from the     * persistence mechanism     * @exception InstanceNotFoundException Could not find or load     * this MBean from persistent storage     */    public void load()        throws MBeanException, RuntimeOperationsException,               InstanceNotFoundException {        final ServiceNotFoundException x = new ServiceNotFoundException(                                "Persistence not supported for this MBean");        throw new MBeanException(x, x.getMessage());    }         /**     * <p>Captures the current state of this MBean instance and writes     * it out to the persistent store.  The state stored could include     * attribute and operation values.</p>     *     * <p>If the implementation of this class does not support     * persistence, an {@link MBeanException} wrapping a {@link     * ServiceNotFoundException} is thrown.</p>     *     * <p>Persistence policy from the MBean and attribute descriptor     * is used to guide execution of this method. The MBean should be     * stored if 'persistPolicy' field is:</p>     *     * <PRE>  != "never"     *   = "always"     *   = "onTimer" and now > 'lastPersistTime' + 'persistPeriod'     *   = "NoMoreOftenThan" and now > 'lastPersistTime' + 'persistPeriod'     *   = "onUnregister"     * </PRE>     *     * <p>Do not store the MBean if 'persistPolicy' field is:</p>     * <PRE>     *    = "never"     *    = "onUpdate"     *    = "onTimer" && now < 'lastPersistTime' + 'persistPeriod'     * </PRE>     *     * @exception MBeanException Wraps another exception, or     * persistence is not supported     * @exception RuntimeOperationsException Wraps exceptions from the     * persistence mechanism     * @exception InstanceNotFoundException Could not find/access the     * persistent store     */    public void store()        throws MBeanException, RuntimeOperationsException,               InstanceNotFoundException {        final ServiceNotFoundException x = new ServiceNotFoundException(                                "Persistence not supported for this MBean");        throw new MBeanException(x, x.getMessage());    }     /*************************************/    /* DynamicMBean Interface            */    /*************************************/     /**     * The resolveForCacheValue method checks the descriptor passed in to     * see if there is a valid cached value in the descriptor.     * The valid value will be in the 'value' field if there is one.     * If the 'currencyTimeLimit' field in the descriptor is:     * <ul>     *   <li><b>&lt;0</b> Then the value is not cached and is never valid.     *         Null is returned. The 'value' and 'lastUpdatedTimeStamp'     *         fields are cleared.</li>     *   <li><b>=0</b> Then the value is always cached and always valid.     *         The 'value' field is returned.     *         The 'lastUpdatedTimeStamp' field is not checked.</li>     *   <li><b>&gt;0</b> Represents the number of seconds that the     *         'value' field is valid.     *         The 'value' field is no longer valid when     *         'lastUpdatedTimeStamp' + 'currencyTimeLimit' &gt; Now.</li>     * </ul>     * <li>When 'value' is valid, 'valid' is returned.</li>     * <li>When 'value' is no longer valid then null is returned and     *     'value' and 'lastUpdatedTimeStamp' fields are cleared.</li>     *     **/    private Object resolveForCacheValue(Descriptor descr)        throws MBeanException, RuntimeOperationsException {         final boolean tracing = MODELMBEAN_LOGGER.isLoggable(Level.FINER);        final String mth = "resolveForCacheValue(Descriptor)";        if (tracing) {            MODELMBEAN_LOGGER.logp(Level.FINER,                    RequiredModelMBean.class.getName(),mth,"Entry");        }         Object response = null;        boolean resetValue = false, returnCachedValue = true;        long currencyPeriod = 0;         if (descr == null) {            if (tracing) {                MODELMBEAN_LOGGER.logp(Level.FINER,                        RequiredModelMBean.class.getName(),mth,                    "Input Descriptor is null");            }            return response;        }         if (tracing) {            MODELMBEAN_LOGGER.logp(Level.FINER,                    RequiredModelMBean.class.getName(),                    mth, "descriptor is " + descr);        }         final Descriptor mmbDescr = modelMBeanInfo.getMBeanDescriptor();        if (mmbDescr == null) {            if (tracing) {                MODELMBEAN_LOGGER.logp(Level.FINER,

Lines 1–500 of 2881.