21 * have any questions. |
21 * have any questions. |
22 */ |
22 */ |
23 |
23 |
24 /* |
24 /* |
25 * @test DynamicWrapperMBeanTest |
25 * @test DynamicWrapperMBeanTest |
26 * @bug 6624232 |
26 * @bug 6624232 6776225 |
27 * @summary Test the DynamicWrapperMBean interface |
27 * @summary Test the DynamicWrapperMBean interface |
28 * @author Eamonn McManus |
28 * @author Eamonn McManus |
29 */ |
29 */ |
30 |
30 |
31 import java.lang.management.ManagementFactory; |
31 import java.lang.management.ManagementFactory; |
|
32 import javax.annotation.Resource; |
|
33 import javax.management.JMX; |
|
34 import javax.management.ListenerNotFoundException; |
|
35 import javax.management.MBeanNotificationInfo; |
32 import javax.management.MBeanServer; |
36 import javax.management.MBeanServer; |
|
37 import javax.management.Notification; |
|
38 import javax.management.NotificationBroadcaster; |
|
39 import javax.management.NotificationBroadcasterSupport; |
|
40 import javax.management.NotificationEmitter; |
|
41 import javax.management.NotificationFilter; |
|
42 import javax.management.NotificationInfo; |
|
43 import javax.management.NotificationListener; |
33 import javax.management.ObjectName; |
44 import javax.management.ObjectName; |
|
45 import javax.management.SendNotification; |
|
46 import javax.management.StandardEmitterMBean; |
34 import javax.management.StandardMBean; |
47 import javax.management.StandardMBean; |
35 import javax.management.modelmbean.ModelMBeanInfo; |
48 import javax.management.modelmbean.ModelMBeanInfo; |
36 import javax.management.modelmbean.ModelMBeanInfoSupport; |
49 import javax.management.modelmbean.ModelMBeanInfoSupport; |
37 import javax.management.modelmbean.ModelMBeanOperationInfo; |
50 import javax.management.modelmbean.ModelMBeanOperationInfo; |
38 import javax.management.modelmbean.RequiredModelMBean; |
51 import javax.management.modelmbean.RequiredModelMBean; |
39 import static javax.management.StandardMBean.Options; |
52 import static javax.management.StandardMBean.Options; |
40 |
53 |
41 public class DynamicWrapperMBeanTest { |
54 public class DynamicWrapperMBeanTest { |
|
55 private static String failure; |
|
56 |
|
57 public static void main(String[] args) throws Exception { |
|
58 wrapTest(); |
|
59 notifTest(); |
|
60 |
|
61 if (failure == null) |
|
62 System.out.println("TEST PASSED"); |
|
63 else |
|
64 throw new Exception("TEST FAILED: " + failure); |
|
65 } |
|
66 |
|
67 private static final Options wrappedVisOpts = new Options(); |
|
68 private static final Options wrappedInvisOpts = new Options(); |
|
69 static { |
|
70 wrappedVisOpts.setWrappedObjectVisible(true); |
|
71 wrappedInvisOpts.setWrappedObjectVisible(false); |
|
72 } |
|
73 |
42 public static interface WrappedMBean { |
74 public static interface WrappedMBean { |
43 public void sayHello(); |
75 public void sayHello(); |
44 } |
76 } |
45 public static class Wrapped implements WrappedMBean { |
77 public static class Wrapped implements WrappedMBean { |
46 public void sayHello() { |
78 public void sayHello() { |
47 System.out.println("Hello"); |
79 System.out.println("Hello"); |
48 } |
80 } |
49 } |
81 } |
50 |
82 |
51 private static String failure; |
83 private static void wrapTest() throws Exception { |
52 |
|
53 public static void main(String[] args) throws Exception { |
|
54 if (Wrapped.class.getClassLoader() == |
84 if (Wrapped.class.getClassLoader() == |
55 StandardMBean.class.getClassLoader()) { |
85 StandardMBean.class.getClassLoader()) { |
56 throw new Exception( |
86 throw new Exception( |
57 "TEST ERROR: Resource and StandardMBean have same ClassLoader"); |
87 "TEST ERROR: Resource and StandardMBean have same ClassLoader"); |
58 } |
88 } |
59 |
89 |
60 Options wrappedVisOpts = new Options(); |
|
61 wrappedVisOpts.setWrappedObjectVisible(true); |
|
62 Options wrappedInvisOpts = new Options(); |
|
63 wrappedInvisOpts.setWrappedObjectVisible(false); |
|
64 assertEquals("Options withWrappedObjectVisible(false)", |
90 assertEquals("Options withWrappedObjectVisible(false)", |
65 new Options(), wrappedInvisOpts); |
91 new Options(), wrappedInvisOpts); |
66 |
92 |
67 Wrapped resource = new Wrapped(); |
93 Wrapped resource = new Wrapped(); |
68 |
94 |
136 assertEquals("isInstanceOf(RequiredModelMBean) for visible resource", |
162 assertEquals("isInstanceOf(RequiredModelMBean) for visible resource", |
137 false, mbs.isInstanceOf(visibleName, RequiredModelMBean.class.getName())); |
163 false, mbs.isInstanceOf(visibleName, RequiredModelMBean.class.getName())); |
138 assertEquals("isInstanceOf(RequiredModelMBean) for invisible resource", |
164 assertEquals("isInstanceOf(RequiredModelMBean) for invisible resource", |
139 true, mbs.isInstanceOf(invisibleName, RequiredModelMBean.class.getName())); |
165 true, mbs.isInstanceOf(invisibleName, RequiredModelMBean.class.getName())); |
140 |
166 |
141 if (failure != null) |
167 mbs.unregisterMBean(visibleName); |
142 throw new Exception("TEST FAILED: " + failure); |
168 mbs.unregisterMBean(invisibleName); |
|
169 } |
|
170 |
|
171 private static enum WrapType { |
|
172 NBS("NotificationBroadcasterSupport"), |
|
173 INJ("@Resource SendNotification"), |
|
174 STD_MBEAN_NBS("StandardMBean delegating to NotificationBroadcasterSupport"), |
|
175 STD_MBEAN_INJ("StandardMBean delegating to @Resource SendNotification"), |
|
176 STD_MBEAN_SUB_NBS("StandardMBean subclass implementing NotificationBroadcaster"), |
|
177 STD_MBEAN_SUB_INJ("StandardMBean subclass with @Resource SendNotification"), |
|
178 STD_EMIT_MBEAN_NBS("StandardEmitterMBean delegating to NotificationBroadcasterSupport"), |
|
179 STD_EMIT_MBEAN_INJ("StandardEmitterMBean delegating to @Resource SendNotification"), |
|
180 STD_EMIT_MBEAN_SUB("StandardEmitterMBean subclass"), |
|
181 STD_EMIT_MBEAN_SUB_INJ("StandardEmitterMBean subclass with @Resource SendNotification"); |
|
182 |
|
183 WrapType(String s) { |
|
184 this.s = s; |
|
185 } |
|
186 |
|
187 @Override |
|
188 public String toString() { |
|
189 return s; |
|
190 } |
|
191 |
|
192 private final String s; |
|
193 } |
|
194 |
|
195 @NotificationInfo( |
|
196 types = {"foo", "bar"} |
|
197 ) |
|
198 public static interface BroadcasterMBean { |
|
199 public void send(Notification n); |
|
200 } |
|
201 |
|
202 public static class Broadcaster |
|
203 extends NotificationBroadcasterSupport implements BroadcasterMBean { |
|
204 public void send(Notification n) { |
|
205 super.sendNotification(n); |
|
206 } |
|
207 } |
|
208 |
|
209 public static interface SendNotifMBean extends BroadcasterMBean { |
|
210 } |
|
211 |
|
212 public static class SendNotif implements SendNotifMBean { |
|
213 @Resource |
|
214 private volatile SendNotification sendNotif; |
|
215 |
|
216 public void send(Notification n) { |
|
217 sendNotif.sendNotification(n); |
|
218 } |
|
219 } |
|
220 |
|
221 public static class StdBroadcaster |
|
222 extends StandardMBean |
|
223 implements BroadcasterMBean, NotificationBroadcaster { |
|
224 private final NotificationBroadcasterSupport nbs = |
|
225 new NotificationBroadcasterSupport(); |
|
226 |
|
227 public StdBroadcaster() throws Exception { |
|
228 super(BroadcasterMBean.class); |
|
229 } |
|
230 |
|
231 public void send(Notification n) { |
|
232 nbs.sendNotification(n); |
|
233 } |
|
234 |
|
235 public void addNotificationListener(NotificationListener listener, |
|
236 NotificationFilter filter, Object handback) { |
|
237 nbs.addNotificationListener(listener, filter, handback); |
|
238 } |
|
239 |
|
240 public MBeanNotificationInfo[] getNotificationInfo() { |
|
241 return null; |
|
242 } |
|
243 |
|
244 public void removeNotificationListener(NotificationListener listener) |
|
245 throws ListenerNotFoundException { |
|
246 nbs.removeNotificationListener(listener); |
|
247 } |
|
248 } |
|
249 |
|
250 public static class StdSendNotif |
|
251 extends StandardMBean implements SendNotifMBean { |
|
252 @Resource |
|
253 private volatile SendNotification sendNotif; |
|
254 |
|
255 public StdSendNotif() throws Exception { |
|
256 super(SendNotifMBean.class); |
|
257 } |
|
258 |
|
259 public void send(Notification n) { |
|
260 sendNotif.sendNotification(n); |
|
261 } |
|
262 } |
|
263 |
|
264 public static class StdEmitterBroadcaster // :-) |
|
265 extends StandardEmitterMBean |
|
266 implements BroadcasterMBean { |
|
267 |
|
268 public StdEmitterBroadcaster() throws Exception { |
|
269 super(BroadcasterMBean.class, null); |
|
270 } |
|
271 |
|
272 public void send(Notification n) { |
|
273 super.sendNotification(n); |
|
274 } |
|
275 } |
|
276 |
|
277 // This case is unlikely - if you're using @Resource SendNotification |
|
278 // then there's no point in using StandardEmitterMBean, since |
|
279 // StandardMBean would suffice. |
|
280 public static class StdEmitterSendNotif |
|
281 extends StandardEmitterMBean implements SendNotifMBean { |
|
282 @Resource |
|
283 private volatile SendNotification sendNotif; |
|
284 |
|
285 public StdEmitterSendNotif() { |
|
286 super(SendNotifMBean.class, null); |
|
287 } |
|
288 |
|
289 public void send(Notification n) { |
|
290 sendNotif.sendNotification(n); |
|
291 } |
|
292 } |
|
293 |
|
294 // Test that JMX.isNotificationSource and |
|
295 // mbs.isInstanceOf("NotificationBroadcaster") work correctly even when |
|
296 // the MBean is a broadcaster by virtue of its wrapped resource. |
|
297 // Test that we find the MBeanNotificationInfo[] from the @NotificationInfo |
|
298 // annotation on BroadcasterMBean. We cover a large number of different |
|
299 // MBean types, but all ultimately implement that interface. |
|
300 private static void notifTest() throws Exception { |
|
301 System.out.println("===Testing notification senders==="); |
|
302 |
|
303 for (WrapType wrapType : WrapType.values()) { |
|
304 System.out.println("---" + wrapType); |
|
305 |
|
306 final Object mbean; |
|
307 |
|
308 switch (wrapType) { |
|
309 case NBS: |
|
310 // An MBean that extends NotificationBroadcasterSupport |
|
311 mbean = new Broadcaster(); |
|
312 break; |
|
313 case INJ: |
|
314 // An MBean that injects SendNotification |
|
315 mbean = new SendNotif(); |
|
316 break; |
|
317 case STD_MBEAN_NBS: |
|
318 // A StandardMBean that delegates to a NotificationBroadcasterSupport |
|
319 mbean = new StandardMBean( |
|
320 new Broadcaster(), BroadcasterMBean.class, wrappedVisOpts); |
|
321 break; |
|
322 case STD_MBEAN_INJ: |
|
323 // A StandardMBean that delegates to an object that injects |
|
324 // SendNotification |
|
325 mbean = new StandardMBean( |
|
326 new SendNotif(), BroadcasterMBean.class, wrappedVisOpts); |
|
327 break; |
|
328 case STD_EMIT_MBEAN_NBS: { |
|
329 // A StandardEmitterMBean that delegates to a NotificationBroadcasterSupport |
|
330 Broadcaster broadcaster = new Broadcaster(); |
|
331 mbean = new StandardEmitterMBean( |
|
332 broadcaster, BroadcasterMBean.class, wrappedVisOpts, |
|
333 broadcaster); |
|
334 break; |
|
335 } |
|
336 case STD_EMIT_MBEAN_INJ: { |
|
337 // A StandardEmitterMBean that delegates to an object that injects |
|
338 // SendNotification |
|
339 SendNotif sendNotif = new SendNotif(); |
|
340 mbean = new StandardEmitterMBean( |
|
341 sendNotif, BroadcasterMBean.class, wrappedVisOpts, |
|
342 null); |
|
343 break; |
|
344 } |
|
345 case STD_MBEAN_SUB_NBS: |
|
346 // A subclass of StandardMBean that implements NotificationBroadcaster |
|
347 mbean = new StdBroadcaster(); |
|
348 break; |
|
349 case STD_MBEAN_SUB_INJ: |
|
350 // A subclass of StandardMBean that injects SendNotification |
|
351 mbean = new StdSendNotif(); |
|
352 break; |
|
353 case STD_EMIT_MBEAN_SUB: |
|
354 // A subclass of StandardEmitterMBean |
|
355 mbean = new StdEmitterBroadcaster(); |
|
356 break; |
|
357 case STD_EMIT_MBEAN_SUB_INJ: |
|
358 // A subclass of StandardEmitterMBean that injects SendNotification |
|
359 // (which is a rather strange thing to do and probably a user |
|
360 // misunderstanding but we should do the right thing anyway). |
|
361 mbean = new StdEmitterSendNotif(); |
|
362 break; |
|
363 default: |
|
364 throw new AssertionError(); |
|
365 } |
|
366 |
|
367 MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); |
|
368 |
|
369 final ObjectName name = new ObjectName("a:type=Sender"); |
|
370 mbs.registerMBean(mbean, name); |
|
371 boolean isBroadcaster = mbs.isInstanceOf( |
|
372 name, NotificationBroadcaster.class.getName()); |
|
373 assertEquals("JMX.isNotificationSource(mbean)", |
|
374 true, JMX.isNotificationSource(mbean)); |
|
375 assertEquals("isInstanceOf(NotificationBroadcaster)", |
|
376 true, isBroadcaster); |
|
377 MBeanNotificationInfo[] mbnis = |
|
378 mbs.getMBeanInfo(name).getNotifications(); |
|
379 assertEquals("MBeanNotificationInfo not empty", |
|
380 true, (mbnis.length > 0)); |
|
381 |
|
382 mbs.unregisterMBean(name); |
|
383 } |
143 } |
384 } |
144 |
385 |
145 private static void assertEquals(String what, Object expect, Object actual) { |
386 private static void assertEquals(String what, Object expect, Object actual) { |
146 if (equal(expect, actual)) |
387 if (equal(expect, actual)) |
147 System.out.println("OK: " + what + " = " + expect); |
388 System.out.println("OK: " + what + " = " + expect); |