blob: aa386062b27af842e888a3d74bf71472ae8ee928 [file] [log] [blame]
/*
* Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* @test
* @bug 6222961
* @summary Test that the counter/gauge/string monitors
* support attributes of arbitrary data types.
* @author Luis-Miguel Alventosa
* @run clean AttributeArbitraryDataTypeTest
* @run build AttributeArbitraryDataTypeTest
* @run main AttributeArbitraryDataTypeTest
*/
import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.PropertyDescriptor;
import java.beans.SimpleBeanInfo;
import java.lang.reflect.Array;
import java.lang.reflect.InvocationTargetException;
import javax.management.AttributeNotFoundException;
import javax.management.MBeanServer;
import javax.management.MBeanServerFactory;
import javax.management.Notification;
import javax.management.NotificationListener;
import javax.management.ObjectName;
import javax.management.monitor.CounterMonitor;
import javax.management.monitor.GaugeMonitor;
import javax.management.monitor.MonitorNotification;
import javax.management.monitor.StringMonitor;
import javax.management.openmbean.CompositeData;
import javax.management.openmbean.CompositeDataSupport;
import javax.management.openmbean.CompositeType;
import javax.management.openmbean.OpenDataException;
import javax.management.openmbean.OpenType;
import javax.management.openmbean.SimpleType;
public class AttributeArbitraryDataTypeTest implements NotificationListener {
// Flag to notify that a message has been received
private volatile boolean counterMessageReceived = false;
private volatile boolean gaugeMessageReceived = false;
private volatile boolean stringMessageReceived = false;
// Match enum
public enum Match { do_not_match_0,
do_not_match_1,
do_not_match_2,
do_match_now };
// MatchBeanInfo class
public static class MatchBeanInfo extends SimpleBeanInfo {
public PropertyDescriptor[] getPropertyDescriptors() {
try {
return new PropertyDescriptor[] {
new PropertyDescriptor("name", Match.class, "name", null) };
} catch (IntrospectionException e ) {
e.printStackTrace();
return null;
}
}
}
// ComplexAttribute class
public class ComplexAttribute {
public Integer getIntegerAttribute() {
return i;
}
public void setIntegerAttribute(Integer i) {
this.i = i;
}
public Double getDoubleAttribute() {
return d;
}
public void setDoubleAttribute(Double d) {
this.d = d;
}
public String getStringAttribute() {
return s;
}
public void setStringAttribute(String s) {
this.s = s;
}
public Integer[] getArrayAttribute() {
return a;
}
public void setArrayAttribute(Integer[] a) {
this.a = a;
}
public Match getEnumAttribute() {
return e;
}
public void setEnumAttribute(Match e) {
this.e = e;
}
private Integer i;
private Double d;
private String s;
private Integer[] a;
private Match e;
}
// MBean class
public class ObservedObject implements ObservedObjectMBean {
// Simple type buried in complex getter
//
public ComplexAttribute getComplexAttribute() {
return ca;
}
public void setComplexAttribute(ComplexAttribute ca) {
this.ca = ca;
}
private ComplexAttribute ca = null;
// Simple type buried in CompositeData
//
public CompositeData getCompositeDataAttribute()
throws OpenDataException {
CompositeType ct = new CompositeType("CompositeDataAttribute",
"Composite Data Attribute",
itemNames,
itemDescriptions,
itemTypes);
Object itemValues[] = { ia, da, sa };
return new CompositeDataSupport(ct, itemNames, itemValues);
}
public Integer ia;
public Double da;
public String sa;
private String itemNames[] = { "IntegerAttribute",
"DoubleAttribute",
"StringAttribute" };
private String itemDescriptions[] = { "Integer Attribute",
"Double Attribute",
"String Attribute" };
private OpenType itemTypes[] = { SimpleType.INTEGER,
SimpleType.DOUBLE,
SimpleType.STRING };
}
// MBean interface
public interface ObservedObjectMBean {
public ComplexAttribute getComplexAttribute();
public void setComplexAttribute(ComplexAttribute ca);
public CompositeData getCompositeDataAttribute()
throws OpenDataException;
}
// Notification handler
public void handleNotification(Notification notification,
Object handback) {
MonitorNotification n = (MonitorNotification) notification;
echo("\tInside handleNotification...");
String type = n.getType();
try {
if (type.equals(MonitorNotification.
THRESHOLD_VALUE_EXCEEDED)) {
echo("\t\t" + n.getObservedAttribute() +
" has reached or exceeded the threshold");
echo("\t\tDerived Gauge = " + n.getDerivedGauge());
echo("\t\tTrigger = " + n.getTrigger());
synchronized (this) {
counterMessageReceived = true;
notifyAll();
}
} else if (type.equals(MonitorNotification.
THRESHOLD_HIGH_VALUE_EXCEEDED)) {
echo("\t\t" + n.getObservedAttribute() +
" has reached or exceeded the high threshold");
echo("\t\tDerived Gauge = " + n.getDerivedGauge());
echo("\t\tTrigger = " + n.getTrigger());
synchronized (this) {
gaugeMessageReceived = true;
notifyAll();
}
} else if (type.equals(MonitorNotification.
STRING_TO_COMPARE_VALUE_MATCHED)) {
echo("\t\t" + n.getObservedAttribute() +
" matches the string-to-compare value");
echo("\t\tDerived Gauge = " + n.getDerivedGauge());
echo("\t\tTrigger = " + n.getTrigger());
synchronized (this) {
stringMessageReceived = true;
notifyAll();
}
} else {
echo("\t\tSkipping notification of type: " + type);
}
} catch (Exception e) {
echo("\tError in handleNotification!");
e.printStackTrace(System.out);
}
}
/**
* Update the counter and check for notifications
*/
public int counterMonitorNotification(int testCase)
throws Exception {
counterMessageReceived = false;
CounterMonitor counterMonitor = null;
try {
MBeanServer server = MBeanServerFactory.newMBeanServer();
String domain = server.getDefaultDomain();
// Create a new CounterMonitor MBean and add it to the MBeanServer.
//
echo(">>> CREATE a new CounterMonitor MBean");
ObjectName counterMonitorName = new ObjectName(
domain + ":type=" + CounterMonitor.class.getName());
counterMonitor = new CounterMonitor();
server.registerMBean(counterMonitor, counterMonitorName);
echo(">>> ADD a listener to the CounterMonitor");
counterMonitor.addNotificationListener(this, null, null);
//
// MANAGEMENT OF A STANDARD MBEAN
//
echo(">>> CREATE a new ObservedObject MBean");
ObjectName obsObjName =
ObjectName.getInstance(domain + ":type=ObservedObject");
ObservedObject obsObj = new ObservedObject();
ComplexAttribute ca = new ComplexAttribute();
switch (testCase) {
case 1:
obsObj.ia = 0;
break;
case 2:
ca.setIntegerAttribute(0);
obsObj.setComplexAttribute(ca);
break;
case 3:
ca.setArrayAttribute(new Integer[0]);
obsObj.setComplexAttribute(ca);
break;
}
server.registerMBean(obsObj, obsObjName);
echo(">>> SET the attributes of the CounterMonitor:");
counterMonitor.addObservedObject(obsObjName);
echo("\tATTRIBUTE \"ObservedObject\" = " + obsObjName);
switch (testCase) {
case 1:
counterMonitor.setObservedAttribute(
"CompositeDataAttribute.IntegerAttribute");
echo("\tATTRIBUTE \"ObservedAttribute\" = " +
"CompositeDataAttribute.IntegerAttribute");
break;
case 2:
counterMonitor.setObservedAttribute(
"ComplexAttribute.integerAttribute");
echo("\tATTRIBUTE \"ObservedAttribute\" = " +
"ComplexAttribute.integerAttribute");
break;
case 3:
counterMonitor.setObservedAttribute(
"ComplexAttribute.arrayAttribute.length");
echo("\tATTRIBUTE \"ObservedAttribute\" = " +
"ComplexAttribute.arrayAttribute.length");
break;
}
counterMonitor.setNotify(true);
echo("\tATTRIBUTE \"NotifyFlag\" = true");
Integer threshold = 2;
counterMonitor.setInitThreshold(threshold);
echo("\tATTRIBUTE \"Threshold\" = " + threshold);
int granularityperiod = 500;
counterMonitor.setGranularityPeriod(granularityperiod);
echo("\tATTRIBUTE \"GranularityPeriod\" = " + granularityperiod);
echo(">>> START the CounterMonitor");
counterMonitor.start();
// Wait for granularity period (multiplied by 2 for sure)
//
Thread.sleep(granularityperiod * 2);
switch (testCase) {
case 1:
obsObj.ia = 1;
break;
case 2:
ca.setIntegerAttribute(1);
break;
case 3:
ca.setArrayAttribute(new Integer[1]);
break;
}
// Wait for granularity period (multiplied by 2 for sure)
//
Thread.sleep(granularityperiod * 2);
switch (testCase) {
case 1:
obsObj.ia = 2;
break;
case 2:
ca.setIntegerAttribute(2);
break;
case 3:
ca.setArrayAttribute(new Integer[2]);
break;
}
// Wait for granularity period (multiplied by 2 for sure)
//
Thread.sleep(granularityperiod * 2);
switch (testCase) {
case 1:
obsObj.ia = 3;
break;
case 2:
ca.setIntegerAttribute(3);
break;
case 3:
ca.setArrayAttribute(new Integer[3]);
break;
}
// Check if notification was received
//
synchronized (this) {
while (!counterMessageReceived) {
try {
wait();
} catch (InterruptedException e) {
System.err.println("Got unexpected exception: " + e);
e.printStackTrace();
break;
}
}
}
if (counterMessageReceived) {
echo("\tOK: CounterMonitor notification received");
} else {
echo("\tKO: CounterMonitor notification missed or not emitted");
return 1;
}
} finally {
if (counterMonitor != null)
counterMonitor.stop();
}
return 0;
}
/**
* Update the gauge and check for notifications
*/
public int gaugeMonitorNotification(int testCase)
throws Exception {
gaugeMessageReceived = false;
GaugeMonitor gaugeMonitor = null;
try {
MBeanServer server = MBeanServerFactory.newMBeanServer();
String domain = server.getDefaultDomain();
// Create a new GaugeMonitor MBean and add it to the MBeanServer.
//
echo(">>> CREATE a new GaugeMonitor MBean");
ObjectName gaugeMonitorName = new ObjectName(
domain + ":type=" + GaugeMonitor.class.getName());
gaugeMonitor = new GaugeMonitor();
server.registerMBean(gaugeMonitor, gaugeMonitorName);
echo(">>> ADD a listener to the GaugeMonitor");
gaugeMonitor.addNotificationListener(this, null, null);
//
// MANAGEMENT OF A STANDARD MBEAN
//
echo(">>> CREATE a new ObservedObject MBean");
ObjectName obsObjName =
ObjectName.getInstance(domain + ":type=ObservedObject");
ObservedObject obsObj = new ObservedObject();
ComplexAttribute ca = new ComplexAttribute();
switch (testCase) {
case 1:
obsObj.da = 0.0;
break;
case 2:
ca.setDoubleAttribute(0.0);
obsObj.setComplexAttribute(ca);
break;
case 3:
ca.setArrayAttribute(new Integer[0]);
obsObj.setComplexAttribute(ca);
break;
}
server.registerMBean(obsObj, obsObjName);
echo(">>> SET the attributes of the GaugeMonitor:");
gaugeMonitor.addObservedObject(obsObjName);
echo("\tATTRIBUTE \"ObservedObject\" = " + obsObjName);
switch (testCase) {
case 1:
gaugeMonitor.setObservedAttribute(
"CompositeDataAttribute.DoubleAttribute");
echo("\tATTRIBUTE \"ObservedAttribute\" = " +
"CompositeDataAttribute.DoubleAttribute");
break;
case 2:
gaugeMonitor.setObservedAttribute(
"ComplexAttribute.doubleAttribute");
echo("\tATTRIBUTE \"ObservedAttribute\" = " +
"ComplexAttribute.doubleAttribute");
break;
case 3:
gaugeMonitor.setObservedAttribute(
"ComplexAttribute.arrayAttribute.length");
echo("\tATTRIBUTE \"ObservedAttribute\" = " +
"ComplexAttribute.arrayAttribute.length");
break;
}
gaugeMonitor.setNotifyLow(false);
gaugeMonitor.setNotifyHigh(true);
echo("\tATTRIBUTE \"Notify Low Flag\" = false");
echo("\tATTRIBUTE \"Notify High Flag\" = true");
switch (testCase) {
case 1:
case 2:
Double highThresholdD = 3.0, lowThresholdD = 2.5;
gaugeMonitor.setThresholds(highThresholdD, lowThresholdD);
echo("\tATTRIBUTE \"Low Threshold\" = " + lowThresholdD);
echo("\tATTRIBUTE \"High Threshold\" = " + highThresholdD);
break;
case 3:
Integer highThreshold = 2, lowThreshold = 1;
gaugeMonitor.setThresholds(highThreshold, lowThreshold);
echo("\tATTRIBUTE \"Low Threshold\" = " + lowThreshold);
echo("\tATTRIBUTE \"High Threshold\" = " + highThreshold);
break;
}
int granularityperiod = 500;
gaugeMonitor.setGranularityPeriod(granularityperiod);
echo("\tATTRIBUTE \"GranularityPeriod\" = " + granularityperiod);
echo(">>> START the GaugeMonitor");
gaugeMonitor.start();
// Wait for granularity period (multiplied by 2 for sure)
//
Thread.sleep(granularityperiod * 2);
switch (testCase) {
case 1:
obsObj.da = 2.0;
break;
case 2:
ca.setDoubleAttribute(2.0);
break;
case 3:
ca.setArrayAttribute(new Integer[2]);
break;
}
// Wait for granularity period (multiplied by 2 for sure)
//
Thread.sleep(granularityperiod * 2);
switch (testCase) {
case 1:
obsObj.da = 4.0;
break;
case 2:
ca.setDoubleAttribute(4.0);
break;
case 3:
ca.setArrayAttribute(new Integer[4]);
break;
}
// Wait for granularity period (multiplied by 2 for sure)
//
Thread.sleep(granularityperiod * 2);
switch (testCase) {
case 1:
obsObj.da = 6.0;
break;
case 2:
ca.setDoubleAttribute(6.0);
break;
case 3:
ca.setArrayAttribute(new Integer[6]);
break;
}
// Check if notification was received
//
synchronized (this) {
while (!gaugeMessageReceived) {
try {
wait();
} catch (InterruptedException e) {
System.err.println("Got unexpected exception: " + e);
e.printStackTrace();
break;
}
}
}
if (gaugeMessageReceived) {
echo("\tOK: GaugeMonitor notification received");
} else {
echo("\tKO: GaugeMonitor notification missed or not emitted");
return 1;
}
} finally {
if (gaugeMonitor != null)
gaugeMonitor.stop();
}
return 0;
}
/**
* Update the string and check for notifications
*/
public int stringMonitorNotification(int testCase)
throws Exception {
stringMessageReceived = false;
StringMonitor stringMonitor = null;
try {
MBeanServer server = MBeanServerFactory.newMBeanServer();
String domain = server.getDefaultDomain();
// Create a new StringMonitor MBean and add it to the MBeanServer.
//
echo(">>> CREATE a new StringMonitor MBean");
ObjectName stringMonitorName = new ObjectName(
domain + ":type=" + StringMonitor.class.getName());
stringMonitor = new StringMonitor();
server.registerMBean(stringMonitor, stringMonitorName);
echo(">>> ADD a listener to the StringMonitor");
stringMonitor.addNotificationListener(this, null, null);
//
// MANAGEMENT OF A STANDARD MBEAN
//
echo(">>> CREATE a new ObservedObject MBean");
ObjectName obsObjName =
ObjectName.getInstance(domain + ":type=ObservedObject");
ObservedObject obsObj = new ObservedObject();
ComplexAttribute ca = new ComplexAttribute();
switch (testCase) {
case 1:
obsObj.sa = "do_not_match_0";
break;
case 2:
ca.setStringAttribute("do_not_match_0");
obsObj.setComplexAttribute(ca);
break;
case 3:
ca.setEnumAttribute(Match.do_not_match_0);
obsObj.setComplexAttribute(ca);
break;
}
server.registerMBean(obsObj, obsObjName);
echo(">>> SET the attributes of the StringMonitor:");
stringMonitor.addObservedObject(obsObjName);
echo("\tATTRIBUTE \"ObservedObject\" = " + obsObjName);
switch (testCase) {
case 1:
stringMonitor.setObservedAttribute(
"CompositeDataAttribute.StringAttribute");
echo("\tATTRIBUTE \"ObservedAttribute\" = " +
"CompositeDataAttribute.StringAttribute");
break;
case 2:
stringMonitor.setObservedAttribute(
"ComplexAttribute.stringAttribute");
echo("\tATTRIBUTE \"ObservedAttribute\" = " +
"ComplexAttribute.stringAttribute");
break;
case 3:
stringMonitor.setObservedAttribute(
"ComplexAttribute.enumAttribute.name");
echo("\tATTRIBUTE \"ObservedAttribute\" = " +
"ComplexAttribute.enumAttribute.name");
break;
}
stringMonitor.setNotifyMatch(true);
echo("\tATTRIBUTE \"NotifyMatch\" = true");
stringMonitor.setNotifyDiffer(false);
echo("\tATTRIBUTE \"NotifyDiffer\" = false");
stringMonitor.setStringToCompare("do_match_now");
echo("\tATTRIBUTE \"StringToCompare\" = \"do_match_now\"");
int granularityperiod = 500;
stringMonitor.setGranularityPeriod(granularityperiod);
echo("\tATTRIBUTE \"GranularityPeriod\" = " + granularityperiod);
echo(">>> START the StringMonitor");
stringMonitor.start();
// Wait for granularity period (multiplied by 2 for sure)
//
Thread.sleep(granularityperiod * 2);
switch (testCase) {
case 1:
obsObj.sa = "do_not_match_1";
break;
case 2:
ca.setStringAttribute("do_not_match_1");
break;
case 3:
ca.setEnumAttribute(Match.do_not_match_1);
break;
}
// Wait for granularity period (multiplied by 2 for sure)
//
Thread.sleep(granularityperiod * 2);
switch (testCase) {
case 1:
obsObj.sa = "do_match_now";
break;
case 2:
ca.setStringAttribute("do_match_now");
break;
case 3:
ca.setEnumAttribute(Match.do_match_now);
break;
}
// Wait for granularity period (multiplied by 2 for sure)
//
Thread.sleep(granularityperiod * 2);
switch (testCase) {
case 1:
obsObj.sa = "do_not_match_2";
break;
case 2:
ca.setStringAttribute("do_not_match_2");
break;
case 3:
ca.setEnumAttribute(Match.do_not_match_2);
break;
}
// Check if notification was received
//
synchronized (this) {
while (!stringMessageReceived) {
try {
wait();
} catch (InterruptedException e) {
System.err.println("Got unexpected exception: " + e);
e.printStackTrace();
break;
}
}
}
if (stringMessageReceived) {
echo("\tOK: StringMonitor notification received");
} else {
echo("\tKO: StringMonitor notification missed or not emitted");
return 1;
}
} finally {
if (stringMonitor != null)
stringMonitor.stop();
}
return 0;
}
/**
* Test the monitor notifications.
*/
public int monitorNotifications() throws Exception {
echo(">>> ----------------------------------------");
int error = counterMonitorNotification(1);
echo(">>> ----------------------------------------");
error += counterMonitorNotification(2);
echo(">>> ----------------------------------------");
error += counterMonitorNotification(3);
echo(">>> ----------------------------------------");
error += gaugeMonitorNotification(1);
echo(">>> ----------------------------------------");
error += gaugeMonitorNotification(2);
echo(">>> ----------------------------------------");
error += gaugeMonitorNotification(3);
echo(">>> ----------------------------------------");
error += stringMonitorNotification(1);
echo(">>> ----------------------------------------");
error += stringMonitorNotification(2);
echo(">>> ----------------------------------------");
error += stringMonitorNotification(3);
echo(">>> ----------------------------------------");
return error;
}
/*
* Print message
*/
private static void echo(String message) {
System.out.println(message);
}
public static Object elementFromComplex(Object complex, String element)
throws AttributeNotFoundException {
try {
if (complex.getClass().isArray() && element.equals("length")) {
return Array.getLength(complex);
} else if (complex instanceof CompositeData) {
return ((CompositeData) complex).get(element);
} else {
// Java Beans introspection
//
BeanInfo bi = java.beans.Introspector.getBeanInfo(complex.getClass());
PropertyDescriptor[] pds = bi.getPropertyDescriptors();
System.out.println("PDs: " + pds.length);
for (PropertyDescriptor pd : pds) {
System.out.println("Property: " + pd.getName());
if (pd.getName().equals(element))
return pd.getReadMethod().invoke(complex);
}
throw new AttributeNotFoundException(
"Could not find the getter method for the property " +
element + " using the Java Beans introspector");
}
} catch (InvocationTargetException e) {
throw new IllegalArgumentException(e);
} catch (AttributeNotFoundException e) {
throw e;
} catch (Exception e) {
AttributeNotFoundException anfe =
new AttributeNotFoundException(e.getMessage());
anfe.initCause(e);
throw anfe;
}
}
/*
* Standalone entry point.
*
* Run the test and report to stdout.
*/
public static void main (String args[]) throws Exception {
Match match = Match.do_match_now;
String name = (String) elementFromComplex(match, "name");
System.out.println("name: " + name);
AttributeArbitraryDataTypeTest test =
new AttributeArbitraryDataTypeTest();
int error = test.monitorNotifications();
if (error > 0) {
echo(">>> Unhappy Bye, Bye!");
throw new IllegalStateException("Test FAILED: Didn't get all " +
"the notifications that were " +
"expected by the test!");
} else {
echo(">>> Happy Bye, Bye!");
}
}
}