jdk/src/share/classes/com/sun/jmx/mbeanserver/MXBeanIntrospector.java
changeset 4156 acaa49a2768a
parent 1699 3611e5fd6da5
child 5506 202f599c92aa
equal deleted inserted replaced
4155:460e37d40f12 4156:acaa49a2768a
    26 package com.sun.jmx.mbeanserver;
    26 package com.sun.jmx.mbeanserver;
    27 
    27 
    28 import com.sun.jmx.mbeanserver.MBeanIntrospector.MBeanInfoMap;
    28 import com.sun.jmx.mbeanserver.MBeanIntrospector.MBeanInfoMap;
    29 import com.sun.jmx.mbeanserver.MBeanIntrospector.PerInterfaceMap;
    29 import com.sun.jmx.mbeanserver.MBeanIntrospector.PerInterfaceMap;
    30 import java.lang.annotation.Annotation;
    30 import java.lang.annotation.Annotation;
    31 import java.lang.ref.WeakReference;
       
    32 import java.lang.reflect.GenericArrayType;
    31 import java.lang.reflect.GenericArrayType;
    33 import java.lang.reflect.InvocationTargetException;
    32 import java.lang.reflect.InvocationTargetException;
    34 import java.lang.reflect.Method;
    33 import java.lang.reflect.Method;
    35 import java.lang.reflect.ParameterizedType;
    34 import java.lang.reflect.ParameterizedType;
    36 import java.lang.reflect.Type;
    35 import java.lang.reflect.Type;
    37 import java.util.Map;
       
    38 import java.util.WeakHashMap;
       
    39 import javax.management.Description;
       
    40 import javax.management.Descriptor;
    36 import javax.management.Descriptor;
    41 import javax.management.ImmutableDescriptor;
    37 import javax.management.ImmutableDescriptor;
    42 import javax.management.IntrospectionException;
       
    43 import javax.management.JMX;
       
    44 import javax.management.MBeanAttributeInfo;
    38 import javax.management.MBeanAttributeInfo;
    45 import javax.management.MBeanException;
    39 import javax.management.MBeanException;
    46 import javax.management.MBeanOperationInfo;
    40 import javax.management.MBeanOperationInfo;
    47 import javax.management.MBeanParameterInfo;
    41 import javax.management.MBeanParameterInfo;
    48 import javax.management.ManagedOperation;
       
    49 import javax.management.NotCompliantMBeanException;
    42 import javax.management.NotCompliantMBeanException;
    50 import javax.management.openmbean.MXBeanMappingFactory;
       
    51 import javax.management.openmbean.OpenMBeanAttributeInfoSupport;
    43 import javax.management.openmbean.OpenMBeanAttributeInfoSupport;
    52 import javax.management.openmbean.OpenMBeanOperationInfoSupport;
    44 import javax.management.openmbean.OpenMBeanOperationInfoSupport;
    53 import javax.management.openmbean.OpenMBeanParameterInfo;
    45 import javax.management.openmbean.OpenMBeanParameterInfo;
    54 import javax.management.openmbean.OpenMBeanParameterInfoSupport;
    46 import javax.management.openmbean.OpenMBeanParameterInfoSupport;
    55 import javax.management.openmbean.OpenType;
    47 import javax.management.openmbean.OpenType;
    58  * Introspector for MXBeans.  There is exactly one instance of this class.
    50  * Introspector for MXBeans.  There is exactly one instance of this class.
    59  *
    51  *
    60  * @since 1.6
    52  * @since 1.6
    61  */
    53  */
    62 class MXBeanIntrospector extends MBeanIntrospector<ConvertingMethod> {
    54 class MXBeanIntrospector extends MBeanIntrospector<ConvertingMethod> {
    63     /* We keep one MXBeanIntrospector per MXBeanMappingFactory, since the results
    55     private static final MXBeanIntrospector instance = new MXBeanIntrospector();
    64      * of the introspection depend on the factory.  The MXBeanIntrospector
    56 
    65      * has a reference back to the factory, so we wrap it in a WeakReference.
    57     static MXBeanIntrospector getInstance() {
    66      * It will be strongly referenced by any MXBeanSupport instances using it;
    58         return instance;
    67      * if there are none then it is OK to gc it.
       
    68      */
       
    69     private static final
       
    70             Map<MXBeanMappingFactory, WeakReference<MXBeanIntrospector>> map =
       
    71             new WeakHashMap<MXBeanMappingFactory, WeakReference<MXBeanIntrospector>>();
       
    72 
       
    73     static MXBeanIntrospector getInstance(MXBeanMappingFactory factory) {
       
    74         if (factory == null)
       
    75             factory = MXBeanMappingFactory.DEFAULT;
       
    76         synchronized (map) {
       
    77             MXBeanIntrospector intro;
       
    78             WeakReference<MXBeanIntrospector> wr = map.get(factory);
       
    79             if (wr != null) {
       
    80                 intro = wr.get();
       
    81                 if (intro != null)
       
    82                     return intro;
       
    83             }
       
    84             intro = new MXBeanIntrospector(factory);
       
    85             wr = new WeakReference<MXBeanIntrospector>(intro);
       
    86             map.put(factory, wr);
       
    87             return intro;
       
    88         }
       
    89     }
       
    90 
       
    91     private MXBeanIntrospector(MXBeanMappingFactory factory) {
       
    92         this.mappingFactory = factory;
       
    93     }
    59     }
    94 
    60 
    95     @Override
    61     @Override
    96     PerInterfaceMap<ConvertingMethod> getPerInterfaceMap() {
    62     PerInterfaceMap<ConvertingMethod> getPerInterfaceMap() {
    97         return perInterfaceMap;
    63         return perInterfaceMap;
   113         return true;
    79         return true;
   114     }
    80     }
   115 
    81 
   116     @Override
    82     @Override
   117     ConvertingMethod mFrom(Method m) {
    83     ConvertingMethod mFrom(Method m) {
   118         return ConvertingMethod.from(m, mappingFactory);
    84         return ConvertingMethod.from(m);
   119     }
    85     }
   120 
    86 
   121     @Override
    87     @Override
   122     String getName(ConvertingMethod m) {
    88     String getName(ConvertingMethod m) {
   123         return m.getName();
    89         return m.getName();
   174         }
   140         }
   175     }
   141     }
   176 
   142 
   177     @Override
   143     @Override
   178     MBeanAttributeInfo getMBeanAttributeInfo(String attributeName,
   144     MBeanAttributeInfo getMBeanAttributeInfo(String attributeName,
   179             ConvertingMethod getter, ConvertingMethod setter)
   145             ConvertingMethod getter, ConvertingMethod setter) {
   180             throws IntrospectionException {
       
   181 
   146 
   182         final boolean isReadable = (getter != null);
   147         final boolean isReadable = (getter != null);
   183         final boolean isWritable = (setter != null);
   148         final boolean isWritable = (setter != null);
   184         final boolean isIs = isReadable && getName(getter).startsWith("is");
   149         final boolean isIs = isReadable && getName(getter).startsWith("is");
   185 
   150 
   186         final String description = getAttributeDescription(
   151         final String description = attributeName;
   187                 attributeName, attributeName,
       
   188                 getter == null ? null : getter.getMethod(),
       
   189                 setter == null ? null : setter.getMethod());
       
   190 
   152 
   191         final OpenType<?> openType;
   153         final OpenType<?> openType;
   192         final Type originalType;
   154         final Type originalType;
   193         if (isReadable) {
   155         if (isReadable) {
   194             openType = getter.getOpenReturnType();
   156             openType = getter.getOpenReturnType();
   233 
   195 
   234     @Override
   196     @Override
   235     MBeanOperationInfo getMBeanOperationInfo(String operationName,
   197     MBeanOperationInfo getMBeanOperationInfo(String operationName,
   236             ConvertingMethod operation) {
   198             ConvertingMethod operation) {
   237         final Method method = operation.getMethod();
   199         final Method method = operation.getMethod();
   238         String description = operationName;
   200         final String description = operationName;
   239         /* Ideally this would be an empty string, but
   201         /* Ideally this would be an empty string, but
   240            OMBOperationInfo constructor forbids that.  */
   202            OMBOperationInfo constructor forbids that.  Also, we
   241         Description d = method.getAnnotation(Description.class);
   203            could consult an annotation to get a useful
   242         if (d != null)
   204            description.  */
   243             description = d.value();
   205 
   244 
   206         final int impact = MBeanOperationInfo.UNKNOWN;
   245         int impact = MBeanOperationInfo.UNKNOWN;
       
   246         ManagedOperation annot = method.getAnnotation(ManagedOperation.class);
       
   247         if (annot != null)
       
   248             impact = annot.impact().getCode();
       
   249 
   207 
   250         final OpenType<?> returnType = operation.getOpenReturnType();
   208         final OpenType<?> returnType = operation.getOpenReturnType();
   251         final Type originalReturnType = operation.getGenericReturnType();
   209         final Type originalReturnType = operation.getGenericReturnType();
   252         final OpenType<?>[] paramTypes = operation.getOpenParameterTypes();
   210         final OpenType<?>[] paramTypes = operation.getOpenParameterTypes();
   253         final Type[] originalParamTypes = operation.getGenericParameterTypes();
   211         final Type[] originalParamTypes = operation.getGenericParameterTypes();
   255             new MBeanParameterInfo[paramTypes.length];
   213             new MBeanParameterInfo[paramTypes.length];
   256         boolean openReturnType = canUseOpenInfo(originalReturnType);
   214         boolean openReturnType = canUseOpenInfo(originalReturnType);
   257         boolean openParameterTypes = true;
   215         boolean openParameterTypes = true;
   258         Annotation[][] annots = method.getParameterAnnotations();
   216         Annotation[][] annots = method.getParameterAnnotations();
   259         for (int i = 0; i < paramTypes.length; i++) {
   217         for (int i = 0; i < paramTypes.length; i++) {
   260             String paramName = Introspector.nameForParameter(annots[i]);
   218             final String paramName = "p" + i;
   261             if (paramName == null)
   219             final String paramDescription = paramName;
   262                 paramName = "p" + i;
       
   263 
       
   264             String paramDescription =
       
   265                     Introspector.descriptionForParameter(annots[i]);
       
   266             if (paramDescription == null)
       
   267                 paramDescription = paramName;
       
   268 
       
   269             final OpenType<?> openType = paramTypes[i];
   220             final OpenType<?> openType = paramTypes[i];
   270             final Type originalType = originalParamTypes[i];
   221             final Type originalType = originalParamTypes[i];
   271             Descriptor descriptor =
   222             Descriptor descriptor =
   272                 typeDescriptor(openType, originalType);
   223                 typeDescriptor(openType, originalType);
   273             descriptor = ImmutableDescriptor.union(descriptor,
   224             descriptor = ImmutableDescriptor.union(descriptor,
   290         }
   241         }
   291 
   242 
   292         Descriptor descriptor =
   243         Descriptor descriptor =
   293             typeDescriptor(returnType, originalReturnType);
   244             typeDescriptor(returnType, originalReturnType);
   294         descriptor = ImmutableDescriptor.union(descriptor,
   245         descriptor = ImmutableDescriptor.union(descriptor,
   295                 Introspector.descriptorForElement(method, false));
   246                 Introspector.descriptorForElement(method));
   296         final MBeanOperationInfo oi;
   247         final MBeanOperationInfo oi;
   297         if (openReturnType && openParameterTypes) {
   248         if (openReturnType && openParameterTypes) {
   298             /* If the return value and all the parameters can be faithfully
   249             /* If the return value and all the parameters can be faithfully
   299              * represented as OpenType then we return an OpenMBeanOperationInfo.
   250              * represented as OpenType then we return an OpenMBeanOperationInfo.
   300              * If any of them is a primitive type, we can't.  Compatibility
   251              * If any of them is a primitive type, we can't.  Compatibility
   341          * currently it does not.
   292          * currently it does not.
   342          */
   293          */
   343         return ImmutableDescriptor.EMPTY_DESCRIPTOR;
   294         return ImmutableDescriptor.EMPTY_DESCRIPTOR;
   344     }
   295     }
   345 
   296 
   346     @Override
       
   347     Descriptor getSpecificMBeanDescriptor() {
       
   348         if (mappingFactory == MXBeanMappingFactory.DEFAULT)
       
   349             return ImmutableDescriptor.EMPTY_DESCRIPTOR;
       
   350         else {
       
   351             return new ImmutableDescriptor(
       
   352                     JMX.MXBEAN_MAPPING_FACTORY_CLASS_FIELD + "=" +
       
   353                     mappingFactory.getClass().getName());
       
   354         }
       
   355     }
       
   356 
       
   357     private static Descriptor typeDescriptor(OpenType<?> openType,
   297     private static Descriptor typeDescriptor(OpenType<?> openType,
   358                                              Type originalType) {
   298                                              Type originalType) {
   359         return new ImmutableDescriptor(
   299         return new ImmutableDescriptor(
   360             new String[] {"openType",
   300             new String[] {"openType",
   361                           "originalType"},
   301                           "originalType"},
   419     }
   359     }
   420 
   360 
   421     private final PerInterfaceMap<ConvertingMethod>
   361     private final PerInterfaceMap<ConvertingMethod>
   422         perInterfaceMap = new PerInterfaceMap<ConvertingMethod>();
   362         perInterfaceMap = new PerInterfaceMap<ConvertingMethod>();
   423 
   363 
   424     private final MBeanInfoMap mbeanInfoMap = new MBeanInfoMap();
   364     private static final MBeanInfoMap mbeanInfoMap = new MBeanInfoMap();
   425 
       
   426     private final MXBeanMappingFactory mappingFactory;
       
   427 }
   365 }