false
.
*/
private boolean isActive = false;
/**
* Monitor sequence number.
* The default value is set to 0.
*/
private final AtomicLong sequenceNumber = new AtomicLong();
/**
* Complex type attribute flag.
* The default value is set to false
.
*/
private boolean isComplexTypeAttribute = false;
/**
* First attribute name extracted from complex type attribute name.
*/
private String firstAttribute;
/**
* Remaining attribute names extracted from complex type attribute name.
*/
private final ListSelected monitor errors that have already been notified.
* *Each element in this array corresponds to an observed object * in the vector. It contains a bit mask of the flags {@link * #OBSERVED_OBJECT_ERROR_NOTIFIED} etc, indicating whether the * corresponding notification has already been sent for the MBean * being monitored.
* */ protected int alreadyNotifieds[] = new int[capacityIncrement]; /** * Reference to the MBean server. This reference is null when the * monitor MBean is not registered in an MBean server. This * reference is initialized before the monitor MBean is registered * in the MBean server. * @see #preRegister(MBeanServer server, ObjectName name) */ protected MBeanServer server; // Flags defining possible monitor errors. // /** * This flag is used to reset the {@link #alreadyNotifieds * alreadyNotifieds} monitor attribute. */ protected static final int RESET_FLAGS_ALREADY_NOTIFIED = 0; /** * Flag denoting that a notification has occurred after changing * the observed object. This flag is used to check that the new * observed object is registered in the MBean server at the time * of the first notification. */ protected static final int OBSERVED_OBJECT_ERROR_NOTIFIED = 1; /** * Flag denoting that a notification has occurred after changing * the observed attribute. This flag is used to check that the * new observed attribute belongs to the observed object at the * time of the first notification. */ protected static final int OBSERVED_ATTRIBUTE_ERROR_NOTIFIED = 2; /** * Flag denoting that a notification has occurred after changing * the observed object or the observed attribute. This flag is * used to check that the observed attribute type is correct * (depending on the monitor in use) at the time of the first * notification. */ protected static final int OBSERVED_ATTRIBUTE_TYPE_ERROR_NOTIFIED = 4; /** * Flag denoting that a notification has occurred after changing * the observed object or the observed attribute. This flag is * used to notify any exception (except the cases described above) * when trying to get the value of the observed attribute at the * time of the first notification. */ protected static final int RUNTIME_ERROR_NOTIFIED = 8; /** * This field is retained for compatibility but should not be referenced. * * @deprecated No replacement. */ @Deprecated protected String dbgTag = Monitor.class.getName(); /* * ------------------------------------------ * PACKAGE VARIABLES * ------------------------------------------ */ /** * List of ObservedObjects to which the attribute to observe belongs. */ final List* Initializes the reference to the MBean server. * * @param server The MBean server in which the monitor MBean will * be registered. * @param name The object name of the monitor MBean. * * @return The name of the monitor MBean registered. * * @exception Exception */ public ObjectName preRegister(MBeanServer server, ObjectName name) throws Exception { MONITOR_LOGGER.logp(Level.FINER, Monitor.class.getName(), "preRegister(MBeanServer, ObjectName)", "initialize the reference on the MBean server"); this.server = server; return name; } /** * Allows the monitor MBean to perform any operations needed after * having been registered in the MBean server or after the * registration has failed. *
* Not used in this context. */ public void postRegister(Boolean registrationDone) { } /** * Allows the monitor MBean to perform any operations it needs * before being unregistered by the MBean server. *
* Stops the monitor. * * @exception Exception */ public void preDeregister() throws Exception { MONITOR_LOGGER.logp(Level.FINER, Monitor.class.getName(), "preDeregister()", "stop the monitor"); // Stop the Monitor. // stop(); } /** * Allows the monitor MBean to perform any operations needed after * having been unregistered by the MBean server. *
* Not used in this context.
*/
public void postDeregister() {
}
/**
* Starts the monitor.
*/
public abstract void start();
/**
* Stops the monitor.
*/
public abstract void stop();
// GETTERS AND SETTERS
//--------------------
/**
* Returns the object name of the first object in the set of observed
* MBeans, or
* This factory creates all new threads used by an Executor in
* the same ThreadGroup. If there is a SecurityManager, it uses
* the group of System.getSecurityManager(), else the group of
* the thread instantiating this DaemonThreadFactory. Each new
* thread is created as a daemon thread with priority
* Thread.NORM_PRIORITY. New threads have names accessible via
* Thread.getName() of "JMX Monitor null
if there is no such object.
*
* @return The object being observed.
*
* @see #setObservedObject(ObjectName)
*
* @deprecated As of JMX 1.2, replaced by {@link #getObservedObjects}
*/
@Deprecated
public synchronized ObjectName getObservedObject() {
if (observedObjects.isEmpty()) {
return null;
} else {
return observedObjects.get(0).getObservedObject();
}
}
/**
* Removes all objects from the set of observed objects, and then adds the
* specified object.
*
* @param object The object to observe.
* @exception IllegalArgumentException The specified
* object is null.
*
* @see #getObservedObject()
*
* @deprecated As of JMX 1.2, replaced by {@link #addObservedObject}
*/
@Deprecated
public synchronized void setObservedObject(ObjectName object)
throws IllegalArgumentException {
if (object == null)
throw new IllegalArgumentException("Null observed object");
if (observedObjects.size() == 1 && containsObservedObject(object))
return;
observedObjects.clear();
addObservedObject(object);
}
/**
* Adds the specified object in the set of observed MBeans, if this object
* is not already present.
*
* @param object The object to observe.
* @exception IllegalArgumentException The specified object is null.
*
*/
public synchronized void addObservedObject(ObjectName object)
throws IllegalArgumentException {
if (object == null) {
throw new IllegalArgumentException("Null observed object");
}
// Check that the specified object is not already contained.
//
if (containsObservedObject(object))
return;
// Add the specified object in the list.
//
ObservedObject o = createObservedObject(object);
o.setAlreadyNotified(RESET_FLAGS_ALREADY_NOTIFIED);
o.setDerivedGauge(INTEGER_ZERO);
o.setDerivedGaugeTimeStamp(System.currentTimeMillis());
observedObjects.add(o);
// Update legacy protected stuff.
//
createAlreadyNotified();
}
/**
* Removes the specified object from the set of observed MBeans.
*
* @param object The object to remove.
*
*/
public synchronized void removeObservedObject(ObjectName object) {
// Check for null object.
//
if (object == null)
return;
final ObservedObject o = getObservedObject(object);
if (o != null) {
// Remove the specified object from the list.
//
observedObjects.remove(o);
// Update legacy protected stuff.
//
createAlreadyNotified();
}
}
/**
* Tests whether the specified object is in the set of observed MBeans.
*
* @param object The object to check.
* @return true
if the specified object is present,
* false
otherwise.
*
*/
public synchronized boolean containsObservedObject(ObjectName object) {
return getObservedObject(object) != null;
}
/**
* Returns an array containing the objects being observed.
*
* @return The objects being observed.
*
*/
public synchronized ObjectName[] getObservedObjects() {
ObjectName[] names = new ObjectName[observedObjects.size()];
for (int i = 0; i < names.length; i++)
names[i] = observedObjects.get(i).getObservedObject();
return names;
}
/**
* Gets the attribute being observed.
*
The observed attribute is not initialized by default (set to null).
*
* @return The attribute being observed.
*
* @see #setObservedAttribute
*/
public synchronized String getObservedAttribute() {
return observedAttribute;
}
/**
* Sets the attribute to observe.
*
The observed attribute is not initialized by default (set to null).
*
* @param attribute The attribute to observe.
* @exception IllegalArgumentException The specified
* attribute is null.
*
* @see #getObservedAttribute
*/
public void setObservedAttribute(String attribute)
throws IllegalArgumentException {
if (attribute == null) {
throw new IllegalArgumentException("Null observed attribute");
}
// Update alreadyNotified array.
//
synchronized (this) {
if (observedAttribute != null &&
observedAttribute.equals(attribute))
return;
observedAttribute = attribute;
// Reset the complex type attribute information
// such that it is recalculated again.
//
cleanupIsComplexTypeAttribute();
int index = 0;
for (ObservedObject o : observedObjects) {
resetAlreadyNotified(o, index++,
OBSERVED_ATTRIBUTE_ERROR_NOTIFIED |
OBSERVED_ATTRIBUTE_TYPE_ERROR_NOTIFIED);
}
}
}
/**
* Gets the granularity period (in milliseconds).
*
The default value of the granularity period is 10 seconds.
*
* @return The granularity period value.
*
* @see #setGranularityPeriod
*/
public synchronized long getGranularityPeriod() {
return granularityPeriod;
}
/**
* Sets the granularity period (in milliseconds).
*
The default value of the granularity period is 10 seconds.
*
* @param period The granularity period value.
* @exception IllegalArgumentException The granularity
* period is less than or equal to zero.
*
* @see #getGranularityPeriod
*/
public synchronized void setGranularityPeriod(long period)
throws IllegalArgumentException {
if (period <= 0) {
throw new IllegalArgumentException("Nonpositive granularity " +
"period");
}
if (granularityPeriod == period)
return;
granularityPeriod = period;
// Reschedule the scheduler task if the monitor is active.
//
if (isActive()) {
cleanupFutures();
schedulerFuture = scheduler.schedule(schedulerTask,
period,
TimeUnit.MILLISECONDS);
}
}
/**
* Tests whether the monitor MBean is active. A monitor MBean is
* marked active when the {@link #start start} method is called.
* It becomes inactive when the {@link #stop stop} method is
* called.
*
* @return true
if the monitor MBean is active,
* false
otherwise.
*/
/* This method must be synchronized so that the monitoring thread will
correctly see modifications to the isActive variable. See the MonitorTask
action executed by the Scheduled Executor Service. */
public synchronized boolean isActive() {
return isActive;
}
/*
* ------------------------------------------
* PACKAGE METHODS
* ------------------------------------------
*/
/**
* Starts the monitor.
*/
void doStart() {
MONITOR_LOGGER.logp(Level.FINER, Monitor.class.getName(),
"doStart()", "start the monitor");
synchronized (this) {
if (isActive()) {
MONITOR_LOGGER.logp(Level.FINER, Monitor.class.getName(),
"doStart()", "the monitor is already active");
return;
}
isActive = true;
// Reset the complex type attribute information
// such that it is recalculated again.
//
cleanupIsComplexTypeAttribute();
// Cache the AccessControlContext of the Monitor.start() caller.
// The monitor tasks will be executed within this context.
//
acc = AccessController.getContext();
// Start the scheduler.
//
cleanupFutures();
schedulerTask.setMonitorTask(new MonitorTask());
schedulerFuture = scheduler.schedule(schedulerTask,
getGranularityPeriod(),
TimeUnit.MILLISECONDS);
}
}
/**
* Stops the monitor.
*/
void doStop() {
MONITOR_LOGGER.logp(Level.FINER, Monitor.class.getName(),
"doStop()", "stop the monitor");
synchronized (this) {
if (!isActive()) {
MONITOR_LOGGER.logp(Level.FINER, Monitor.class.getName(),
"doStop()", "the monitor is not active");
return;
}
isActive = false;
// Cancel the scheduler task associated with the
// scheduler and its associated monitor task.
//
cleanupFutures();
// Reset the AccessControlContext.
//
acc = noPermissionsACC;
// Reset the complex type attribute information
// such that it is recalculated again.
//
cleanupIsComplexTypeAttribute();
}
}
/**
* Gets the derived gauge of the specified object, if this object is
* contained in the set of observed MBeans, or null
otherwise.
*
* @param object the name of the object whose derived gauge is to
* be returned.
*
* @return The derived gauge of the specified object.
*
* @since 1.6
*/
synchronized Object getDerivedGauge(ObjectName object) {
final ObservedObject o = getObservedObject(object);
return o == null ? null : o.getDerivedGauge();
}
/**
* Gets the derived gauge timestamp of the specified object, if
* this object is contained in the set of observed MBeans, or
* 0
otherwise.
*
* @param object the name of the object whose derived gauge
* timestamp is to be returned.
*
* @return The derived gauge timestamp of the specified object.
*
*/
synchronized long getDerivedGaugeTimeStamp(ObjectName object) {
final ObservedObject o = getObservedObject(object);
return o == null ? 0 : o.getDerivedGaugeTimeStamp();
}
Object getAttribute(MBeanServerConnection mbsc,
ObjectName object,
String attribute)
throws AttributeNotFoundException,
InstanceNotFoundException,
MBeanException,
ReflectionException,
IOException {
// Check for "ObservedAttribute" replacement.
// This could happen if a thread A called setObservedAttribute()
// while other thread B was in the middle of the monitor() method
// and received the old observed attribute value.
//
final boolean lookupMBeanInfo;
synchronized (this) {
if (!isActive())
throw new IllegalArgumentException(
"The monitor has been stopped");
if (!attribute.equals(getObservedAttribute()))
throw new IllegalArgumentException(
"The observed attribute has been changed");
lookupMBeanInfo =
(firstAttribute == null && attribute.indexOf('.') != -1);
}
// Look up MBeanInfo if needed
//
final MBeanInfo mbi;
if (lookupMBeanInfo) {
try {
mbi = mbsc.getMBeanInfo(object);
} catch (IntrospectionException e) {
throw new IllegalArgumentException(e);
}
} else {
mbi = null;
}
// Check for complex type attribute
//
final String fa;
synchronized (this) {
if (!isActive())
throw new IllegalArgumentException(
"The monitor has been stopped");
if (!attribute.equals(getObservedAttribute()))
throw new IllegalArgumentException(
"The observed attribute has been changed");
if (firstAttribute == null) {
if (attribute.indexOf('.') != -1) {
MBeanAttributeInfo mbaiArray[] = mbi.getAttributes();
for (MBeanAttributeInfo mbai : mbaiArray) {
if (attribute.equals(mbai.getName())) {
firstAttribute = attribute;
break;
}
}
if (firstAttribute == null) {
String tokens[] = attribute.split("\\.", -1);
firstAttribute = tokens[0];
for (int i = 1; i < tokens.length; i++)
remainingAttributes.add(tokens[i]);
isComplexTypeAttribute = true;
}
} else {
firstAttribute = attribute;
}
}
fa = firstAttribute;
}
return mbsc.getAttribute(object, fa);
}
Comparable> getComparableFromAttribute(ObjectName object,
String attribute,
Object value)
throws AttributeNotFoundException {
if (isComplexTypeAttribute) {
Object v = value;
for (String attr : remainingAttributes)
v = Introspector.elementFromComplex(v, attr);
return (Comparable>) v;
} else {
return (Comparable>) value;
}
}
boolean isComparableTypeValid(ObjectName object,
String attribute,
Comparable> value) {
return true;
}
String buildErrorNotification(ObjectName object,
String attribute,
Comparable> value) {
return null;
}
void onErrorNotification(MonitorNotification notification) {
}
Comparable> getDerivedGaugeFromComparable(ObjectName object,
String attribute,
Comparable> value) {
return (Comparable>) value;
}
MonitorNotification buildAlarmNotification(ObjectName object,
String attribute,
Comparable> value){
return null;
}
boolean isThresholdTypeValid(ObjectName object,
String attribute,
Comparable> value) {
return true;
}
static Class extends Number> classForType(NumericalType type) {
switch (type) {
case BYTE:
return Byte.class;
case SHORT:
return Short.class;
case INTEGER:
return Integer.class;
case LONG:
return Long.class;
case FLOAT:
return Float.class;
case DOUBLE:
return Double.class;
default:
throw new IllegalArgumentException(
"Unsupported numerical type");
}
}
static boolean isValidForType(Object value, Class extends Number> c) {
return ((value == INTEGER_ZERO) || c.isInstance(value));
}
/**
* Get the specified {@code ObservedObject} if this object is
* contained in the set of observed MBeans, or {@code null}
* otherwise.
*
* @param object the name of the {@code ObservedObject} to retrieve.
*
* @return The {@code ObservedObject} associated to the supplied
* {@code ObjectName}.
*
* @since 1.6
*/
synchronized ObservedObject getObservedObject(ObjectName object) {
for (ObservedObject o : observedObjects)
if (o.getObservedObject().equals(object))
return o;
return null;
}
/**
* Factory method for ObservedObject creation.
*
* @since 1.6
*/
ObservedObject createObservedObject(ObjectName object) {
return new ObservedObject(object);
}
/**
* Create the {@link #alreadyNotified} array from
* the {@code ObservedObject} array list.
*/
synchronized void createAlreadyNotified() {
// Update elementCount.
//
elementCount = observedObjects.size();
// Update arrays.
//
alreadyNotifieds = new int[elementCount];
for (int i = 0; i < elementCount; i++) {
alreadyNotifieds[i] = observedObjects.get(i).getAlreadyNotified();
}
updateDeprecatedAlreadyNotified();
}
/**
* Update the deprecated {@link #alreadyNotified} field.
*/
synchronized void updateDeprecatedAlreadyNotified() {
if (elementCount > 0)
alreadyNotified = alreadyNotifieds[0];
else
alreadyNotified = 0;
}
/**
* Update the {@link #alreadyNotifieds} array element at the given index
* with the already notified flag in the given {@code ObservedObject}.
* Ensure the deprecated {@link #alreadyNotified} field is updated
* if appropriate.
*/
synchronized void updateAlreadyNotified(ObservedObject o, int index) {
alreadyNotifieds[index] = o.getAlreadyNotified();
if (index == 0)
updateDeprecatedAlreadyNotified();
}
/**
* Check if the given bits in the given element of {@link #alreadyNotifieds}
* are set.
*/
synchronized boolean isAlreadyNotified(ObservedObject o, int mask) {
return ((o.getAlreadyNotified() & mask) != 0);
}
/**
* Set the given bits in the given element of {@link #alreadyNotifieds}.
* Ensure the deprecated {@link #alreadyNotified} field is updated
* if appropriate.
*/
synchronized void setAlreadyNotified(ObservedObject o, int index,
int mask, int an[]) {
final int i = computeAlreadyNotifiedIndex(o, index, an);
if (i == -1)
return;
o.setAlreadyNotified(o.getAlreadyNotified() | mask);
updateAlreadyNotified(o, i);
}
/**
* Reset the given bits in the given element of {@link #alreadyNotifieds}.
* Ensure the deprecated {@link #alreadyNotified} field is updated
* if appropriate.
*/
synchronized void resetAlreadyNotified(ObservedObject o,
int index, int mask) {
o.setAlreadyNotified(o.getAlreadyNotified() & ~mask);
updateAlreadyNotified(o, index);
}
/**
* Reset all bits in the given element of {@link #alreadyNotifieds}.
* Ensure the deprecated {@link #alreadyNotified} field is updated
* if appropriate.
*/
synchronized void resetAllAlreadyNotified(ObservedObject o,
int index, int an[]) {
final int i = computeAlreadyNotifiedIndex(o, index, an);
if (i == -1)
return;
o.setAlreadyNotified(RESET_FLAGS_ALREADY_NOTIFIED);
updateAlreadyNotified(o, index);
}
/**
* Check if the {@link #alreadyNotifieds} array has been modified.
* If true recompute the index for the given observed object.
*/
synchronized int computeAlreadyNotifiedIndex(ObservedObject o,
int index, int an[]) {
if (an == alreadyNotifieds) {
return index;
} else {
return observedObjects.indexOf(o);
}
}
/*
* ------------------------------------------
* PRIVATE METHODS
* ------------------------------------------
*/
/**
* This method is used by the monitor MBean to create and send a
* monitor notification to all the listeners registered for this
* kind of notification.
*
* @param type The notification type.
* @param timeStamp The notification emission date.
* @param msg The notification message.
* @param derGauge The derived gauge.
* @param trigger The threshold/string (depending on the monitor
* type) that triggered off the notification.
* @param object The ObjectName of the observed object that triggered
* off the notification.
* @param onError Flag indicating if this monitor notification is
* an error notification or an alarm notification.
*/
private void sendNotification(String type, long timeStamp, String msg,
Object derGauge, Object trigger,
ObjectName object, boolean onError) {
if (!isActive())
return;
if (MONITOR_LOGGER.isLoggable(Level.FINER)) {
MONITOR_LOGGER.logp(Level.FINER, Monitor.class.getName(),
"sendNotification", "send notification: " +
"\n\tNotification observed object = " + object +
"\n\tNotification observed attribute = " + observedAttribute +
"\n\tNotification derived gauge = " + derGauge);
}
long seqno = sequenceNumber.getAndIncrement();
MonitorNotification mn =
new MonitorNotification(type,
this,
seqno,
timeStamp,
msg,
object,
observedAttribute,
derGauge,
trigger);
if (onError)
onErrorNotification(mn);
sendNotification(mn);
}
/**
* This method is called by the monitor each time
* the granularity period has been exceeded.
* @param o The observed object.
*/
private void monitor(ObservedObject o, int index, int an[]) {
String attribute;
String notifType = null;
String msg = null;
Object derGauge = null;
Object trigger = null;
ObjectName object;
Comparable> value = null;
MonitorNotification alarm = null;
if (!isActive())
return;
// Check that neither the observed object nor the
// observed attribute are null. If the observed
// object or observed attribute is null, this means
// that the monitor started before a complete
// initialization and nothing is done.
//
synchronized (this) {
object = o.getObservedObject();
attribute = getObservedAttribute();
if (object == null || attribute == null) {
return;
}
}
// Check that the observed object is registered in the
// MBean server and that the observed attribute
// belongs to the observed object.
//
Object attributeValue = null;
try {
attributeValue = getAttribute(server, object, attribute);
if (attributeValue == null)
if (isAlreadyNotified(
o, OBSERVED_ATTRIBUTE_TYPE_ERROR_NOTIFIED))
return;
else {
notifType = OBSERVED_ATTRIBUTE_TYPE_ERROR;
setAlreadyNotified(
o, index, OBSERVED_ATTRIBUTE_TYPE_ERROR_NOTIFIED, an);
msg = "The observed attribute value is null.";
MONITOR_LOGGER.logp(Level.FINEST, Monitor.class.getName(),
"monitor", msg);
}
} catch (NullPointerException np_ex) {
if (isAlreadyNotified(o, RUNTIME_ERROR_NOTIFIED))
return;
else {
notifType = RUNTIME_ERROR;
setAlreadyNotified(o, index, RUNTIME_ERROR_NOTIFIED, an);
msg =
"The monitor must be registered in the MBean " +
"server or an MBeanServerConnection must be " +
"explicitly supplied.";
MONITOR_LOGGER.logp(Level.FINEST, Monitor.class.getName(),
"monitor", msg);
MONITOR_LOGGER.logp(Level.FINEST, Monitor.class.getName(),
"monitor", np_ex.toString());
}
} catch (InstanceNotFoundException inf_ex) {
if (isAlreadyNotified(o, OBSERVED_OBJECT_ERROR_NOTIFIED))
return;
else {
notifType = OBSERVED_OBJECT_ERROR;
setAlreadyNotified(
o, index, OBSERVED_OBJECT_ERROR_NOTIFIED, an);
msg =
"The observed object must be accessible in " +
"the MBeanServerConnection.";
MONITOR_LOGGER.logp(Level.FINEST, Monitor.class.getName(),
"monitor", msg);
MONITOR_LOGGER.logp(Level.FINEST, Monitor.class.getName(),
"monitor", inf_ex.toString());
}
} catch (AttributeNotFoundException anf_ex) {
if (isAlreadyNotified(o, OBSERVED_ATTRIBUTE_ERROR_NOTIFIED))
return;
else {
notifType = OBSERVED_ATTRIBUTE_ERROR;
setAlreadyNotified(
o, index, OBSERVED_ATTRIBUTE_ERROR_NOTIFIED, an);
msg =
"The observed attribute must be accessible in " +
"the observed object.";
MONITOR_LOGGER.logp(Level.FINEST, Monitor.class.getName(),
"monitor", msg);
MONITOR_LOGGER.logp(Level.FINEST, Monitor.class.getName(),
"monitor", anf_ex.toString());
}
} catch (MBeanException mb_ex) {
if (isAlreadyNotified(o, RUNTIME_ERROR_NOTIFIED))
return;
else {
notifType = RUNTIME_ERROR;
setAlreadyNotified(o, index, RUNTIME_ERROR_NOTIFIED, an);
msg = mb_ex.getMessage() == null ? "" : mb_ex.getMessage();
MONITOR_LOGGER.logp(Level.FINEST, Monitor.class.getName(),
"monitor", msg);
MONITOR_LOGGER.logp(Level.FINEST, Monitor.class.getName(),
"monitor", mb_ex.toString());
}
} catch (ReflectionException ref_ex) {
if (isAlreadyNotified(o, RUNTIME_ERROR_NOTIFIED)) {
return;
} else {
notifType = RUNTIME_ERROR;
setAlreadyNotified(o, index, RUNTIME_ERROR_NOTIFIED, an);
msg = ref_ex.getMessage() == null ? "" : ref_ex.getMessage();
MONITOR_LOGGER.logp(Level.FINEST, Monitor.class.getName(),
"monitor", msg);
MONITOR_LOGGER.logp(Level.FINEST, Monitor.class.getName(),
"monitor", ref_ex.toString());
}
} catch (IOException io_ex) {
if (isAlreadyNotified(o, RUNTIME_ERROR_NOTIFIED))
return;
else {
notifType = RUNTIME_ERROR;
setAlreadyNotified(o, index, RUNTIME_ERROR_NOTIFIED, an);
msg = io_ex.getMessage() == null ? "" : io_ex.getMessage();
MONITOR_LOGGER.logp(Level.FINEST, Monitor.class.getName(),
"monitor", msg);
MONITOR_LOGGER.logp(Level.FINEST, Monitor.class.getName(),
"monitor", io_ex.toString());
}
} catch (RuntimeException rt_ex) {
if (isAlreadyNotified(o, RUNTIME_ERROR_NOTIFIED))
return;
else {
notifType = RUNTIME_ERROR;
setAlreadyNotified(o, index, RUNTIME_ERROR_NOTIFIED, an);
msg = rt_ex.getMessage() == null ? "" : rt_ex.getMessage();
MONITOR_LOGGER.logp(Level.FINEST, Monitor.class.getName(),
"monitor", msg);
MONITOR_LOGGER.logp(Level.FINEST, Monitor.class.getName(),
"monitor", rt_ex.toString());
}
}
synchronized (this) {
// Check if the monitor has been stopped.
//
if (!isActive())
return;
// Check if the observed attribute has been changed.
//
// Avoid race condition where mbs.getAttribute() succeeded but
// another thread replaced the observed attribute meanwhile.
//
// Avoid setting computed derived gauge on erroneous attribute.
//
if (!attribute.equals(getObservedAttribute()))
return;
// Derive a Comparable object from the ObservedAttribute value
// if the type of the ObservedAttribute value is a complex type.
//
if (msg == null) {
try {
value = getComparableFromAttribute(object,
attribute,
attributeValue);
} catch (ClassCastException e) {
if (isAlreadyNotified(
o, OBSERVED_ATTRIBUTE_TYPE_ERROR_NOTIFIED))
return;
else {
notifType = OBSERVED_ATTRIBUTE_TYPE_ERROR;
setAlreadyNotified(o, index,
OBSERVED_ATTRIBUTE_TYPE_ERROR_NOTIFIED, an);
msg =
"The observed attribute value does not " +
"implement the Comparable interface.";
MONITOR_LOGGER.logp(Level.FINEST,
Monitor.class.getName(), "monitor", msg);
MONITOR_LOGGER.logp(Level.FINEST,
Monitor.class.getName(), "monitor", e.toString());
}
} catch (AttributeNotFoundException e) {
if (isAlreadyNotified(o, OBSERVED_ATTRIBUTE_ERROR_NOTIFIED))
return;
else {
notifType = OBSERVED_ATTRIBUTE_ERROR;
setAlreadyNotified(
o, index, OBSERVED_ATTRIBUTE_ERROR_NOTIFIED, an);
msg =
"The observed attribute must be accessible in " +
"the observed object.";
MONITOR_LOGGER.logp(Level.FINEST,
Monitor.class.getName(), "monitor", msg);
MONITOR_LOGGER.logp(Level.FINEST,
Monitor.class.getName(), "monitor", e.toString());
}
} catch (RuntimeException e) {
if (isAlreadyNotified(o, RUNTIME_ERROR_NOTIFIED))
return;
else {
notifType = RUNTIME_ERROR;
setAlreadyNotified(o, index,
RUNTIME_ERROR_NOTIFIED, an);
msg = e.getMessage() == null ? "" : e.getMessage();
MONITOR_LOGGER.logp(Level.FINEST,
Monitor.class.getName(), "monitor", msg);
MONITOR_LOGGER.logp(Level.FINEST,
Monitor.class.getName(), "monitor", e.toString());
}
}
}
// Check that the observed attribute type is supported by this
// monitor.
//
if (msg == null) {
if (!isComparableTypeValid(object, attribute, value)) {
if (isAlreadyNotified(
o, OBSERVED_ATTRIBUTE_TYPE_ERROR_NOTIFIED))
return;
else {
notifType = OBSERVED_ATTRIBUTE_TYPE_ERROR;
setAlreadyNotified(o, index,
OBSERVED_ATTRIBUTE_TYPE_ERROR_NOTIFIED, an);
msg = "The observed attribute type is not valid.";
MONITOR_LOGGER.logp(Level.FINEST,
Monitor.class.getName(), "monitor", msg);
}
}
}
// Check that threshold type is supported by this monitor.
//
if (msg == null) {
if (!isThresholdTypeValid(object, attribute, value)) {
if (isAlreadyNotified(o, THRESHOLD_ERROR_NOTIFIED))
return;
else {
notifType = THRESHOLD_ERROR;
setAlreadyNotified(o, index,
THRESHOLD_ERROR_NOTIFIED, an);
msg = "The threshold type is not valid.";
MONITOR_LOGGER.logp(Level.FINEST,
Monitor.class.getName(), "monitor", msg);
}
}
}
// Let someone subclassing the monitor to perform additional
// monitor consistency checks and report errors if necessary.
//
if (msg == null) {
msg = buildErrorNotification(object, attribute, value);
if (msg != null) {
if (isAlreadyNotified(o, RUNTIME_ERROR_NOTIFIED))
return;
else {
notifType = RUNTIME_ERROR;
setAlreadyNotified(o, index,
RUNTIME_ERROR_NOTIFIED, an);
MONITOR_LOGGER.logp(Level.FINEST,
Monitor.class.getName(), "monitor", msg);
}
}
}
// If no errors were found then clear all error flags and
// let the monitor decide if a notification must be sent.
//
if (msg == null) {
// Clear all already notified flags.
//
resetAllAlreadyNotified(o, index, an);
// Get derived gauge from comparable value.
//
derGauge = getDerivedGaugeFromComparable(object,
attribute,
value);
o.setDerivedGauge(derGauge);
o.setDerivedGaugeTimeStamp(System.currentTimeMillis());
// Check if an alarm must be fired.
//
alarm = buildAlarmNotification(object,
attribute,
(Comparable>) derGauge);
}
}
// Notify monitor errors
//
if (msg != null)
sendNotification(notifType,
System.currentTimeMillis(),
msg,
derGauge,
trigger,
object,
true);
// Notify monitor alarms
//
if (alarm != null && alarm.getType() != null)
sendNotification(alarm.getType(),
System.currentTimeMillis(),
alarm.getMessage(),
derGauge,
alarm.getTrigger(),
object,
false);
}
/**
* Cleanup the scheduler and monitor tasks futures.
*/
private synchronized void cleanupFutures() {
if (schedulerFuture != null) {
schedulerFuture.cancel(false);
schedulerFuture = null;
}
if (monitorFuture != null) {
monitorFuture.cancel(false);
monitorFuture = null;
}
}
/**
* Cleanup the "is complex type attribute" info.
*/
private synchronized void cleanupIsComplexTypeAttribute() {
firstAttribute = null;
remainingAttributes.clear();
isComplexTypeAttribute = false;
}
/**
* SchedulerTask nested class: This class implements the Runnable interface.
*
* The SchedulerTask is executed periodically with a given fixed delay by
* the Scheduled Executor Service.
*/
private class SchedulerTask implements Runnable {
private MonitorTask task;
/*
* ------------------------------------------
* CONSTRUCTORS
* ------------------------------------------
*/
public SchedulerTask() {
}
/*
* ------------------------------------------
* GETTERS/SETTERS
* ------------------------------------------
*/
public void setMonitorTask(MonitorTask task) {
this.task = task;
}
/*
* ------------------------------------------
* PUBLIC METHODS
* ------------------------------------------
*/
public void run() {
synchronized (Monitor.this) {
Monitor.this.monitorFuture = task.submit();
}
}
}
/**
* MonitorTask nested class: This class implements the Runnable interface.
*
* The MonitorTask is executed periodically with a given fixed delay by the
* Scheduled Executor Service.
*/
private class MonitorTask implements Runnable {
private ThreadPoolExecutor executor;
/*
* ------------------------------------------
* CONSTRUCTORS
* ------------------------------------------
*/
public MonitorTask() {
// Find out if there's already an existing executor for the calling
// thread and reuse it. Otherwise, create a new one and store it in
// the executors map. If there is a SecurityManager, the group of
// System.getSecurityManager() is used, else the group of the thread
// instantiating this MonitorTask, i.e. the group of the thread that
// calls "Monitor.start()".
SecurityManager s = System.getSecurityManager();
ThreadGroup group = (s != null) ? s.getThreadGroup() :
Thread.currentThread().getThreadGroup();
synchronized (executorsLock) {
for (ThreadPoolExecutor e : executors.keySet()) {
DaemonThreadFactory tf =
(DaemonThreadFactory) e.getThreadFactory();
ThreadGroup tg = tf.getThreadGroup();
if (tg == group) {
executor = e;
break;
}
}
if (executor == null) {
executor = new ThreadPoolExecutor(
maximumPoolSize,
maximumPoolSize,
60L,
TimeUnit.SECONDS,
new LinkedBlockingQueue