--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/management/mxbean/MXBeanNotifTest.java Fri Dec 18 17:42:06 2015 +0100
@@ -0,0 +1,385 @@
+/*
+ * Copyright (c) 2005, 2015, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8058865
+ * @summary Checks MXBean proper registration both as its implementation class and interface
+ * @author Olivier Lagneau
+ * @modules java.management
+ * @library /lib/testlibrary
+ * @compile Basic.java
+ * @run main/othervm/timeout=300 -DDEBUG_STANDARD MXBeanNotifTest -numOfNotifications 239 -timeForNotificationInSeconds 4
+ */
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+import java.util.concurrent.ArrayBlockingQueue;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.TimeUnit;
+
+import java.lang.management.ManagementFactory;
+
+import javax.management.Attribute;
+import javax.management.Descriptor;
+import javax.management.ImmutableDescriptor;
+import javax.management.MBeanServer;
+import javax.management.MBeanInfo;
+import javax.management.MBeanNotificationInfo;
+import javax.management.Notification;
+import javax.management.NotificationListener;
+import javax.management.MBeanServerConnection;
+import javax.management.ObjectName;
+
+import javax.management.remote.JMXConnector;
+import javax.management.remote.JMXConnectorFactory;
+import javax.management.remote.JMXConnectorServer;
+import javax.management.remote.JMXConnectorServerFactory;
+import javax.management.remote.JMXServiceURL;
+
+import javax.management.openmbean.CompositeType;
+import javax.management.openmbean.CompositeData;
+import javax.management.openmbean.CompositeDataSupport;
+import javax.management.openmbean.OpenType;
+import javax.management.openmbean.SimpleType;
+import javax.management.openmbean.TabularData;
+import javax.management.openmbean.TabularDataSupport;
+import javax.management.openmbean.TabularType;
+
+public class MXBeanNotifTest implements NotificationListener {
+
+ private static String BASIC_MXBEAN_CLASS_NAME = "Basic";
+ private static String BASIC_MXBEAN_INTERFACE_NAME = "BasicMXBean";
+
+ private long timeForNotificationInSeconds = 3L;
+ private int numOfNotifications = 1;
+ private BlockingQueue<Notification> notifList = null;
+ private int numOfNotifDescriptorElements = 13;
+
+ /*
+ * First Debug properties and arguments are collect in expected
+ * map (argName, value) format, then calls original test's run method.
+ */
+ public static void main(String args[]) throws Exception {
+
+ System.out.println("=================================================");
+
+ // Parses parameters
+ Utils.parseDebugProperties();
+ Map<String, Object> map = Utils.parseParameters(args) ;
+
+ // Run test
+ MXBeanNotifTest test = new MXBeanNotifTest();
+ test.run(map);
+
+ }
+
+ protected void parseArgs(Map<String, Object> args) throws Exception {
+
+ String arg = null;
+
+ // Init numOfNotifications
+ // It is the number of notifications we should trigger and check.
+ arg = (String)args.get("-numOfNotifications") ;
+ if (arg != null) {
+ numOfNotifications = (new Integer(arg)).intValue();
+ }
+
+ // Init timeForNotificationInSeconds
+ // It is the maximum time in seconds we wait for each notification.
+ arg = (String)args.get("-timeForEachNotificationInSeconds") ;
+ if (arg != null) {
+ timeForNotificationInSeconds = (new Long(arg)).longValue();
+ }
+
+ }
+
+ public void run(Map<String, Object> args) {
+
+ System.out.println("MXBeanNotifTest::run: Start") ;
+ int errorCount = 0 ;
+
+ try {
+ parseArgs(args);
+ notifList = new ArrayBlockingQueue<Notification>(numOfNotifications);
+
+ // JMX MbeanServer used inside single VM as if remote.
+ MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
+
+ JMXServiceURL url = new JMXServiceURL("rmi", null, 0);
+ JMXConnectorServer cs =
+ JMXConnectorServerFactory.newJMXConnectorServer(url, null, mbs);
+ cs.start();
+
+ JMXServiceURL addr = cs.getAddress();
+ JMXConnector cc = JMXConnectorFactory.connect(addr);
+ MBeanServerConnection mbsc = cc.getMBeanServerConnection();
+
+ // ----
+ System.out.println("MXBeanNotifTest::run: Create and register the MBean");
+ ObjectName objName = new ObjectName("sqe:type=Basic,protocol=rmi") ;
+ mbsc.createMBean(BASIC_MXBEAN_CLASS_NAME, objName);
+ System.out.println("---- OK\n") ;
+
+ // ----
+ System.out.println("MXBeanNotifTest::run: Add me as notification listener");
+ mbsc.addNotificationListener(objName, this, null, null);
+
+ // ----
+ System.out.println("MXBeanNotifTest::run: Retrieve the Descriptor"
+ + " that should be in MBeanNotificationInfo");
+ TabularData tabData =
+ (TabularData)mbsc.getAttribute(objName, "NotifDescriptorAsMapAtt");
+ Map<String, String> descrMap = new HashMap<>();
+
+ for (Iterator<?> it = tabData.values().iterator(); it.hasNext(); ) {
+ CompositeData compData = (CompositeData)it.next();
+ descrMap.put((String)compData.get("key"),
+ (String)compData.get("value"));
+ }
+
+ Descriptor refNotifDescriptor = new ImmutableDescriptor(descrMap);
+ System.out.println("---- OK\n") ;
+
+ // ----
+ // Because the MBean holding the targeted attribute is MXBean, we
+ // should use for the setAttribute a converted form for the
+ // attribute value as described by the MXBean mapping rules.
+ // This explains all that lovely stuff for creating a
+ // TabularDataSupport.
+ //
+ // WARNING : the MBeanInfo of the MXBean used on opposite side
+ // is computed when the MBean is registered.
+ // It means the Descriptor considered for the MBeanNotificationInfo
+ // is not the one we set in the lines below, it is too late.
+ // However, we check that set is harmless when we check
+ // the MBeanNotificationInfo.
+ //
+ System.out.println("MXBeanNotifTest::run: Set a Map<String, String>"
+ + " attribute");
+ String typeName =
+ "java.util.Map<java.lang.String,java.lang.String>";
+ String[] keyValue = new String[] {"key", "value"};
+ OpenType<?>[] openTypes =
+ new OpenType<?>[] {SimpleType.STRING, SimpleType.STRING};
+ CompositeType rowType = new CompositeType(typeName, typeName,
+ keyValue, keyValue, openTypes);
+ TabularType tabType = new TabularType(typeName, typeName,
+ rowType, new String[]{"key"});
+ TabularDataSupport convertedDescrMap =
+ new TabularDataSupport(tabType);
+
+ for (int i = 0; i < numOfNotifDescriptorElements; i++) {
+ Object[] descrValue = {"field" + i, "value" + i};
+ CompositeData data =
+ new CompositeDataSupport(rowType, keyValue, descrValue);
+ convertedDescrMap.put(data);
+ }
+
+ Attribute descrAtt =
+ new Attribute("NotifDescriptorAsMapAtt", convertedDescrMap);
+ mbsc.setAttribute(objName, descrAtt);
+ System.out.println("---- OK\n") ;
+
+ // ----
+ System.out.println("MXBeanNotifTest::run: Compare the Descriptor from"
+ + " the MBeanNotificationInfo against a reference");
+ MBeanInfo mbInfo = mbsc.getMBeanInfo(objName);
+ errorCount += checkMBeanInfo(mbInfo, refNotifDescriptor);
+ System.out.println("---- DONE\n") ;
+
+ // ----
+ System.out.println("Check isInstanceOf(Basic)");
+
+ if ( ! mbsc.isInstanceOf(objName, BASIC_MXBEAN_CLASS_NAME) ) {
+ errorCount++;
+ System.out.println("---- ERROR isInstanceOf returned false\n") ;
+ } else {
+ System.out.println("---- OK\n") ;
+ }
+
+ // ----
+ System.out.println("Check isInstanceOf(BasicMXBean)");
+
+ if ( ! mbsc.isInstanceOf(objName, BASIC_MXBEAN_INTERFACE_NAME) ) {
+ errorCount++;
+ System.out.println("---- ERROR isInstanceOf returned false\n") ;
+ } else {
+ System.out.println("---- OK\n") ;
+ }
+
+ // ----
+ System.out.println("MXBeanNotifTest::run: Ask for "
+ + numOfNotifications + " notification(s)");
+ Object[] sendNotifParam = new Object[1];
+ String[] sendNotifSig = new String[]{"java.lang.String"};
+
+ for (int i = 0; i < numOfNotifications; i++) {
+ // Select which type of notification we ask for
+ if ( i % 2 == 0 ) {
+ sendNotifParam[0] = Basic.NOTIF_TYPE_0;
+ } else {
+ sendNotifParam[0] = Basic.NOTIF_TYPE_1;
+ }
+
+ // Trigger notification emission
+ mbsc.invoke(objName,
+ "sendNotification",
+ sendNotifParam,
+ sendNotifSig);
+
+ // Wait for it then check it when it comes early enough
+ Notification notif =
+ notifList.poll(timeForNotificationInSeconds,
+ TimeUnit.SECONDS) ;
+ // The very first notification is likely to come in slower than
+ // all the others. Because that test isn't targeting the speed
+ // notifications are delivered with, we prefer to secure it.
+ if (i == 0 && notif == null) {
+ System.out.println("MXBeanNotifTest::run: Wait extra "
+ + timeForNotificationInSeconds + " second(s) the "
+ + " very first notification");
+ notif = notifList.poll(timeForNotificationInSeconds,
+ TimeUnit.SECONDS);
+ }
+
+ if ( notif == null ) {
+ errorCount++;
+ System.out.println("---- ERROR No notification received"
+ + " within allocated " + timeForNotificationInSeconds
+ + " second(s) !");
+ } else {
+ errorCount +=
+ checkNotification(notif,
+ (String)sendNotifParam[0],
+ Basic.NOTIFICATION_MESSAGE,
+ objName);
+ }
+ }
+
+ int toc = 0;
+ while ( notifList.size() < 2 && toc < 10 ) {
+ Thread.sleep(499);
+ toc++;
+ }
+ System.out.println("---- DONE\n") ;
+ } catch(Exception e) {
+ Utils.printThrowable(e, true) ;
+ throw new RuntimeException(e);
+ }
+
+ if ( errorCount == 0 ) {
+ System.out.println("MXBeanNotifTest::run: Done without any error") ;
+ } else {
+ System.out.println("MXBeanNotifTest::run: Done with "
+ + errorCount
+ + " error(s)") ;
+ throw new RuntimeException("errorCount = " + errorCount);
+ }
+ }
+
+
+ private int checkMBeanInfo(MBeanInfo mbi, Descriptor refDescr) {
+ MBeanNotificationInfo[] notifsInfo = mbi.getNotifications();
+ int res = 0;
+
+ for (MBeanNotificationInfo mbni : notifsInfo) {
+ if ( mbni.getDescriptor().equals(refDescr) ) {
+ System.out.println("(OK)");
+ } else {
+ System.out.println("(ERROR) Descriptor of the notification is "
+ + mbni.getDescriptor()
+ + " as we expect "
+ + refDescr);
+ res++;
+ }
+ }
+
+ return res;
+ }
+
+
+ private int checkNotification(Notification notif,
+ String refType,
+ String refMessage,
+ ObjectName refSource) {
+ int res = 0;
+
+ Utils.debug(Utils.DEBUG_VERBOSE,
+ "\t getSource " + notif.getSource());
+ Utils.debug(Utils.DEBUG_VERBOSE,
+ "\t getMessage " + notif.getMessage());
+ Utils.debug(Utils.DEBUG_VERBOSE,
+ "\t getSequenceNumber " + notif.getSequenceNumber());
+ Utils.debug(Utils.DEBUG_VERBOSE,
+ "\t getTimeStamp " + notif.getTimeStamp());
+ Utils.debug(Utils.DEBUG_VERBOSE,
+ "\t getType " + notif.getType());
+ Utils.debug(Utils.DEBUG_VERBOSE,
+ "\t getUserData " + notif.getUserData());
+
+ if ( ! notif.getType().equals(refType) ) {
+ res++;
+ System.out.println("(ERROR) Type is not "
+ + refType + " in notification\n" + notif);
+ } else {
+ if ( notif.getType().equals(Basic.NOTIF_TYPE_0)
+ && ! (notif instanceof javax.management.Notification) ) {
+ res++;
+ System.out.println("(ERROR) Notification is not instance of "
+ + " javax.management.Notification but rather "
+ + notif.getClass().getName());
+ } else if ( notif.getType().equals(Basic.NOTIF_TYPE_1)
+ && ! (notif instanceof SqeNotification) ) {
+ res++;
+ System.out.println("(ERROR) Notification is not instance of "
+ + " javasoft.sqe.jmx.share.SqeNotification but rather "
+ + notif.getClass().getName());
+ }
+ }
+
+ if ( ! notif.getMessage().equals(refMessage) ) {
+ res++;
+ System.out.println("(ERROR) Message is not "
+ + refMessage + " in notification\n" + notif);
+ }
+
+ if ( ! notif.getSource().equals(refSource) ) {
+ res++;
+ System.out.println("(ERROR) Source is not "
+ + refSource + " in notification\n" + notif);
+ }
+
+ return res;
+ }
+
+ public void handleNotification(Notification notification, Object handback) {
+ Utils.debug(Utils.DEBUG_VERBOSE,
+ "MXBeanNotifTest::handleNotification: Received "
+ + notification);
+ notifList.add(notification);
+ }
+
+}