jdk/test/javax/management/Introspector/AnnotatedNotificationInfoTest.java
changeset 1697 98a530cd0594
parent 1627 aec3a9aa6901
equal deleted inserted replaced
1696:aef312419918 1697:98a530cd0594
    36 import javax.annotation.Resource;
    36 import javax.annotation.Resource;
    37 import javax.management.AttributeChangeNotification;
    37 import javax.management.AttributeChangeNotification;
    38 import javax.management.Description;
    38 import javax.management.Description;
    39 import javax.management.Descriptor;
    39 import javax.management.Descriptor;
    40 import javax.management.ImmutableDescriptor;
    40 import javax.management.ImmutableDescriptor;
       
    41 import javax.management.ListenerNotFoundException;
    41 import javax.management.MBean;
    42 import javax.management.MBean;
    42 import javax.management.MBeanInfo;
    43 import javax.management.MBeanInfo;
    43 import javax.management.MBeanNotificationInfo;
    44 import javax.management.MBeanNotificationInfo;
    44 import javax.management.MBeanServer;
    45 import javax.management.MBeanServer;
    45 import javax.management.MXBean;
    46 import javax.management.MXBean;
       
    47 import javax.management.Notification;
       
    48 import javax.management.NotificationBroadcaster;
    46 import javax.management.NotificationBroadcasterSupport;
    49 import javax.management.NotificationBroadcasterSupport;
       
    50 import javax.management.NotificationFilter;
    47 import javax.management.NotificationInfo;
    51 import javax.management.NotificationInfo;
    48 import javax.management.NotificationInfos;
    52 import javax.management.NotificationInfos;
       
    53 import javax.management.NotificationListener;
    49 import javax.management.ObjectName;
    54 import javax.management.ObjectName;
    50 import javax.management.SendNotification;
    55 import javax.management.SendNotification;
    51 
    56 
    52 public class AnnotatedNotificationInfoTest {
    57 public class AnnotatedNotificationInfoTest {
    53     // Data for the first test.  This tests that MBeanNotificationInfo
    58 
       
    59     static final Descriptor expectedDescriptor = new ImmutableDescriptor(
       
    60             "foo=bar", "descriptionResourceBundleBaseName=bundle",
       
    61             "descriptionResourceKey=key");
       
    62     static final MBeanNotificationInfo expected = new MBeanNotificationInfo(
       
    63             new String[] {"foo", "bar"},
       
    64             AttributeChangeNotification.class.getName(),
       
    65             "description",
       
    66             expectedDescriptor);
       
    67 
       
    68     // Data for the first kind of test.  This tests that MBeanNotificationInfo
    54     // is correctly derived from @NotificationInfo.
    69     // is correctly derived from @NotificationInfo.
    55     // Every static field called mbean* is expected to be an MBean
    70     // Every static field called mbean* is expected to be an MBean
    56     // with a single MBeanNotificationInfo that has the same value
    71     // with a single MBeanNotificationInfo that has the same value
    57     // in each case.
    72     // in each case.
    58 
    73 
   252     @MXBean
   267     @MXBean
   253     public static class MXBean2 extends ParentImpl {}
   268     public static class MXBean2 extends ParentImpl {}
   254 
   269 
   255     private static Object mbeanMXBean2 = new MXBean2();
   270     private static Object mbeanMXBean2 = new MXBean2();
   256 
   271 
   257     // Classes for the second test.  This tests the simplest case, which is
   272     // Test that @NotificationInfo and @NotificationInfos are ignored if
   258     // the first example in the javadoc for @NotificationInfo.  Notice that
   273     // the MBean returns a non-empty MBeanNotificationInfo[] from its
   259     // this MBean is not a NotificationBroadcaster and does not inject a
   274     // NotificationBroadcaster.getNotifications() implementation.
   260     // SendNotification!  That should possibly be an error, but it's currently
   275 
   261     // allowed by the spec.
   276     @NotificationInfo(types={"blim", "blam"})
       
   277     public static interface Explicit1MBean {}
       
   278 
       
   279     public static class Explicit1
       
   280             extends NotificationBroadcasterSupport implements Explicit1MBean {
       
   281         public Explicit1() {
       
   282             super(expected);
       
   283         }
       
   284     }
       
   285 
       
   286     private static Object mbeanExplicit1 = new Explicit1();
       
   287 
       
   288     @NotificationInfos(
       
   289         {
       
   290             @NotificationInfo(types="blim"), @NotificationInfo(types="blam")
       
   291         }
       
   292     )
       
   293     public static interface Explicit2MXBean {}
       
   294 
       
   295     public static class Explicit2
       
   296             implements NotificationBroadcaster, Explicit2MXBean {
       
   297         public void addNotificationListener(NotificationListener listener,
       
   298                 NotificationFilter filter, Object handback) {}
       
   299 
       
   300         public void removeNotificationListener(NotificationListener listener)
       
   301                 throws ListenerNotFoundException {}
       
   302 
       
   303         public MBeanNotificationInfo[] getNotificationInfo() {
       
   304             return new MBeanNotificationInfo[] {expected};
       
   305         }
       
   306     }
       
   307 
       
   308     // Data for the second kind of test.  This tests that @NotificationInfo is
       
   309     // ignored if the MBean is not a notification source.  Every static
       
   310     // field called ignoredMBean* is expected to be an MBean on which
       
   311     // isInstanceOf(NotificationBroadcaster.class.getName() is false,
       
   312     // addNotificationListener produces an exception, and the
       
   313     // MBeanNotificationInfo array is empty.
   262     @NotificationInfo(types={"com.example.notifs.create",
   314     @NotificationInfo(types={"com.example.notifs.create",
   263                              "com.example.notifs.destroy"})
   315                              "com.example.notifs.destroy"})
   264     public static interface CacheMBean {
   316     public static interface CacheMBean {
   265         public int getCachedNum();
   317         public int getCachedNum();
   266     }
   318     }
   269         public int getCachedNum() {
   321         public int getCachedNum() {
   270             return 0;
   322             return 0;
   271         }
   323         }
   272     }
   324     }
   273 
   325 
       
   326     private static Object ignoredMBean1 = new Cache();
       
   327 
       
   328     @NotificationInfos(
       
   329         @NotificationInfo(types={"foo", "bar"})
       
   330     )
       
   331     public static interface Cache2MBean {
       
   332         public int getCachedNum();
       
   333     }
       
   334 
       
   335     public static class Cache2 implements Cache2MBean {
       
   336         public int getCachedNum() {
       
   337             return 0;
       
   338         }
       
   339     }
       
   340 
       
   341     private static Object ignoredMBean2 = new Cache2();
       
   342 
       
   343     private static final NotificationListener nullListener =
       
   344             new NotificationListener() {
       
   345                 public void handleNotification(
       
   346                         Notification notification, Object handback) {}
       
   347             };
       
   348 
       
   349     // Test that inheriting inconsistent @NotificationInfo annotations is
       
   350     // an error, but not if they are overridden by a non-empty getNotifications()
       
   351 
       
   352     @NotificationInfo(types={"blim"})
       
   353     public static interface Inconsistent1 {}
       
   354 
       
   355     @NotificationInfo(types={"blam"})
       
   356     public static interface Inconsistent2 {}
       
   357 
       
   358     public static interface InconsistentMBean extends Inconsistent1, Inconsistent2 {}
       
   359 
       
   360     public static class Inconsistent
       
   361             extends NotificationBroadcasterSupport implements InconsistentMBean {}
       
   362 
       
   363     public static class Consistent
       
   364             extends Inconsistent implements NotificationBroadcaster {
       
   365         public void addNotificationListener(NotificationListener listener,
       
   366                 NotificationFilter filter, Object handback) {}
       
   367 
       
   368         public void removeNotificationListener(NotificationListener listener)
       
   369                 throws ListenerNotFoundException {}
       
   370 
       
   371         public MBeanNotificationInfo[] getNotificationInfo() {
       
   372             return new MBeanNotificationInfo[] {expected};
       
   373         }
       
   374     }
       
   375 
       
   376     private static Object mbeanConsistent = new Consistent();
       
   377 
       
   378     @NotificationInfo(
       
   379             types = {"foo", "bar"},
       
   380             notificationClass = AttributeChangeNotification.class,
       
   381             description = @Description(
       
   382                 value = "description",
       
   383                 bundleBaseName = "bundle",
       
   384                 key = "key"),
       
   385             descriptorFields = {"foo=bar"})
       
   386     public static interface Consistent2MBean extends Inconsistent1, Inconsistent2 {}
       
   387 
       
   388     public static class Consistent2
       
   389             extends NotificationBroadcasterSupport implements Consistent2MBean {}
       
   390 
       
   391     private static Object mbeanConsistent2 = new Consistent2();
       
   392 
   274     public static void main(String[] args) throws Exception {
   393     public static void main(String[] args) throws Exception {
   275         if (!AnnotatedNotificationInfoTest.class.desiredAssertionStatus())
   394         if (!AnnotatedNotificationInfoTest.class.desiredAssertionStatus())
   276             throw new Exception("Test must be run with -ea");
   395             throw new Exception("Test must be run with -ea");
   277 
   396 
   278         MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
   397         MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
   279         ObjectName on = new ObjectName("a:b=c");
   398         ObjectName on = new ObjectName("a:b=c");
   280 
   399 
   281         Descriptor expectedDescriptor = new ImmutableDescriptor(
       
   282                 "foo=bar", "descriptionResourceBundleBaseName=bundle",
       
   283                 "descriptionResourceKey=key");
       
   284         MBeanNotificationInfo expected = new MBeanNotificationInfo(
       
   285                 new String[] {"foo", "bar"},
       
   286                 AttributeChangeNotification.class.getName(),
       
   287                 "description",
       
   288                 expectedDescriptor);
       
   289 
       
   290         System.out.println("Testing MBeans...");
   400         System.out.println("Testing MBeans...");
   291         for (Field mbeanField :
   401         for (Field mbeanField :
   292                 AnnotatedNotificationInfoTest.class.getDeclaredFields()) {
   402                 AnnotatedNotificationInfoTest.class.getDeclaredFields()) {
   293             if (!mbeanField.getName().startsWith("mbean"))
   403             boolean notifier;
       
   404             if (mbeanField.getName().startsWith("mbean"))
       
   405                 notifier = true;
       
   406             else if (mbeanField.getName().startsWith("ignoredMBean"))
       
   407                 notifier = false;
       
   408             else
   294                 continue;
   409                 continue;
   295             System.out.println("..." + mbeanField.getName());
   410             System.out.println("..." + mbeanField.getName());
   296             Object mbean = mbeanField.get(null);
   411             Object mbean = mbeanField.get(null);
   297             mbs.registerMBean(mbean, on);
   412             mbs.registerMBean(mbean, on);
   298             MBeanInfo mbi = mbs.getMBeanInfo(on);
   413             MBeanInfo mbi = mbs.getMBeanInfo(on);
   299             MBeanNotificationInfo[] mbnis = mbi.getNotifications();
   414             MBeanNotificationInfo[] mbnis = mbi.getNotifications();
   300             assert mbnis.length == 1 : mbnis.length;
   415             if (notifier) {
   301             assert mbnis[0].equals(expected) : mbnis[0];
   416                 assert mbnis.length == 1 : mbnis.length;
       
   417                 assert mbnis[0].equals(expected) : mbnis[0];
       
   418             } else {
       
   419                 assert mbnis.length == 0 : mbnis.length;
       
   420                 assert !mbs.isInstanceOf(on, NotificationBroadcaster.class.getName());
       
   421                 try {
       
   422                     mbs.addNotificationListener(on, nullListener, null, null);
       
   423                     assert false : "addNotificationListener works";
       
   424                 } catch (Exception e) {
       
   425                     // OK: addNL correctly refused
       
   426                 }
       
   427             }
   302             mbs.unregisterMBean(on);
   428             mbs.unregisterMBean(on);
   303         }
   429         }
   304 
   430 
   305         mbs.registerMBean(new Cache(), on);
   431         // Test that inconsistent @NotificationInfo annotations produce an
   306         MBeanInfo mbi = mbs.getMBeanInfo(on);
   432         // error.
   307         MBeanNotificationInfo[] mbnis = mbi.getNotifications();
   433         try {
   308         assert mbnis.length == 1 : mbnis.length;
   434             mbs.registerMBean(new Inconsistent(), on);
   309         String[] types = mbnis[0].getNotifTypes();
   435             System.out.println(mbs.getMBeanInfo(on));
   310         String[] expectedTypes =
   436             assert false : "Inconsistent @NotificationInfo not detected";
   311                 CacheMBean.class.getAnnotation(NotificationInfo.class).types();
   437         } catch (Exception e) {
   312         assert Arrays.equals(types, expectedTypes) : Arrays.toString(types);
   438             System.out.println(
       
   439                     "Inconsistent @NotificationInfo correctly produced " + e);
       
   440         }
   313     }
   441     }
   314 }
   442 }