jdk/test/javax/management/mxbean/MXBeanNotifTest.java
changeset 34827 de746e7eb1e3
child 43503 bc7f8619ab70
equal deleted inserted replaced
34826:4bbdce2630f8 34827:de746e7eb1e3
       
     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 8058865
       
    27  * @summary Checks MXBean proper registration both as its implementation class and interface
       
    28  * @author Olivier Lagneau
       
    29  * @modules java.management
       
    30  * @library /lib/testlibrary
       
    31  * @compile Basic.java
       
    32  * @run main/othervm/timeout=300 -DDEBUG_STANDARD MXBeanNotifTest -numOfNotifications 239 -timeForNotificationInSeconds 4
       
    33  */
       
    34 
       
    35 import java.util.HashMap;
       
    36 import java.util.Iterator;
       
    37 import java.util.Map;
       
    38 
       
    39 import java.util.concurrent.ArrayBlockingQueue;
       
    40 import java.util.concurrent.BlockingQueue;
       
    41 import java.util.concurrent.TimeUnit;
       
    42 
       
    43 import java.lang.management.ManagementFactory;
       
    44 
       
    45 import javax.management.Attribute;
       
    46 import javax.management.Descriptor;
       
    47 import javax.management.ImmutableDescriptor;
       
    48 import javax.management.MBeanServer;
       
    49 import javax.management.MBeanInfo;
       
    50 import javax.management.MBeanNotificationInfo;
       
    51 import javax.management.Notification;
       
    52 import javax.management.NotificationListener;
       
    53 import javax.management.MBeanServerConnection;
       
    54 import javax.management.ObjectName;
       
    55 
       
    56 import javax.management.remote.JMXConnector;
       
    57 import javax.management.remote.JMXConnectorFactory;
       
    58 import javax.management.remote.JMXConnectorServer;
       
    59 import javax.management.remote.JMXConnectorServerFactory;
       
    60 import javax.management.remote.JMXServiceURL;
       
    61 
       
    62 import javax.management.openmbean.CompositeType;
       
    63 import javax.management.openmbean.CompositeData;
       
    64 import javax.management.openmbean.CompositeDataSupport;
       
    65 import javax.management.openmbean.OpenType;
       
    66 import javax.management.openmbean.SimpleType;
       
    67 import javax.management.openmbean.TabularData;
       
    68 import javax.management.openmbean.TabularDataSupport;
       
    69 import javax.management.openmbean.TabularType;
       
    70 
       
    71 public class MXBeanNotifTest implements NotificationListener {
       
    72 
       
    73     private static String BASIC_MXBEAN_CLASS_NAME = "Basic";
       
    74     private static String BASIC_MXBEAN_INTERFACE_NAME = "BasicMXBean";
       
    75 
       
    76     private long timeForNotificationInSeconds = 3L;
       
    77     private int numOfNotifications = 1;
       
    78     private BlockingQueue<Notification> notifList = null;
       
    79     private int numOfNotifDescriptorElements = 13;
       
    80 
       
    81     /*
       
    82      * First Debug properties and arguments are collect in expected
       
    83      * map  (argName, value) format, then calls original test's run method.
       
    84      */
       
    85     public static void main(String args[]) throws Exception {
       
    86 
       
    87         System.out.println("=================================================");
       
    88 
       
    89         // Parses parameters
       
    90         Utils.parseDebugProperties();
       
    91         Map<String, Object> map = Utils.parseParameters(args) ;
       
    92 
       
    93         // Run test
       
    94         MXBeanNotifTest test = new MXBeanNotifTest();
       
    95         test.run(map);
       
    96 
       
    97     }
       
    98 
       
    99     protected void parseArgs(Map<String, Object> args) throws Exception {
       
   100 
       
   101         String arg = null;
       
   102 
       
   103         // Init numOfNotifications
       
   104         // It is the number of notifications we should trigger and check.
       
   105         arg = (String)args.get("-numOfNotifications") ;
       
   106         if (arg != null) {
       
   107             numOfNotifications = (new Integer(arg)).intValue();
       
   108         }
       
   109 
       
   110         // Init timeForNotificationInSeconds
       
   111         // It is the maximum time in seconds we wait for each notification.
       
   112         arg = (String)args.get("-timeForEachNotificationInSeconds") ;
       
   113         if (arg != null) {
       
   114             timeForNotificationInSeconds = (new Long(arg)).longValue();
       
   115         }
       
   116 
       
   117     }
       
   118 
       
   119     public void run(Map<String, Object> args) {
       
   120 
       
   121         System.out.println("MXBeanNotifTest::run: Start") ;
       
   122         int errorCount = 0 ;
       
   123 
       
   124         try {
       
   125             parseArgs(args);
       
   126             notifList = new ArrayBlockingQueue<Notification>(numOfNotifications);
       
   127 
       
   128             // JMX MbeanServer used inside single VM as if remote.
       
   129             MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
       
   130 
       
   131             JMXServiceURL url = new JMXServiceURL("rmi", null, 0);
       
   132             JMXConnectorServer cs =
       
   133                 JMXConnectorServerFactory.newJMXConnectorServer(url, null, mbs);
       
   134             cs.start();
       
   135 
       
   136             JMXServiceURL addr = cs.getAddress();
       
   137             JMXConnector cc = JMXConnectorFactory.connect(addr);
       
   138             MBeanServerConnection mbsc = cc.getMBeanServerConnection();
       
   139 
       
   140             // ----
       
   141             System.out.println("MXBeanNotifTest::run: Create and register the MBean");
       
   142             ObjectName objName = new ObjectName("sqe:type=Basic,protocol=rmi") ;
       
   143             mbsc.createMBean(BASIC_MXBEAN_CLASS_NAME, objName);
       
   144             System.out.println("---- OK\n") ;
       
   145 
       
   146             // ----
       
   147             System.out.println("MXBeanNotifTest::run: Add me as notification listener");
       
   148             mbsc.addNotificationListener(objName, this, null, null);
       
   149 
       
   150             // ----
       
   151             System.out.println("MXBeanNotifTest::run: Retrieve the Descriptor"
       
   152                     + " that should be in MBeanNotificationInfo");
       
   153             TabularData tabData =
       
   154                 (TabularData)mbsc.getAttribute(objName, "NotifDescriptorAsMapAtt");
       
   155             Map<String, String> descrMap = new HashMap<>();
       
   156 
       
   157             for (Iterator<?> it = tabData.values().iterator(); it.hasNext(); ) {
       
   158                 CompositeData compData = (CompositeData)it.next();
       
   159                 descrMap.put((String)compData.get("key"),
       
   160                         (String)compData.get("value"));
       
   161             }
       
   162 
       
   163             Descriptor refNotifDescriptor = new ImmutableDescriptor(descrMap);
       
   164             System.out.println("---- OK\n") ;
       
   165 
       
   166             // ----
       
   167             // Because the MBean holding the targeted attribute is MXBean, we
       
   168             // should use for the setAttribute a converted form for the
       
   169             // attribute value as described by the MXBean mapping rules.
       
   170             // This explains all that lovely stuff for creating a
       
   171             // TabularDataSupport.
       
   172             //
       
   173             // WARNING : the MBeanInfo of the MXBean used on opposite side
       
   174             // is computed when the MBean is registered.
       
   175             // It means the Descriptor considered for the MBeanNotificationInfo
       
   176             // is not the one we set in the lines below, it is too late.
       
   177             // However, we check that set is harmless when we check
       
   178             // the MBeanNotificationInfo.
       
   179             //
       
   180             System.out.println("MXBeanNotifTest::run: Set a Map<String, String>"
       
   181                     + " attribute");
       
   182             String typeName =
       
   183                     "java.util.Map<java.lang.String,java.lang.String>";
       
   184             String[] keyValue = new String[] {"key", "value"};
       
   185             OpenType<?>[] openTypes =
       
   186                     new OpenType<?>[] {SimpleType.STRING, SimpleType.STRING};
       
   187             CompositeType rowType = new CompositeType(typeName, typeName,
       
   188                     keyValue, keyValue, openTypes);
       
   189             TabularType tabType = new TabularType(typeName, typeName,
       
   190                     rowType, new String[]{"key"});
       
   191             TabularDataSupport convertedDescrMap =
       
   192                     new TabularDataSupport(tabType);
       
   193 
       
   194             for (int i = 0; i < numOfNotifDescriptorElements; i++) {
       
   195                 Object[] descrValue = {"field" + i, "value" + i};
       
   196                 CompositeData data =
       
   197                         new CompositeDataSupport(rowType, keyValue, descrValue);
       
   198                 convertedDescrMap.put(data);
       
   199             }
       
   200 
       
   201             Attribute descrAtt =
       
   202                     new Attribute("NotifDescriptorAsMapAtt", convertedDescrMap);
       
   203             mbsc.setAttribute(objName, descrAtt);
       
   204             System.out.println("---- OK\n") ;
       
   205 
       
   206             // ----
       
   207             System.out.println("MXBeanNotifTest::run: Compare the Descriptor from"
       
   208                     + " the MBeanNotificationInfo against a reference");
       
   209             MBeanInfo mbInfo = mbsc.getMBeanInfo(objName);
       
   210             errorCount += checkMBeanInfo(mbInfo, refNotifDescriptor);
       
   211             System.out.println("---- DONE\n") ;
       
   212 
       
   213             // ----
       
   214             System.out.println("Check isInstanceOf(Basic)");
       
   215 
       
   216             if ( ! mbsc.isInstanceOf(objName, BASIC_MXBEAN_CLASS_NAME) ) {
       
   217                 errorCount++;
       
   218                 System.out.println("---- ERROR isInstanceOf returned false\n") ;
       
   219             } else {
       
   220                 System.out.println("---- OK\n") ;
       
   221             }
       
   222 
       
   223             // ----
       
   224             System.out.println("Check isInstanceOf(BasicMXBean)");
       
   225 
       
   226             if ( ! mbsc.isInstanceOf(objName, BASIC_MXBEAN_INTERFACE_NAME) ) {
       
   227                 errorCount++;
       
   228                 System.out.println("---- ERROR isInstanceOf returned false\n") ;
       
   229             } else {
       
   230                 System.out.println("---- OK\n") ;
       
   231             }
       
   232 
       
   233             // ----
       
   234             System.out.println("MXBeanNotifTest::run: Ask for "
       
   235                     + numOfNotifications + " notification(s)");
       
   236             Object[] sendNotifParam = new Object[1];
       
   237             String[] sendNotifSig = new String[]{"java.lang.String"};
       
   238 
       
   239             for (int i = 0; i < numOfNotifications; i++) {
       
   240                 // Select which type of notification we ask for
       
   241                 if ( i % 2 == 0 ) {
       
   242                     sendNotifParam[0] = Basic.NOTIF_TYPE_0;
       
   243                 } else {
       
   244                     sendNotifParam[0] = Basic.NOTIF_TYPE_1;
       
   245                 }
       
   246 
       
   247                 // Trigger notification emission
       
   248                 mbsc.invoke(objName,
       
   249                         "sendNotification",
       
   250                         sendNotifParam,
       
   251                         sendNotifSig);
       
   252 
       
   253                 // Wait for it then check it when it comes early enough
       
   254                 Notification notif =
       
   255                         notifList.poll(timeForNotificationInSeconds,
       
   256                         TimeUnit.SECONDS) ;
       
   257                 // The very first notification is likely to come in slower than
       
   258                 // all the others. Because that test isn't targeting the speed
       
   259                 // notifications are delivered with, we prefer to secure it.
       
   260                 if (i == 0 && notif == null) {
       
   261                     System.out.println("MXBeanNotifTest::run: Wait extra "
       
   262                             + timeForNotificationInSeconds + " second(s) the "
       
   263                             + " very first notification");
       
   264                     notif = notifList.poll(timeForNotificationInSeconds,
       
   265                             TimeUnit.SECONDS);
       
   266                 }
       
   267 
       
   268                 if ( notif == null ) {
       
   269                     errorCount++;
       
   270                     System.out.println("---- ERROR No notification received"
       
   271                             + " within allocated " + timeForNotificationInSeconds
       
   272                             + " second(s) !");
       
   273                 } else {
       
   274                     errorCount +=
       
   275                             checkNotification(notif,
       
   276                             (String)sendNotifParam[0],
       
   277                             Basic.NOTIFICATION_MESSAGE,
       
   278                             objName);
       
   279                 }
       
   280             }
       
   281 
       
   282             int toc = 0;
       
   283             while ( notifList.size() < 2 && toc < 10 ) {
       
   284                 Thread.sleep(499);
       
   285                 toc++;
       
   286             }
       
   287             System.out.println("---- DONE\n") ;
       
   288         } catch(Exception e) {
       
   289             Utils.printThrowable(e, true) ;
       
   290             throw new RuntimeException(e);
       
   291         }
       
   292 
       
   293         if ( errorCount == 0 ) {
       
   294             System.out.println("MXBeanNotifTest::run: Done without any error") ;
       
   295         } else {
       
   296             System.out.println("MXBeanNotifTest::run: Done with "
       
   297                     + errorCount
       
   298                     + " error(s)") ;
       
   299             throw new RuntimeException("errorCount = " + errorCount);
       
   300         }
       
   301     }
       
   302 
       
   303 
       
   304     private int checkMBeanInfo(MBeanInfo mbi, Descriptor refDescr) {
       
   305         MBeanNotificationInfo[] notifsInfo = mbi.getNotifications();
       
   306         int res = 0;
       
   307 
       
   308         for (MBeanNotificationInfo mbni : notifsInfo) {
       
   309             if ( mbni.getDescriptor().equals(refDescr) ) {
       
   310                 System.out.println("(OK)");
       
   311             } else {
       
   312                 System.out.println("(ERROR) Descriptor of the notification is "
       
   313                         + mbni.getDescriptor()
       
   314                         + " as we expect "
       
   315                         + refDescr);
       
   316                 res++;
       
   317             }
       
   318         }
       
   319 
       
   320         return res;
       
   321     }
       
   322 
       
   323 
       
   324     private int checkNotification(Notification notif,
       
   325             String refType,
       
   326             String refMessage,
       
   327             ObjectName refSource) {
       
   328         int res = 0;
       
   329 
       
   330         Utils.debug(Utils.DEBUG_VERBOSE,
       
   331                 "\t getSource " + notif.getSource());
       
   332         Utils.debug(Utils.DEBUG_VERBOSE,
       
   333                 "\t getMessage " + notif.getMessage());
       
   334         Utils.debug(Utils.DEBUG_VERBOSE,
       
   335                 "\t getSequenceNumber " + notif.getSequenceNumber());
       
   336         Utils.debug(Utils.DEBUG_VERBOSE,
       
   337                 "\t getTimeStamp " + notif.getTimeStamp());
       
   338         Utils.debug(Utils.DEBUG_VERBOSE,
       
   339                 "\t getType " + notif.getType());
       
   340         Utils.debug(Utils.DEBUG_VERBOSE,
       
   341                 "\t getUserData " + notif.getUserData());
       
   342 
       
   343         if ( ! notif.getType().equals(refType) ) {
       
   344             res++;
       
   345             System.out.println("(ERROR) Type is not "
       
   346                     + refType + " in notification\n" + notif);
       
   347         } else {
       
   348             if ( notif.getType().equals(Basic.NOTIF_TYPE_0)
       
   349             && ! (notif instanceof javax.management.Notification) ) {
       
   350                 res++;
       
   351                 System.out.println("(ERROR) Notification is not instance of "
       
   352                         + " javax.management.Notification but rather "
       
   353                         + notif.getClass().getName());
       
   354             } else if ( notif.getType().equals(Basic.NOTIF_TYPE_1)
       
   355             && ! (notif instanceof SqeNotification) ) {
       
   356                 res++;
       
   357                 System.out.println("(ERROR) Notification is not instance of "
       
   358                         + " javasoft.sqe.jmx.share.SqeNotification but rather "
       
   359                         + notif.getClass().getName());
       
   360             }
       
   361         }
       
   362 
       
   363         if ( ! notif.getMessage().equals(refMessage) ) {
       
   364             res++;
       
   365             System.out.println("(ERROR) Message is not "
       
   366                     + refMessage + " in notification\n" + notif);
       
   367         }
       
   368 
       
   369         if ( ! notif.getSource().equals(refSource) ) {
       
   370             res++;
       
   371             System.out.println("(ERROR) Source is not "
       
   372                     + refSource + " in notification\n" + notif);
       
   373         }
       
   374 
       
   375         return res;
       
   376     }
       
   377 
       
   378     public void handleNotification(Notification notification, Object handback) {
       
   379         Utils.debug(Utils.DEBUG_VERBOSE,
       
   380                 "MXBeanNotifTest::handleNotification: Received "
       
   381                 + notification);
       
   382         notifList.add(notification);
       
   383     }
       
   384 
       
   385 }