1 /*
   2  * Copyright (c) 2004, 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 4981829
  27  * @summary Test that the counter monitor, when running in difference mode,
  28  *          emits a notification every time the threshold is exceeded.
  29  * @author Luis-Miguel Alventosa, Shanliang JIANG
  30  * @modules java.management
  31  * @run clean CounterMonitorTest
  32  * @run build CounterMonitorTest
  33  * @run main CounterMonitorTest
  34  */
  35 
  36 import javax.management.*;
  37 import javax.management.monitor.*;
  38 
  39 public class CounterMonitorTest implements NotificationListener {
  40 
  41     // threshold number
  42     private Number threshold = new Integer(2);
  43 
  44     // modulus number
  45     private Number modulus = new Integer(7);
  46 
  47     // difference mode flag
  48     private boolean differenceModeFlag = true;
  49 
  50     // notify flag
  51     private boolean notifyFlag = true;
  52 
  53     // granularity period
  54     private int granularityperiod = 10;
  55 
  56     // derived gauge
  57     private volatile int derivedGauge = 2;
  58 
  59     // flag to notify that a message has been received
  60     private volatile boolean messageReceived = false;
  61 
  62     private volatile Object observedValue = null;
  63 
  64     // MBean class
  65     public class StdObservedObject implements StdObservedObjectMBean {
  66         public Object getNbObjects() {
  67             echo(">>> StdObservedObject.getNbObjects: " + count);
  68             synchronized(CounterMonitorTest.class) {
  69                 observedValue = count;
  70                 CounterMonitorTest.class.notifyAll();
  71             }
  72             return observedValue;
  73         }
  74         public void setNbObjects(Object n) {
  75             echo(">>> StdObservedObject.setNbObjects: " + n);
  76             count = n;
  77         }
  78         private volatile Object count= null;
  79     }
  80 
  81     // MBean interface
  82     public interface StdObservedObjectMBean {
  83         public Object getNbObjects();
  84         public void setNbObjects(Object n);
  85     }
  86 
  87     // Notification handler
  88     public void handleNotification(Notification notification,
  89                                    Object handback) {
  90         MonitorNotification n = (MonitorNotification) notification;
  91         echo("\tInside handleNotification...");
  92         String type = n.getType();
  93         try {
  94             if (type.equals(MonitorNotification.THRESHOLD_VALUE_EXCEEDED)) {
  95                 echo("\t\t" + n.getObservedAttribute() +
  96                      " has reached or exceeded the threshold");
  97                 echo("\t\tDerived Gauge = " + n.getDerivedGauge());
  98 
  99                 synchronized (this) {
 100                     messageReceived = true;
 101                     notifyAll();
 102                 }
 103             } else {
 104                 echo("\t\tSkipping notification of type: " + type);
 105             }
 106         } catch (Exception e) {
 107             echo("\tError in handleNotification!");
 108             e.printStackTrace(System.out);
 109         }
 110     }
 111 
 112     /**
 113      * Update the counter and check for notifications
 114      */
 115     public void thresholdNotification() throws Exception {
 116 
 117         CounterMonitor counterMonitor = new CounterMonitor();
 118         try {
 119             MBeanServer server = MBeanServerFactory.newMBeanServer();
 120 
 121             String domain = server.getDefaultDomain();
 122 
 123             // Create a new CounterMonitor MBean and add it to the MBeanServer.
 124             //
 125             echo(">>> CREATE a new CounterMonitor MBean");
 126             ObjectName counterMonitorName = new ObjectName(
 127                             domain + ":type=" + CounterMonitor.class.getName());
 128             server.registerMBean(counterMonitor, counterMonitorName);
 129 
 130             echo(">>> ADD a listener to the CounterMonitor");
 131             counterMonitor.addNotificationListener(this, null, null);
 132 
 133             //
 134             // MANAGEMENT OF A STANDARD MBEAN
 135             //
 136 
 137             echo(">>> CREATE a new StdObservedObject MBean");
 138 
 139             ObjectName stdObsObjName =
 140                 new ObjectName(domain + ":type=StdObservedObject");
 141             StdObservedObject stdObsObj = new StdObservedObject();
 142             server.registerMBean(stdObsObj, stdObsObjName);
 143 
 144             echo(">>> SET the attributes of the CounterMonitor:");
 145 
 146             counterMonitor.addObservedObject(stdObsObjName);
 147             echo("\tATTRIBUTE \"ObservedObject\"    = " + stdObsObjName);
 148 
 149             counterMonitor.setObservedAttribute("NbObjects");
 150             echo("\tATTRIBUTE \"ObservedAttribute\" = NbObjects");
 151 
 152             counterMonitor.setNotify(notifyFlag);
 153             echo("\tATTRIBUTE \"Notify\"            = " + notifyFlag);
 154 
 155             counterMonitor.setInitThreshold(threshold);
 156             echo("\tATTRIBUTE \"Threshold\"         = " + threshold);
 157 
 158             counterMonitor.setGranularityPeriod(granularityperiod);
 159             echo("\tATTRIBUTE \"GranularityPeriod\" = " + granularityperiod);
 160 
 161             counterMonitor.setModulus(modulus);
 162             echo("\tATTRIBUTE \"Modulus\"           = " + modulus);
 163 
 164             counterMonitor.setDifferenceMode(differenceModeFlag);
 165             echo("\tATTRIBUTE \"DifferenceMode\"    = " + differenceModeFlag);
 166 
 167             echo(">>> START the CounterMonitor");
 168             counterMonitor.start();
 169 
 170             // Set initial value
 171             //
 172             Integer data = new Integer(0);
 173             echo(">>> Set data = " + data.intValue());
 174 
 175             Attribute attrib = new Attribute("NbObjects", data);
 176             server.setAttribute(stdObsObjName, attrib);
 177 
 178             waitObservation(data);
 179 
 180             // Loop through the values
 181             //
 182             while (derivedGauge++ < 10) {
 183                 System.out.print(">>> Set data from " + data.intValue());
 184                 data = new Integer(data.intValue() + derivedGauge);
 185                 echo(" to " + data.intValue());
 186 
 187                 attrib = new Attribute("NbObjects", data);
 188                 server.setAttribute(stdObsObjName, attrib);
 189                 waitObservation(data);
 190 
 191                 echo("\tdoWait in Counter Monitor");
 192                 doWait();
 193 
 194                 // Check if notification was received
 195                 //
 196                 if (messageReceived) {
 197                     echo("\tOKAY: Notification received");
 198                 } else {
 199                     echo("\tError: notification missed or not emitted");
 200                     throw new IllegalStateException("Notification lost");
 201                 }
 202                 messageReceived = false;
 203             }
 204         } finally {
 205             counterMonitor.stop();
 206         }
 207 
 208         echo(">>> Bye! Bye!");
 209     }
 210 
 211     /*
 212      * Wait messageReceived to be true
 213      */
 214     synchronized void doWait() {
 215         while (!messageReceived) {
 216             try {
 217                 wait();
 218             } catch (InterruptedException e) {
 219                 System.err.println("Got unexpected exception: " + e);
 220                 e.printStackTrace();
 221                 break;
 222             }
 223         }
 224     }
 225 
 226     private void waitObservation(Object value) {
 227         synchronized (CounterMonitorTest.class) {
 228             while (value != observedValue) {
 229                 try {
 230                     CounterMonitorTest.class.wait();
 231                 } catch (InterruptedException e) {
 232                     System.err.println("Got unexpected exception: " + e);
 233                     e.printStackTrace();
 234                     break;
 235                 }
 236             }
 237         }
 238     }
 239 
 240     /*
 241      * Print message
 242      */
 243     void echo(String message) {
 244         System.out.println(message);
 245     }
 246 
 247     /*
 248      * Standalone entry point.
 249      *
 250      * Run the test and report to stdout.
 251      */
 252     public static void main (String args[]) throws Exception {
 253         CounterMonitorTest test = new CounterMonitorTest();
 254         test.thresholdNotification();
 255     }
 256 }