KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sun > jmx > mbeanserver > MXBeanIntrospector


1 /*
2  * @(#)MXBeanIntrospector.java 1.10 06/04/12
3  *
4  * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
5  * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
6  */

7
8 package com.sun.jmx.mbeanserver;
9
10 import java.lang.annotation.Annotation JavaDoc;
11 import java.lang.reflect.GenericArrayType JavaDoc;
12 import java.lang.reflect.InvocationTargetException JavaDoc;
13 import java.lang.reflect.Method JavaDoc;
14 import java.lang.reflect.Type JavaDoc;
15 import javax.management.Descriptor JavaDoc;
16 import javax.management.ImmutableDescriptor JavaDoc;
17 import javax.management.MBeanAttributeInfo JavaDoc;
18 import javax.management.MBeanException JavaDoc;
19 import javax.management.MBeanOperationInfo JavaDoc;
20 import javax.management.MBeanParameterInfo JavaDoc;
21 import javax.management.NotCompliantMBeanException JavaDoc;
22 import javax.management.openmbean.OpenMBeanAttributeInfoSupport JavaDoc;
23 import javax.management.openmbean.OpenMBeanOperationInfoSupport JavaDoc;
24 import javax.management.openmbean.OpenMBeanParameterInfo JavaDoc;
25 import javax.management.openmbean.OpenMBeanParameterInfoSupport JavaDoc;
26 import javax.management.openmbean.OpenType JavaDoc;
27
28 /**
29  * Introspector for MXBeans. There is exactly one instance of this class.
30  *
31  * @since 1.6
32  */

