Introspector.java revision 1790
/*
* Copyright 1999-2008 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
/**
* 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 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
* <pre>
* javax.management.DynamicMBean.class.isAssignableFrom(c)
* </pre>
* This method does not check for any JMX MBean compliance:
* <ul><li>If <code>true</code> is returned, then instances of
* <code>c</code> are DynamicMBean.</li>
* <li>If <code>false</code> is returned, then no further
* assumption can be made on instances of <code>c</code>.
* In particular, instances of <code>c</code> may, or may not
* be JMX standard MBeans.</li>
* </ul>
* @param c The class of the MBean under examination.
* @return <code>true</code> if instances of <code>c</code> are
* Dynamic MBeans, <code>false</code> otherwise.
*
**/
// Check if the MBean implements the DynamicMBean interface
}
/**
* Basic method for testing that a MBean of a given class can be
* instantiated by the MBean server.<p>
* This method checks that:
* <ul><li>The given class is a concrete class.</li>
* <li>The given class exposes at least one public constructor.</li>
* </ul>
* If these conditions are not met, throws a NotCompliantMBeanException.
* @param c The class of the MBean we want to create.
* @exception NotCompliantMBeanException if the MBean class makes it
* impossible to instantiate the MBean from within the
* MBeanServer.
*
**/
public static void testCreation(Class<?> c)
throws NotCompliantMBeanException {
// Check if the class is a concrete class
final int mods = c.getModifiers();
throw new NotCompliantMBeanException("MBean class must be concrete");
}
// Check if the MBean has a public constructor
throw new NotCompliantMBeanException("MBean class must have public constructor");
}
}
throws NotCompliantMBeanException {
// Is DynamicMBean?
//
return;
// Is Standard MBean?
//
final Exception mbeanException;
try {
return;
} catch (NotCompliantMBeanException e) {
mbeanException = e;
}
// Is MXBean?
//
final Exception mxbeanException;
try {
return;
} catch (NotCompliantMBeanException e) {
mxbeanException = e;
}
"DynamicMBean, and neither follows the Standard MBean conventions (" +
throw new NotCompliantMBeanException(msg);
}
throws NotCompliantMBeanException {
if (mbean instanceof DynamicMBean)
return (DynamicMBean) mbean;
try {
} catch (NotCompliantMBeanException e) {
// Ignore exception - we need to check whether
// mbean is an MXBean first.
}
if (c != null)
return new StandardMBeanSupport(mbean, c);
try {
} catch (NotCompliantMBeanException e) {
// Ignore exception - we cannot decide whether mbean was supposed
// to be an MBean or an MXBean. We will call checkCompliance()
// to generate the appropriate exception.
}
if (c != null)
return new MXBeanSupport(mbean, c);
}
/**
* Basic method for testing if a given class is a JMX compliant MBean.
*
* @param baseClass The class to be tested
*
* @return <code>null</code> if the MBean is a DynamicMBean,
* the computed {@link javax.management.MBeanInfo} otherwise.
* @exception NotCompliantMBeanException The specified class is not a
* JMX compliant MBean
*/
throws NotCompliantMBeanException {
// ------------------------------
// ------------------------------
// Check if the MBean implements the MBean or the Dynamic
// MBean interface
return null;
}
throws NotCompliantMBeanException {
}
/**
* Basic method for testing if a given class is a JMX compliant
* Standard MBean. This method is only called by the legacy code
* in com.sun.management.jmx.
*
* @param baseClass The class to be tested.
*
* @param mbeanInterface the MBean interface that the class implements,
* or null if the interface must be determined by introspection.
*
* @return the computed {@link javax.management.MBeanInfo}.
* @exception NotCompliantMBeanException The specified class is not a
* JMX compliant Standard MBean
*/
public static synchronized MBeanInfo
Class<?> mbeanInterface)
throws NotCompliantMBeanException {
if (mbeanInterface == null)
}
private static <M> MBeanInfo
throws NotCompliantMBeanException {
}
/**
* Get the MBean interface implemented by a JMX Standard
* MBean class. This method is only called by the legacy
* code in "com.sun.management.jmx".
*
* @param baseClass The class to be tested.
*
* @return The MBean interface implemented by the MBean.
* Return <code>null</code> if the MBean is a DynamicMBean,
* or if no MBean interface is found.
*/
// Check if the given class implements the MBean interface
// or the Dynamic MBean interface
try {
return getStandardMBeanInterface(baseClass);
} catch (NotCompliantMBeanException e) {
return null;
}
}
/**
* 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 Standard MBean.
*
* @throws NotCompliantMBeanException The specified class is
* not a JMX compliant Standard MBean.
*/
throws NotCompliantMBeanException {
if (mbeanInterface != null) break;
}
if (mbeanInterface != null) {
return mbeanInterface;
} else {
" is not a JMX compliant Standard MBean";
throw new NotCompliantMBeanException(msg);
}
}
/**
* Get the MXBean interface implemented by a JMX MXBean class.
*
* @param baseClass The class to be tested.
*
* @return The MXBean interface implemented by the MXBean.
*
* @throws NotCompliantMBeanException The specified class is
* not a JMX compliant MXBean.
*/
throws NotCompliantMBeanException {
try {
} catch (Exception e) {
throw throwException(baseClass,e);
}
}
/*
* ------------------------------------------
* PRIVATE METHODS
* ------------------------------------------
*/
/**
* Try to find the MBean interface corresponding to the class aName
* - i.e. <i>aName</i>MBean, from within aClass and its superclasses.
**/
private static <T> Class<? super T> findMBeanInterface(
for (int i=0;i<len;i++) {
}
}
return null;
}
return ImmutableDescriptor.EMPTY_DESCRIPTOR;
return descriptorForAnnotations(annots);
}
return ImmutableDescriptor.EMPTY_DESCRIPTOR;
for (Annotation a : annots) {
try {
} catch (RuntimeException e) {
// we don't expect this - except for possibly
// security exceptions?
// RuntimeExceptions shouldn't be "UndeclaredThrowable".
// anyway...
//
throw e;
} catch (Exception e) {
// we don't expect this
throw new UndeclaredThrowableException(e);
}
"Inconsistent values for descriptor field " + name +
throw new IllegalArgumentException(msg);
}
}
}
}
if (descriptorMap.isEmpty())
return ImmutableDescriptor.EMPTY_DESCRIPTOR;
else
return new ImmutableDescriptor(descriptorMap);
}
/**
* Throws a NotCompliantMBeanException or a SecurityException.
* @param notCompliant the class which was under examination
* @param cause the raeson why NotCompliantMBeanException should
* be thrown.
* @return nothing - this method always throw an exception.
* The return type makes it possible to write
* <pre> throw throwException(clazz,cause); </pre>
* @throws SecurityException - if cause is a SecurityException
* @throws NotCompliantMBeanException otherwise.
**/
throws NotCompliantMBeanException, SecurityException {
if (cause instanceof SecurityException)
throw (SecurityException) cause;
if (cause instanceof NotCompliantMBeanException)
throw (NotCompliantMBeanException)cause;
final NotCompliantMBeanException res =
throw res;
}
// Convert a value from an annotation element to a descriptor field value
// E.g. with @interface Foo {class value()} an annotation @Foo(String.class)
// will produce a Descriptor field value "java.lang.String"
// An annotation element cannot have a null value but never mind
if (x == null)
return null;
x instanceof String[])
return x;
// Remaining possibilities: array of primitive (e.g. int[]),
// enum, class, array of enum or class.
if (c.isArray()) {
if (c.getComponentType().isPrimitive())
return x;
return ss;
}
if (x instanceof Class<?>)
if (x instanceof Enum<?>)
// The only other possibility is that the value is another
// annotation, or that the language has evolved since this code
// was written. We don't allow for either of those currently.
// If it is indeed another annotation, then x will be a proxy
// with an unhelpful name like $Proxy2. So we extract the
// proxy's interface to use that in the exception message.
if (Proxy.isProxyClass(c))
throw new IllegalArgumentException("Illegal type for annotation " +
"element using @DescriptorKey: " + c.getName());
}
// This must be consistent with the check for duplicate field values in
// ImmutableDescriptor.union. But we don't expect to be called very
// often so this inefficient check should be enough.
}
/**
* Returns the XXMBean interface or null if no such interface exists
*
* @param c The interface to be tested
* @param clName The name of the class implementing this interface
*/
return c;
}
}
return null;
}
throws AttributeNotFoundException {
try {
} else if (complex instanceof CompositeData) {
} else {
// Java Beans introspection
//
throw new AttributeNotFoundException(
"Could not find the getter method for the property " +
element + " using the Java Beans introspector");
}
} catch (InvocationTargetException e) {
throw new IllegalArgumentException(e);
} catch (AttributeNotFoundException e) {
throw e;
} catch (Exception e) {
new AttributeNotFoundException(e.getMessage()), e);
}
}
}