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