/* * @(#)Introspector.java 1.68 03/12/19 * * Copyright 2004 Sun Microsystems, Inc. All rights reserved. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. */ package com.sun.jmx.mbeanserver; // Java import import java.lang.reflect.Constructor; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.util.ArrayList; import java.util.List; import java.util.Iterator; // RI Import import javax.management.IntrospectionException; import javax.management.MBeanAttributeInfo; import javax.management.MBeanConstructorInfo; import javax.management.MBeanInfo; import javax.management.MBeanOperationInfo; import javax.management.MBeanParameterInfo; import javax.management.NotCompliantMBeanException; /** * This class contains the methods for performing all the tests needed to verify * that a class represents a JMX compliant MBean. * * @since 1.5 */ public class Introspector { /* * ------------------------------------------ * PRIVATE VARIABLES * ------------------------------------------ */ private static final String attributeDescription = "Attribute exposed for management"; private static final String operationDescription = "Operation exposed for management"; private static final String constructorDescription = "Public constructor of the MBean"; private static final String mbeanInfoDescription = "Information on the management interface of the MBean"; /* * ------------------------------------------ * PRIVATE CONSTRUCTORS * ------------------------------------------ */ // private constructor defined to "hide" the default public constructor private Introspector() { // ------------------------------ // ------------------------------ } /* * ------------------------------------------ * PUBLIC METHODS * ------------------------------------------ */ /** * Tell whether a MBean of the given class is a Dynamic MBean. * This method does nothing more than returning *
* javax.management.DynamicMBean.class.isAssignableFrom(c) ** This method does not check for any JMX MBean compliance: *
true
is returned, then instances of
* c
are DynamicMBean.false
is returned, then no further
* assumption can be made on instances of c
.
* In particular, instances of c
may, or may not
* be JMX standard MBeans.true
if instances of c
are
* Dynamic MBeans, false
otherwise.
*
* @since.unbundled JMX RI 1.2
**/
public static final boolean isDynamic(final Class c) {
// Check if the MBean implements the DynamicMBean interface
return javax.management.DynamicMBean.class.isAssignableFrom(c);
}
/**
* Basic method for testing that a MBean of a given class can be
* instantiated by the MBean server.* This method checks that: *
null
if the MBean is a DynamicMBean,
* the computed {@link javax.management.MBeanInfo} otherwise.
* @exception NotCompliantMBeanException The specified class is not a
* JMX compliant MBean
*/
public static MBeanInfo testCompliance(Class baseClass)
throws NotCompliantMBeanException {
// ------------------------------
// ------------------------------
// Check if the MBean implements the MBean or the Dynamic
// MBean interface
if (isDynamic(baseClass))
return null;
return testCompliance(baseClass, null);
}
/**
* Basic method for testing if a given class is a JMX compliant MBean.
*
* @param baseClass The class to be tested
*
* @return null
if the MBean is a DynamicMBean,
* the computed {@link javax.management.MBeanInfo} otherwise.
* @exception NotCompliantMBeanException The specified class is not a
* JMX compliant MBean
*/
static MBeanInfo testCompliance(final Class baseClass,
Class mbeanInterface)
throws NotCompliantMBeanException {
if (baseClass.isInterface())
throw new NotCompliantMBeanException(baseClass.getName() +
" must be a class.");
// ------------------------------
// ------------------------------
if (mbeanInterface == null)
// No interface specified: look for default MBean interface.
mbeanInterface = getStandardMBeanInterface(baseClass);
else if (! mbeanInterface.isAssignableFrom(baseClass)) {
// specified interface not implemented by given class
final String msg =
baseClass.getName() + " does not implement the " +
mbeanInterface.getName() + " interface";
throw new NotCompliantMBeanException(msg);
} else if (! mbeanInterface.isInterface()) {
// Base class X, but XMBean is not an interface
final String msg =
baseClass.getName() + ": " + mbeanInterface.getName() +
" is not an interface";
throw new NotCompliantMBeanException(msg);
}
if (mbeanInterface == null) {
// Error: MBean does not implement javax.management.DynamicMBean
// nor MBean interface
final String baseClassName = baseClass.getName();
final String msg =
baseClassName + " does not implement the " + baseClassName +
"MBean interface or the DynamicMBean interface";
throw new NotCompliantMBeanException(msg);
}
final int mods = mbeanInterface.getModifiers();
if (!Modifier.isPublic(mods))
throw new NotCompliantMBeanException(mbeanInterface.getName() +
" implemented by " +
baseClass.getName() +
" must be public");
return (introspect(baseClass, mbeanInterface));
}
/**
* Get the MBean interface implemented by a JMX standard MBean
* class.
*
* @param baseClass The class to be tested
*
* @return The MBean interface implemented by the MBean.
* Return null
if the MBean is a DynamicMBean,
* or if no MBean interface is found.
*
*/
public static Class getMBeanInterface(Class baseClass) {
// ------------------------------
// ------------------------------
// Check if the MBean implements the MBean or the Dynamic
// MBean interface
if (isDynamic(baseClass)) return null;
return getStandardMBeanInterface(baseClass);
}
/**
* Get the MBean interface implemented by a JMX standard MBean
* class.
*
* @param baseClass The class to be tested
*
* @return The MBean interface implemented by the MBean.
* Return null
if no MBean interface is found.
* Does not check whether the MBean is a DynamicMBean.
*
*/
static Class getStandardMBeanInterface(Class baseClass) {
// ------------------------------
// ------------------------------
Class current = baseClass;
Class mbeanInterface = null;
while (current != null) {
mbeanInterface =
findMBeanInterface(current, current.getName());
if (mbeanInterface != null) break;
current = current.getSuperclass();
}
return mbeanInterface;
}
/*
* ------------------------------------------
* PRIVATE METHODS
* ------------------------------------------
*/
/**
* Try to find the MBean interface corresponding to the class aName
* - i.e. aNameMBean, from within aClass and its superclasses.
**/
private static Class findMBeanInterface(Class aClass, String aName) {
Class current = aClass;
while (current != null) {
final Class[] interfaces = current.getInterfaces();
final int len = interfaces.length;
for (int i=0;i