33 class MXBeanIntrospector extends MBeanIntrospector<ConvertingMethod> {
34     private static final MXBeanIntrospector instance = new MXBeanIntrospector();
35
36     static MXBeanIntrospector getInstance() {
37     return instance;
38     }
39
40     @Override JavaDoc
41     PerInterfaceMap<ConvertingMethod> getPerInterfaceMap() {
42     return perInterfaceMap;
43     }
44
45     @Override JavaDoc
46     MBeanInfoMap getMBeanInfoMap() {
47     return mbeanInfoMap;
48     }
49
50     @Override JavaDoc
51     MBeanAnalyzer<ConvertingMethod> getAnalyzer(Class JavaDoc<?> mbeanInterface)
52         throws NotCompliantMBeanException JavaDoc {
53     return MBeanAnalyzer.analyzer(mbeanInterface, this);
54     }
55
56     @Override JavaDoc
57     boolean isMXBean() {
58     return true;
59     }
60
61     @Override JavaDoc
62     ConvertingMethod mFrom(Method JavaDoc m) {
63     return ConvertingMethod.from(m);
64     }
65
66     @Override JavaDoc
67     String JavaDoc getName(ConvertingMethod m) {
68     return m.getName();
69     }
70
71     @Override JavaDoc
72     Type JavaDoc getGenericReturnType(ConvertingMethod m) {
73     return m.getGenericReturnType();
74     }
75
76     @Override JavaDoc
77     Type JavaDoc[] getGenericParameterTypes(ConvertingMethod m) {
78     return m.getGenericParameterTypes();
79     }
80
81     @Override JavaDoc
82     String JavaDoc[] getSignature(ConvertingMethod m) {
83     return m.getOpenSignature();
84     }
85
86     @Override JavaDoc
87     void checkMethod(ConvertingMethod m) {
88     m.checkCallFromOpen();
89     }
90
91     @Override JavaDoc
92     Object JavaDoc invokeM2(ConvertingMethod m, Object JavaDoc target, Object JavaDoc[] args,
93             Object JavaDoc cookie)
94         throws InvocationTargetException JavaDoc, IllegalAccessException JavaDoc,
95            MBeanException JavaDoc {
96     return m.invokeWithOpenReturn((MXBeanLookup) cookie, target, args);
97     }
98
99     @Override JavaDoc
100     boolean validParameter(ConvertingMethod m, Object JavaDoc value, int paramNo,
101                            Object JavaDoc cookie) {
102         if (value == null) {
103             // Null is a valid value for all OpenTypes, even though
104
// OpenType.isValue(null) will return false. It can always be
105
// matched to the corresponding Java type, except when that
106
// type is primitive.
107
Type JavaDoc t = m.getGenericParameterTypes()[paramNo];
108             return (!(t instanceof Class JavaDoc) || !((Class JavaDoc) t).isPrimitive());
109         } else {
110             Object JavaDoc v;
111             try {
112                 v = m.fromOpenParameter((MXBeanLookup) cookie, value, paramNo);
113             } catch (Exception JavaDoc e) {
114                 // Ignore the exception and let MBeanIntrospector.invokeSetter()
115
// throw the initial exception.
116
return true;
117             }
118             return isValidParameter(m.getMethod(), v, paramNo);
119         }
120     }
121
122     @Override JavaDoc
123     MBeanAttributeInfo JavaDoc getMBeanAttributeInfo(String JavaDoc attributeName,
124             ConvertingMethod getter, ConvertingMethod setter) {
125
126         final boolean isReadable = (getter != null);
127         final boolean isWritable = (setter != null);
128         final boolean isIs = isReadable && getName(getter).startsWith("is");
129
130         final String JavaDoc description = attributeName;
131         
132         final OpenType JavaDoc<?> openType;
133         final Type JavaDoc originalType;
134         if (isReadable) {
135             openType = getter.getOpenReturnType();
136             originalType = getter.getGenericReturnType();
137         } else {
138             openType = setter.getOpenParameterTypes()[0];
139             originalType = setter.getGenericParameterTypes()[0];
140         }
141         Descriptor JavaDoc descriptor = typeDescriptor(openType, originalType);
142         if (isReadable) {
143             descriptor = ImmutableDescriptor.union(descriptor,
144                     getter.getDescriptor());
145         }
146         if (isWritable) {
147             descriptor = ImmutableDescriptor.union(descriptor,
148                     setter.getDescriptor());
149         }
150
151         final MBeanAttributeInfo JavaDoc ai;
152         if (canUseOpenInfo(originalType)) {
153             ai = new OpenMBeanAttributeInfoSupport JavaDoc(attributeName,
154                                                    description,
155                                                    openType,
156                                                    isReadable,
157                                                    isWritable,
158                                                    isIs,
159                                                    descriptor);
160         } else {
161             ai = new MBeanAttributeInfo JavaDoc(attributeName,
162                                         originalTypeString(originalType),
163                                         description,
164                                         isReadable,
165                                         isWritable,
166                                         isIs,
167                                         descriptor);
168         }
169         // could also consult annotations for defaultValue,
170
// minValue, maxValue, legalValues
171

172         return ai;
173     }
174
175     @Override JavaDoc
176     MBeanOperationInfo JavaDoc getMBeanOperationInfo(String JavaDoc operationName,
177             ConvertingMethod operation) {
178         final Method JavaDoc method = operation.getMethod();
179         final String JavaDoc description = operationName;
180         /* Ideally this would be an empty string, but
181            OMBOperationInfo constructor forbids that. Also, we
182            could consult an annotation to get a useful
183            description. */

184
185         final int impact = MBeanOperationInfo.UNKNOWN;
186
187         final OpenType JavaDoc<?> returnType = operation.getOpenReturnType();
188         final Type JavaDoc originalReturnType = operation.getGenericReturnType();
189         final OpenType JavaDoc<?>[] paramTypes = operation.getOpenParameterTypes();
190         final Type JavaDoc[] originalParamTypes = operation.getGenericParameterTypes();
191         final MBeanParameterInfo JavaDoc[] params =
192             new MBeanParameterInfo JavaDoc[paramTypes.length];
193         boolean openReturnType = canUseOpenInfo(originalReturnType);
194         boolean openParameterTypes = true;
195         Annotation JavaDoc[][] annots = method.getParameterAnnotations();
196         for (int i = 0; i < paramTypes.length; i++) {
197             final String JavaDoc paramName = "p" + i;
198             final String JavaDoc paramDescription = paramName;
199             final OpenType JavaDoc<?> openType = paramTypes[i];
200             final Type JavaDoc originalType = originalParamTypes[i];
201             Descriptor JavaDoc descriptor =
202                 typeDescriptor(openType, originalType);
203             descriptor = ImmutableDescriptor.union(descriptor,
204                     Introspector.descriptorForAnnotations(annots[i]));
205             final MBeanParameterInfo JavaDoc pi;
206             if (canUseOpenInfo(originalType)) {
207                 pi = new OpenMBeanParameterInfoSupport JavaDoc("p" + i,
208                                                        paramDescription,
209                                                        openType,
210                                                        descriptor);
211             } else {
212                 openParameterTypes = false;
213                 pi = new MBeanParameterInfo JavaDoc(
214                     "p" + i,
215                     originalTypeString(originalType),
216                     paramDescription,
217                     descriptor);
218             }
219             params[i] = pi;
220         }
221
222         Descriptor JavaDoc descriptor =
223             typeDescriptor(returnType, originalReturnType);
224         descriptor = ImmutableDescriptor.union(descriptor,
225                 Introspector.descriptorForElement(method));
226         final MBeanOperationInfo JavaDoc oi;
227         if (openReturnType && openParameterTypes) {
228             /* If the return value and all the parameters can be faithfully
229              * represented as OpenType then we return an OpenMBeanOperationInfo.
230              * If any of them is a primitive type, we can't. Compatibility
231              * with JSR 174 means that we must return an MBean*Info where
232              * the getType() is the primitive type, not its wrapped type as
233              * we would get with an OpenMBean*Info. The OpenType is available
234              * in the Descriptor in either case.
235              */

236             final OpenMBeanParameterInfo JavaDoc[] oparams =
237                 new OpenMBeanParameterInfo JavaDoc[params.length];
238             System.arraycopy(params, 0, oparams, 0, params.length);
239             oi = new OpenMBeanOperationInfoSupport JavaDoc(operationName,
240                                                    description,
241                                                    oparams,
242                                                    returnType,
243                                                    impact,
244                                                    descriptor);
245         } else {
246             oi = new MBeanOperationInfo JavaDoc(operationName,
247                                         description,
248                                         params,
249                                         openReturnType ?
250                                         returnType.getClassName() :
251                                         originalTypeString(originalReturnType),
252                                         impact,
253                                         descriptor);
254         }
255         
256         return oi;
257     }
258
259     @Override JavaDoc
260     Descriptor JavaDoc getBasicMBeanDescriptor() {
261     return new ImmutableDescriptor JavaDoc("mxbean=true",
262                        "immutableInfo=true");
263     }
264
265     @Override JavaDoc
266     Descriptor JavaDoc getMBeanDescriptor(Class JavaDoc<?> resourceClass) {
267     /* We already have immutableInfo=true in the Descriptor
268      * included in the MBeanInfo for the MXBean interface. This
269      * method is being called for the MXBean *class* to add any
270      * new items beyond those in the interface Descriptor, which
271      * currently it does not.
272      */

273     return ImmutableDescriptor.EMPTY_DESCRIPTOR;
274     }
275
276     private static Descriptor JavaDoc typeDescriptor(OpenType JavaDoc openType,
277                                              Type JavaDoc originalType) {
278         return new ImmutableDescriptor JavaDoc(
279             new String JavaDoc[] {"openType",
280                           "originalType"},
281             new Object JavaDoc[] {openType,
282                           originalTypeString(originalType)});
283     }
284
285     /**
286      * <p>True if this type can be faithfully represented in an
287      * OpenMBean*Info.</p>
288      *
289      * <p>Compatibility with JSR 174 means that primitive types must be
290      * represented by an MBean*Info whose getType() is the primitive type
291      * string, e.g. "int". If we used an OpenMBean*Info then this string
292      * would be the wrapped type, e.g. "java.lang.Integer".</p>
293      *
294      * <p>Compatibility with JMX 1.2 (including J2SE 5.0) means that arrays
295      * of primitive types cannot use an ArrayType representing an array of
296      * primitives, because that didn't exist in JMX 1.2.</p>
297      */

298     private static boolean canUseOpenInfo(Type JavaDoc type) {
299         if (type instanceof GenericArrayType JavaDoc) {
300             return canUseOpenInfo(
301                 ((GenericArrayType JavaDoc) type).getGenericComponentType());
302         } else if (type instanceof Class JavaDoc && ((Class JavaDoc<?>) type).isArray()) {
303             return canUseOpenInfo(
304                 ((Class JavaDoc<?>) type).getComponentType());
305         }
306         return (!(type instanceof Class JavaDoc && ((Class JavaDoc<?>) type).isPrimitive()));
307     }
308
309     private static String JavaDoc originalTypeString(Type JavaDoc type) {
310         if (type instanceof Class JavaDoc)
311             return ((Class JavaDoc) type).getName();
312         else
313             return type.toString();
314     }
315
316     private static final PerInterfaceMap<ConvertingMethod>
317         perInterfaceMap = new PerInterfaceMap<ConvertingMethod>();
318
319     private static final MBeanInfoMap mbeanInfoMap = new MBeanInfoMap();
320 }
321
Popular Tags