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 6200391
27  * @summary Test that the jmx.monitor.error.runtime monitor notification
28  *          is emitted when getAttribute throws RuntimeException.
29  * @author Luis-Miguel Alventosa
30  *
31  * @run clean RuntimeExceptionTest MBeanServerBuilderImpl
32  *            MBeanServerForwarderInvocationHandler
33  * @run build RuntimeExceptionTest MBeanServerBuilderImpl
34  *            MBeanServerForwarderInvocationHandler
35  * @run main RuntimeExceptionTest
36  */
37 
38 import java.lang.reflect.Proxy;
39 import javax.management.MBeanServer;
40 import javax.management.MBeanServerFactory;
41 import javax.management.Notification;
42 import javax.management.NotificationListener;
43 import javax.management.ObjectName;
44 import javax.management.monitor.CounterMonitor;
45 import javax.management.monitor.GaugeMonitor;
46 import javax.management.monitor.MonitorNotification;
47 import javax.management.monitor.StringMonitor;
48 
49 public class RuntimeExceptionTest implements NotificationListener {
50 
51     // MBean class
52     public class ObservedObject implements ObservedObjectMBean {
getIntegerAttribute()53         public Integer getIntegerAttribute() {
54             return i;
55         }
setIntegerAttribute(Integer i)56         public void setIntegerAttribute(Integer i) {
57             this.i = i;
58         }
getStringAttribute()59         public String getStringAttribute() {
60             return s;
61         }
setStringAttribute(String s)62         public void setStringAttribute(String s) {
63             this.s = s;
64         }
65         private Integer i = 1;
66         private String s = "dummy";
67     }
68 
69     // MBean interface
70     public interface ObservedObjectMBean {
getIntegerAttribute()71         public Integer getIntegerAttribute();
setIntegerAttribute(Integer i)72         public void setIntegerAttribute(Integer i);
getStringAttribute()73         public String getStringAttribute();
setStringAttribute(String s)74         public void setStringAttribute(String s);
75     }
76 
77     // Notification handler
handleNotification(Notification notification, Object handback)78     public void handleNotification(Notification notification, Object handback) {
79         echo(">>> Received notification: " + notification);
80         if (notification instanceof MonitorNotification) {
81             String type = notification.getType();
82             if (type.equals(MonitorNotification.RUNTIME_ERROR)) {
83                 MonitorNotification mn = (MonitorNotification) notification;
84                 echo("\tType: " + mn.getType());
85                 echo("\tTimeStamp: " + mn.getTimeStamp());
86                 echo("\tObservedObject: " + mn.getObservedObject());
87                 echo("\tObservedAttribute: " + mn.getObservedAttribute());
88                 echo("\tDerivedGauge: " + mn.getDerivedGauge());
89                 echo("\tTrigger: " + mn.getTrigger());
90 
91                 synchronized (this) {
92                     messageReceived = true;
93                     notifyAll();
94                 }
95             }
96         }
97     }
98 
99     /**
100      * Update the counter and check for notifications
101      */
counterMonitorNotification()102     public int counterMonitorNotification() throws Exception {
103 
104         CounterMonitor counterMonitor = new CounterMonitor();
105         try {
106             // Create a new CounterMonitor MBean and add it to the MBeanServer.
107             //
108             echo(">>> CREATE a new CounterMonitor MBean");
109             ObjectName counterMonitorName = new ObjectName(
110                             domain + ":type=" + CounterMonitor.class.getName());
111             server.registerMBean(counterMonitor, counterMonitorName);
112 
113             echo(">>> ADD a listener to the CounterMonitor");
114             counterMonitor.addNotificationListener(this, null, null);
115 
116             //
117             // MANAGEMENT OF A STANDARD MBEAN
118             //
119 
120             echo(">>> SET the attributes of the CounterMonitor:");
121 
122             counterMonitor.addObservedObject(obsObjName);
123             echo("\tATTRIBUTE \"ObservedObject\"    = " + obsObjName);
124 
125             counterMonitor.setObservedAttribute("IntegerAttribute");
126             echo("\tATTRIBUTE \"ObservedAttribute\" = IntegerAttribute");
127 
128             counterMonitor.setNotify(false);
129             echo("\tATTRIBUTE \"NotifyFlag\"        = false");
130 
131             Integer threshold = 2;
132             counterMonitor.setInitThreshold(threshold);
133             echo("\tATTRIBUTE \"Threshold\"         = " + threshold);
134 
135             int granularityperiod = 500;
136             counterMonitor.setGranularityPeriod(granularityperiod);
137             echo("\tATTRIBUTE \"GranularityPeriod\" = " + granularityperiod);
138 
139             echo(">>> START the CounterMonitor");
140             counterMonitor.start();
141 
142             // Check if notification was received
143             //
144             doWait();
145             if (messageReceived) {
146                 echo("\tOK: CounterMonitor got RUNTIME_ERROR notification!");
147             } else {
148                 echo("\tKO: CounterMonitor did not get " +
149                      "RUNTIME_ERROR notification!");
150                 return 1;
151             }
152         } finally {
153             messageReceived = false;
154             if (counterMonitor != null)
155                 counterMonitor.stop();
156         }
157 
158         return 0;
159     }
160 
161     /**
162      * Update the gauge and check for notifications
163      */
gaugeMonitorNotification()164     public int gaugeMonitorNotification() throws Exception {
165 
166         GaugeMonitor gaugeMonitor = new GaugeMonitor();
167         try {
168             // Create a new GaugeMonitor MBean and add it to the MBeanServer.
169             //
170             echo(">>> CREATE a new GaugeMonitor MBean");
171             ObjectName gaugeMonitorName = new ObjectName(
172                             domain + ":type=" + GaugeMonitor.class.getName());
173             server.registerMBean(gaugeMonitor, gaugeMonitorName);
174 
175             echo(">>> ADD a listener to the GaugeMonitor");
176             gaugeMonitor.addNotificationListener(this, null, null);
177 
178             //
179             // MANAGEMENT OF A STANDARD MBEAN
180             //
181 
182             echo(">>> SET the attributes of the GaugeMonitor:");
183 
184             gaugeMonitor.addObservedObject(obsObjName);
185             echo("\tATTRIBUTE \"ObservedObject\"    = " + obsObjName);
186 
187             gaugeMonitor.setObservedAttribute("IntegerAttribute");
188             echo("\tATTRIBUTE \"ObservedAttribute\" = IntegerAttribute");
189 
190             gaugeMonitor.setNotifyLow(false);
191             gaugeMonitor.setNotifyHigh(false);
192             echo("\tATTRIBUTE \"Notify Low  Flag\"  = false");
193             echo("\tATTRIBUTE \"Notify High Flag\"  = false");
194 
195             Integer highThreshold = 3, lowThreshold = 2;
196             gaugeMonitor.setThresholds(highThreshold, lowThreshold);
197             echo("\tATTRIBUTE \"Low  Threshold\"    = " + lowThreshold);
198             echo("\tATTRIBUTE \"High Threshold\"    = " + highThreshold);
199 
200             int granularityperiod = 500;
201             gaugeMonitor.setGranularityPeriod(granularityperiod);
202             echo("\tATTRIBUTE \"GranularityPeriod\" = " + granularityperiod);
203 
204             echo(">>> START the GaugeMonitor");
205             gaugeMonitor.start();
206 
207             // Check if notification was received
208             //
209             doWait();
210             if (messageReceived) {
211                 echo("\tOK: GaugeMonitor got RUNTIME_ERROR notification!");
212             } else {
213                 echo("\tKO: GaugeMonitor did not get " +
214                      "RUNTIME_ERROR notification!");
215                 return 1;
216             }
217         } finally {
218             messageReceived = false;
219             if (gaugeMonitor != null)
220                 gaugeMonitor.stop();
221         }
222 
223         return 0;
224     }
225 
226     /**
227      * Update the string and check for notifications
228      */
stringMonitorNotification()229     public int stringMonitorNotification() throws Exception {
230 
231         StringMonitor stringMonitor = new StringMonitor();
232         try {
233             // Create a new StringMonitor MBean and add it to the MBeanServer.
234             //
235             echo(">>> CREATE a new StringMonitor MBean");
236             ObjectName stringMonitorName = new ObjectName(
237                             domain + ":type=" + StringMonitor.class.getName());
238             server.registerMBean(stringMonitor, stringMonitorName);
239 
240             echo(">>> ADD a listener to the StringMonitor");
241             stringMonitor.addNotificationListener(this, null, null);
242 
243             //
244             // MANAGEMENT OF A STANDARD MBEAN
245             //
246 
247             echo(">>> SET the attributes of the StringMonitor:");
248 
249             stringMonitor.addObservedObject(obsObjName);
250             echo("\tATTRIBUTE \"ObservedObject\"    = " + obsObjName);
251 
252             stringMonitor.setObservedAttribute("StringAttribute");
253             echo("\tATTRIBUTE \"ObservedAttribute\" = StringAttribute");
254 
255             stringMonitor.setNotifyMatch(false);
256             echo("\tATTRIBUTE \"NotifyMatch\"       = false");
257 
258             stringMonitor.setNotifyDiffer(false);
259             echo("\tATTRIBUTE \"NotifyDiffer\"      = false");
260 
261             stringMonitor.setStringToCompare("dummy");
262             echo("\tATTRIBUTE \"StringToCompare\"   = \"dummy\"");
263 
264             int granularityperiod = 500;
265             stringMonitor.setGranularityPeriod(granularityperiod);
266             echo("\tATTRIBUTE \"GranularityPeriod\" = " + granularityperiod);
267 
268             echo(">>> START the StringMonitor");
269             stringMonitor.start();
270 
271             // Check if notification was received
272             //
273             doWait();
274             if (messageReceived) {
275                 echo("\tOK: StringMonitor got RUNTIME_ERROR notification!");
276             } else {
277                 echo("\tKO: StringMonitor did not get " +
278                      "RUNTIME_ERROR notification!");
279                 return 1;
280             }
281         } finally {
282             messageReceived = false;
283             if (stringMonitor != null)
284                 stringMonitor.stop();
285         }
286 
287         return 0;
288     }
289 
290     /**
291      * Test the monitor notifications.
292      */
monitorNotifications()293     public int monitorNotifications() throws Exception {
294 
295         server = MBeanServerFactory.newMBeanServer();
296 
297         MBeanServerForwarderInvocationHandler mbsfih =
298             (MBeanServerForwarderInvocationHandler)
299             Proxy.getInvocationHandler(server);
300 
301         mbsfih.setGetAttributeException(
302             new RuntimeException("Test RuntimeException"));
303 
304         domain = server.getDefaultDomain();
305 
306         obsObjName = ObjectName.getInstance(domain + ":type=ObservedObject");
307         server.registerMBean(new ObservedObject(), obsObjName);
308 
309         echo(">>> ----------------------------------------");
310         int error = counterMonitorNotification();
311         echo(">>> ----------------------------------------");
312         error += gaugeMonitorNotification();
313         echo(">>> ----------------------------------------");
314         error += stringMonitorNotification();
315         echo(">>> ----------------------------------------");
316         return error;
317     }
318 
319     /*
320      * Print message
321      */
echo(String message)322     private static void echo(String message) {
323         System.out.println(message);
324     }
325 
326     /*
327      * Standalone entry point.
328      *
329      * Run the test and report to stdout.
330      */
main(String args[])331     public static void main (String args[]) throws Exception {
332         System.setProperty("javax.management.builder.initial",
333                            MBeanServerBuilderImpl.class.getName());
334         RuntimeExceptionTest test = new RuntimeExceptionTest();
335         int error = test.monitorNotifications();
336         if (error > 0) {
337             echo(">>> Unhappy Bye, Bye!");
338             throw new IllegalStateException("Test FAILED: Didn't get all " +
339                                             "the notifications that were " +
340                                             "expected by the test!");
341         } else {
342             echo(">>> Happy Bye, Bye!");
343         }
344     }
345 
346     /*
347      * Wait messageReceived to be true
348      */
doWait()349     synchronized void doWait() {
350         while (!messageReceived) {
351             try {
352                 wait();
353             } catch (InterruptedException e) {
354                 System.err.println("Got unexpected exception: " + e);
355                 e.printStackTrace();
356                 break;
357             }
358         }
359     }
360 
361     // Flag to notify that a message has been received
362     private volatile boolean messageReceived = false;
363 
364     private MBeanServer server;
365     private ObjectName obsObjName;
366     private String domain;
367 }
368