📄 mbeanintrospector.java
字号:
/* * @(#)MBeanIntrospector.java 1.10 06/01/23 * * 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.ref.WeakReference;import java.lang.reflect.Array;import java.lang.reflect.Constructor;import java.lang.reflect.InvocationTargetException;import java.lang.reflect.Method;import java.lang.reflect.Type;import java.util.List;import java.util.WeakHashMap;import javax.management.Descriptor;import javax.management.ImmutableDescriptor;import javax.management.InvalidAttributeValueException;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.NotCompliantMBeanException;import javax.management.NotificationBroadcaster;import javax.management.ReflectionException;/** * An introspector for MBeans of a certain type. There is one instance * of this class for Standard MBeans and one for MXBeans, characterized * by the two concrete subclasses of this abstract class. * * @param <M> the representation of methods for this kind of MBean: * Method for Standard MBeans, ConvertingMethod for MXBeans. * * @since 1.6 *//* * Using a type parameter <M> allows us to deal with the fact that * Method and ConvertingMethod have no useful common ancestor, on * which we could call getName, getGenericReturnType, etc. A simpler approach * would be to wrap every Method in an object that does have a common * ancestor with ConvertingMethod. But that would mean an extra object * for every Method in every Standard MBean interface. */abstract class MBeanIntrospector<M> { static final class PerInterfaceMap<M> extends WeakHashMap<Class<?>, WeakReference<PerInterface<M>>> {} /** The map from interface to PerInterface for this type of MBean. */ abstract PerInterfaceMap<M> getPerInterfaceMap(); /** * The map from concrete implementation class and interface to * MBeanInfo for this type of MBean. */ abstract MBeanInfoMap getMBeanInfoMap(); /** Make an interface analyzer for this type of MBean. */ abstract MBeanAnalyzer<M> getAnalyzer(Class<?> mbeanInterface) throws NotCompliantMBeanException; /** True if MBeans with this kind of introspector are MXBeans. */ abstract boolean isMXBean(); /** Find the M corresponding to the given Method. */ abstract M mFrom(Method m); /** Get the name of this method. */ abstract String getName(M m); /** * Get the return type of this method. This is the return type * of a method in a Java interface, so for MXBeans it is the * declared Java type, not the mapped Open Type. */ abstract Type getGenericReturnType(M m); /** * Get the parameter types of this method in the Java interface * it came from. */ abstract Type[] getGenericParameterTypes(M m); /** * Get the signature of this method as a caller would have to supply * it in MBeanServer.invoke. For MXBeans, the named types will be * the mapped Open Types for the parameters. */ abstract String[] getSignature(M m); /** * Check that this method is valid. For example, a method in an * MXBean interface is not valid if one of its parameters cannot be * mapped to an Open Type. */ abstract void checkMethod(M m) throws IllegalArgumentException; /** * Invoke the method with the given target and arguments. * * @param cookie Additional information about the target. For an * MXBean, this is the MXBeanLookup associated with the MXBean. */ /* * It would be cleaner if the type of the cookie were a * type parameter to this class, but that would involve a lot of * messy type parameter propagation just to avoid a couple of casts. */ abstract Object invokeM2(M m, Object target, Object[] args, Object cookie) throws InvocationTargetException, IllegalAccessException, MBeanException; /** * Test whether the given value is valid for the given parameter of this * M. */ abstract boolean validParameter(M m, Object value, int paramNo, Object cookie); /** * Construct an MBeanAttributeInfo for the given attribute based on the * given getter and setter. One but not both of the getter and setter * may be null. */ abstract MBeanAttributeInfo getMBeanAttributeInfo(String attributeName, M getter, M setter); /** * Construct an MBeanOperationInfo for the given operation based on * the M it was derived from. */ abstract MBeanOperationInfo getMBeanOperationInfo(String operationName, M operation); /** * Get a Descriptor containing fields that MBeans of this kind will * always have. For example, MXBeans will always have "mxbean=true". */ abstract Descriptor getBasicMBeanDescriptor(); /** * Get a Descriptor containing additional fields beyond the ones * from getBasicMBeanDescriptor that MBeans whose concrete class * is resourceClass will always have. */ abstract Descriptor getMBeanDescriptor(Class<?> resourceClass); final PerInterface<M> getPerInterface(Class<?> mbeanInterface) throws NotCompliantMBeanException { PerInterfaceMap<M> map = getPerInterfaceMap(); synchronized (map) { WeakReference<PerInterface<M>> wr = map.get(mbeanInterface); PerInterface<M> pi = (wr == null) ? null : wr.get(); if (pi == null) { try { MBeanAnalyzer<M> analyzer = getAnalyzer(mbeanInterface); MBeanInfo mbeanInfo = makeInterfaceMBeanInfo(mbeanInterface, analyzer); pi = new PerInterface<M>(mbeanInterface, this, analyzer, mbeanInfo); wr = new WeakReference<PerInterface<M>>(pi); map.put(mbeanInterface, wr); } catch (Exception x) { throw Introspector.throwException(mbeanInterface,x); } } return pi; } } /** * Make the MBeanInfo skeleton for the given MBean interface using * the given analyzer. This will never be the MBeanInfo of any real * MBean (because the getClassName() must be a concrete class), but * its MBeanAttributeInfo[] and MBeanOperationInfo[] can be inserted * into such an MBeanInfo, and its Descriptor can be the basis for * the MBeanInfo's Descriptor. */ private MBeanInfo makeInterfaceMBeanInfo(Class<?> mbeanInterface, MBeanAnalyzer<M> analyzer) { final MBeanInfoMaker maker = new MBeanInfoMaker(); analyzer.visit(maker); final String description = "Information on the management interface of the MBean"; return maker.makeMBeanInfo(mbeanInterface, description); } /** True if the given getter and setter are consistent. */ final boolean consistent(M getter, M setter) { return (getter == null || setter == null || getGenericReturnType(getter).equals(getGenericParameterTypes(setter)[0])); } /** * Invoke the given M on the given target with the given args and cookie. * Wrap exceptions appropriately. */ final Object invokeM(M m, Object target, Object[] args, Object cookie) throws MBeanException, ReflectionException { try { return invokeM2(m, target, args, cookie); } catch (InvocationTargetException e) { unwrapInvocationTargetException(e); throw new RuntimeException(e); // not reached } catch (IllegalAccessException e) { throw new ReflectionException(e, e.toString()); } /* We do not catch and wrap RuntimeException or Error, * because we're in a DynamicMBean, so the logic for DynamicMBeans * will do the wrapping. */ } /**
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -