Package com.sun.jmx.mbeanserver

Source Code of com.sun.jmx.mbeanserver.MBeanSupport

/*
* @(#)MBeanSupport.java  1.6 05/11/17
*
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*/

package com.sun.jmx.mbeanserver;

import static com.sun.jmx.mbeanserver.Util.*;
import java.lang.annotation.Annotation;
import java.lang.ref.WeakReference;
import java.lang.reflect.Constructor;
import java.lang.reflect.GenericArrayType;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.WeakHashMap;
import javax.management.Attribute;
import javax.management.AttributeList;
import javax.management.AttributeNotFoundException;
import javax.management.Descriptor;
import javax.management.DynamicMBean;
import javax.management.ImmutableDescriptor;
import javax.management.InstanceAlreadyExistsException;
import javax.management.InvalidAttributeValueException;
import javax.management.JMX;
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.MBeanParameterInfo;
import javax.management.MBeanRegistration;
import javax.management.MBeanServer;
import javax.management.NotCompliantMBeanException;
import javax.management.NotificationBroadcaster;
import javax.management.ObjectName;
import javax.management.ReflectionException;
import javax.management.openmbean.OpenMBeanAttributeInfoSupport;
import javax.management.openmbean.OpenMBeanOperationInfoSupport;
import javax.management.openmbean.OpenMBeanParameterInfo;
import javax.management.openmbean.OpenMBeanParameterInfoSupport;
import javax.management.openmbean.OpenType;

