- /*
- * @(#)StringMonitor.java 4.41 04/05/18
- *
- * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
- * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
- */
-
- package javax.management.monitor;
-
-
- // java imports
- //
- import java.util.Date;
- import java.util.Timer;
- import java.util.TimerTask;
-
- // jmx imports
- //
- import javax.management.ObjectName;
- import javax.management.MBeanNotificationInfo;
- import javax.management.AttributeNotFoundException;
- import javax.management.InstanceNotFoundException;
- import javax.management.MBeanException;
- import javax.management.ReflectionException;
-
- /**
- * Defines a monitor MBean designed to observe the values of a string
- * attribute.
- * <P>
- * A string monitor sends notifications as follows:
- * <UL>
- * <LI> if the attribute value matches the string to compare value,
- * a {@link MonitorNotification#STRING_TO_COMPARE_VALUE_MATCHED
- * match notification} is sent.
- * The notify match flag must be set to <CODE>true</CODE>.
- * <BR>Subsequent matchings of the string to compare values do not
- * cause further notifications unless
- * the attribute value differs from the string to compare value.
- * <LI> if the attribute value differs from the string to compare value,
- * a {@link MonitorNotification#STRING_TO_COMPARE_VALUE_DIFFERED
- * differ notification} is sent.
- * The notify differ flag must be set to <CODE>true</CODE>.
- * <BR>Subsequent differences from the string to compare value do
- * not cause further notifications unless
- * the attribute value matches the string to compare value.
- * </UL>
- *
- * @version 4.41 05/18/04
- * @author Sun Microsystems, Inc
- *
- * @since 1.5
- */
- public class StringMonitor extends Monitor implements StringMonitorMBean {
-
-
- // TRACES & DEBUG
- //---------------
-
- String makeDebugTag() {
- return "StringMonitor";
- }
-
- /*
- * ------------------------------------------
- * PRIVATE VARIABLES
- * ------------------------------------------
- */
-
- private final static String[] types = {
- MonitorNotification.RUNTIME_ERROR,
- MonitorNotification.OBSERVED_OBJECT_ERROR,
- MonitorNotification.OBSERVED_ATTRIBUTE_ERROR,
- MonitorNotification.OBSERVED_ATTRIBUTE_TYPE_ERROR,
- MonitorNotification.STRING_TO_COMPARE_VALUE_MATCHED,
- MonitorNotification.STRING_TO_COMPARE_VALUE_DIFFERED};
- private final static MBeanNotificationInfo[] notifsInfo = {
- new MBeanNotificationInfo(types,
- "javax.management.monitor.MonitorNotification",
- "Notifications sent by the StringMonitor MBean")};
-
- /**
- * String to compare with the observed attribute.
- * <BR>The default value is an empty character sequence.
- */
- private String stringToCompare = "";
-
- /**
- * Flag indicating if the string monitor notifies when matching
- * the string to compare.
- * <BR>The default value is set to <CODE>false</CODE>.
- */
- private boolean notifyMatch = false;
-
- /**
- * Flag indicating if the string monitor notifies when differing
- * from the string to compare.
- * <BR>The default value is set to <CODE>false</CODE>.
- */
- private boolean notifyDiffer = false;
-
- /**
- * Derived gauges.
- * <BR>Each element in this array corresponds to an observed object
- * in the list.
- */
- private String derivedGauge[] = new String[capacityIncrement];
-
- /**
- * Derived gauge timestamps.
- * <BR>Each element in this array corresponds to an observed object
- * in the list.
- */
- private long derivedGaugeTimestamp[] = new long[capacityIncrement];
-
- /**
- * This attribute is used to handle the matching/differing mechanism.
- * <BR>Each element in this array corresponds to an observed object
- * in the list.
- */
- private int status[] = new int[capacityIncrement];
-
- // Flags needed to implement the matching/differing mechanism.
- //
- private static final int MATCHING = 0;
- private static final int DIFFERING = 1;
- private static final int MATCHING_OR_DIFFERING = 2;
-
- /**
- * Timer.
- */
- private transient Timer timer = null;
-
-
- /*
- * ------------------------------------------
- * CONSTRUCTORS
- * ------------------------------------------
- */
-
- /**
- * Default constructor.
- */
- public StringMonitor() {
- dbgTag = makeDebugTag();
- }
-
- /*
- * ------------------------------------------
- * PUBLIC METHODS
- * ------------------------------------------
- */
-
- /**
- * Starts the string monitor.
- */
- public synchronized void start() {
-
- if (isTraceOn()) {
- trace("start", "start the string monitor");
- }
-
- if (isActive) {
- if (isTraceOn()) {
- trace("start", "the string monitor is already activated");
- }
-
- return;
- }
-
- isActive = true;
-
- // Reset values.
- //
- for (int i = 0; i < elementCount; i++) {
- status[i] = MATCHING_OR_DIFFERING;
- }
-
- // Start the AlarmClock.
- //
- timer = new Timer();
- timer.schedule(new StringAlarmClock(this),
- getGranularityPeriod(), getGranularityPeriod());
- }
-
- /**
- * Stops the string monitor.
- */
- /* This method is not synchronized, because if it were there could
- be a deadlock with a thread that attempted to get the lock on
- the monitor before being interrupted or noticing that it had
- been interrupted. */
- public void stop() {
-
- if (isTraceOn()) {
- trace("stop", "stop the string monitor");
- }
-
- synchronized(this) {
- if (!isActive) {
- if (isTraceOn()) {
- trace("stop", "the string monitor is already deactivated");
- }
-
- return;
- }
-
- isActive = false;
-
- // Stop the AlarmClock.
- //
- if (timer != null) {
- timer.cancel();
- timer = null;
- }
- }
- }
-
- // GETTERS AND SETTERS
- //--------------------
-
- /**
- * Sets the granularity period (in milliseconds).
- * <BR>The default value of the granularity period is 10 seconds.
- *
- * @param period The granularity period value.
- * @exception java.lang.IllegalArgumentException The granularity
- * period is less than or equal to zero.
- *
- * @see Monitor#setGranularityPeriod(long)
- */
- public synchronized void setGranularityPeriod(long period)
- throws IllegalArgumentException {
- super.setGranularityPeriod(period);
-
- // Reschedule timer task if timer is already running
- //
- if (isActive) {
- timer.cancel();
- timer = new Timer();
- timer.schedule(new StringAlarmClock(this),
- getGranularityPeriod(), getGranularityPeriod());
- }
- }
-
- /**
- * Gets the derived gauge of the specified object, if this object is
- * contained in the set of observed MBeans, or <code>null</code> otherwise.
- *
- * @param object the name of the MBean whose derived gauge is required.
- *
- * @return The derived gauge of the specified object.
- *
- * @since.unbundled JMX 1.2
- */
- public synchronized String getDerivedGauge(ObjectName object) {
- int index = indexOf(object);
- if (index != -1)
- return derivedGauge[index];
- else
- return null;
- }
-
- /**
- * Gets the derived gauge timestamp of the specified object, if
- * this object is contained in the set of observed MBeans, or
- * <code>null</code> otherwise.
- *
- * @param object the name of the MBean whose derived gauge
- * timestamp is required.
- *
- * @return The derived gauge timestamp of the specified object.
- *
- * @since.unbundled JMX 1.2
- */
- public synchronized long getDerivedGaugeTimeStamp(ObjectName object) {
- int index = indexOf(object);
- if (index != -1)
- return derivedGaugeTimestamp[index];
- else
- return 0;
- }
-
- /**
- * Returns the derived gauge of the first object in the set of
- * observed MBeans.
- *
- * @return The derived gauge.
- * @deprecated As of JMX 1.2, replaced by {@link #getDerivedGauge(ObjectName)}
- */
- public synchronized String getDerivedGauge() {
- return derivedGauge[0];
- }
-
- /**
- * Gets the derived gauge timestamp of the first object in the set
- * of observed MBeans.
- *
- * @return The derived gauge timestamp.
- * @deprecated As of JMX 1.2, replaced by
- * {@link #getDerivedGaugeTimeStamp(ObjectName)}
- */
- @Deprecated
- public synchronized long getDerivedGaugeTimeStamp() {
- return derivedGaugeTimestamp[0];
- }
-
- /**
- * Gets the string to compare with the observed attribute common
- * to all observed MBeans.
- *
- * @return The string value.
- *
- * @see #setStringToCompare
- */
- public synchronized String getStringToCompare() {
- return stringToCompare;
- }
-
- /**
- * Sets the string to compare with the observed attribute common
- * to all observed MBeans.
- *
- * @param value The string value.
- * @exception java.lang.IllegalArgumentException The specified
- * string to compare is null.
- *
- * @see #getStringToCompare
- */
- public synchronized void setStringToCompare(String value)
- throws java.lang.IllegalArgumentException {
-
- if (value == null) {
- throw new IllegalArgumentException("Null string to compare");
- }
-
- stringToCompare = value;
-
- // Reset values.
- //
- for (int i = 0; i < elementCount; i++) {
- status[i] = MATCHING_OR_DIFFERING;
- }
- }
-
- /**
- * Gets the matching notification's on/off switch value common to
- * all observed MBeans.
- *
- * @return <CODE>true</CODE> if the string monitor notifies when
- * matching the string to compare, <CODE>false</CODE> otherwise.
- *
- * @see #setNotifyMatch
- */
- public synchronized boolean getNotifyMatch() {
- return notifyMatch;
- }
-
- /**
- * Sets the matching notification's on/off switch value common to
- * all observed MBeans.
- *
- * @param value The matching notification's on/off switch value.
- *
- * @see #getNotifyMatch
- */
- public synchronized void setNotifyMatch(boolean value) {
- notifyMatch = value;
- }
-
- /**
- * Gets the differing notification's on/off switch value common to
- * all observed MBeans.
- *
- * @return <CODE>true</CODE> if the string monitor notifies when
- * differing from the string to compare, <CODE>false</CODE> otherwise.
- *
- * @see #setNotifyDiffer
- */
- public synchronized boolean getNotifyDiffer() {
- return notifyDiffer;
- }
-
- /**
- * Sets the differing notification's on/off switch value common to
- * all observed MBeans.
- *
- * @param value The differing notification's on/off switch value.
- *
- * @see #getNotifyDiffer
- */
- public synchronized void setNotifyDiffer(boolean value) {
- notifyDiffer = value;
- }
-
- /**
- * Returns a <CODE>NotificationInfo</CODE> object containing the
- * name of the Java class of the notification
- * and the notification types sent by the string monitor.
- */
- public MBeanNotificationInfo[] getNotificationInfo() {
- return notifsInfo;
- }
-
- /*
- * ------------------------------------------
- * PRIVATE METHODS
- * ------------------------------------------
- */
-
- /**
- * Updates the derived gauge and the derived gauge timestamp attributes
- * of the observed object at the specified index.
- *
- * @param scanString The value of the observed attribute.
- * @param index The index of the observed object.
- */
- private synchronized void updateDerivedGauge(Object scanString,
- int index) {
- derivedGaugeTimestamp[index] = System.currentTimeMillis();
- derivedGauge[index] = (String)scanString;
- }
-
- /**
- * Updates the notification attributes of the observed object at the
- * specified index and notifies the listeners only once if the
- * notifyMatch/notifyDiffer flag is set to <CODE>true</CODE>.
- * @param index The index of the observed object.
- */
- private void updateNotifications(int index) {
- boolean sendNotify = false;
- String type = null;
- long timeStamp = 0;
- String msg = null;
- Object derGauge = null;
- Object trigger = null;
-
- synchronized(this) {
- // Send matching notification if notifyMatch is true.
- // Send differing notification if notifyDiffer is true.
- //
- if (status[index] == MATCHING_OR_DIFFERING) {
- if (derivedGauge[index].equals(stringToCompare)) {
- if (notifyMatch) {
- sendNotify = true;
- type =
- MonitorNotification.STRING_TO_COMPARE_VALUE_MATCHED;
- timeStamp = derivedGaugeTimestamp[index];
- msg = "";
- derGauge = derivedGauge[index];
- trigger = stringToCompare;
- }
-
- status[index] = DIFFERING;
- } else {
- if (notifyDiffer) {
- sendNotify = true;
- type =
- MonitorNotification.STRING_TO_COMPARE_VALUE_DIFFERED;
- timeStamp = derivedGaugeTimestamp[index];
- msg = "";
- derGauge = derivedGauge[index];
- trigger = stringToCompare;
- }
- status[index] = MATCHING;
- }
- } else {
- if (status[index] == MATCHING) {
- if (derivedGauge[index].equals(stringToCompare)) {
- if (notifyMatch) {
- sendNotify = true;
- type =
- MonitorNotification.STRING_TO_COMPARE_VALUE_MATCHED;
- timeStamp = derivedGaugeTimestamp[index];
- msg = "";
- derGauge = derivedGauge[index];
- trigger = stringToCompare;
-
- }
- status[index] = DIFFERING;
- }
- } else if (status[index] == DIFFERING) {
- if (!derivedGauge[index].equals(stringToCompare)) {
- if (notifyDiffer) {
- sendNotify = true;
- type =
- MonitorNotification.STRING_TO_COMPARE_VALUE_DIFFERED;
- timeStamp = derivedGaugeTimestamp[index];
- msg = "";
- derGauge = derivedGauge[index];
- trigger = stringToCompare;
- }
- status[index] = MATCHING;
- }
- }
- }
- }
-
- if (sendNotify) {
- sendNotification(type, timeStamp, msg, derGauge, trigger, index);
- }
- }
-
- /*
- * ------------------------------------------
- * PACKAGE METHODS
- * ------------------------------------------
- */
-
- /**
- * This method is called by the string monitor each time
- * the granularity period has been exceeded.
- * @param index The index of the observed object.
- */
- void notifyAlarmClock(int index) {
- boolean sendNotify = false;
- String type = null;
- long timeStamp = 0;
- String msg = null;
- Object derGauge = null;
- Object trigger = null;
-
- Object scan_string = null;
- String notif_type = null;
-
- synchronized(this) {
- if (!isActive)
- return;
-
- // Check if the observed object and observed attribute are valid.
- //
-
- // 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.
- //
- if ((getObservedObject(index) == null) ||
- (getObservedAttribute() == null))
- return;
-
- // Check that the observed object is registered in the
- // MBean server and that the observed attribute belongs to
- // the observed object.
- //
- try {
- scan_string = server.getAttribute(getObservedObject(index),
- getObservedAttribute());
- if (scan_string == null)
- return;
- } catch (NullPointerException np_ex) {
- if (alreadyNotified(index, RUNTIME_ERROR_NOTIFIED))
- return;
- else {
- notif_type = MonitorNotification.RUNTIME_ERROR;
- setAlreadyNotified(index, RUNTIME_ERROR_NOTIFIED);
- msg =
- "The string monitor must be registered in " +
- "the MBean server.";
- }
- } catch (InstanceNotFoundException inf_ex) {
- if (alreadyNotified(index, OBSERVED_OBJECT_ERROR_NOTIFIED))
- return;
- else {
- notif_type = MonitorNotification.OBSERVED_OBJECT_ERROR;
- setAlreadyNotified(index, OBSERVED_OBJECT_ERROR_NOTIFIED);
- msg =
- "The observed object must be registered in " +
- "the MBean server.";
- }
- } catch (AttributeNotFoundException anf_ex) {
- if (alreadyNotified(index, OBSERVED_ATTRIBUTE_ERROR_NOTIFIED))
- return;
- else {
- notif_type = MonitorNotification.OBSERVED_ATTRIBUTE_ERROR;
- setAlreadyNotified(index,
- OBSERVED_ATTRIBUTE_ERROR_NOTIFIED);
- msg =
- "The observed attribute must be accessible in " +
- "the observed object.";
- }
- } catch (MBeanException mb_ex) {
- if (alreadyNotified(index, RUNTIME_ERROR_NOTIFIED))
- return;
- else {
- notif_type = MonitorNotification.RUNTIME_ERROR;
- setAlreadyNotified(index, RUNTIME_ERROR_NOTIFIED);
- msg = mb_ex.getMessage();
- }
- } catch (ReflectionException ref_ex) {
- if (alreadyNotified(index, OBSERVED_ATTRIBUTE_ERROR_NOTIFIED))
- return;
- else {
- notif_type = MonitorNotification.OBSERVED_ATTRIBUTE_ERROR;
- setAlreadyNotified(index, OBSERVED_ATTRIBUTE_ERROR_NOTIFIED);
- msg = ref_ex.getMessage();
- }
- }
-
- if (msg == null) {
- // Check that the observed attribute is of type "String".
- //
- if (!(scan_string instanceof String)) {
- if (alreadyNotified(index,
- OBSERVED_ATTRIBUTE_TYPE_ERROR_NOTIFIED))
- return;
- else {
- notif_type =
- MonitorNotification.OBSERVED_ATTRIBUTE_TYPE_ERROR;
- setAlreadyNotified(index,
- OBSERVED_ATTRIBUTE_TYPE_ERROR_NOTIFIED);
- msg =
- "The observed attribute type must be " +
- "a string type.";
- }
- }
- }
-
- if (msg == null) {
-
- // Clear all already notified flags.
- //
- resetAllAlreadyNotified(index);
-
- // Update the derived gauge attributes.
- //
- updateDerivedGauge(scan_string, index);
-
- // Notify the listeners.
- //
- updateNotifications(index);
-
- } else {
-
- // msg != null, will send the monitor error notification.
-
- timeStamp = derivedGaugeTimestamp[index];
- derGauge = derivedGauge[index];
-
- // Reset values.
- //
- status[index] = MATCHING_OR_DIFFERING;
- }
- }
-
- if (msg != null) {
- sendNotification(type, timeStamp, msg, derGauge, null, index);
- }
- }
-
- /**
- * This method is called when adding a new observed object in the vector.
- * It updates all the string specific arrays.
- * @param index The index of the observed object.
- */
- synchronized void insertSpecificElementAt(int index) {
- // Update derivedGauge, derivedGaugeTimestamp, and status arrays.
- //
-
- if (index != elementCount)
- throw new Error("Internal error: index != elementCount");
-
- if (elementCount >= derivedGauge.length) {
- derivedGauge = expandArray(derivedGauge);
- derivedGaugeTimestamp = expandArray(derivedGaugeTimestamp);
- status = expandArray(status);
- }
-
- derivedGauge[index] = "";
- derivedGaugeTimestamp[index] = System.currentTimeMillis();
- status[index] = MATCHING_OR_DIFFERING;
- }
-
- /**
- * This method is called when removing an observed object from the vector.
- * It updates all the string specific arrays.
- * @param index The index of the observed object.
- */
- synchronized void removeSpecificElementAt(int index) {
- if (index < 0 || index >= elementCount)
- return;
-
- // Update derivedGauge, derivedGaugeTimestamp, and status arrays.
- //
- removeElementAt(derivedGauge, index);
- removeElementAt(derivedGaugeTimestamp, index);
- removeElementAt(status, index);
- }
-
- /**
- * StringAlarmClock inner class:
- * This class provides a simple implementation of an alarm clock MBean.
- * The aim of this MBean is to set up an alarm which wakes up the
- * string monitor every granularity period.
- */
-
- private static class StringAlarmClock extends TimerTask {
-
- StringMonitor listener = null;
-
- /*
- * ------------------------------------------
- * CONSTRUCTORS
- * ------------------------------------------
- */
-
- public StringAlarmClock(StringMonitor listener) {
- this.listener = listener;
- }
-
- /*
- * ------------------------------------------
- * PUBLIC METHODS
- * ------------------------------------------
- */
-
- /**
- * This method is called by the StringAlarmClock thread when
- * it is started.
- */
- public void run() {
- if (listener.isActive) {
- for (int i = 0; i < listener.elementCount; i++) {
- listener.notifyAlarmClock(i);
- }
- }
- }
- }
- }