author | emcmanus |
Thu, 27 Nov 2008 15:44:32 +0100 | |
changeset 1636 | eb801ce73ac9 |
parent 1627 | aec3a9aa6901 |
child 1697 | 98a530cd0594 |
permissions | -rw-r--r-- |
2 | 1 |
/* |
715 | 2 |
* Copyright 2005-2008 Sun Microsystems, Inc. All Rights Reserved. |
2 | 3 |
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 |
* |
|
5 |
* This code is free software; you can redistribute it and/or modify it |
|
6 |
* under the terms of the GNU General Public License version 2 only, as |
|
7 |
* published by the Free Software Foundation. Sun designates this |
|
8 |
* particular file as subject to the "Classpath" exception as provided |
|
9 |
* by Sun in the LICENSE file that accompanied this code. |
|
10 |
* |
|
11 |
* This code is distributed in the hope that it will be useful, but WITHOUT |
|
12 |
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
|
13 |
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
|
14 |
* version 2 for more details (a copy is included in the LICENSE file that |
|
15 |
* accompanied this code). |
|
16 |
* |
|
17 |
* You should have received a copy of the GNU General Public License version |
|
18 |
* 2 along with this work; if not, write to the Free Software Foundation, |
|
19 |
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
|
20 |
* |
|
21 |
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, |
|
22 |
* CA 95054 USA or visit www.sun.com if you need additional information or |
|
23 |
* have any questions. |
|
24 |
*/ |
|
25 |
||
26 |
package com.sun.jmx.mbeanserver; |
|
27 |
||
28 |
||
29 |
import static com.sun.jmx.mbeanserver.Util.*; |
|
30 |
||
31 |
import java.lang.ref.WeakReference; |
|
32 |
import java.lang.reflect.Array; |
|
33 |
import java.lang.reflect.Constructor; |
|
34 |
import java.lang.reflect.InvocationTargetException; |
|
35 |
import java.lang.reflect.Method; |
|
36 |
import java.lang.reflect.Type; |
|
287 | 37 |
import java.util.Arrays; |
2 | 38 |
import java.util.List; |
833
bfa2bef7517c
6323980: Annotations to simplify MBean development
emcmanus
parents:
687
diff
changeset
|
39 |
import java.util.Map; |
2 | 40 |
import java.util.WeakHashMap; |
833
bfa2bef7517c
6323980: Annotations to simplify MBean development
emcmanus
parents:
687
diff
changeset
|
41 |
import javax.management.Description; |
2 | 42 |
|
43 |
import javax.management.Descriptor; |
|
44 |
import javax.management.ImmutableDescriptor; |
|
687 | 45 |
import javax.management.IntrospectionException; |
2 | 46 |
import javax.management.InvalidAttributeValueException; |
1627
aec3a9aa6901
6772779: @NotificationInfo does not create MBeanNotificationInfo in the MBean's MBeanInfo
emcmanus
parents:
1221
diff
changeset
|
47 |
import javax.management.JMX; |
833
bfa2bef7517c
6323980: Annotations to simplify MBean development
emcmanus
parents:
687
diff
changeset
|
48 |
import javax.management.MBean; |
2 | 49 |
import javax.management.MBeanAttributeInfo; |
50 |
import javax.management.MBeanConstructorInfo; |
|
51 |
import javax.management.MBeanException; |
|
52 |
import javax.management.MBeanInfo; |
|
53 |
import javax.management.MBeanNotificationInfo; |
|
54 |
import javax.management.MBeanOperationInfo; |
|
833
bfa2bef7517c
6323980: Annotations to simplify MBean development
emcmanus
parents:
687
diff
changeset
|
55 |
import javax.management.MXBean; |
bfa2bef7517c
6323980: Annotations to simplify MBean development
emcmanus
parents:
687
diff
changeset
|
56 |
import javax.management.ManagedAttribute; |
bfa2bef7517c
6323980: Annotations to simplify MBean development
emcmanus
parents:
687
diff
changeset
|
57 |
import javax.management.ManagedOperation; |
2 | 58 |
import javax.management.NotCompliantMBeanException; |
59 |
import javax.management.NotificationBroadcaster; |
|
833
bfa2bef7517c
6323980: Annotations to simplify MBean development
emcmanus
parents:
687
diff
changeset
|
60 |
import javax.management.NotificationInfo; |
bfa2bef7517c
6323980: Annotations to simplify MBean development
emcmanus
parents:
687
diff
changeset
|
61 |
import javax.management.NotificationInfos; |
2 | 62 |
import javax.management.ReflectionException; |
63 |
||
64 |
/** |
|
65 |
* An introspector for MBeans of a certain type. There is one instance |
|
687 | 66 |
* of this class for Standard MBeans, and one for every MXBeanMappingFactory; |
67 |
* these two cases correspond to the two concrete subclasses of this abstract |
|
68 |
* class. |
|
2 | 69 |
* |
70 |
* @param <M> the representation of methods for this kind of MBean: |
|
71 |
* Method for Standard MBeans, ConvertingMethod for MXBeans. |
|
72 |
* |
|
73 |
* @since 1.6 |
|
74 |
*/ |
|
75 |
/* |
|
76 |
* Using a type parameter <M> allows us to deal with the fact that |
|
77 |
* Method and ConvertingMethod have no useful common ancestor, on |
|
78 |
* which we could call getName, getGenericReturnType, etc. A simpler approach |
|
79 |
* would be to wrap every Method in an object that does have a common |
|
80 |
* ancestor with ConvertingMethod. But that would mean an extra object |
|
81 |
* for every Method in every Standard MBean interface. |
|
82 |
*/ |
|
1636
eb801ce73ac9
6776225: JMX.isNotificationSource wrong when DynamicWrapperMBean + SendNotification injection
emcmanus
parents:
1627
diff
changeset
|
83 |
public abstract class MBeanIntrospector<M> { |
2 | 84 |
static final class PerInterfaceMap<M> |
85 |
extends WeakHashMap<Class<?>, WeakReference<PerInterface<M>>> {} |
|
86 |
||
87 |
/** The map from interface to PerInterface for this type of MBean. */ |
|
88 |
abstract PerInterfaceMap<M> getPerInterfaceMap(); |
|
89 |
/** |
|
90 |
* The map from concrete implementation class and interface to |
|
91 |
* MBeanInfo for this type of MBean. |
|
92 |
*/ |
|
93 |
abstract MBeanInfoMap getMBeanInfoMap(); |
|
94 |
||
95 |
/** Make an interface analyzer for this type of MBean. */ |
|
96 |
abstract MBeanAnalyzer<M> getAnalyzer(Class<?> mbeanInterface) |
|
97 |
throws NotCompliantMBeanException; |
|
98 |
||
99 |
/** True if MBeans with this kind of introspector are MXBeans. */ |
|
100 |
abstract boolean isMXBean(); |
|
101 |
||
102 |
/** Find the M corresponding to the given Method. */ |
|
103 |
abstract M mFrom(Method m); |
|
104 |
||
105 |
/** Get the name of this method. */ |
|
106 |
abstract String getName(M m); |
|
107 |
||
108 |
/** |
|
109 |
* Get the return type of this method. This is the return type |
|
110 |
* of a method in a Java interface, so for MXBeans it is the |
|
111 |
* declared Java type, not the mapped Open Type. |
|
112 |
*/ |
|
113 |
abstract Type getGenericReturnType(M m); |
|
114 |
||
115 |
/** |
|
116 |
* Get the parameter types of this method in the Java interface |
|
117 |
* it came from. |
|
118 |
*/ |
|
119 |
abstract Type[] getGenericParameterTypes(M m); |
|
120 |
||
121 |
/** |
|
122 |
* Get the signature of this method as a caller would have to supply |
|
123 |
* it in MBeanServer.invoke. For MXBeans, the named types will be |
|
124 |
* the mapped Open Types for the parameters. |
|
125 |
*/ |
|
126 |
abstract String[] getSignature(M m); |
|
127 |
||
128 |
/** |
|
129 |
* Check that this method is valid. For example, a method in an |
|
130 |
* MXBean interface is not valid if one of its parameters cannot be |
|
131 |
* mapped to an Open Type. |
|
132 |
*/ |
|
687 | 133 |
abstract void checkMethod(M m); |
2 | 134 |
|
135 |
/** |
|
136 |
* Invoke the method with the given target and arguments. |
|
137 |
* |
|
138 |
* @param cookie Additional information about the target. For an |
|
139 |
* MXBean, this is the MXBeanLookup associated with the MXBean. |
|
140 |
*/ |
|
141 |
/* |
|
142 |
* It would be cleaner if the type of the cookie were a |
|
143 |
* type parameter to this class, but that would involve a lot of |
|
144 |
* messy type parameter propagation just to avoid a couple of casts. |
|
145 |
*/ |
|
146 |
abstract Object invokeM2(M m, Object target, Object[] args, Object cookie) |
|
147 |
throws InvocationTargetException, IllegalAccessException, |
|
148 |
MBeanException; |
|
149 |
||
150 |
/** |
|
151 |
* Test whether the given value is valid for the given parameter of this |
|
152 |
* M. |
|
153 |
*/ |
|
154 |
abstract boolean validParameter(M m, Object value, int paramNo, |
|
155 |
Object cookie); |
|
156 |
||
157 |
/** |
|
158 |
* Construct an MBeanAttributeInfo for the given attribute based on the |
|
159 |
* given getter and setter. One but not both of the getter and setter |
|
160 |
* may be null. |
|
161 |
*/ |
|
162 |
abstract MBeanAttributeInfo getMBeanAttributeInfo(String attributeName, |
|
687 | 163 |
M getter, M setter) throws IntrospectionException; |
164 |
||
833
bfa2bef7517c
6323980: Annotations to simplify MBean development
emcmanus
parents:
687
diff
changeset
|
165 |
final String getAttributeDescription( |
bfa2bef7517c
6323980: Annotations to simplify MBean development
emcmanus
parents:
687
diff
changeset
|
166 |
String attributeName, String defaultDescription, |
bfa2bef7517c
6323980: Annotations to simplify MBean development
emcmanus
parents:
687
diff
changeset
|
167 |
Method getter, Method setter) throws IntrospectionException { |
bfa2bef7517c
6323980: Annotations to simplify MBean development
emcmanus
parents:
687
diff
changeset
|
168 |
String g = Introspector.descriptionForElement(getter); |
bfa2bef7517c
6323980: Annotations to simplify MBean development
emcmanus
parents:
687
diff
changeset
|
169 |
String s = Introspector.descriptionForElement(setter); |
bfa2bef7517c
6323980: Annotations to simplify MBean development
emcmanus
parents:
687
diff
changeset
|
170 |
if (g == null) { |
bfa2bef7517c
6323980: Annotations to simplify MBean development
emcmanus
parents:
687
diff
changeset
|
171 |
if (s == null) |
bfa2bef7517c
6323980: Annotations to simplify MBean development
emcmanus
parents:
687
diff
changeset
|
172 |
return defaultDescription; |
bfa2bef7517c
6323980: Annotations to simplify MBean development
emcmanus
parents:
687
diff
changeset
|
173 |
else |
bfa2bef7517c
6323980: Annotations to simplify MBean development
emcmanus
parents:
687
diff
changeset
|
174 |
return s; |
bfa2bef7517c
6323980: Annotations to simplify MBean development
emcmanus
parents:
687
diff
changeset
|
175 |
} else if (s == null || g.equals(s)) { |
bfa2bef7517c
6323980: Annotations to simplify MBean development
emcmanus
parents:
687
diff
changeset
|
176 |
return g; |
bfa2bef7517c
6323980: Annotations to simplify MBean development
emcmanus
parents:
687
diff
changeset
|
177 |
} else { |
bfa2bef7517c
6323980: Annotations to simplify MBean development
emcmanus
parents:
687
diff
changeset
|
178 |
throw new IntrospectionException( |
bfa2bef7517c
6323980: Annotations to simplify MBean development
emcmanus
parents:
687
diff
changeset
|
179 |
"Inconsistent @Description on getter and setter for " + |
bfa2bef7517c
6323980: Annotations to simplify MBean development
emcmanus
parents:
687
diff
changeset
|
180 |
"attribute " + attributeName); |
bfa2bef7517c
6323980: Annotations to simplify MBean development
emcmanus
parents:
687
diff
changeset
|
181 |
} |
bfa2bef7517c
6323980: Annotations to simplify MBean development
emcmanus
parents:
687
diff
changeset
|
182 |
} |
bfa2bef7517c
6323980: Annotations to simplify MBean development
emcmanus
parents:
687
diff
changeset
|
183 |
|
2 | 184 |
/** |
185 |
* Construct an MBeanOperationInfo for the given operation based on |
|
186 |
* the M it was derived from. |
|
187 |
*/ |
|
188 |
abstract MBeanOperationInfo getMBeanOperationInfo(String operationName, |
|
189 |
M operation); |
|
190 |
||
191 |
/** |
|
192 |
* Get a Descriptor containing fields that MBeans of this kind will |
|
193 |
* always have. For example, MXBeans will always have "mxbean=true". |
|
194 |
*/ |
|
195 |
abstract Descriptor getBasicMBeanDescriptor(); |
|
196 |
||
197 |
/** |
|
198 |
* Get a Descriptor containing additional fields beyond the ones |
|
199 |
* from getBasicMBeanDescriptor that MBeans whose concrete class |
|
200 |
* is resourceClass will always have. |
|
201 |
*/ |
|
202 |
abstract Descriptor getMBeanDescriptor(Class<?> resourceClass); |
|
203 |
||
687 | 204 |
/** |
205 |
* Get any additional Descriptor entries for this introspector instance. |
|
206 |
* If there is a non-default MXBeanMappingFactory, it will appear in |
|
207 |
* this Descriptor. |
|
208 |
* @return Additional Descriptor entries, or an empty Descriptor if none. |
|
209 |
*/ |
|
210 |
Descriptor getSpecificMBeanDescriptor() { |
|
211 |
return ImmutableDescriptor.EMPTY_DESCRIPTOR; |
|
212 |
} |
|
213 |
||
287 | 214 |
void checkCompliance(Class<?> mbeanType) throws NotCompliantMBeanException { |
833
bfa2bef7517c
6323980: Annotations to simplify MBean development
emcmanus
parents:
687
diff
changeset
|
215 |
if (!mbeanType.isInterface() && |
bfa2bef7517c
6323980: Annotations to simplify MBean development
emcmanus
parents:
687
diff
changeset
|
216 |
!mbeanType.isAnnotationPresent(MBean.class) && |
bfa2bef7517c
6323980: Annotations to simplify MBean development
emcmanus
parents:
687
diff
changeset
|
217 |
!Introspector.hasMXBeanAnnotation(mbeanType)) { |
bfa2bef7517c
6323980: Annotations to simplify MBean development
emcmanus
parents:
687
diff
changeset
|
218 |
throw new NotCompliantMBeanException("Not an interface and " + |
bfa2bef7517c
6323980: Annotations to simplify MBean development
emcmanus
parents:
687
diff
changeset
|
219 |
"does not have @" + MBean.class.getSimpleName() + |
bfa2bef7517c
6323980: Annotations to simplify MBean development
emcmanus
parents:
687
diff
changeset
|
220 |
" or @" + MXBean.class.getSimpleName() + " annotation: " + |
287 | 221 |
mbeanType.getName()); |
222 |
} |
|
223 |
} |
|
224 |
||
225 |
/** |
|
226 |
* Get the methods to be analyzed to build the MBean interface. |
|
227 |
*/ |
|
228 |
List<Method> getMethods(final Class<?> mbeanType) throws Exception { |
|
833
bfa2bef7517c
6323980: Annotations to simplify MBean development
emcmanus
parents:
687
diff
changeset
|
229 |
if (mbeanType.isInterface()) |
bfa2bef7517c
6323980: Annotations to simplify MBean development
emcmanus
parents:
687
diff
changeset
|
230 |
return Arrays.asList(mbeanType.getMethods()); |
bfa2bef7517c
6323980: Annotations to simplify MBean development
emcmanus
parents:
687
diff
changeset
|
231 |
|
bfa2bef7517c
6323980: Annotations to simplify MBean development
emcmanus
parents:
687
diff
changeset
|
232 |
final List<Method> methods = newList(); |
bfa2bef7517c
6323980: Annotations to simplify MBean development
emcmanus
parents:
687
diff
changeset
|
233 |
getAnnotatedMethods(mbeanType, methods); |
bfa2bef7517c
6323980: Annotations to simplify MBean development
emcmanus
parents:
687
diff
changeset
|
234 |
return methods; |
287 | 235 |
} |
2 | 236 |
|
237 |
final PerInterface<M> getPerInterface(Class<?> mbeanInterface) |
|
238 |
throws NotCompliantMBeanException { |
|
239 |
PerInterfaceMap<M> map = getPerInterfaceMap(); |
|
240 |
synchronized (map) { |
|
241 |
WeakReference<PerInterface<M>> wr = map.get(mbeanInterface); |
|
242 |
PerInterface<M> pi = (wr == null) ? null : wr.get(); |
|
243 |
if (pi == null) { |
|
244 |
try { |
|
245 |
MBeanAnalyzer<M> analyzer = getAnalyzer(mbeanInterface); |
|
246 |
MBeanInfo mbeanInfo = |
|
247 |
makeInterfaceMBeanInfo(mbeanInterface, analyzer); |
|
248 |
pi = new PerInterface<M>(mbeanInterface, this, analyzer, |
|
249 |
mbeanInfo); |
|
250 |
wr = new WeakReference<PerInterface<M>>(pi); |
|
251 |
map.put(mbeanInterface, wr); |
|
252 |
} catch (Exception x) { |
|
253 |
throw Introspector.throwException(mbeanInterface,x); |
|
254 |
} |
|
255 |
} |
|
256 |
return pi; |
|
257 |
} |
|
258 |
} |
|
259 |
||
260 |
/** |
|
261 |
* Make the MBeanInfo skeleton for the given MBean interface using |
|
262 |
* the given analyzer. This will never be the MBeanInfo of any real |
|
263 |
* MBean (because the getClassName() must be a concrete class), but |
|
264 |
* its MBeanAttributeInfo[] and MBeanOperationInfo[] can be inserted |
|
265 |
* into such an MBeanInfo, and its Descriptor can be the basis for |
|
266 |
* the MBeanInfo's Descriptor. |
|
267 |
*/ |
|
268 |
private MBeanInfo makeInterfaceMBeanInfo(Class<?> mbeanInterface, |
|
687 | 269 |
MBeanAnalyzer<M> analyzer) throws IntrospectionException { |
2 | 270 |
final MBeanInfoMaker maker = new MBeanInfoMaker(); |
271 |
analyzer.visit(maker); |
|
833
bfa2bef7517c
6323980: Annotations to simplify MBean development
emcmanus
parents:
687
diff
changeset
|
272 |
final String defaultDescription = |
2 | 273 |
"Information on the management interface of the MBean"; |
833
bfa2bef7517c
6323980: Annotations to simplify MBean development
emcmanus
parents:
687
diff
changeset
|
274 |
String description = Introspector.descriptionForElement(mbeanInterface); |
bfa2bef7517c
6323980: Annotations to simplify MBean development
emcmanus
parents:
687
diff
changeset
|
275 |
if (description == null) |
bfa2bef7517c
6323980: Annotations to simplify MBean development
emcmanus
parents:
687
diff
changeset
|
276 |
description = defaultDescription; |
2 | 277 |
return maker.makeMBeanInfo(mbeanInterface, description); |
278 |
} |
|
279 |
||
280 |
/** True if the given getter and setter are consistent. */ |
|
281 |
final boolean consistent(M getter, M setter) { |
|
282 |
return (getter == null || setter == null || |
|
283 |
getGenericReturnType(getter).equals(getGenericParameterTypes(setter)[0])); |
|
284 |
} |
|
285 |
||
286 |
/** |
|
287 |
* Invoke the given M on the given target with the given args and cookie. |
|
288 |
* Wrap exceptions appropriately. |
|
289 |
*/ |
|
290 |
final Object invokeM(M m, Object target, Object[] args, Object cookie) |
|
291 |
throws MBeanException, ReflectionException { |
|
292 |
try { |
|
293 |
return invokeM2(m, target, args, cookie); |
|
294 |
} catch (InvocationTargetException e) { |
|
295 |
unwrapInvocationTargetException(e); |
|
296 |
throw new RuntimeException(e); // not reached |
|
297 |
} catch (IllegalAccessException e) { |
|
298 |
throw new ReflectionException(e, e.toString()); |
|
299 |
} |
|
300 |
/* We do not catch and wrap RuntimeException or Error, |
|
301 |
* because we're in a DynamicMBean, so the logic for DynamicMBeans |
|
302 |
* will do the wrapping. |
|
303 |
*/ |
|
304 |
} |
|
305 |
||
306 |
/** |
|
307 |
* Invoke the given setter on the given target with the given argument |
|
308 |
* and cookie. Wrap exceptions appropriately. |
|
309 |
*/ |
|
310 |
/* If the value is of the wrong type for the method we are about to |
|
311 |
* invoke, we are supposed to throw an InvalidAttributeValueException. |
|
312 |
* Rather than making the check always, we invoke the method, then |
|
313 |
* if it throws an exception we check the type to see if that was |
|
314 |
* what caused the exception. The assumption is that an exception |
|
315 |
* from an invalid type will arise before any user method is ever |
|
316 |
* called (either in reflection or in OpenConverter). |
|
317 |
*/ |
|
318 |
final void invokeSetter(String name, M setter, Object target, Object arg, |
|
319 |
Object cookie) |
|
320 |
throws MBeanException, ReflectionException, |
|
321 |
InvalidAttributeValueException { |
|
322 |
try { |
|
323 |
invokeM2(setter, target, new Object[] {arg}, cookie); |
|
324 |
} catch (IllegalAccessException e) { |
|
325 |
throw new ReflectionException(e, e.toString()); |
|
326 |
} catch (RuntimeException e) { |
|
327 |
maybeInvalidParameter(name, setter, arg, cookie); |
|
328 |
throw e; |
|
329 |
} catch (InvocationTargetException e) { |
|
330 |
maybeInvalidParameter(name, setter, arg, cookie); |
|
331 |
unwrapInvocationTargetException(e); |
|
332 |
} |
|
333 |
} |
|
334 |
||
335 |
private void maybeInvalidParameter(String name, M setter, Object arg, |
|
336 |
Object cookie) |
|
337 |
throws InvalidAttributeValueException { |
|
338 |
if (!validParameter(setter, arg, 0, cookie)) { |
|
339 |
final String msg = |
|
340 |
"Invalid value for attribute " + name + ": " + arg; |
|
341 |
throw new InvalidAttributeValueException(msg); |
|
342 |
} |
|
343 |
} |
|
344 |
||
345 |
static boolean isValidParameter(Method m, Object value, int paramNo) { |
|
346 |
Class<?> c = m.getParameterTypes()[paramNo]; |
|
347 |
try { |
|
348 |
// Following is expensive but we only call this method to determine |
|
349 |
// if an exception is due to an incompatible parameter type. |
|
350 |
// Plain old c.isInstance doesn't work for primitive types. |
|
351 |
Object a = Array.newInstance(c, 1); |
|
352 |
Array.set(a, 0, value); |
|
353 |
return true; |
|
354 |
} catch (IllegalArgumentException e) { |
|
355 |
return false; |
|
356 |
} |
|
357 |
} |
|
358 |
||
359 |
private static void |
|
360 |
unwrapInvocationTargetException(InvocationTargetException e) |
|
361 |
throws MBeanException { |
|
362 |
Throwable t = e.getCause(); |
|
363 |
if (t instanceof RuntimeException) |
|
364 |
throw (RuntimeException) t; |
|
365 |
else if (t instanceof Error) |
|
366 |
throw (Error) t; |
|
367 |
else |
|
368 |
throw new MBeanException((Exception) t, |
|
369 |
(t == null ? null : t.toString())); |
|
370 |
} |
|
371 |
||
372 |
/** A visitor that constructs the per-interface MBeanInfo. */ |
|
687 | 373 |
private class MBeanInfoMaker |
374 |
implements MBeanAnalyzer.MBeanVisitor<M, IntrospectionException> { |
|
2 | 375 |
|
376 |
public void visitAttribute(String attributeName, |
|
377 |
M getter, |
|
687 | 378 |
M setter) throws IntrospectionException { |
2 | 379 |
MBeanAttributeInfo mbai = |
380 |
getMBeanAttributeInfo(attributeName, getter, setter); |
|
381 |
||
382 |
attrs.add(mbai); |
|
383 |
} |
|
384 |
||
385 |
public void visitOperation(String operationName, |
|
386 |
M operation) { |
|
387 |
MBeanOperationInfo mboi = |
|
388 |
getMBeanOperationInfo(operationName, operation); |
|
389 |
||
390 |
ops.add(mboi); |
|
391 |
} |
|
392 |
||
393 |
/** Make an MBeanInfo based on the attributes and operations |
|
394 |
* found in the interface. */ |
|
395 |
MBeanInfo makeMBeanInfo(Class<?> mbeanInterface, |
|
396 |
String description) { |
|
397 |
final MBeanAttributeInfo[] attrArray = |
|
398 |
attrs.toArray(new MBeanAttributeInfo[0]); |
|
399 |
final MBeanOperationInfo[] opArray = |
|
400 |
ops.toArray(new MBeanOperationInfo[0]); |
|
401 |
final String interfaceClassName = |
|
402 |
"interfaceClassName=" + mbeanInterface.getName(); |
|
687 | 403 |
final Descriptor classNameDescriptor = |
2 | 404 |
new ImmutableDescriptor(interfaceClassName); |
405 |
final Descriptor mbeanDescriptor = getBasicMBeanDescriptor(); |
|
406 |
final Descriptor annotatedDescriptor = |
|
407 |
Introspector.descriptorForElement(mbeanInterface); |
|
408 |
final Descriptor descriptor = |
|
687 | 409 |
DescriptorCache.getInstance().union( |
410 |
classNameDescriptor, |
|
2 | 411 |
mbeanDescriptor, |
412 |
annotatedDescriptor); |
|
413 |
||
414 |
return new MBeanInfo(mbeanInterface.getName(), |
|
415 |
description, |
|
416 |
attrArray, |
|
417 |
null, |
|
418 |
opArray, |
|
419 |
null, |
|
420 |
descriptor); |
|
421 |
} |
|
422 |
||
423 |
private final List<MBeanAttributeInfo> attrs = newList(); |
|
424 |
private final List<MBeanOperationInfo> ops = newList(); |
|
425 |
} |
|
426 |
||
427 |
/* |
|
428 |
* Looking up the MBeanInfo for a given base class (implementation class) |
|
429 |
* is complicated by the fact that we may use the same base class with |
|
430 |
* several different explicit MBean interfaces via the |
|
431 |
* javax.management.StandardMBean class. It is further complicated |
|
432 |
* by the fact that we have to be careful not to retain a strong reference |
|
433 |
* to any Class object for fear we would prevent a ClassLoader from being |
|
434 |
* garbage-collected. So we have a first lookup from the base class |
|
435 |
* to a map for each interface that base class might specify giving |
|
436 |
* the MBeanInfo constructed for that base class and interface. |
|
437 |
*/ |
|
438 |
static class MBeanInfoMap |
|
439 |
extends WeakHashMap<Class<?>, WeakHashMap<Class<?>, MBeanInfo>> { |
|
440 |
} |
|
441 |
||
442 |
/** |
|
443 |
* Return the MBeanInfo for the given resource, based on the given |
|
444 |
* per-interface data. |
|
445 |
*/ |
|
687 | 446 |
final MBeanInfo getMBeanInfo(Object resource, PerInterface<M> perInterface) |
447 |
throws NotCompliantMBeanException { |
|
2 | 448 |
MBeanInfo mbi = |
449 |
getClassMBeanInfo(resource.getClass(), perInterface); |
|
833
bfa2bef7517c
6323980: Annotations to simplify MBean development
emcmanus
parents:
687
diff
changeset
|
450 |
MBeanNotificationInfo[] notifs; |
bfa2bef7517c
6323980: Annotations to simplify MBean development
emcmanus
parents:
687
diff
changeset
|
451 |
try { |
bfa2bef7517c
6323980: Annotations to simplify MBean development
emcmanus
parents:
687
diff
changeset
|
452 |
notifs = findNotifications(resource); |
bfa2bef7517c
6323980: Annotations to simplify MBean development
emcmanus
parents:
687
diff
changeset
|
453 |
} catch (RuntimeException e) { |
bfa2bef7517c
6323980: Annotations to simplify MBean development
emcmanus
parents:
687
diff
changeset
|
454 |
NotCompliantMBeanException x = |
bfa2bef7517c
6323980: Annotations to simplify MBean development
emcmanus
parents:
687
diff
changeset
|
455 |
new NotCompliantMBeanException(e.getMessage()); |
bfa2bef7517c
6323980: Annotations to simplify MBean development
emcmanus
parents:
687
diff
changeset
|
456 |
x.initCause(e); |
bfa2bef7517c
6323980: Annotations to simplify MBean development
emcmanus
parents:
687
diff
changeset
|
457 |
throw x; |
bfa2bef7517c
6323980: Annotations to simplify MBean development
emcmanus
parents:
687
diff
changeset
|
458 |
} |
687 | 459 |
Descriptor d = getSpecificMBeanDescriptor(); |
460 |
boolean anyNotifs = (notifs != null && notifs.length > 0); |
|
461 |
if (!anyNotifs && ImmutableDescriptor.EMPTY_DESCRIPTOR.equals(d)) |
|
2 | 462 |
return mbi; |
463 |
else { |
|
687 | 464 |
d = ImmutableDescriptor.union(d, mbi.getDescriptor()); |
2 | 465 |
return new MBeanInfo(mbi.getClassName(), |
466 |
mbi.getDescription(), |
|
467 |
mbi.getAttributes(), |
|
468 |
mbi.getConstructors(), |
|
469 |
mbi.getOperations(), |
|
470 |
notifs, |
|
687 | 471 |
d); |
2 | 472 |
} |
473 |
} |
|
474 |
||
475 |
/** |
|
476 |
* Return the basic MBeanInfo for resources of the given class and |
|
477 |
* per-interface data. This MBeanInfo might not be the final MBeanInfo |
|
478 |
* for instances of the class, because if the class is a |
|
479 |
* NotificationBroadcaster then each instance gets to decide what |
|
480 |
* MBeanNotificationInfo[] to put in its own MBeanInfo. |
|
481 |
*/ |
|
482 |
final MBeanInfo getClassMBeanInfo(Class<?> resourceClass, |
|
483 |
PerInterface<M> perInterface) { |
|
484 |
MBeanInfoMap map = getMBeanInfoMap(); |
|
485 |
synchronized (map) { |
|
486 |
WeakHashMap<Class<?>, MBeanInfo> intfMap = map.get(resourceClass); |
|
487 |
if (intfMap == null) { |
|
488 |
intfMap = new WeakHashMap<Class<?>, MBeanInfo>(); |
|
489 |
map.put(resourceClass, intfMap); |
|
490 |
} |
|
491 |
Class<?> intfClass = perInterface.getMBeanInterface(); |
|
492 |
MBeanInfo mbi = intfMap.get(intfClass); |
|
493 |
if (mbi == null) { |
|
494 |
MBeanInfo imbi = perInterface.getMBeanInfo(); |
|
495 |
Descriptor descriptor = |
|
496 |
ImmutableDescriptor.union(imbi.getDescriptor(), |
|
497 |
getMBeanDescriptor(resourceClass)); |
|
498 |
mbi = new MBeanInfo(resourceClass.getName(), |
|
499 |
imbi.getDescription(), |
|
500 |
imbi.getAttributes(), |
|
501 |
findConstructors(resourceClass), |
|
502 |
imbi.getOperations(), |
|
503 |
(MBeanNotificationInfo[]) null, |
|
504 |
descriptor); |
|
505 |
intfMap.put(intfClass, mbi); |
|
506 |
} |
|
507 |
return mbi; |
|
508 |
} |
|
509 |
} |
|
510 |
||
833
bfa2bef7517c
6323980: Annotations to simplify MBean development
emcmanus
parents:
687
diff
changeset
|
511 |
/* |
bfa2bef7517c
6323980: Annotations to simplify MBean development
emcmanus
parents:
687
diff
changeset
|
512 |
* Add to "methods" every public method that has the @ManagedAttribute |
bfa2bef7517c
6323980: Annotations to simplify MBean development
emcmanus
parents:
687
diff
changeset
|
513 |
* or @ManagedOperation annotation, in the given class or any of |
bfa2bef7517c
6323980: Annotations to simplify MBean development
emcmanus
parents:
687
diff
changeset
|
514 |
* its superclasses or superinterfaces. |
bfa2bef7517c
6323980: Annotations to simplify MBean development
emcmanus
parents:
687
diff
changeset
|
515 |
* |
bfa2bef7517c
6323980: Annotations to simplify MBean development
emcmanus
parents:
687
diff
changeset
|
516 |
* We always add superclass or superinterface methods first, so that |
bfa2bef7517c
6323980: Annotations to simplify MBean development
emcmanus
parents:
687
diff
changeset
|
517 |
* the stable sort used by eliminateCovariantMethods will put the |
bfa2bef7517c
6323980: Annotations to simplify MBean development
emcmanus
parents:
687
diff
changeset
|
518 |
* method from the most-derived class last. This means that we will |
bfa2bef7517c
6323980: Annotations to simplify MBean development
emcmanus
parents:
687
diff
changeset
|
519 |
* see the version of the @ManagedAttribute (or ...Operation) annotation |
bfa2bef7517c
6323980: Annotations to simplify MBean development
emcmanus
parents:
687
diff
changeset
|
520 |
* from that method, which might have a different description or whatever. |
bfa2bef7517c
6323980: Annotations to simplify MBean development
emcmanus
parents:
687
diff
changeset
|
521 |
*/ |
bfa2bef7517c
6323980: Annotations to simplify MBean development
emcmanus
parents:
687
diff
changeset
|
522 |
private static void getAnnotatedMethods(Class<?> c, List<Method> methods) |
bfa2bef7517c
6323980: Annotations to simplify MBean development
emcmanus
parents:
687
diff
changeset
|
523 |
throws Exception { |
bfa2bef7517c
6323980: Annotations to simplify MBean development
emcmanus
parents:
687
diff
changeset
|
524 |
Class<?> sup = c.getSuperclass(); |
bfa2bef7517c
6323980: Annotations to simplify MBean development
emcmanus
parents:
687
diff
changeset
|
525 |
if (sup != null) |
bfa2bef7517c
6323980: Annotations to simplify MBean development
emcmanus
parents:
687
diff
changeset
|
526 |
getAnnotatedMethods(sup, methods); |
bfa2bef7517c
6323980: Annotations to simplify MBean development
emcmanus
parents:
687
diff
changeset
|
527 |
Class<?>[] intfs = c.getInterfaces(); |
bfa2bef7517c
6323980: Annotations to simplify MBean development
emcmanus
parents:
687
diff
changeset
|
528 |
for (Class<?> intf : intfs) |
bfa2bef7517c
6323980: Annotations to simplify MBean development
emcmanus
parents:
687
diff
changeset
|
529 |
getAnnotatedMethods(intf, methods); |
bfa2bef7517c
6323980: Annotations to simplify MBean development
emcmanus
parents:
687
diff
changeset
|
530 |
for (Method m : c.getMethods()) { |
bfa2bef7517c
6323980: Annotations to simplify MBean development
emcmanus
parents:
687
diff
changeset
|
531 |
// We are careful not to add m if it is inherited from a parent |
bfa2bef7517c
6323980: Annotations to simplify MBean development
emcmanus
parents:
687
diff
changeset
|
532 |
// class or interface, because duplicate methods lead to nasty |
bfa2bef7517c
6323980: Annotations to simplify MBean development
emcmanus
parents:
687
diff
changeset
|
533 |
// behaviour in eliminateCovariantMethods. |
bfa2bef7517c
6323980: Annotations to simplify MBean development
emcmanus
parents:
687
diff
changeset
|
534 |
if (m.getDeclaringClass() == c && |
bfa2bef7517c
6323980: Annotations to simplify MBean development
emcmanus
parents:
687
diff
changeset
|
535 |
(m.isAnnotationPresent(ManagedAttribute.class) || |
bfa2bef7517c
6323980: Annotations to simplify MBean development
emcmanus
parents:
687
diff
changeset
|
536 |
m.isAnnotationPresent(ManagedOperation.class))) |
bfa2bef7517c
6323980: Annotations to simplify MBean development
emcmanus
parents:
687
diff
changeset
|
537 |
methods.add(m); |
bfa2bef7517c
6323980: Annotations to simplify MBean development
emcmanus
parents:
687
diff
changeset
|
538 |
} |
bfa2bef7517c
6323980: Annotations to simplify MBean development
emcmanus
parents:
687
diff
changeset
|
539 |
} |
bfa2bef7517c
6323980: Annotations to simplify MBean development
emcmanus
parents:
687
diff
changeset
|
540 |
|
2 | 541 |
static MBeanNotificationInfo[] findNotifications(Object moi) { |
1627
aec3a9aa6901
6772779: @NotificationInfo does not create MBeanNotificationInfo in the MBean's MBeanInfo
emcmanus
parents:
1221
diff
changeset
|
542 |
if (moi instanceof NotificationBroadcaster) { |
aec3a9aa6901
6772779: @NotificationInfo does not create MBeanNotificationInfo in the MBean's MBeanInfo
emcmanus
parents:
1221
diff
changeset
|
543 |
MBeanNotificationInfo[] mbn = |
aec3a9aa6901
6772779: @NotificationInfo does not create MBeanNotificationInfo in the MBean's MBeanInfo
emcmanus
parents:
1221
diff
changeset
|
544 |
((NotificationBroadcaster) moi).getNotificationInfo(); |
aec3a9aa6901
6772779: @NotificationInfo does not create MBeanNotificationInfo in the MBean's MBeanInfo
emcmanus
parents:
1221
diff
changeset
|
545 |
if (mbn != null && mbn.length > 0) { |
aec3a9aa6901
6772779: @NotificationInfo does not create MBeanNotificationInfo in the MBean's MBeanInfo
emcmanus
parents:
1221
diff
changeset
|
546 |
MBeanNotificationInfo[] result = |
aec3a9aa6901
6772779: @NotificationInfo does not create MBeanNotificationInfo in the MBean's MBeanInfo
emcmanus
parents:
1221
diff
changeset
|
547 |
new MBeanNotificationInfo[mbn.length]; |
aec3a9aa6901
6772779: @NotificationInfo does not create MBeanNotificationInfo in the MBean's MBeanInfo
emcmanus
parents:
1221
diff
changeset
|
548 |
for (int i = 0; i < mbn.length; i++) { |
aec3a9aa6901
6772779: @NotificationInfo does not create MBeanNotificationInfo in the MBean's MBeanInfo
emcmanus
parents:
1221
diff
changeset
|
549 |
MBeanNotificationInfo ni = mbn[i]; |
aec3a9aa6901
6772779: @NotificationInfo does not create MBeanNotificationInfo in the MBean's MBeanInfo
emcmanus
parents:
1221
diff
changeset
|
550 |
if (ni.getClass() != MBeanNotificationInfo.class) |
aec3a9aa6901
6772779: @NotificationInfo does not create MBeanNotificationInfo in the MBean's MBeanInfo
emcmanus
parents:
1221
diff
changeset
|
551 |
ni = (MBeanNotificationInfo) ni.clone(); |
aec3a9aa6901
6772779: @NotificationInfo does not create MBeanNotificationInfo in the MBean's MBeanInfo
emcmanus
parents:
1221
diff
changeset
|
552 |
result[i] = ni; |
aec3a9aa6901
6772779: @NotificationInfo does not create MBeanNotificationInfo in the MBean's MBeanInfo
emcmanus
parents:
1221
diff
changeset
|
553 |
} |
aec3a9aa6901
6772779: @NotificationInfo does not create MBeanNotificationInfo in the MBean's MBeanInfo
emcmanus
parents:
1221
diff
changeset
|
554 |
return result; |
aec3a9aa6901
6772779: @NotificationInfo does not create MBeanNotificationInfo in the MBean's MBeanInfo
emcmanus
parents:
1221
diff
changeset
|
555 |
} |
2 | 556 |
} |
1627
aec3a9aa6901
6772779: @NotificationInfo does not create MBeanNotificationInfo in the MBean's MBeanInfo
emcmanus
parents:
1221
diff
changeset
|
557 |
return findNotificationsFromAnnotations(moi.getClass()); |
2 | 558 |
} |
559 |
||
1636
eb801ce73ac9
6776225: JMX.isNotificationSource wrong when DynamicWrapperMBean + SendNotification injection
emcmanus
parents:
1627
diff
changeset
|
560 |
public static MBeanNotificationInfo[] findNotificationsFromAnnotations( |
833
bfa2bef7517c
6323980: Annotations to simplify MBean development
emcmanus
parents:
687
diff
changeset
|
561 |
Class<?> mbeanClass) { |
bfa2bef7517c
6323980: Annotations to simplify MBean development
emcmanus
parents:
687
diff
changeset
|
562 |
Class<?> c = getAnnotatedNotificationInfoClass(mbeanClass); |
bfa2bef7517c
6323980: Annotations to simplify MBean development
emcmanus
parents:
687
diff
changeset
|
563 |
if (c == null) |
bfa2bef7517c
6323980: Annotations to simplify MBean development
emcmanus
parents:
687
diff
changeset
|
564 |
return null; |
bfa2bef7517c
6323980: Annotations to simplify MBean development
emcmanus
parents:
687
diff
changeset
|
565 |
NotificationInfo ni = c.getAnnotation(NotificationInfo.class); |
bfa2bef7517c
6323980: Annotations to simplify MBean development
emcmanus
parents:
687
diff
changeset
|
566 |
NotificationInfos nis = c.getAnnotation(NotificationInfos.class); |
bfa2bef7517c
6323980: Annotations to simplify MBean development
emcmanus
parents:
687
diff
changeset
|
567 |
List<NotificationInfo> list = newList(); |
bfa2bef7517c
6323980: Annotations to simplify MBean development
emcmanus
parents:
687
diff
changeset
|
568 |
if (ni != null) |
bfa2bef7517c
6323980: Annotations to simplify MBean development
emcmanus
parents:
687
diff
changeset
|
569 |
list.add(ni); |
bfa2bef7517c
6323980: Annotations to simplify MBean development
emcmanus
parents:
687
diff
changeset
|
570 |
if (nis != null) |
bfa2bef7517c
6323980: Annotations to simplify MBean development
emcmanus
parents:
687
diff
changeset
|
571 |
list.addAll(Arrays.asList(nis.value())); |
bfa2bef7517c
6323980: Annotations to simplify MBean development
emcmanus
parents:
687
diff
changeset
|
572 |
if (list.isEmpty()) |
bfa2bef7517c
6323980: Annotations to simplify MBean development
emcmanus
parents:
687
diff
changeset
|
573 |
return null; |
bfa2bef7517c
6323980: Annotations to simplify MBean development
emcmanus
parents:
687
diff
changeset
|
574 |
List<MBeanNotificationInfo> mbnis = newList(); |
bfa2bef7517c
6323980: Annotations to simplify MBean development
emcmanus
parents:
687
diff
changeset
|
575 |
for (NotificationInfo x : list) { |
bfa2bef7517c
6323980: Annotations to simplify MBean development
emcmanus
parents:
687
diff
changeset
|
576 |
// The Descriptor includes any fields explicitly specified by |
bfa2bef7517c
6323980: Annotations to simplify MBean development
emcmanus
parents:
687
diff
changeset
|
577 |
// x.descriptorFields(), plus any fields from the contained |
bfa2bef7517c
6323980: Annotations to simplify MBean development
emcmanus
parents:
687
diff
changeset
|
578 |
// @Description annotation. |
bfa2bef7517c
6323980: Annotations to simplify MBean development
emcmanus
parents:
687
diff
changeset
|
579 |
Descriptor d = new ImmutableDescriptor(x.descriptorFields()); |
bfa2bef7517c
6323980: Annotations to simplify MBean development
emcmanus
parents:
687
diff
changeset
|
580 |
d = ImmutableDescriptor.union( |
bfa2bef7517c
6323980: Annotations to simplify MBean development
emcmanus
parents:
687
diff
changeset
|
581 |
d, Introspector.descriptorForAnnotation(x.description())); |
bfa2bef7517c
6323980: Annotations to simplify MBean development
emcmanus
parents:
687
diff
changeset
|
582 |
MBeanNotificationInfo mbni = new MBeanNotificationInfo( |
bfa2bef7517c
6323980: Annotations to simplify MBean development
emcmanus
parents:
687
diff
changeset
|
583 |
x.types(), x.notificationClass().getName(), |
bfa2bef7517c
6323980: Annotations to simplify MBean development
emcmanus
parents:
687
diff
changeset
|
584 |
x.description().value(), d); |
bfa2bef7517c
6323980: Annotations to simplify MBean development
emcmanus
parents:
687
diff
changeset
|
585 |
mbnis.add(mbni); |
bfa2bef7517c
6323980: Annotations to simplify MBean development
emcmanus
parents:
687
diff
changeset
|
586 |
} |
bfa2bef7517c
6323980: Annotations to simplify MBean development
emcmanus
parents:
687
diff
changeset
|
587 |
return mbnis.toArray(new MBeanNotificationInfo[mbnis.size()]); |
bfa2bef7517c
6323980: Annotations to simplify MBean development
emcmanus
parents:
687
diff
changeset
|
588 |
} |
bfa2bef7517c
6323980: Annotations to simplify MBean development
emcmanus
parents:
687
diff
changeset
|
589 |
|
bfa2bef7517c
6323980: Annotations to simplify MBean development
emcmanus
parents:
687
diff
changeset
|
590 |
private static final Map<Class<?>, WeakReference<Class<?>>> |
bfa2bef7517c
6323980: Annotations to simplify MBean development
emcmanus
parents:
687
diff
changeset
|
591 |
annotatedNotificationInfoClasses = newWeakHashMap(); |
bfa2bef7517c
6323980: Annotations to simplify MBean development
emcmanus
parents:
687
diff
changeset
|
592 |
|
bfa2bef7517c
6323980: Annotations to simplify MBean development
emcmanus
parents:
687
diff
changeset
|
593 |
private static Class<?> getAnnotatedNotificationInfoClass(Class<?> baseClass) { |
bfa2bef7517c
6323980: Annotations to simplify MBean development
emcmanus
parents:
687
diff
changeset
|
594 |
synchronized (annotatedNotificationInfoClasses) { |
bfa2bef7517c
6323980: Annotations to simplify MBean development
emcmanus
parents:
687
diff
changeset
|
595 |
WeakReference<Class<?>> wr = |
bfa2bef7517c
6323980: Annotations to simplify MBean development
emcmanus
parents:
687
diff
changeset
|
596 |
annotatedNotificationInfoClasses.get(baseClass); |
bfa2bef7517c
6323980: Annotations to simplify MBean development
emcmanus
parents:
687
diff
changeset
|
597 |
if (wr != null) |
bfa2bef7517c
6323980: Annotations to simplify MBean development
emcmanus
parents:
687
diff
changeset
|
598 |
return wr.get(); |
bfa2bef7517c
6323980: Annotations to simplify MBean development
emcmanus
parents:
687
diff
changeset
|
599 |
Class<?> c = null; |
bfa2bef7517c
6323980: Annotations to simplify MBean development
emcmanus
parents:
687
diff
changeset
|
600 |
if (baseClass.isAnnotationPresent(NotificationInfo.class) || |
bfa2bef7517c
6323980: Annotations to simplify MBean development
emcmanus
parents:
687
diff
changeset
|
601 |
baseClass.isAnnotationPresent(NotificationInfos.class)) { |
bfa2bef7517c
6323980: Annotations to simplify MBean development
emcmanus
parents:
687
diff
changeset
|
602 |
c = baseClass; |
bfa2bef7517c
6323980: Annotations to simplify MBean development
emcmanus
parents:
687
diff
changeset
|
603 |
} else { |
bfa2bef7517c
6323980: Annotations to simplify MBean development
emcmanus
parents:
687
diff
changeset
|
604 |
Class<?>[] intfs = baseClass.getInterfaces(); |
bfa2bef7517c
6323980: Annotations to simplify MBean development
emcmanus
parents:
687
diff
changeset
|
605 |
for (Class<?> intf : intfs) { |
bfa2bef7517c
6323980: Annotations to simplify MBean development
emcmanus
parents:
687
diff
changeset
|
606 |
Class<?> c1 = getAnnotatedNotificationInfoClass(intf); |
bfa2bef7517c
6323980: Annotations to simplify MBean development
emcmanus
parents:
687
diff
changeset
|
607 |
if (c1 != null) { |
bfa2bef7517c
6323980: Annotations to simplify MBean development
emcmanus
parents:
687
diff
changeset
|
608 |
if (c != null) { |
bfa2bef7517c
6323980: Annotations to simplify MBean development
emcmanus
parents:
687
diff
changeset
|
609 |
throw new IllegalArgumentException( |
bfa2bef7517c
6323980: Annotations to simplify MBean development
emcmanus
parents:
687
diff
changeset
|
610 |
"Class " + baseClass.getName() + " inherits " + |
bfa2bef7517c
6323980: Annotations to simplify MBean development
emcmanus
parents:
687
diff
changeset
|
611 |
"@NotificationInfo(s) from both " + |
bfa2bef7517c
6323980: Annotations to simplify MBean development
emcmanus
parents:
687
diff
changeset
|
612 |
c.getName() + " and " + c1.getName()); |
bfa2bef7517c
6323980: Annotations to simplify MBean development
emcmanus
parents:
687
diff
changeset
|
613 |
} |
bfa2bef7517c
6323980: Annotations to simplify MBean development
emcmanus
parents:
687
diff
changeset
|
614 |
c = c1; |
bfa2bef7517c
6323980: Annotations to simplify MBean development
emcmanus
parents:
687
diff
changeset
|
615 |
} |
bfa2bef7517c
6323980: Annotations to simplify MBean development
emcmanus
parents:
687
diff
changeset
|
616 |
} |
bfa2bef7517c
6323980: Annotations to simplify MBean development
emcmanus
parents:
687
diff
changeset
|
617 |
} |
bfa2bef7517c
6323980: Annotations to simplify MBean development
emcmanus
parents:
687
diff
changeset
|
618 |
// Record the result of the search. If no @NotificationInfo(s) |
bfa2bef7517c
6323980: Annotations to simplify MBean development
emcmanus
parents:
687
diff
changeset
|
619 |
// were found, c is null, and we store a WeakReference(null). |
bfa2bef7517c
6323980: Annotations to simplify MBean development
emcmanus
parents:
687
diff
changeset
|
620 |
// This prevents us from having to search again and fail again. |
bfa2bef7517c
6323980: Annotations to simplify MBean development
emcmanus
parents:
687
diff
changeset
|
621 |
annotatedNotificationInfoClasses.put(baseClass, |
bfa2bef7517c
6323980: Annotations to simplify MBean development
emcmanus
parents:
687
diff
changeset
|
622 |
new WeakReference<Class<?>>(c)); |
bfa2bef7517c
6323980: Annotations to simplify MBean development
emcmanus
parents:
687
diff
changeset
|
623 |
return c; |
bfa2bef7517c
6323980: Annotations to simplify MBean development
emcmanus
parents:
687
diff
changeset
|
624 |
} |
bfa2bef7517c
6323980: Annotations to simplify MBean development
emcmanus
parents:
687
diff
changeset
|
625 |
} |
bfa2bef7517c
6323980: Annotations to simplify MBean development
emcmanus
parents:
687
diff
changeset
|
626 |
|
2 | 627 |
private static MBeanConstructorInfo[] findConstructors(Class<?> c) { |
1221
e3dc70e4e610
6746196: Some JMX classes do not compile with Eclipse compiler
emcmanus
parents:
834
diff
changeset
|
628 |
Constructor<?>[] cons = c.getConstructors(); |
2 | 629 |
MBeanConstructorInfo[] mbc = new MBeanConstructorInfo[cons.length]; |
630 |
for (int i = 0; i < cons.length; i++) { |
|
833
bfa2bef7517c
6323980: Annotations to simplify MBean development
emcmanus
parents:
687
diff
changeset
|
631 |
String descr = "Public constructor of the MBean"; |
bfa2bef7517c
6323980: Annotations to simplify MBean development
emcmanus
parents:
687
diff
changeset
|
632 |
Description d = cons[i].getAnnotation(Description.class); |
bfa2bef7517c
6323980: Annotations to simplify MBean development
emcmanus
parents:
687
diff
changeset
|
633 |
if (d != null) |
bfa2bef7517c
6323980: Annotations to simplify MBean development
emcmanus
parents:
687
diff
changeset
|
634 |
descr = d.value(); |
2 | 635 |
mbc[i] = new MBeanConstructorInfo(descr, cons[i]); |
636 |
} |
|
637 |
return mbc; |
|
638 |
} |
|
639 |
||
640 |
} |