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