/* * Copyright 2007-2008 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, * CA 95054 USA or visit www.sun.com if you need additional information or * have any questions. */ /* * @test DynamicWrapperMBeanTest * @bug 6624232 6776225 * @summary Test the DynamicWrapperMBean interface * @author Eamonn McManus */ import java.lang.management.ManagementFactory; import javax.annotation.Resource; import javax.management.JMX; import javax.management.ListenerNotFoundException; import javax.management.MBeanNotificationInfo; import javax.management.MBeanServer; import javax.management.Notification; import javax.management.NotificationBroadcaster; import javax.management.NotificationBroadcasterSupport; import javax.management.NotificationEmitter; import javax.management.NotificationFilter; import javax.management.NotificationInfo; import javax.management.NotificationListener; import javax.management.ObjectName; import javax.management.SendNotification; import javax.management.StandardEmitterMBean; import javax.management.StandardMBean; import javax.management.modelmbean.ModelMBeanInfo; import javax.management.modelmbean.ModelMBeanInfoSupport; import javax.management.modelmbean.ModelMBeanOperationInfo; import javax.management.modelmbean.RequiredModelMBean; import static javax.management.StandardMBean.Options; public class DynamicWrapperMBeanTest { private static String failure; public static void main(String[] args) throws Exception { wrapTest(); notifTest(); if (failure == null) System.out.println("TEST PASSED"); else throw new Exception("TEST FAILED: " + failure); } private static final Options wrappedVisOpts = new Options(); private static final Options wrappedInvisOpts = new Options(); static { wrappedVisOpts.setWrappedObjectVisible(true); wrappedInvisOpts.setWrappedObjectVisible(false); } public static interface WrappedMBean { public void sayHello(); } public static class Wrapped implements WrappedMBean { public void sayHello() { System.out.println("Hello"); } } private static void wrapTest() throws Exception { if (Wrapped.class.getClassLoader() == StandardMBean.class.getClassLoader()) { throw new Exception( "TEST ERROR: Resource and StandardMBean have same ClassLoader"); } assertEquals("Options withWrappedObjectVisible(false)", new Options(), wrappedInvisOpts); Wrapped resource = new Wrapped(); StandardMBean visible = new StandardMBean(resource, WrappedMBean.class, wrappedVisOpts); StandardMBean invisible = new StandardMBean(resource, WrappedMBean.class, wrappedInvisOpts); assertEquals("getResource withWrappedObjectVisible(true)", resource, visible.getWrappedObject()); assertEquals("getResource withWrappedObjectVisible(false)", invisible, invisible.getWrappedObject()); System.out.println("===Testing StandardMBean==="); ObjectName visibleName = new ObjectName("a:type=visible"); ObjectName invisibleName = new ObjectName("a:type=invisible"); MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); mbs.registerMBean(visible, visibleName); mbs.registerMBean(invisible, invisibleName); assertEquals("ClassLoader for visible resource", Wrapped.class.getClassLoader(), mbs.getClassLoaderFor(visibleName)); assertEquals("ClassLoader for invisible resource", StandardMBean.class.getClassLoader(), mbs.getClassLoaderFor(invisibleName)); assertEquals("isInstanceOf(WrappedMBean) for visible wrapped", true, mbs.isInstanceOf(visibleName, WrappedMBean.class.getName())); assertEquals("isInstanceOf(WrappedMBean) for invisible wrapped", false, mbs.isInstanceOf(invisibleName, WrappedMBean.class.getName())); assertEquals("isInstanceOf(StandardMBean) for visible wrapped", false, mbs.isInstanceOf(visibleName, StandardMBean.class.getName())); assertEquals("isInstanceOf(StandardMBean) for invisible wrapped", true, mbs.isInstanceOf(invisibleName, StandardMBean.class.getName())); mbs.unregisterMBean(visibleName); mbs.unregisterMBean(invisibleName); System.out.println("===Testing RequiredModelMBean==="); // Godawful Model MBeans... ModelMBeanOperationInfo mmboi = new ModelMBeanOperationInfo( "say hello to the nice man", Wrapped.class.getMethod("sayHello")); ModelMBeanInfo visibleMmbi = new ModelMBeanInfoSupport( Wrapped.class.getName(), "Visible wrapped", null, null, new ModelMBeanOperationInfo[] {mmboi}, null); ModelMBeanInfo invisibleMmbi = new ModelMBeanInfoSupport( Wrapped.class.getName(), "Invisible wrapped", null, null, new ModelMBeanOperationInfo[] {mmboi}, null); RequiredModelMBean visibleRmmb = new RequiredModelMBean(visibleMmbi); RequiredModelMBean invisibleRmmb = new RequiredModelMBean(invisibleMmbi); visibleRmmb.setManagedResource(resource, "VisibleObjectReference"); invisibleRmmb.setManagedResource(resource, "ObjectReference"); mbs.registerMBean(visibleRmmb, visibleName); mbs.registerMBean(invisibleRmmb, invisibleName); assertEquals("ClassLoader for visible wrapped", Wrapped.class.getClassLoader(), mbs.getClassLoaderFor(visibleName)); assertEquals("ClassLoader for invisible wrapped", StandardMBean.class.getClassLoader(), mbs.getClassLoaderFor(invisibleName)); assertEquals("isInstanceOf(WrappedMBean) for visible resource", true, mbs.isInstanceOf(visibleName, WrappedMBean.class.getName())); assertEquals("isInstanceOf(WrappedMBean) for invisible resource", false, mbs.isInstanceOf(invisibleName, WrappedMBean.class.getName())); assertEquals("isInstanceOf(RequiredModelMBean) for visible resource", false, mbs.isInstanceOf(visibleName, RequiredModelMBean.class.getName())); assertEquals("isInstanceOf(RequiredModelMBean) for invisible resource", true, mbs.isInstanceOf(invisibleName, RequiredModelMBean.class.getName())); mbs.unregisterMBean(visibleName); mbs.unregisterMBean(invisibleName); } private static enum WrapType { NBS("NotificationBroadcasterSupport"), INJ("@Resource SendNotification"), STD_MBEAN_NBS("StandardMBean delegating to NotificationBroadcasterSupport"), STD_MBEAN_INJ("StandardMBean delegating to @Resource SendNotification"), STD_MBEAN_SUB_NBS("StandardMBean subclass implementing NotificationBroadcaster"), STD_MBEAN_SUB_INJ("StandardMBean subclass with @Resource SendNotification"), STD_EMIT_MBEAN_NBS("StandardEmitterMBean delegating to NotificationBroadcasterSupport"), STD_EMIT_MBEAN_INJ("StandardEmitterMBean delegating to @Resource SendNotification"), STD_EMIT_MBEAN_SUB("StandardEmitterMBean subclass"), STD_EMIT_MBEAN_SUB_INJ("StandardEmitterMBean subclass with @Resource SendNotification"); WrapType(String s) { this.s = s; } @Override public String toString() { return s; } private final String s; } @NotificationInfo( types = {"foo", "bar"} ) public static interface BroadcasterMBean { public void send(Notification n); } public static class Broadcaster extends NotificationBroadcasterSupport implements BroadcasterMBean { public void send(Notification n) { super.sendNotification(n); } } public static interface SendNotifMBean extends BroadcasterMBean { } public static class SendNotif implements SendNotifMBean { @Resource private volatile SendNotification sendNotif; public void send(Notification n) { sendNotif.sendNotification(n); } } public static class StdBroadcaster extends StandardMBean implements BroadcasterMBean, NotificationBroadcaster { private final NotificationBroadcasterSupport nbs = new NotificationBroadcasterSupport(); public StdBroadcaster() throws Exception { super(BroadcasterMBean.class); } public void send(Notification n) { nbs.sendNotification(n); } public void addNotificationListener(NotificationListener listener, NotificationFilter filter, Object handback) { nbs.addNotificationListener(listener, filter, handback); } public MBeanNotificationInfo[] getNotificationInfo() { return null; } public void removeNotificationListener(NotificationListener listener) throws ListenerNotFoundException { nbs.removeNotificationListener(listener); } } public static class StdSendNotif extends StandardMBean implements SendNotifMBean { @Resource private volatile SendNotification sendNotif; public StdSendNotif() throws Exception { super(SendNotifMBean.class); } public void send(Notification n) { sendNotif.sendNotification(n); } } public static class StdEmitterBroadcaster // :-) extends StandardEmitterMBean implements BroadcasterMBean { public StdEmitterBroadcaster() throws Exception { super(BroadcasterMBean.class, null); } public void send(Notification n) { super.sendNotification(n); } } // This case is unlikely - if you're using @Resource SendNotification // then there's no point in using StandardEmitterMBean, since // StandardMBean would suffice. public static class StdEmitterSendNotif extends StandardEmitterMBean implements SendNotifMBean { @Resource private volatile SendNotification sendNotif; public StdEmitterSendNotif() { super(SendNotifMBean.class, null); } public void send(Notification n) { sendNotif.sendNotification(n); } } // Test that JMX.isNotificationSource and // mbs.isInstanceOf("NotificationBroadcaster") work correctly even when // the MBean is a broadcaster by virtue of its wrapped resource. // Test that we find the MBeanNotificationInfo[] from the @NotificationInfo // annotation on BroadcasterMBean. We cover a large number of different // MBean types, but all ultimately implement that interface. private static void notifTest() throws Exception { System.out.println("===Testing notification senders==="); for (WrapType wrapType : WrapType.values()) { System.out.println("---" + wrapType); final Object mbean; switch (wrapType) { case NBS: // An MBean that extends NotificationBroadcasterSupport mbean = new Broadcaster(); break; case INJ: // An MBean that injects SendNotification mbean = new SendNotif(); break; case STD_MBEAN_NBS: // A StandardMBean that delegates to a NotificationBroadcasterSupport mbean = new StandardMBean( new Broadcaster(), BroadcasterMBean.class, wrappedVisOpts); break; case STD_MBEAN_INJ: // A StandardMBean that delegates to an object that injects // SendNotification mbean = new StandardMBean( new SendNotif(), BroadcasterMBean.class, wrappedVisOpts); break; case STD_EMIT_MBEAN_NBS: { // A StandardEmitterMBean that delegates to a NotificationBroadcasterSupport Broadcaster broadcaster = new Broadcaster(); mbean = new StandardEmitterMBean( broadcaster, BroadcasterMBean.class, wrappedVisOpts, broadcaster); break; } case STD_EMIT_MBEAN_INJ: { // A StandardEmitterMBean that delegates to an object that injects // SendNotification SendNotif sendNotif = new SendNotif(); mbean = new StandardEmitterMBean( sendNotif, BroadcasterMBean.class, wrappedVisOpts, null); break; } case STD_MBEAN_SUB_NBS: // A subclass of StandardMBean that implements NotificationBroadcaster mbean = new StdBroadcaster(); break; case STD_MBEAN_SUB_INJ: // A subclass of StandardMBean that injects SendNotification mbean = new StdSendNotif(); break; case STD_EMIT_MBEAN_SUB: // A subclass of StandardEmitterMBean mbean = new StdEmitterBroadcaster(); break; case STD_EMIT_MBEAN_SUB_INJ: // A subclass of StandardEmitterMBean that injects SendNotification // (which is a rather strange thing to do and probably a user // misunderstanding but we should do the right thing anyway). mbean = new StdEmitterSendNotif(); break; default: throw new AssertionError(); } MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); final ObjectName name = new ObjectName("a:type=Sender"); mbs.registerMBean(mbean, name); boolean isBroadcaster = mbs.isInstanceOf( name, NotificationBroadcaster.class.getName()); assertEquals("JMX.isNotificationSource(mbean)", true, JMX.isNotificationSource(mbean)); assertEquals("isInstanceOf(NotificationBroadcaster)", true, isBroadcaster); MBeanNotificationInfo[] mbnis = mbs.getMBeanInfo(name).getNotifications(); assertEquals("MBeanNotificationInfo not empty", true, (mbnis.length > 0)); mbs.unregisterMBean(name); } } private static void assertEquals(String what, Object expect, Object actual) { if (equal(expect, actual)) System.out.println("OK: " + what + " = " + expect); else fail(what + " should be " + expect + ", is " + actual); } private static boolean equal(Object x, Object y) { if (x == y) return true; if (x == null || y == null) return false; return x.equals(y); } private static void fail(String why) { failure = why; System.out.println("FAIL: " + why); } }