Path: blob/master/test/jdk/javax/management/mxbean/MXBeanNotifTest.java
41152 views
/*1* Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/2223/*24* @test25* @bug 805886526* @summary Checks MXBean proper registration both as its implementation class and interface27* @author Olivier Lagneau28* @modules java.management.rmi29* @library /lib/testlibrary30* @compile Basic.java31* @run main/othervm/timeout=300 -DDEBUG_STANDARD MXBeanNotifTest -numOfNotifications 239 -timeForNotificationInSeconds 432*/3334import java.util.HashMap;35import java.util.Iterator;36import java.util.Map;3738import java.util.concurrent.ArrayBlockingQueue;39import java.util.concurrent.BlockingQueue;40import java.util.concurrent.TimeUnit;4142import java.lang.management.ManagementFactory;4344import javax.management.Attribute;45import javax.management.Descriptor;46import javax.management.ImmutableDescriptor;47import javax.management.MBeanServer;48import javax.management.MBeanInfo;49import javax.management.MBeanNotificationInfo;50import javax.management.Notification;51import javax.management.NotificationListener;52import javax.management.MBeanServerConnection;53import javax.management.ObjectName;5455import javax.management.remote.JMXConnector;56import javax.management.remote.JMXConnectorFactory;57import javax.management.remote.JMXConnectorServer;58import javax.management.remote.JMXConnectorServerFactory;59import javax.management.remote.JMXServiceURL;6061import javax.management.openmbean.CompositeType;62import javax.management.openmbean.CompositeData;63import javax.management.openmbean.CompositeDataSupport;64import javax.management.openmbean.OpenType;65import javax.management.openmbean.SimpleType;66import javax.management.openmbean.TabularData;67import javax.management.openmbean.TabularDataSupport;68import javax.management.openmbean.TabularType;6970public class MXBeanNotifTest implements NotificationListener {7172private static String BASIC_MXBEAN_CLASS_NAME = "Basic";73private static String BASIC_MXBEAN_INTERFACE_NAME = "BasicMXBean";7475private long timeForNotificationInSeconds = 3L;76private int numOfNotifications = 1;77private BlockingQueue<Notification> notifList = null;78private int numOfNotifDescriptorElements = 13;7980/*81* First Debug properties and arguments are collect in expected82* map (argName, value) format, then calls original test's run method.83*/84public static void main(String args[]) throws Exception {8586System.out.println("=================================================");8788// Parses parameters89Utils.parseDebugProperties();90Map<String, Object> map = Utils.parseParameters(args) ;9192// Run test93MXBeanNotifTest test = new MXBeanNotifTest();94test.run(map);9596}9798protected void parseArgs(Map<String, Object> args) throws Exception {99100String arg = null;101102// Init numOfNotifications103// It is the number of notifications we should trigger and check.104arg = (String)args.get("-numOfNotifications") ;105if (arg != null) {106numOfNotifications = (new Integer(arg)).intValue();107}108109// Init timeForNotificationInSeconds110// It is the maximum time in seconds we wait for each notification.111arg = (String)args.get("-timeForEachNotificationInSeconds") ;112if (arg != null) {113timeForNotificationInSeconds = (new Long(arg)).longValue();114}115116}117118public void run(Map<String, Object> args) {119120System.out.println("MXBeanNotifTest::run: Start") ;121int errorCount = 0 ;122123try {124parseArgs(args);125notifList = new ArrayBlockingQueue<Notification>(numOfNotifications);126127// JMX MbeanServer used inside single VM as if remote.128MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();129130JMXServiceURL url = new JMXServiceURL("rmi", null, 0);131JMXConnectorServer cs =132JMXConnectorServerFactory.newJMXConnectorServer(url, null, mbs);133cs.start();134135JMXServiceURL addr = cs.getAddress();136JMXConnector cc = JMXConnectorFactory.connect(addr);137MBeanServerConnection mbsc = cc.getMBeanServerConnection();138139// ----140System.out.println("MXBeanNotifTest::run: Create and register the MBean");141ObjectName objName = new ObjectName("sqe:type=Basic,protocol=rmi") ;142mbsc.createMBean(BASIC_MXBEAN_CLASS_NAME, objName);143System.out.println("---- OK\n") ;144145// ----146System.out.println("MXBeanNotifTest::run: Add me as notification listener");147mbsc.addNotificationListener(objName, this, null, null);148149// ----150System.out.println("MXBeanNotifTest::run: Retrieve the Descriptor"151+ " that should be in MBeanNotificationInfo");152TabularData tabData =153(TabularData)mbsc.getAttribute(objName, "NotifDescriptorAsMapAtt");154Map<String, String> descrMap = new HashMap<>();155156for (Iterator<?> it = tabData.values().iterator(); it.hasNext(); ) {157CompositeData compData = (CompositeData)it.next();158descrMap.put((String)compData.get("key"),159(String)compData.get("value"));160}161162Descriptor refNotifDescriptor = new ImmutableDescriptor(descrMap);163System.out.println("---- OK\n") ;164165// ----166// Because the MBean holding the targeted attribute is MXBean, we167// should use for the setAttribute a converted form for the168// attribute value as described by the MXBean mapping rules.169// This explains all that lovely stuff for creating a170// TabularDataSupport.171//172// WARNING : the MBeanInfo of the MXBean used on opposite side173// is computed when the MBean is registered.174// It means the Descriptor considered for the MBeanNotificationInfo175// is not the one we set in the lines below, it is too late.176// However, we check that set is harmless when we check177// the MBeanNotificationInfo.178//179System.out.println("MXBeanNotifTest::run: Set a Map<String, String>"180+ " attribute");181String typeName =182"java.util.Map<java.lang.String,java.lang.String>";183String[] keyValue = new String[] {"key", "value"};184OpenType<?>[] openTypes =185new OpenType<?>[] {SimpleType.STRING, SimpleType.STRING};186CompositeType rowType = new CompositeType(typeName, typeName,187keyValue, keyValue, openTypes);188TabularType tabType = new TabularType(typeName, typeName,189rowType, new String[]{"key"});190TabularDataSupport convertedDescrMap =191new TabularDataSupport(tabType);192193for (int i = 0; i < numOfNotifDescriptorElements; i++) {194Object[] descrValue = {"field" + i, "value" + i};195CompositeData data =196new CompositeDataSupport(rowType, keyValue, descrValue);197convertedDescrMap.put(data);198}199200Attribute descrAtt =201new Attribute("NotifDescriptorAsMapAtt", convertedDescrMap);202mbsc.setAttribute(objName, descrAtt);203System.out.println("---- OK\n") ;204205// ----206System.out.println("MXBeanNotifTest::run: Compare the Descriptor from"207+ " the MBeanNotificationInfo against a reference");208MBeanInfo mbInfo = mbsc.getMBeanInfo(objName);209errorCount += checkMBeanInfo(mbInfo, refNotifDescriptor);210System.out.println("---- DONE\n") ;211212// ----213System.out.println("Check isInstanceOf(Basic)");214215if ( ! mbsc.isInstanceOf(objName, BASIC_MXBEAN_CLASS_NAME) ) {216errorCount++;217System.out.println("---- ERROR isInstanceOf returned false\n") ;218} else {219System.out.println("---- OK\n") ;220}221222// ----223System.out.println("Check isInstanceOf(BasicMXBean)");224225if ( ! mbsc.isInstanceOf(objName, BASIC_MXBEAN_INTERFACE_NAME) ) {226errorCount++;227System.out.println("---- ERROR isInstanceOf returned false\n") ;228} else {229System.out.println("---- OK\n") ;230}231232// ----233System.out.println("MXBeanNotifTest::run: Ask for "234+ numOfNotifications + " notification(s)");235Object[] sendNotifParam = new Object[1];236String[] sendNotifSig = new String[]{"java.lang.String"};237238for (int i = 0; i < numOfNotifications; i++) {239// Select which type of notification we ask for240if ( i % 2 == 0 ) {241sendNotifParam[0] = Basic.NOTIF_TYPE_0;242} else {243sendNotifParam[0] = Basic.NOTIF_TYPE_1;244}245246// Trigger notification emission247mbsc.invoke(objName,248"sendNotification",249sendNotifParam,250sendNotifSig);251252// Wait for it then check it when it comes early enough253Notification notif =254notifList.poll(timeForNotificationInSeconds,255TimeUnit.SECONDS) ;256// The very first notification is likely to come in slower than257// all the others. Because that test isn't targeting the speed258// notifications are delivered with, we prefer to secure it.259if (i == 0 && notif == null) {260System.out.println("MXBeanNotifTest::run: Wait extra "261+ timeForNotificationInSeconds + " second(s) the "262+ " very first notification");263notif = notifList.poll(timeForNotificationInSeconds,264TimeUnit.SECONDS);265}266267if ( notif == null ) {268errorCount++;269System.out.println("---- ERROR No notification received"270+ " within allocated " + timeForNotificationInSeconds271+ " second(s) !");272} else {273errorCount +=274checkNotification(notif,275(String)sendNotifParam[0],276Basic.NOTIFICATION_MESSAGE,277objName);278}279}280281int toc = 0;282while ( notifList.size() < 2 && toc < 10 ) {283Thread.sleep(499);284toc++;285}286System.out.println("---- DONE\n") ;287} catch(Exception e) {288Utils.printThrowable(e, true) ;289throw new RuntimeException(e);290}291292if ( errorCount == 0 ) {293System.out.println("MXBeanNotifTest::run: Done without any error") ;294} else {295System.out.println("MXBeanNotifTest::run: Done with "296+ errorCount297+ " error(s)") ;298throw new RuntimeException("errorCount = " + errorCount);299}300}301302303private int checkMBeanInfo(MBeanInfo mbi, Descriptor refDescr) {304MBeanNotificationInfo[] notifsInfo = mbi.getNotifications();305int res = 0;306307for (MBeanNotificationInfo mbni : notifsInfo) {308if ( mbni.getDescriptor().equals(refDescr) ) {309System.out.println("(OK)");310} else {311System.out.println("(ERROR) Descriptor of the notification is "312+ mbni.getDescriptor()313+ " as we expect "314+ refDescr);315res++;316}317}318319return res;320}321322323private int checkNotification(Notification notif,324String refType,325String refMessage,326ObjectName refSource) {327int res = 0;328329Utils.debug(Utils.DEBUG_VERBOSE,330"\t getSource " + notif.getSource());331Utils.debug(Utils.DEBUG_VERBOSE,332"\t getMessage " + notif.getMessage());333Utils.debug(Utils.DEBUG_VERBOSE,334"\t getSequenceNumber " + notif.getSequenceNumber());335Utils.debug(Utils.DEBUG_VERBOSE,336"\t getTimeStamp " + notif.getTimeStamp());337Utils.debug(Utils.DEBUG_VERBOSE,338"\t getType " + notif.getType());339Utils.debug(Utils.DEBUG_VERBOSE,340"\t getUserData " + notif.getUserData());341342if ( ! notif.getType().equals(refType) ) {343res++;344System.out.println("(ERROR) Type is not "345+ refType + " in notification\n" + notif);346} else {347if ( notif.getType().equals(Basic.NOTIF_TYPE_0)348&& ! (notif instanceof javax.management.Notification) ) {349res++;350System.out.println("(ERROR) Notification is not instance of "351+ " javax.management.Notification but rather "352+ notif.getClass().getName());353} else if ( notif.getType().equals(Basic.NOTIF_TYPE_1)354&& ! (notif instanceof SqeNotification) ) {355res++;356System.out.println("(ERROR) Notification is not instance of "357+ " javasoft.sqe.jmx.share.SqeNotification but rather "358+ notif.getClass().getName());359}360}361362if ( ! notif.getMessage().equals(refMessage) ) {363res++;364System.out.println("(ERROR) Message is not "365+ refMessage + " in notification\n" + notif);366}367368if ( ! notif.getSource().equals(refSource) ) {369res++;370System.out.println("(ERROR) Source is not "371+ refSource + " in notification\n" + notif);372}373374return res;375}376377public void handleNotification(Notification notification, Object handback) {378Utils.debug(Utils.DEBUG_VERBOSE,379"MXBeanNotifTest::handleNotification: Received "380+ notification);381notifList.add(notification);382}383384}385386387