1 /*
   2  * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
   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.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 
  24 /*
  25  * @test
  26  * @bug 5042004
  27  * @summary Check that MBeans with the same class have identical MBeanInfo
  28  * unless they are NotificationBroadcasters
  29  * @author Eamonn McManus
  30  * @modules java.management
  31  * @run clean IdenticalMBeanInfoTest
  32  * @run build IdenticalMBeanInfoTest
  33  * @run main IdenticalMBeanInfoTest
  34  */
  35 
  36 import javax.management.*;
  37 
  38 /* What we test here is not required by the spec.  It is an
  39    optimization that can save a considerable amount of memory when
  40    there are many MBeans of the same type.  There is no reason why two
  41    Standard MBeans of the same type should have different MBeanInfo
  42    objects, unless they are NotificationBroadcasters and return
  43    different arrays from getNotificationInfo().  Note that two MBeans
  44    that share the same MBean interface but are of different classes
  45    cannot have the same MBeanInfo because the MBeanInfo includes the
  46    implementation class name.  */
  47 public class IdenticalMBeanInfoTest {
  48     private static String failure = null;
  49 
  50     public static interface WhatsitMBean {
  51         public int getReadOnly();
  52         public int getReadWrite();
  53         public void setReadWrite(int x);
  54         public int op(int x, int y);
  55     }
  56 
  57     public static class Whatsit implements WhatsitMBean {
  58         public Whatsit() {}
  59         public Whatsit(int irrelevant) {}
  60 
  61         public int getReadOnly() { return 0; }
  62         public int getReadWrite() { return 0; }
  63         public void setReadWrite(int x) {}
  64         public int op(int x, int y) { return 0; }
  65     }
  66 
  67     public static interface BroadcasterMBean extends WhatsitMBean {
  68     }
  69 
  70     public static class Broadcaster extends Whatsit
  71             implements BroadcasterMBean, NotificationBroadcaster {
  72         private static int nextId = 1;
  73         private int id = nextId++;
  74 
  75         public void addNotificationListener(NotificationListener l,
  76                                             NotificationFilter f,
  77                                             Object h) {}
  78 
  79         public void removeNotificationListener(NotificationListener l) {}
  80 
  81         public MBeanNotificationInfo[] getNotificationInfo() {
  82             return new MBeanNotificationInfo[] {
  83                 new MBeanNotificationInfo(new String[] {"type" + id},
  84                                           "something",
  85                                           "a something")
  86             };
  87         }
  88     }
  89 
  90     public static void main(String[] args) throws Exception {
  91         MBeanServer mbs = MBeanServerFactory.createMBeanServer();
  92         ObjectName on1 = new ObjectName("d:type=Whatsit,number=1");
  93         ObjectName on2 = new ObjectName("d:type=Whatsit,number=2");
  94         ObjectName on3 = new ObjectName("d:type=Whatsit,number=3");
  95         ObjectName on4 = new ObjectName("d:type=Whatsit,number=4");
  96         ObjectName on5 = new ObjectName("d:type=Whatsit,number=5");
  97 
  98         mbs.registerMBean(new Whatsit(), on1);
  99         mbs.createMBean(Whatsit.class.getName(), on2);
 100         DynamicMBean mbean =
 101             new StandardMBean(new Whatsit(), WhatsitMBean.class);
 102         mbs.registerMBean(mbean, on3);
 103         mbs.registerMBean(new Broadcaster(), on4);
 104         mbs.createMBean(Broadcaster.class.getName(), on5);
 105         MBeanInfo mbi1 = mbs.getMBeanInfo(on1);
 106         MBeanInfo mbi2 = mbs.getMBeanInfo(on2);
 107         MBeanInfo mbi3 = mbs.getMBeanInfo(on3);
 108         MBeanInfo mbi4 = mbs.getMBeanInfo(on4);
 109         MBeanInfo mbi5 = mbs.getMBeanInfo(on5);
 110 
 111         if (mbi1 != mbi2) {
 112             fail("Two MBeans of the same class should have identical " +
 113                  "MBeanInfo");
 114         }
 115 
 116         if (mbi2 != mbi3) {
 117             if (true)
 118                 System.out.println("IGNORING StandardMBean(...) failure");
 119             else
 120                 fail("Plain Standard MBean should have identical MBeanInfo " +
 121                      "to StandardMBean(...) with same class as resource");
 122         }
 123 
 124         if (mbi4 == mbi5 || mbi4.equals(mbi5)) {
 125             fail("Two MBeans of the same class should NOT have identical " +
 126                  "MBeanInfo if they are NotificationBroadcasters and "+
 127                  "do not return the same MBeanNotificationInfo[]");
 128         }
 129 
 130         if (failure == null) {
 131             System.out.println("Test passed");
 132             return;
 133         }
 134 
 135         throw new Exception("TEST FAILED: " + failure);
 136     }
 137 
 138     private static void fail(String why) {
 139         System.out.println("FAILURE: " + why);
 140         failure = why;
 141     }
 142 }