/*
 * Copyright 1999-2007 Sun Microsystems, Inc.  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.  Sun designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Sun in the LICENSE file that accompanied this code.
 *
 * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
 * CA 95054 USA or visit www.sun.com if you need additional information or
 * have any questions.
 */

package javax.management.monitor;

import static com.sun.jmx.defaults.JmxProperties.MONITOR_LOGGER;
import com.sun.jmx.mbeanserver.GetPropertyAction;
import com.sun.jmx.remote.util.EnvHelp;
import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.io.IOException;
import java.lang.reflect.Array;
import java.lang.reflect.InvocationTargetException;
import java.security.AccessControlContext;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
import java.util.logging.Level;
import javax.management.AttributeNotFoundException;
import javax.management.InstanceNotFoundException;
import javax.management.IntrospectionException;
import javax.management.MBeanAttributeInfo;
import javax.management.MBeanException;
import javax.management.MBeanInfo;
import javax.management.MBeanRegistration;
import javax.management.MBeanServer;
import javax.management.MBeanServerConnection;
import javax.management.NotificationBroadcasterSupport;
import javax.management.ObjectName;
import javax.management.ReflectionException;
import static javax.management.monitor.MonitorNotification.*;
import javax.management.openmbean.CompositeData;

/**
 * Defines the part common to all monitor MBeans.
 * A monitor MBean monitors values of an attribute common to a set of observed
 * MBeans. The observed attribute is monitored at intervals specified by the
 * granularity period. A gauge value (derived gauge) is derived from the values
 * of the observed attribute.
 *
 *
 * @since 1.5
 */
