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 correct exception and error events from NotificationListener
  28  * @author Olivier Lagneau
  29  * @modules java.management
  30  * @library /lib/testlibrary
  31  * @compile Basic.java
  32  * @run main/othervm/timeout=300 -DDEBUG_STANDARD MXBeanExceptionHandlingTest -timeForNotificationInSeconds 3
  33  */
  34 
  35 
  36 import java.util.Map;
  37 import java.util.HashMap;
  38 import java.util.concurrent.ArrayBlockingQueue;
  39 import java.util.concurrent.BlockingQueue;
  40 
  41 import java.lang.management.ManagementFactory;
  42 import javax.management.MBeanServer;
  43 import javax.management.MBeanException;
  44 import javax.management.MBeanServerDelegate;
  45 import javax.management.Notification;
  46 import javax.management.NotificationListener;
  47 import javax.management.MBeanServerConnection;
  48 import javax.management.ObjectName;
  49 import javax.management.RuntimeErrorException;
  50 import javax.management.remote.JMXConnector;
  51 import javax.management.remote.JMXConnectorFactory;
  52 import javax.management.remote.JMXConnectorServer;
  53 import javax.management.remote.JMXConnectorServerFactory;
  54 import javax.management.remote.JMXServiceURL;
  55 
  56 public class MXBeanExceptionHandlingTest implements NotificationListener {
  57 
  58     private static String BASIC_MXBEAN_CLASS_NAME = "Basic";
  59 
  60     private long timeForNotificationInSeconds = 3L;
  61     private int numOfNotifications = 2;
  62     private BlockingQueue<Notification> notifList = null;
  63 
  64 
  65     /*
  66      * First Debug properties and arguments are collect in expected
  67      * map  (argName, value) format, then calls original test's run method.
  68      */
  69     public static void main(String args[]) throws Exception {
  70 
  71         System.out.println("=================================================");
  72 
  73         // Parses parameters
  74         Utils.parseDebugProperties();
  75         Map<String, Object> map = Utils.parseParameters(args) ;
  76 
  77         // Run test
  78         MXBeanExceptionHandlingTest test = new MXBeanExceptionHandlingTest();
  79         test.run(map);
  80 
  81     }
  82 
  83     protected void parseArgs(Map<String, Object> args) throws Exception {
  84 
  85         String arg = null;
  86 
  87         // Init timeForNotificationInSeconds
  88         // It is the maximum time in seconds we wait for a notification.
  89         arg = (String)args.get("-timeForNotificationInSeconds") ;
  90         if (arg != null) {
  91             timeForNotificationInSeconds = (new Long(arg)).longValue();
  92         }
  93 
  94     }
  95 
  96     public void run(Map<String, Object> args) {
  97 
  98         System.out.println("MXBeanExceptionHandlingTest::run: Start") ;
  99         int errorCount = 0 ;
 100 
 101         try {
 102             parseArgs(args);
 103             notifList = new ArrayBlockingQueue<Notification>(numOfNotifications);
 104 
 105             // JMX MbeanServer used inside single VM as if remote.
 106             MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
 107 
 108             JMXServiceURL url = new JMXServiceURL("rmi", null, 0);
 109             JMXConnectorServer cs =
 110                 JMXConnectorServerFactory.newJMXConnectorServer(url, null, mbs);
 111             cs.start();
 112 
 113             JMXServiceURL addr = cs.getAddress();
 114             JMXConnector cc = JMXConnectorFactory.connect(addr);
 115             MBeanServerConnection mbsc = cc.getMBeanServerConnection();
 116 
 117             // ----
 118             System.out.println("Add me as notification listener");
 119             mbsc.addNotificationListener(MBeanServerDelegate.DELEGATE_NAME,
 120                     this, null, null);
 121             System.out.println("---- OK\n") ;
 122 
 123             // ----
 124             System.out.println("Create and register the MBean");
 125             ObjectName objName = new ObjectName("sqe:type=Basic,protocol=rmi") ;
 126             mbsc.createMBean(BASIC_MXBEAN_CLASS_NAME, objName);
 127             System.out.println("---- OK\n") ;
 128 
 129             // ----
 130             System.out.println("Call method throwException on our MXBean");
 131 
 132             try {
 133                 mbsc.invoke(objName, "throwException", null, null);
 134                 errorCount++;
 135                 System.out.println("(ERROR) Did not get awaited MBeanException") ;
 136             } catch (MBeanException mbe) {
 137                 System.out.println("(OK) Got awaited MBeanException") ;
 138                 Throwable cause = mbe.getCause();
 139 
 140                 if ( cause instanceof java.lang.Exception ) {
 141                     System.out.println("(OK) Cause is of the right class") ;
 142                     String mess = cause.getMessage();
 143 
 144                     if ( mess.equals(Basic.EXCEPTION_MESSAGE ) ) {
 145                         System.out.println("(OK) Cause message is fine") ;
 146                     } else {
 147                         errorCount++;
 148                         System.out.println("(ERROR) Cause has message "
 149                                 + cause.getMessage()
 150                                 + " as we expect "
 151                                 + Basic.EXCEPTION_MESSAGE) ;
 152                     }
 153                 } else {
 154                     errorCount++;
 155                     System.out.println("(ERROR) Cause is of  class "
 156                             + cause.getClass().getName()
 157                             + " as we expect java.lang.Exception") ;
 158                 }
 159             } catch (Exception e) {
 160                 errorCount++;
 161                 System.out.println("(ERROR) Did not get awaited MBeanException but "
 162                         + e) ;
 163                 Utils.printThrowable(e, true);
 164             }
 165             System.out.println("---- DONE\n") ;
 166 
 167             // ----
 168             System.out.println("Call method throwError on our MXBean");
 169 
 170             try {
 171                 mbsc.invoke(objName, "throwError", null, null);
 172                 errorCount++;
 173                 System.out.println("(ERROR) Did not get awaited RuntimeErrorException") ;
 174             } catch (RuntimeErrorException ree) {
 175                 System.out.println("(OK) Got awaited RuntimeErrorException") ;
 176                 Throwable cause = ree.getCause();
 177 
 178                 if ( cause instanceof java.lang.InternalError ) {
 179                     System.out.println("(OK) Cause is of the right class") ;
 180                     String mess = cause.getMessage();
 181 
 182                     if ( mess.equals(Basic.EXCEPTION_MESSAGE ) ) {
 183                         System.out.println("(OK) Cause message is fine") ;
 184                     } else {
 185                         errorCount++;
 186                         System.out.println("(ERROR) Cause has message "
 187                                 + cause.getMessage()
 188                                 + " as we expect "
 189                                 + Basic.EXCEPTION_MESSAGE) ;
 190                     }
 191                 } else {
 192                     errorCount++;
 193                     System.out.println("(ERROR) Cause is of  class "
 194                             + cause.getClass().getName()
 195                             + " as we expect java.lang.InternalError") ;
 196                 }
 197             } catch (Exception e) {
 198                 errorCount++;
 199                 System.out.println("(ERROR) Did not get awaited RuntimeErrorException but "
 200                         + e) ;
 201                 Utils.printThrowable(e, true);
 202             }
 203             System.out.println("---- DONE\n") ;
 204 
 205             // ----
 206             System.out.println("Unregister the MBean");
 207             mbsc.unregisterMBean(objName);
 208             System.out.println("---- OK\n") ;
 209 
 210             Thread.sleep(timeForNotificationInSeconds * 1000);
 211             int numOfReceivedNotif = notifList.size();
 212 
 213             if ( numOfReceivedNotif == numOfNotifications ) {
 214                 System.out.println("(OK) We received "
 215                         + numOfNotifications
 216                         + " Notifications") ;
 217             } else {
 218                 errorCount++;
 219                 System.out.println("(ERROR) We received "
 220                         + numOfReceivedNotif
 221                         + " Notifications in place of "
 222                         + numOfNotifications) ;
 223             }
 224         } catch(Exception e) {
 225             Utils.printThrowable(e, true) ;
 226             throw new RuntimeException(e);
 227         }
 228 
 229         if ( errorCount == 0 ) {
 230             System.out.println("MXBeanExceptionHandlingTest::run: Done without any error") ;
 231         } else {
 232             System.out.println("MXBeanExceptionHandlingTest::run: Done with "
 233                     + errorCount
 234                     + " error(s)") ;
 235             throw new RuntimeException("errorCount = " + errorCount);
 236         }
 237     }
 238 
 239     public void handleNotification(Notification notification, Object handback) {
 240         System.out.println("MXBeanExceptionHandlingTest::handleNotification: Received "
 241                 + notification);
 242         notifList.add(notification);
 243     }
 244 
 245 }