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