alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Java example source code file (StandardMBean.java)

This example Java source code file (StandardMBean.java) is included in the alvinalexander.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Learn more about this Java project at its project page.

Java - Java tags/keywords

boolean, class, illegalargumentexception, log, logging, mbeanattributeinfo, mbeanconstructorinfo, mbeaninfo, mbeaninfosafeaction, mbeanoperationinfo, mbeanparameterinfo, notcompliantmbeanexception, object, openmbeanparameterinfo, security, standardmbean, string, util

The StandardMBean.java Java example source code

/*
 * 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 and with a management
 * interface defined (as for current Standard MBeans) by any interface
 * <i>Intf, in one of two general ways:

* * <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>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> * * </ul> * * <p>In either case, the class Impl must implement the * interface <i>Intf.

* * <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, using the * specified <var>mbeanInterface class. * @param implementation The implementation of this MBean. * If <code>null, and null implementation is allowed, * then the implementation is assumed to be <var>this. * @param mbeanInterface The Management Interface exported by this * MBean's implementation. If <code>null, then this * object will use standard JMX design pattern to determine * the management interface associated with the given * implementation. * @param nullImplementationAllowed <code>true 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. * @exception IllegalArgumentException if the given * <var>implementation is null, and null is not allowed. **/ private <T> void construct(T implementation, Class 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, using the specified * <var>mbeanInterface class.

* * @param implementation The implementation of this MBean. * @param mbeanInterface The Management Interface exported by this * MBean's implementation. If <code>null, 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 is null. * @exception NotCompliantMBeanException if the <var>mbeanInterface * does not follow JMX design patterns for Management Interfaces, or * if the given <var>implementation does not implement the * specified interface. **/ public <T> StandardMBean(T implementation, Class mbeanInterface) throws NotCompliantMBeanException { construct(implementation, mbeanInterface, false, false); } /** * <p>Make a DynamicMBean out of this, using the specified * <var>mbeanInterface class.

* * <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 * does not follow JMX design patterns for Management Interfaces, or * if <var>this 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, using the specified * <var>mbeanInterface 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, 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 is null, or if the mbeanInterface * does not follow JMX design patterns for Management Interfaces, or * if the given <var>implementation does not implement the * specified interface. * * @since 1.6 **/ public <T> StandardMBean(T implementation, Class mbeanInterface, boolean isMXBean) { try { construct(implementation, mbeanInterface, false, isMXBean); } catch (NotCompliantMBeanException e) { throw new IllegalArgumentException(e); } } /** * <p>Make a DynamicMBean out of this, using the specified * <var>mbeanInterface 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 * does not follow JMX design patterns for Management Interfaces, or * if <var>this 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.

* * @param implementation The new implementation of this Standard MBean * (or MXBean). The <code>implementation object must implement * the Standard MBean (or MXBean) interface that was supplied when this * <code>StandardMBean was constructed. * * @exception IllegalArgumentException if the given * <var>implementation is null. * * @exception NotCompliantMBeanException if the given * <var>implementation 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.<Classcast(getMBeanInterface())); } else { this.mbean = new StandardMBeanSupport(implementation, Util.<Classcast(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 * {@link MBeanInfo#getDescription() info.getDescription()}. * @param info The default MBeanInfo derived by reflection. * @return the description for the new MBeanInfo. **/ protected String getDescription(MBeanInfo info) { if (info == null) return null; return info.getDescription(); } /** * <p>Customization hook: * Get the description that will be used in the MBeanFeatureInfo * returned by this MBean.</p> * * <p>Subclasses may redefine this method in order to supply * their custom description. The default implementation returns * {@link MBeanFeatureInfo#getDescription() * info.getDescription()}.</p> * * <p>This method is called by * {@link #getDescription(MBeanAttributeInfo)}, * {@link #getDescription(MBeanOperationInfo)}, * {@link #getDescription(MBeanConstructorInfo)}.</p> * * @param info The default MBeanFeatureInfo derived by reflection. * @return the description for the given MBeanFeatureInfo. **/ protected String getDescription(MBeanFeatureInfo info) { if (info == null) return null; return info.getDescription(); } /** * Customization hook: * Get the description that will be used in the MBeanAttributeInfo * returned by this MBean. * * <p>Subclasses may redefine this method in order to supply their * custom description. The default implementation returns {@link * #getDescription(MBeanFeatureInfo) * getDescription((MBeanFeatureInfo) info)}. * @param info The default MBeanAttributeInfo derived by reflection. * @return the description for the given MBeanAttributeInfo. **/ protected String getDescription(MBeanAttributeInfo info) { return getDescription((MBeanFeatureInfo)info); } /** * Customization hook: * Get the description that will be used in the MBeanConstructorInfo * returned by this MBean. * <br> * Subclasses may redefine this method in order to supply their * custom description. * The default implementation returns {@link * #getDescription(MBeanFeatureInfo) * getDescription((MBeanFeatureInfo) info)}. * @param info The default MBeanConstructorInfo derived by reflection. * @return the description for the given MBeanConstructorInfo. **/ protected String getDescription(MBeanConstructorInfo info) { return getDescription((MBeanFeatureInfo)info); } /** * Customization hook: * Get the description that will be used for the <var>sequence * MBeanParameterInfo of the MBeanConstructorInfo returned by this MBean. * <br> * Subclasses may redefine this method in order to supply their * custom description. The default implementation returns * {@link MBeanParameterInfo#getDescription() param.getDescription()}. * * @param ctor The default MBeanConstructorInfo derived by reflection. * @param param The default MBeanParameterInfo derived by reflection. * @param sequence The sequence number of the parameter considered * ("0" for the first parameter, "1" for the second parameter, * etc...). * @return the description for the given MBeanParameterInfo. **/ protected String getDescription(MBeanConstructorInfo ctor, MBeanParameterInfo param, int sequence) { if (param == null) return null; return param.getDescription(); } /** * Customization hook: * Get the name that will be used for the <var>sequence * MBeanParameterInfo of the MBeanConstructorInfo returned by this MBean. * <br> * Subclasses may redefine this method in order to supply their * custom parameter name. The default implementation returns * {@link MBeanParameterInfo#getName() param.getName()}. * * @param ctor The default MBeanConstructorInfo derived by reflection. * @param param The default MBeanParameterInfo derived by reflection. * @param sequence The sequence number of the parameter considered * ("0" for the first parameter, "1" for the second parameter, * etc...). * @return the name for the given MBeanParameterInfo. **/ protected String getParameterName(MBeanConstructorInfo ctor, MBeanParameterInfo param, int sequence) { if (param == null) return null; return param.getName(); } /** * Customization hook: * Get the description that will be used in the MBeanOperationInfo * returned by this MBean. * <br> * Subclasses may redefine this method in order to supply their * custom description. The default implementation returns * {@link #getDescription(MBeanFeatureInfo) * getDescription((MBeanFeatureInfo) info)}. * @param info The default MBeanOperationInfo derived by reflection. * @return the description for the given MBeanOperationInfo. **/ protected String getDescription(MBeanOperationInfo info) { return getDescription((MBeanFeatureInfo)info); } /** * Customization hook: * Get the <var>impact flag of the operation that will be used in * the MBeanOperationInfo returned by this MBean. * <br> * Subclasses may redefine this method in order to supply their * custom impact flag. The default implementation returns * {@link MBeanOperationInfo#getImpact() info.getImpact()}. * @param info The default MBeanOperationInfo derived by reflection. * @return the impact flag for the given MBeanOperationInfo. **/ protected int getImpact(MBeanOperationInfo info) { if (info == null) return MBeanOperationInfo.UNKNOWN; return info.getImpact(); } /** * Customization hook: * Get the name that will be used for the <var>sequence * MBeanParameterInfo of the MBeanOperationInfo returned by this MBean. * <br> * Subclasses may redefine this method in order to supply their * custom parameter name. The default implementation returns * {@link MBeanParameterInfo#getName() param.getName()}. * * @param op The default MBeanOperationInfo derived by reflection. * @param param The default MBeanParameterInfo derived by reflection. * @param sequence The sequence number of the parameter considered * ("0" for the first parameter, "1" for the second parameter, * etc...). * @return the name to use for the given MBeanParameterInfo. **/ protected String getParameterName(MBeanOperationInfo op, MBeanParameterInfo param, int sequence) { if (param == null) return null; return param.getName(); } /** * Customization hook: * Get the description that will be used for the <var>sequence * MBeanParameterInfo of the MBeanOperationInfo returned by this MBean. * <br> * Subclasses may redefine this method in order to supply their * custom description. The default implementation returns * {@link MBeanParameterInfo#getDescription() param.getDescription()}. * * @param op The default MBeanOperationInfo derived by reflection. * @param param The default MBeanParameterInfo derived by reflection. * @param sequence The sequence number of the parameter considered * ("0" for the first parameter, "1" for the second parameter, * etc...). * @return the description for the given MBeanParameterInfo. **/ protected String getDescription(MBeanOperationInfo op, MBeanParameterInfo param, int sequence) { if (param == null) return null; return param.getDescription(); } /** * Customization hook: * Get the MBeanConstructorInfo[] that will be used in the MBeanInfo * returned by this MBean. * <br> * By default, this method returns <code>null if the wrapped * implementation is not <var>this. Indeed, if the wrapped * implementation is not this object itself, it will not be possible * to recreate a wrapped implementation by calling the implementation * constructors through <code>MBeanServer.createMBean(...).
* Otherwise, if the wrapped implementation is <var>this, * <var>ctors is returned. * <br> * Subclasses may redefine this method in order to modify this * behavior, if needed. * @param ctors The default MBeanConstructorInfo[] derived by reflection. * @param impl The wrapped implementation. If <code>null is * passed, the wrapped implementation is ignored and * <var>ctors is returned. * @return the MBeanConstructorInfo[] for the new MBeanInfo. **/ protected MBeanConstructorInfo[] getConstructors(MBeanConstructorInfo[] ctors, Object impl) { if (ctors == null) return null; if (impl != null && impl != this) return null; return ctors; } /** * Customization hook: * Get the MBeanNotificationInfo[] that will be used in the MBeanInfo * returned by this MBean. * <br> * Subclasses may redefine this method in order to supply their * custom notifications. * @param info The default MBeanInfo derived by reflection. * @return the MBeanNotificationInfo[] for the new MBeanInfo. **/ MBeanNotificationInfo[] getNotifications(MBeanInfo info) { return null; } /** * <p>Get the Descriptor that will be used in the MBeanInfo * returned by this MBean.</p> * * <p>Subclasses may redefine this method in order to supply * their custom descriptor.</p> * * <p>The default implementation of this method returns a Descriptor * that contains at least the field {@code interfaceClassName}, with * value {@link #getMBeanInterface()}.getName(). It may also contain * the field {@code immutableInfo}, with a value that is the string * {@code "true"} if the implementation can determine that the * {@code MBeanInfo} returned by {@link #getMBeanInfo()} will always * be the same. It may contain other fields: fields defined by the * JMX specification must have appropriate values, and other fields * must follow the conventions for non-standard field names.</p> * * @param info The default MBeanInfo derived by reflection. * @return the Descriptor for the new MBeanInfo. */ Descriptor getDescriptor(MBeanInfo info, boolean immutableInfo) { ImmutableDescriptor desc; if (info == null || info.getDescriptor() == null || info.getDescriptor().getFieldNames().length == 0) { final String interfaceClassNameS = "interfaceClassName=" + getMBeanInterface().getName(); final String immutableInfoS = "immutableInfo=" + immutableInfo; desc = new ImmutableDescriptor(interfaceClassNameS, immutableInfoS); desc = descriptors.get(desc); } else { Descriptor d = info.getDescriptor(); Map<String,Object> fields = new HashMap(); for (String fieldName : d.getFieldNames()) { if (fieldName.equals("immutableInfo")) { // Replace immutableInfo as the underlying MBean/MXBean // could already implement NotificationBroadcaster and // return immutableInfo=true in its MBeanInfo. fields.put(fieldName, Boolean.toString(immutableInfo)); } else { fields.put(fieldName, d.getFieldValue(fieldName)); } } desc = new ImmutableDescriptor(fields); } return desc; } /** * Customization hook: * Return the MBeanInfo cached for this object. * * <p>Subclasses may redefine this method in order to implement their * own caching policy. The default implementation stores one * {@link MBeanInfo} object per instance. * * @return The cached MBeanInfo, or null if no MBeanInfo is cached. * * @see #cacheMBeanInfo(MBeanInfo) **/ protected MBeanInfo getCachedMBeanInfo() { return cachedMBeanInfo; } /** * Customization hook: * cache the MBeanInfo built for this object. * * <p>Subclasses may redefine this method in order to implement * their own caching policy. The default implementation stores * <code>info in this instance. A subclass can define * other policies, such as not saving <code>info (so it is * reconstructed every time {@link #getMBeanInfo()} is called) or * sharing a unique {@link MBeanInfo} object when several * <code>StandardMBean instances have equal {@link * MBeanInfo} values. * * @param info the new <code>MBeanInfo to cache. Any * previously cached value is discarded. This parameter may be * null, in which case there is no new cached value. **/ protected void cacheMBeanInfo(MBeanInfo info) { cachedMBeanInfo = info; } private boolean isMXBean() { return mbean.isMXBean(); } private static <T> boolean identicalArrays(T[] a, T[] b) { if (a == b) return true; if (a == null || b == null || a.length != b.length) return false; for (int i = 0; i < a.length; i++) { if (a[i] != b[i]) return false; } return true; } private static <T> boolean equal(T a, T b) { if (a == b) return true; if (a == null || b == null) return false; return a.equals(b); } private static MBeanParameterInfo customize(MBeanParameterInfo pi, String name, String description) { if (equal(name, pi.getName()) && equal(description, pi.getDescription())) return pi; else if (pi instanceof OpenMBeanParameterInfo) { OpenMBeanParameterInfo opi = (OpenMBeanParameterInfo) pi; return new OpenMBeanParameterInfoSupport(name, description, opi.getOpenType(), pi.getDescriptor()); } else { return new MBeanParameterInfo(name, pi.getType(), description, pi.getDescriptor()); } } private static MBeanConstructorInfo customize(MBeanConstructorInfo ci, String description, MBeanParameterInfo[] signature) { if (equal(description, ci.getDescription()) && identicalArrays(signature, ci.getSignature())) return ci; if (ci instanceof OpenMBeanConstructorInfo) { OpenMBeanParameterInfo[] oparams = paramsToOpenParams(signature); return new OpenMBeanConstructorInfoSupport(ci.getName(), description, oparams, ci.getDescriptor()); } else { return new MBeanConstructorInfo(ci.getName(), description, signature, ci.getDescriptor()); } } private static MBeanOperationInfo customize(MBeanOperationInfo oi, String description, MBeanParameterInfo[] signature, int impact) { if (equal(description, oi.getDescription()) && identicalArrays(signature, oi.getSignature()) && impact == oi.getImpact()) return oi; if (oi instanceof OpenMBeanOperationInfo) { OpenMBeanOperationInfo ooi = (OpenMBeanOperationInfo) oi; OpenMBeanParameterInfo[] oparams = paramsToOpenParams(signature); return new OpenMBeanOperationInfoSupport(oi.getName(), description, oparams, ooi.getReturnOpenType(), impact, oi.getDescriptor()); } else { return new MBeanOperationInfo(oi.getName(), description, signature, oi.getReturnType(), impact, oi.getDescriptor()); } } private static MBeanAttributeInfo customize(MBeanAttributeInfo ai, String description) { if (equal(description, ai.getDescription())) return ai; if (ai instanceof OpenMBeanAttributeInfo) { OpenMBeanAttributeInfo oai = (OpenMBeanAttributeInfo) ai; return new OpenMBeanAttributeInfoSupport(ai.getName(), description, oai.getOpenType(), ai.isReadable(), ai.isWritable(), ai.isIs(), ai.getDescriptor()); } else { return new MBeanAttributeInfo(ai.getName(), ai.getType(), description, ai.isReadable(), ai.isWritable(), ai.isIs(), ai.getDescriptor()); } } private static OpenMBeanParameterInfo[] paramsToOpenParams(MBeanParameterInfo[] params) { if (params instanceof OpenMBeanParameterInfo[]) return (OpenMBeanParameterInfo[]) params; OpenMBeanParameterInfo[] oparams = new OpenMBeanParameterInfoSupport[params.length]; System.arraycopy(params, 0, oparams, 0, params.length); return oparams; } // ------------------------------------------------------------------ // Build the custom MBeanConstructorInfo[] // ------------------------------------------------------------------ private MBeanConstructorInfo[] getConstructors(MBeanInfo info, Object impl) { final MBeanConstructorInfo[] ctors = getConstructors(info.getConstructors(), impl); if (ctors == null) return null; final int ctorlen = ctors.length; final MBeanConstructorInfo[] nctors = new MBeanConstructorInfo[ctorlen]; for (int i=0; i<ctorlen; i++) { final MBeanConstructorInfo c = ctors[i]; final MBeanParameterInfo[] params = c.getSignature(); final MBeanParameterInfo[] nps; if (params != null) { final int plen = params.length; nps = new MBeanParameterInfo[plen]; for (int ii=0;ii<plen;ii++) { MBeanParameterInfo p = params[ii]; nps[ii] = customize(p, getParameterName(c,p,ii), getDescription(c,p,ii)); } } else { nps = null; } nctors[i] = customize(c, getDescription(c), nps); } return nctors; } // ------------------------------------------------------------------ // Build the custom MBeanOperationInfo[] // ------------------------------------------------------------------ private MBeanOperationInfo[] getOperations(MBeanInfo info) { final MBeanOperationInfo[] ops = info.getOperations(); if (ops == null) return null; final int oplen = ops.length; final MBeanOperationInfo[] nops = new MBeanOperationInfo[oplen]; for (int i=0; i<oplen; i++) { final MBeanOperationInfo o = ops[i]; final MBeanParameterInfo[] params = o.getSignature(); final MBeanParameterInfo[] nps; if (params != null) { final int plen = params.length; nps = new MBeanParameterInfo[plen]; for (int ii=0;ii<plen;ii++) { MBeanParameterInfo p = params[ii]; nps[ii] = customize(p, getParameterName(o,p,ii), getDescription(o,p,ii)); } } else { nps = null; } nops[i] = customize(o, getDescription(o), nps, getImpact(o)); } return nops; } // ------------------------------------------------------------------ // Build the custom MBeanAttributeInfo[] // ------------------------------------------------------------------ private MBeanAttributeInfo[] getAttributes(MBeanInfo info) { final MBeanAttributeInfo[] atts = info.getAttributes(); if (atts == null) return null; // should not happen final MBeanAttributeInfo[] natts; final int attlen = atts.length; natts = new MBeanAttributeInfo[attlen]; for (int i=0; i<attlen; i++) { final MBeanAttributeInfo a = atts[i]; natts[i] = customize(a, getDescription(a)); } return natts; } /** * <p>Allows the MBean to perform any operations it needs before * being registered in the MBean server. If the name of the MBean * is not specified, the MBean can provide a name for its * registration. If any exception is raised, the MBean will not be * registered in the MBean server.</p> * * <p>The default implementation of this method returns the {@code name} * parameter. It does nothing else for * Standard MBeans. For MXBeans, it records the {@code MBeanServer} * and {@code ObjectName} parameters so they can be used to translate * inter-MXBean references.</p> * * <p>It is good practice for a subclass that overrides this method * to call the overridden method via {@code super.preRegister(...)}. * This is necessary if this object is an MXBean that is referenced * by attributes or operations in other MXBeans.</p> * * @param server The MBean server in which the MBean will be registered. * * @param name The object name of the MBean. This name is null if * the name parameter to one of the <code>createMBean or * <code>registerMBean methods in the {@link MBeanServer} * interface is null. In that case, this method must return a * non-null ObjectName for the new MBean. * * @return The name under which the MBean is to be registered. * This value must not be null. If the <code>name * parameter is not null, it will usually but not necessarily be * the returned value. * * @throws IllegalArgumentException if this is an MXBean and * {@code name} is null. * * @throws InstanceAlreadyExistsException if this is an MXBean and * it has already been registered under another name (in this * MBean Server or another). * * @throws Exception no other checked exceptions are thrown by * this method but {@code Exception} is declared so that subclasses * can override the method and throw their own exceptions. * * @since 1.6 */ public ObjectName preRegister(MBeanServer server, ObjectName name) throws Exception { mbean.register(server, name); return name; } /** * <p>Allows the MBean to perform any operations needed after having been * registered in the MBean server or after the registration has failed.</p> * * <p>The default implementation of this method does nothing for * Standard MBeans. For MXBeans, it undoes any work done by * {@link #preRegister preRegister} if registration fails.</p> * * <p>It is good practice for a subclass that overrides this method * to call the overridden method via {@code super.postRegister(...)}. * This is necessary if this object is an MXBean that is referenced * by attributes or operations in other MXBeans.</p> * * @param registrationDone Indicates whether or not the MBean has * been successfully registered in the MBean server. The value * false means that the registration phase has failed. * * @since 1.6 */ public void postRegister(Boolean registrationDone) { if (!registrationDone) mbean.unregister(); } /** * <p>Allows the MBean to perform any operations it needs before * being unregistered by the MBean server.</p> * * <p>The default implementation of this method does nothing.

* * <p>It is good practice for a subclass that overrides this method * to call the overridden method via {@code super.preDeregister(...)}.</p> * * @throws Exception no checked exceptions are throw by this method * but {@code Exception} is declared so that subclasses can override * this method and throw their own exceptions. * * @since 1.6 */ public void preDeregister() throws Exception { } /** * <p>Allows the MBean to perform any operations needed after having been * unregistered in the MBean server.</p> * * <p>The default implementation of this method does nothing for * Standard MBeans. For MXBeans, it removes any information that * was recorded by the {@link #preRegister preRegister} method.</p> * * <p>It is good practice for a subclass that overrides this method * to call the overridden method via {@code super.postRegister(...)}. * This is necessary if this object is an MXBean that is referenced * by attributes or operations in other MXBeans.</p> * * @since 1.6 */ public void postDeregister() { mbean.unregister(); } // // MBeanInfo immutability // /** * Cached results of previous calls to immutableInfo. This is * a WeakHashMap so that we don't prevent a class from being * garbage collected just because we know whether its MBeanInfo * is immutable. */ private static final Map<Class mbeanInfoSafeMap = new WeakHashMap<Class(); /** * Return true if {@code subclass} is known to preserve the immutability * of the {@code MBeanInfo}. The {@code subclass} is considered to have * an immutable {@code MBeanInfo} if it does not override any of the * getMBeanInfo, getCachedMBeanInfo, cacheMBeanInfo and getNotificationInfo * methods. */ static boolean immutableInfo(Class<? extends StandardMBean> subclass) { if (subclass == StandardMBean.class || subclass == StandardEmitterMBean.class) return true; synchronized (mbeanInfoSafeMap) { Boolean safe = mbeanInfoSafeMap.get(subclass); if (safe == null) { try { MBeanInfoSafeAction action = new MBeanInfoSafeAction(subclass); safe = AccessController.doPrivileged(action); } catch (Exception e) { // e.g. SecurityException /* We don't know, so we assume it isn't. */ safe = false; } mbeanInfoSafeMap.put(subclass, safe); } return safe; } } static boolean overrides(Class<?> subclass, Class superclass, String name, Class<?>... params) { for (Class<?> c = subclass; c != superclass; c = c.getSuperclass()) { try { c.getDeclaredMethod(name, params); return true; } catch (NoSuchMethodException e) { // OK: this class doesn't override it } } return false; } private static class MBeanInfoSafeAction implements PrivilegedAction<Boolean> { private final Class<?> subclass; MBeanInfoSafeAction(Class<?> subclass) { this.subclass = subclass; } public Boolean run() { // Check for "void cacheMBeanInfo(MBeanInfo)" method. // if (overrides(subclass, StandardMBean.class, "cacheMBeanInfo", MBeanInfo.class)) return false; // Check for "MBeanInfo getCachedMBeanInfo()" method. // if (overrides(subclass, StandardMBean.class, "getCachedMBeanInfo", (Class<?>[]) null)) return false; // Check for "MBeanInfo getMBeanInfo()" method. // if (overrides(subclass, StandardMBean.class, "getMBeanInfo", (Class<?>[]) null)) return false; // Check for "MBeanNotificationInfo[] getNotificationInfo()" // method. // // This method is taken into account for the MBeanInfo // immutability checks if and only if the given subclass is // StandardEmitterMBean itself or can be assigned to // StandardEmitterMBean. // if (StandardEmitterMBean.class.isAssignableFrom(subclass)) if (overrides(subclass, StandardEmitterMBean.class, "getNotificationInfo", (Class<?>[]) null)) return false; return true; } } }

Other Java examples (source code examples)

Here is a short list of links related to this Java StandardMBean.java source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2024 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.