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
36import java.util.Map;
37import java.util.HashMap;
38import java.util.concurrent.ArrayBlockingQueue;
39import java.util.concurrent.BlockingQueue;
40
41import java.lang.management.ManagementFactory;
42import javax.management.MBeanServer;
43import javax.management.MBeanException;
44import javax.management.MBeanServerDelegate;
45import javax.management.Notification;
46import javax.management.NotificationListener;
47import javax.management.MBeanServerConnection;
48import javax.management.ObjectName;
49import javax.management.RuntimeErrorException;
50import javax.management.remote.JMXConnector;
51import javax.management.remote.JMXConnectorFactory;
52import javax.management.remote.JMXConnectorServer;
53import javax.management.remote.JMXConnectorServerFactory;
54import javax.management.remote.JMXServiceURL;
55
56public 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}
246