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.rmi
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      */
main(String args[])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 
parseArgs(Map<String, Object> args)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 
run(Map<String, Object> args)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 
handleNotification(Notification notification, Object handback)239     public void handleNotification(Notification notification, Object handback) {
240         System.out.println("MXBeanExceptionHandlingTest::handleNotification: Received "
241                 + notification);
242         notifList.add(notification);
243     }
244 
245 }
246