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; |
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"}, |