/**
* Base class for MBeans.  There is one instance of this class for
* every Standard MBean and every MXBean.  We try to limit the amount
* of information per instance so we can handle very large numbers of
* MBeans confortably.
*
* @param <M> either Method or ConvertingMethod, for Standard MBeans
* and MXBeans respectively.
*
* @since 1.6
*/
/*
* We maintain a couple of caches to increase sharing between
* different MBeans of the same type and also to reduce creation time
* for the second and subsequent instances of the same type.
*
* The first cache maps from an MBean interface to a PerInterface
* object containing information parsed out of the interface.  The
* interface is either a Standard MBean interface or an MXBean
* interface, and there is one cache for each case.
*
* The PerInterface includes an MBeanInfo.  This contains the
* attributes and operations parsed out of the interface's methods,
* plus a basic Descriptor for the interface containing at least the
* interfaceClassName field and any fields derived from annotations on
* the interface.  This MBeanInfo can never be the MBeanInfo for any
* actual MBean, because an MBeanInfo's getClassName() is the name of
* a concrete class and we don't know what the class will be.
* Furthermore a real MBeanInfo may need to add constructors and/or
* notifications to the MBeanInfo.
*
* The PerInterface also contains an MBeanDispatcher which is able to
* route getAttribute, setAttribute, and invoke to the appropriate
* method of the interface, including doing any necessary translation
* of parameters and return values for MXBeans.
*
* The PerInterface also contains the original Class for the interface.
*
* We need to be careful about references.  When there are no MBeans
* with a given interface, there must not be any strong references to
* the interface Class.  Otherwise it could never be garbage collected,
* and neither could its ClassLoader or any other classes loaded by
* its ClassLoader.  Therefore the cache must wrap the PerInterface
* in a WeakReference.  Each instance of MBeanSupport has a strong
* reference to its PerInterface, which prevents PerInterface instances
* from being garbage-collected prematurely.
*
* The second cache maps from a concrete class and an MBean interface
* that that class implements to the MBeanInfo for that class and
* interface.  (The ability to specify an interface separately comes
* from the class StandardMBean.  MBeans registered directly in the
* MBean Server will always have the same interface here.)
*
* The MBeanInfo in this second cache will be the MBeanInfo from the
* PerInterface cache for the given itnerface, but with the
* getClassName() having the concrete class's name, and the public
* constructors based on the concrete class's constructors.  This
* MBeanInfo can be shared between all instances of the concrete class
* specifying the same interface, except instances that are
* NotificationBroadcasters.  NotificationBroadcasters supply the
* MBeanNotificationInfo[] in the MBeanInfo based on the instance
* method NotificationBroadcaster.getNotificationInfo(), so two
* instances of the same concrete class do not necessarily have the
* same MBeanNotificationInfo[].  Currently we do not try to detect
* when they do, although it would probably be worthwhile doing that
* since it is a very common case.
*
* Standard MBeans additionally have the property that
* getNotificationInfo() must in principle be called every time
* getMBeanInfo() is called for the MBean, since the returned array is
* allowed to change over time.  We attempt to reduce the cost of
* doing this by detecting when the Standard MBean is a subclass of
* NotificationBroadcasterSupport that does not override
* getNotificationInfo(), meaning that the MBeanNotificationInfo[] is
* the one that was supplied to the constructor.  MXBeans do not have
* this problem because their getNotificationInfo() method is called
* only once.
*
*/
public abstract class MBeanSupport<M>
        implements DynamicMBean2, MBeanRegistration {

    <T> MBeanSupport(T resource, Class<T> mbeanInterface)
            throws NotCompliantMBeanException {
  if (mbeanInterface == null)
      throw new NotCompliantMBeanException("Null MBean interface");
  if (!mbeanInterface.isInstance(resource)) {
      final String msg =
    "Resource class " + resource.getClass().getName() +
    " is not an instance of " + mbeanInterface.getName();
      throw new NotCompliantMBeanException(msg);
  }
  this.resource = resource;
        MBeanIntrospector introspector = getMBeanIntrospector();
        this.perInterface = introspector.getPerInterface(mbeanInterface);
  this.mbeanInfo = introspector.getMBeanInfo(resource, perInterface);
    }

    /** Return the appropriate introspector for this type of MBean. */
    abstract MBeanIntrospector<M> getMBeanIntrospector();
   
    /**
     * Return a cookie for this MBean.  This cookie will be passed to
     * MBean method invocations where it can supply additional information
     * to the invocation.  For example, with MXBeans it can be used to
     * supply the MXBeanLookup context for resolving inter-MXBean references.
     */
    abstract Object getCookie();

    public final boolean isMXBean() {
  return perInterface.isMXBean();
    }

    // Methods that javax.management.StandardMBean should call from its
    // preRegister and postRegister, given that it is not supposed to
    // call the contained object's preRegister etc methods even if it has them
    public abstract void register(MBeanServer mbs, ObjectName name)
            throws Exception;
    public abstract void unregister();

    public final ObjectName preRegister(MBeanServer server, ObjectName name)
            throws Exception {
        if (resource instanceof MBeanRegistration)
            return ((MBeanRegistration) resource).preRegister(server, name);
        else
            return name;
    }
   
    public final void preRegister2(MBeanServer server, ObjectName name)
            throws Exception {
        register(server, name);
    }
   
    public final void registerFailed() {
        unregister();
    }

    public final void postRegister(Boolean registrationDone) {
        if (resource instanceof MBeanRegistration)
            ((MBeanRegistration) resource).postRegister(registrationDone);
    }
   
    public final void preDeregister() throws Exception {
        if (resource instanceof MBeanRegistration)
            ((MBeanRegistration) resource).preDeregister();
    }

    public final void postDeregister() {
        // Undo any work from registration.  We do this in postDeregister
        // not preDeregister, because if the user preDeregister throws an
        // exception then the MBean is not unregistered.
        try {
            unregister();
        } finally {
            if (resource instanceof MBeanRegistration)
                ((MBeanRegistration) resource).postDeregister();
        }
    }

    public final Object getAttribute(String attribute)
      throws AttributeNotFoundException,
       MBeanException,
       ReflectionException {
  return perInterface.getAttribute(resource, attribute, getCookie());
    }

    public final AttributeList getAttributes(String[] attributes) {
  final AttributeList result = new AttributeList(attributes.length);
  for (String attrName : attributes) {
      try {
    final Object attrValue = getAttribute(attrName);
    result.add(new Attribute(attrName, attrValue));
      } catch (Exception e) {
    // OK: attribute is not included in returned list, per spec
    // XXX: log the exception
      }
  }
  return result;
    }

    public final void setAttribute(Attribute attribute)
      throws AttributeNotFoundException,
       InvalidAttributeValueException,
       MBeanException,
       ReflectionException {
  final String name = attribute.getName();
  final Object value = attribute.getValue();
  perInterface.setAttribute(resource, name, value, getCookie());
    }

    public final AttributeList setAttributes(AttributeList attributes) {
  final AttributeList result = new AttributeList(attributes.size());
  for (Object attrObj : attributes) {
      // We can't use AttributeList.asList because it has side-effects
      Attribute attr = (Attribute) attrObj;
      try {
    setAttribute(attr);
    result.add(new Attribute(attr.getName(), attr.getValue()));
      } catch (Exception e) {
    // OK: attribute is not included in returned list, per spec
    // XXX: log the exception
      }
  }
  return result;
    }

    public final Object invoke(String operation, Object[] params,
       String[] signature)
      throws MBeanException, ReflectionException {
  return perInterface.invoke(resource, operation, params, signature,
           getCookie());
    }

    // Overridden by StandardMBeanSupport
    public MBeanInfo getMBeanInfo() {
  return mbeanInfo;
    }
   
    public final String getClassName() {
        return resource.getClass().getName();
    }

    public final Object getResource() {
  return resource;
    }
   
    public final Class<?> getMBeanInterface() {
        return perInterface.getMBeanInterface();
    }

    private final MBeanInfo mbeanInfo;
    private final Object resource;
    private final PerInterface<M> perInterface;
}
TOP

Related Classes of com.sun.jmx.mbeanserver.MBeanSupport

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.