public abstract class Monitor
    extends NotificationBroadcasterSupport
    implements MonitorMBean, MBeanRegistration {

    /*
     * ------------------------------------------
     *  PACKAGE CLASSES
     * ------------------------------------------
     */

    static class ObservedObject {

        public ObservedObject(ObjectName observedObject) {
            this.observedObject = observedObject;
        }

        public final ObjectName getObservedObject() {
            return observedObject;
        }
        public final synchronized int getAlreadyNotified() {
            return alreadyNotified;
        }
        public final synchronized void setAlreadyNotified(int alreadyNotified) {
            this.alreadyNotified = alreadyNotified;
        }
        public final synchronized Object getDerivedGauge() {
            return derivedGauge;
        }
        public final synchronized void setDerivedGauge(Object derivedGauge) {
            this.derivedGauge = derivedGauge;
        }
        public final synchronized long getDerivedGaugeTimeStamp() {
            return derivedGaugeTimeStamp;
        }
        public final synchronized void setDerivedGaugeTimeStamp(
                                                 long derivedGaugeTimeStamp) {
            this.derivedGaugeTimeStamp = derivedGaugeTimeStamp;
        }

        private final ObjectName observedObject;
        private int alreadyNotified;
        private Object derivedGauge;
        private long derivedGaugeTimeStamp;
    }

    /*
     * ------------------------------------------
     *  PRIVATE VARIABLES
     * ------------------------------------------
     */

    /**
     * Attribute to observe.
     */
    private String observedAttribute;

    /**
     * Monitor granularity period (in milliseconds).
     * The default value is set to 10 seconds.
     */
    private long granularityPeriod = 10000;

    /**
     * Monitor state.
     * The default value is set to <CODE>false</CODE>.
     */
    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 <CODE>false</CODE>.
     */
    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 List<String> remainingAttributes =
        new CopyOnWriteArrayList<String>();

    /**
     * AccessControlContext of the Monitor.start() caller.
     */
    private AccessControlContext acc;

    /**
     * Scheduler Service.
     */
    private static final ScheduledExecutorService scheduler =
        Executors.newSingleThreadScheduledExecutor(
            new DaemonThreadFactory("Scheduler"));

    /**
     * Maximum Pool Size
     */
    private static final int maximumPoolSize;

    /**
     * Executor Service.
     */
    private static final ExecutorService executor;
    static {
        final String maximumPoolSizeSysProp = "jmx.x.monitor.maximum.pool.size";
        final String maximumPoolSizeStr = AccessController.doPrivileged(
            new GetPropertyAction(maximumPoolSizeSysProp));
        if (maximumPoolSizeStr == null ||
            maximumPoolSizeStr.trim().length() == 0) {
            maximumPoolSize = 10;
        } else {
            int maximumPoolSizeTmp = 10;
            try {
                maximumPoolSizeTmp = Integer.parseInt(maximumPoolSizeStr);
            } catch (NumberFormatException e) {
                if (MONITOR_LOGGER.isLoggable(Level.FINER)) {
                    MONITOR_LOGGER.logp(Level.FINER, Monitor.class.getName(),
                            "<static initializer>",
                            "Wrong value for " + maximumPoolSizeSysProp +
                            " system property", e);
                    MONITOR_LOGGER.logp(Level.FINER, Monitor.class.getName(),
                            "<static initializer>",
                            maximumPoolSizeSysProp + " defaults to 10");
                }
                maximumPoolSizeTmp = 10;
            }
            if (maximumPoolSizeTmp < 1) {
                maximumPoolSize = 1;
            } else {
                maximumPoolSize = maximumPoolSizeTmp;
            }
        }
        executor = new ThreadPoolExecutor(
                maximumPoolSize,
                maximumPoolSize,
                60L,
                TimeUnit.SECONDS,
                new LinkedBlockingQueue<Runnable>(),
                new DaemonThreadFactory("Executor"));
        ((ThreadPoolExecutor)executor).allowCoreThreadTimeOut(true);
    }

    /**
     * Monitor task to be executed by the Executor Service.
     */
    private final MonitorTask monitorTask = new MonitorTask();

    /**
     * Future associated to the current monitor task.
     */
    private Future<?> monitorFuture;

    /**
     * Scheduler task to be executed by the Scheduler Service.
     */
    private final SchedulerTask schedulerTask = new SchedulerTask(monitorTask);

    /**
     * ScheduledFuture associated to the current scheduler task.
     */
    private ScheduledFuture<?> schedulerFuture;

    /*
     * ------------------------------------------
     *  PROTECTED VARIABLES
     * ------------------------------------------
     */

    /**
     * The amount by which the capacity of the monitor arrays are
     * automatically incremented when their size becomes greater than
     * their capacity.
     */
    protected final static int capacityIncrement = 16;

    /**
     * The number of valid components in the vector of observed objects.
     *
     */
    protected int elementCount = 0;

    /**
     * Monitor errors that have already been notified.
     * @deprecated equivalent to {@link #alreadyNotifieds}[0].
     */
    @Deprecated
    protected int alreadyNotified = 0;

    /**
     * <p>Selected monitor errors that have already been notified.</p>
     *
     * <p>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.</p>
     *
     */
    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<ObservedObject> observedObjects =
        new CopyOnWriteArrayList<ObservedObject>();

    /**
     * Flag denoting that a notification has occurred after changing
     * the threshold. This flag is used to notify any exception
     * related to invalid thresholds settings.
     */
    static final int THRESHOLD_ERROR_NOTIFIED                           = 16;

    /**
     * Enumeration used to keep trace of the derived gauge type
     * in counter and gauge monitors.
     */
    enum NumericalType { BYTE, SHORT, INTEGER, LONG, FLOAT, DOUBLE };

    /**
     * Constant used to initialize all the numeric values.
     */
    static final Integer INTEGER_ZERO = new Integer(0);


    /*
     * ------------------------------------------
     *  PUBLIC METHODS
     * ------------------------------------------
     */

    /**
     * Allows the monitor MBean to perform any operations it needs
     * before being registered in the MBean server.
     * <P>
     * 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.
     * <P>
     * 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.
     * <P>
     * 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.
     * <P>
     * 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 <code>null</code> 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(null);
        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 <CODE>true</CODE> if the specified object is present,
     * <CODE>false</CODE> 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.
     * <BR>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.
     * <BR>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).
     * <BR>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).
     * <BR>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 <CODE>true</CODE> if the monitor MBean is active,
     * <CODE>false</CODE> 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();
            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 = null;

            // 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 <code>null</code> 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
     * <code>0</code> 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 = introspect(object, attr, v);
            return (Comparable<?>) v;
        } else {
            return (Comparable<?>) value;
        }
    }

    Object introspect(ObjectName object,
                      String attribute,
                      Object value)
        throws AttributeNotFoundException {
        try {
            if (value.getClass().isArray() && attribute.equals("length")) {
                return Array.getLength(value);
            } else if (value instanceof CompositeData) {
                return ((CompositeData) value).get(attribute);
            } else {
                // Java Beans introspection
                //
                BeanInfo bi = Introspector.getBeanInfo(value.getClass());
                PropertyDescriptor[] pds = bi.getPropertyDescriptors();
                for (PropertyDescriptor pd : pds)
                    if (pd.getName().equals(attribute))
                        return pd.getReadMethod().invoke(value);
                throw new AttributeNotFoundException(
                    "Could not find the getter method for the property " +
                    attribute + " using the Java Beans introspector");
            }
        } catch (InvocationTargetException e) {
            throw new IllegalArgumentException(e);
        } catch (AttributeNotFoundException e) {
            throw e;
        } catch (Exception e) {
            throw EnvHelp.initCause(
                new AttributeNotFoundException(e.getMessage()), e);
        }
    }

    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 = null;
        String notifType = null;
        String msg = null;
        Object derGauge = null;
        Object trigger = null;
        ObjectName object = null;
        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 Runnable task = null;

        /*
         * ------------------------------------------
         *  CONSTRUCTORS
         * ------------------------------------------
         */

        public SchedulerTask(Runnable task) {
            this.task = task;
        }

        /*
         * ------------------------------------------
         *  PUBLIC METHODS
         * ------------------------------------------
         */

        public void run() {
            synchronized (Monitor.this) {
                Monitor.this.monitorFuture = executor.submit(task);
            }
        }
    }

    /**
     * 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 {

        /*
         * ------------------------------------------
         *  CONSTRUCTORS
         * ------------------------------------------
         */

        public MonitorTask() {
        }

        /*
         * ------------------------------------------
         *  PUBLIC METHODS
         * ------------------------------------------
         */

        public void run() {
            final ScheduledFuture<?> sf;
            synchronized (Monitor.this) {
                sf = Monitor.this.schedulerFuture;
            }
            AccessController.doPrivileged(new PrivilegedAction<Void>() {
                public Void run() {
                    if (Monitor.this.isActive()) {
                        final int an[] = alreadyNotifieds;
                        int index = 0;
                        for (ObservedObject o : Monitor.this.observedObjects) {
                            if (Monitor.this.isActive()) {
                                Monitor.this.monitor(o, index++, an);
                            }
                        }
                    }
                    return null;
                }
            }, Monitor.this.acc);
            synchronized (Monitor.this) {
                if (Monitor.this.isActive() &&
                    Monitor.this.schedulerFuture == sf) {
                    Monitor.this.monitorFuture = null;
                    Monitor.this.schedulerFuture =
                        scheduler.schedule(Monitor.this.schedulerTask,
                                           Monitor.this.getGranularityPeriod(),
                                           TimeUnit.MILLISECONDS);
                }
            }
        }
    }

    /**
     * Daemon thread factory used by the monitor executors.
     * <P>
     * 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 <pool-name> Pool [Thread-M]",
     * where M is the sequence number of the thread created by this
     * factory.
     */
    private static class DaemonThreadFactory implements ThreadFactory {
        final ThreadGroup group;
        final AtomicInteger threadNumber = new AtomicInteger(1);
        final String namePrefix;
        final String nameSuffix = "]";

        public DaemonThreadFactory(String poolName) {
            SecurityManager s = System.getSecurityManager();
            group = (s != null) ? s.getThreadGroup() :
                                  Thread.currentThread().getThreadGroup();
            namePrefix = "JMX Monitor " + poolName + " Pool [Thread-";
        }

        public Thread newThread(Runnable r) {
            Thread t = new Thread(group,
                                  r,
                                  namePrefix +
                                  threadNumber.getAndIncrement() +
                                  nameSuffix,
                                  0);
            t.setDaemon(true);
            if (t.getPriority() != Thread.NORM_PRIORITY)
                t.setPriority(Thread.NORM_PRIORITY);
            return t;
        }
    }
}
