package javax.management.monitor;
import java.util.Iterator;
import javax.management.MBeanAttributeInfo;
import javax.management.MBeanNotificationInfo;
import javax.management.ObjectName;
import org.jboss.mx.util.MonitorRunnable;
import org.jboss.mx.util.ObservedObject;
import org.jboss.mx.util.MonitorCallback;
public class GaugeMonitor
extends Monitor
implements GaugeMonitorMBean
{
int THRESHOLD_HIGH_EXCEEDED_NOTIFIED = 16;
int THRESHOLD_LOW_EXCEEDED_NOTIFIED = 32;
int THRESHOLD_ERROR_NOTIFIED = 64;
boolean differenceMode = false;
Number highThreshold = new Integer(0);
Number lowThreshold = new Integer(0);
boolean notifyHigh = false;
boolean notifyLow = false;
private MonitorRunnable monitorRunnable;
public GaugeMonitor()
{
}
public MBeanNotificationInfo[] getNotificationInfo()
{
MBeanNotificationInfo[] result = new MBeanNotificationInfo[1];
String[] types = new String[]
{
MonitorNotification.RUNTIME_ERROR,
MonitorNotification.OBSERVED_OBJECT_ERROR,
MonitorNotification.OBSERVED_ATTRIBUTE_ERROR,
MonitorNotification.OBSERVED_ATTRIBUTE_TYPE_ERROR,
MonitorNotification.THRESHOLD_ERROR,
MonitorNotification.THRESHOLD_HIGH_VALUE_EXCEEDED,
MonitorNotification.THRESHOLD_LOW_VALUE_EXCEEDED
};
result[0] = new MBeanNotificationInfo(types,
"javax.management.monitor.MonitorNotification",
"Notifications sent by the Gauge Monitor Service MBean");
return result;
}
public Number getDerivedGauge()
{
ObservedObject object = getFirstObservedObject();
if (object != null)
return (Number) object.getDerivedGauge();
else
return null;
}
public Number getDerivedGauge(ObjectName name)
{
ObservedObject object = retrieveObservedObject(name);
if (object != null)
return (Number) object.getDerivedGauge();
else
return null;
}
public long getDerivedGaugeTimeStamp()
{
ObservedObject object = getFirstObservedObject();
if (object != null)
return object.getDerivedGaugeTimeStamp();
else
return 0L;
}
public long getDerivedGaugeTimeStamp(ObjectName name)
{
ObservedObject object = retrieveObservedObject(name);
if (object != null)
return object.getDerivedGaugeTimeStamp();
else
return 0L;
}
public boolean getDifferenceMode()
{
return differenceMode;
}
public void setDifferenceMode(boolean value)
{
differenceMode = value;
}
public boolean getNotifyHigh()
{
return notifyHigh;
}
public void setNotifyHigh(boolean value)
{
notifyHigh = value;
}
public boolean getNotifyLow()
{
return notifyLow;
}
public void setNotifyLow(boolean value)
{
notifyLow = value;
}
public Number getHighThreshold()
{
return highThreshold;
}
public Number getLowThreshold()
{
return lowThreshold;
}
public void setThresholds(Number highValue, Number lowValue)
throws IllegalArgumentException
{
if (highValue == null)
throw new IllegalArgumentException("Null high threshold");
if (lowValue == null)
throw new IllegalArgumentException("Null low threshold");
if (highValue.getClass() != lowValue.getClass())
throw new IllegalArgumentException("High and low different types");
if (highValue.doubleValue() < lowValue.doubleValue())
throw new IllegalArgumentException("High less than low threshold");
highThreshold = highValue;
lowThreshold = lowValue;
}
public synchronized void start()
{
if (active)
return;
active = true;
for (Iterator i = retrieveObservedObjects().values().iterator(); i.hasNext();)
{
ObservedObject object = (ObservedObject) i.next();
initObservedObject(object);
}
MonitorCallback callback = new MonitorCallback()
{
public void monitorCallback(ObservedObject object,
MBeanAttributeInfo attributeInfo, Object value) throws Exception
{
monitor(object, attributeInfo, value);
}
public MonitorNotification createNotification(String type, Object source,
long timeStamp, String message, Object derivedGauge,
String observedAttribute, ObjectName observedObject,
Object trigger)
{
return new MonitorNotification(type, source, nextSeqNo(), timeStamp,
message, derivedGauge, observedAttribute, observedObject,
trigger);
}
};
monitorRunnable = new MonitorRunnable(this, objectName, callback,
observedObjects, server);
}
public synchronized void stop()
{
if (!active)
return;
active = false;
monitorRunnable.setScheduler(null);
monitorRunnable = null;
}
void initObservedObject(ObservedObject object)
{
super.initObservedObject(object);
object.setDerivedGauge(new Integer(0));
object.setLastValue(null);
}
void monitor(ObservedObject object, MBeanAttributeInfo attributeInfo, Object value)
throws Exception
{
if (!(value instanceof Number))
{
sendAttributeTypeErrorNotification(object, "Attribute is not a number");
return;
}
if (highThreshold.getClass() != value.getClass()
|| lowThreshold.getClass() != value.getClass())
{
sendThresholdErrorNotification(object, value);
return;
}
Number number = (Number) value;
Number lastValue = (Number) object.getLastValue();
Number derivedGauge = (Number) object.getDerivedGauge();
if (differenceMode)
{
if (lastValue == null)
derivedGauge = getZero(number);
else
derivedGauge = sub(number, lastValue);
}
else
derivedGauge = number;
object.setDerivedGauge(derivedGauge);
object.setDerivedGaugeTimeStamp(System.currentTimeMillis());
if (derivedGauge.doubleValue() <= lowThreshold.doubleValue())
{
if (object.notAlreadyNotified(THRESHOLD_LOW_EXCEEDED_NOTIFIED))
{
object.setNotAlreadyNotified(THRESHOLD_HIGH_EXCEEDED_NOTIFIED);
sendThresholdLowExceededNotification(object, derivedGauge);
}
}
if (derivedGauge.doubleValue() >= highThreshold.doubleValue())
{
if (object.notAlreadyNotified(THRESHOLD_HIGH_EXCEEDED_NOTIFIED))
{
object.setNotAlreadyNotified(THRESHOLD_LOW_EXCEEDED_NOTIFIED);
sendThresholdHighExceededNotification(object, derivedGauge);
}
}
object.setLastValue(number);
}
Number getZero(Number value)
{
if (value instanceof Byte)
return new Byte((byte) 0);
if (value instanceof Integer)
return new Integer(0);
if (value instanceof Long)
return new Long(0);
if (value instanceof Short)
return new Short((short) 0);
if (value instanceof Float)
return new Float(0);
return new Double(0);
}
Number sub(Number value1, Number value2)
{
if (value1 instanceof Byte)
return new Byte((byte) (value1.byteValue() - value2.byteValue()));
if (value1 instanceof Integer)
return new Integer(value1.intValue() - value2.intValue());
if (value1 instanceof Long)
return new Long((value1.longValue() - value2.longValue()));
if (value1 instanceof Short)
return new Short((short) (value1.shortValue() - value2.shortValue()));
if (value1 instanceof Float)
return new Float((value1.floatValue() - value2.floatValue()));
return new Double(value1.doubleValue() - value2.doubleValue());
}
void sendThresholdLowExceededNotification(ObservedObject object, Object value)
{
if (notifyLow)
{
sendNotification(object, MonitorNotification.THRESHOLD_LOW_VALUE_EXCEEDED,
object.getDerivedGaugeTimeStamp(), "low threshold exceeded", observedAttribute,
value, lowThreshold);
}
}
void sendThresholdHighExceededNotification(ObservedObject object, Object value)
{
if (notifyHigh)
{
sendNotification(object, MonitorNotification.THRESHOLD_HIGH_VALUE_EXCEEDED,
object.getDerivedGaugeTimeStamp(), "high threshold exceeded", observedAttribute,
value, highThreshold);
}
}
void sendThresholdErrorNotification(ObservedObject object, Object value)
{
if (object.notAlreadyNotified(THRESHOLD_ERROR_NOTIFIED))
sendNotification(object, MonitorNotification.THRESHOLD_ERROR,
object.getDerivedGaugeTimeStamp(),
"High or Low Threshold not the correct type",
observedAttribute, null, null);
}
}