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