422 lines · 16.3 KB · Java
RawDownload
/* * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation.  Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package sun.jvmstat.monitor; import java.util.*;import java.net.*;import java.lang.reflect.*; import sun.jvmstat.monitor.event.HostListener; /** * An abstraction for a host that contains instrumented Java Virtual * Machines. The class provides abstract factory methods for creating * concrete instances of this class and factory methods for creating * {@link MonitoredVm} instances. Concrete implementations of this class * provide methods for managing the communications protocols and provide * for event notification. * * @author Brian Doherty * @since 1.5 * * @see HostIdentifier * @see VmIdentifier * @see MonitoredVm * @see HostListener */public abstract class MonitoredHost {    private static Map<HostIdentifier, MonitoredHost> monitoredHosts =                new HashMap<HostIdentifier, MonitoredHost>();     /*     * The monitoring implementation override mechanism. The value of     * this property is used as the class name for the concrete MonitoredHost     * subclass that implements the monitoring APIs.  Setting this property     * will cause the remaining override mechanisms to be ignored. When     * this mechanism is used, the HostIdentifier scheme name, which     * indicates the communications protocol, is not used to locate a     * the protocol specific package. However, the HostIdentifier is     * still passed to the corresponding single arg constructor.     * This property is not expected to be set in normal circumstances.     */    private static final String IMPL_OVERRIDE_PROP_NAME =            "sun.jvmstat.monitor.MonitoredHost";     /*     * The monitoring package name override mechanism. The value     * the this property is used as base package name for the     * monitoring implementation package. This property is not     * expected to be set under normal circumstances.     */    private static final String IMPL_PKG_PROP_NAME =            "sun.jvmstat.monitor.package";    private static final String IMPL_PACKAGE =            System.getProperty(IMPL_PKG_PROP_NAME, "sun.jvmstat.perfdata");     /*     * The default optimized local protocol override mechanism. The value     * of this property is used to construct the default package name     * for the default optimized local protocol as follows:     *        <IMPL_PACKAGE>.monitor.<LOCAL_PROTOCOL>     * This property is not expected to be set under normal circumstances.     */    private static final String LOCAL_PROTOCOL_PROP_NAME =            "sun.jvmstat.monitor.local";    private static final String LOCAL_PROTOCOL =            System.getProperty(LOCAL_PROTOCOL_PROP_NAME, "local");     /*     * The default remote protocol override mechanism. The value of     * this property is used to construct the default package name     * for the default remote protocol protocol as follows:     *        <IMPL_PACKAGE>.monitor.protocol.<REMOTE_PROTOCOL>     * This property is not expected to be set under normal circumstances.     */    private static final String REMOTE_PROTOCOL_PROP_NAME =            "sun.jvmstat.monitor.remote";    private static final String REMOTE_PROTOCOL =            System.getProperty(REMOTE_PROTOCOL_PROP_NAME, "rmi");     /*     * The default class name of the MonitoredHost implementation subclass.     * There is no override mechanism for this variable, other than the     * IMPL_OVERRIDE_PROP_NAME override, which is larger in scope. A concrete     * instance of this class is expected to be found in:     *     <IMPL_PACKAGE>.monitor.protocol.<protocol>.<MONITORED_HOST_CLASS>     */    private static final String MONITORED_HOST_CLASS = "MonitoredHostProvider";     /**     * The HostIdentifier for this MonitoredHost instance.     */    protected HostIdentifier hostId;     /**     * The polling interval, in milliseconds, for this MonitoredHost instance.     */    protected int interval;     /**     * The last Exception encountered while polling this MonitoredHost.     */    protected Exception lastException;     /**     * Factory method to construct MonitoredHost instances to manage     * connections to the host indicated by <tt>hostIdString</tt>     *     * @param hostIdString a String representation of a {@link HostIdentifier}     * @return MonitoredHost - the MonitoredHost instance for communicating     *                         with the indicated host using the protocol     *                         specified in hostIdString.     * @throws MonitorException  Thrown if monitoring errors occur.     * @throws URISyntaxException Thrown when the hostIdString is poorly     *                            formed. This exception may get encapsulated     *                            into MonitorException in a future revision.     */    public static MonitoredHost getMonitoredHost(String hostIdString)                  throws MonitorException, URISyntaxException {        HostIdentifier hostId = new HostIdentifier(hostIdString);        return getMonitoredHost(hostId);    }     /**     * Factory method to construct a MonitoredHost instance to manage the     * connection to the Java Virtual Machine indicated by <tt>vmid</tt>.     *     * This method provide a convenient short cut for attaching to a specific     * instrumented Java Virtual Machine. The information in the VmIdentifier     * is used to construct a corresponding HostIdentifier, which in turn is     * used to create the MonitoredHost instance.     *     * @param vmid The identifier for the target Java Virtual Machine.     * @return MonitoredHost - The MonitoredHost object needed to attach to     *                         the target Java Virtual Machine.     *     * @throws MonitorException Thrown if monitoring errors occur.     */    public static MonitoredHost getMonitoredHost(VmIdentifier vmid)                 throws MonitorException {        // use the VmIdentifier to construct the corresponding HostIdentifier        HostIdentifier hostId = new HostIdentifier(vmid);        return getMonitoredHost(hostId);    }     /**     * Factory method to construct a MonitoredHost instance to manage the     * connection to the host indicated by <tt>hostId</tt>.     *     * @param hostId the identifier for the target host.     * @return MonitoredHost - The MonitoredHost object needed to attach to     *                         the target host.     *     * @throws MonitorException Thrown if monitoring errors occur.     */    public static MonitoredHost getMonitoredHost(HostIdentifier hostId)                  throws MonitorException {        /*         * determine the class name to load. If the system property is set,         * use the indicated class. otherwise, use the default class.         */        String classname = System.getProperty(IMPL_OVERRIDE_PROP_NAME);        MonitoredHost mh = null;         synchronized(monitoredHosts) {            mh = monitoredHosts.get(hostId);            if (mh != null) {                if (mh.isErrored()) {                    monitoredHosts.remove(hostId);                } else {                    return mh;                }            }        }         hostId = resolveHostId(hostId);         if (classname == null) {            // construct the class name            classname = IMPL_PACKAGE + ".monitor.protocol."                        + hostId.getScheme() + "." + MONITORED_HOST_CLASS;        }         try {            // run the constructor taking a single String parameter.            Class<?> c = Class.forName(classname);             Constructor cons = c.getConstructor(                new Class[] { hostId.getClass() }            );             mh = (MonitoredHost)cons.newInstance(new Object[] { hostId } );             synchronized(monitoredHosts) {                monitoredHosts.put(mh.hostId, mh);            }            return mh;        } catch (ClassNotFoundException e) {            // from Class.forName();            throw new IllegalArgumentException("Could not find " + classname                                               + ": " + e.getMessage(), e);        } catch (NoSuchMethodException e) {            // from Class.getConstructor();            throw new IllegalArgumentException(                "Expected constructor missing in " + classname + ": "                + e.getMessage(), e);        } catch (IllegalAccessException e) {            // from Constructor.newInstance()            throw new IllegalArgumentException(                "Unexpected constructor access in " + classname + ": "                + e.getMessage(), e);        } catch (InstantiationException e) {            throw new IllegalArgumentException(classname + "is abstract: "                                               + e.getMessage(), e);        } catch (InvocationTargetException e) {            Throwable cause = e.getCause();            if (cause instanceof MonitorException) {                throw (MonitorException)cause;            }            throw new RuntimeException("Unexpected exception", e);        }    }     /**     * Method to resolve unspecified components of the given HostIdentifier     * by constructing a new HostIdentifier that replaces the unspecified     * components with the default values.     *     * @param hostId the unresolved HostIdentifier.     * @return HostIdentifier - a resolved HostIdentifier.     *     * @throws MonitorException Thrown if monitoring errors occur.     */    protected static HostIdentifier resolveHostId(HostIdentifier hostId)                     throws MonitorException {        String hostname = hostId.getHost();        String scheme = hostId.getScheme();        StringBuffer sb = new StringBuffer();         assert hostname != null;         if (scheme == null) {            if (hostname.compareTo("localhost") == 0) {                scheme = LOCAL_PROTOCOL;            } else {                scheme = REMOTE_PROTOCOL;            }        }         sb.append(scheme).append(":").append(hostId.getSchemeSpecificPart());         String frag = hostId.getFragment();        if (frag != null) {            sb.append("#").append(frag);        }         try {            return new HostIdentifier(sb.toString());        } catch (URISyntaxException e) {            // programming error - HostIdentifier was valid.            assert false;            throw new IllegalArgumentException("Malformed URI created: "                                               + sb.toString());        }    }     /**     * Return the resolved HostIdentifier for this MonitoredHost.     *     * @return HostIdentifier - the resolved HostIdentifier.     */    public HostIdentifier getHostIdentifier() {        return hostId;    }     /* ---- Methods to support polled MonitoredHost Implementations ----- */     /**     * Set the polling interval for this MonitoredHost.     *     * @param interval the polling interval, in milliseconds     */    public void setInterval(int interval) {        this.interval = interval;    }     /**     * Get the polling interval.     *     * @return int - the polling interval in milliseconds for this MonitoredHost     */    public int getInterval() {        return interval;    }     /**     * Set the last exception encountered while polling this MonitoredHost.     *     * @param lastException the last exception encountered;     */    public void setLastException(Exception lastException) {        this.lastException = lastException;    }     /**     * Get the last exception encountered while polling this MonitoredHost.     *     * @return Exception - the last exception occurred while polling this     *                     MonitoredHost, or <tt>null</tt> if no exception     *                     has occurred or the exception has been cleared,     */    public Exception getLastException() {        return lastException;    }     /**     * Clear the last exception.     */    public void clearLastException() {        lastException = null;    }     /**     * Test if this MonitoredHost is in the errored state. If this method     * returns true, then the Exception returned by getLastException()     * indicates the Exception that caused the error condition.     *     * @return boolean - true if the MonitoredHost instance has experienced     *                   an error, or false if it hasn't or if any past     *                   error has been cleared.     */    public boolean isErrored() {        return lastException != null;    }     /**     * Get the MonitoredVm for the given Java Virtual Machine. The default     * sampling interval is used for the MonitoredVm instance.     *     * @param id the VmIdentifier specifying the target Java Virtual Machine.     * @return MonitoredVm - the MonitoredVm instance for the target Java     *                       Virtual Machine.     * @throws MonitorException Thrown if monitoring errors occur.     */    public abstract MonitoredVm getMonitoredVm(VmIdentifier id)                                throws MonitorException;     /**     * Get the MonitoredVm for the given Java Virtual Machine. The sampling     * interval is set to the given interval.     *     * @param id the VmIdentifier specifying the target Java Virtual Machine.     * @param interval the sampling interval for the target Java Virtual Machine.     * @return MonitoredVm - the MonitoredVm instance for the target Java     *                       Virtual Machine.     * @throws MonitorException Thrown if monitoring errors occur.     */    public abstract MonitoredVm getMonitoredVm(VmIdentifier id, int interval)                                throws MonitorException;     /**     * Detach from the indicated MonitoredVm.     *     * @param vm the monitored Java Virtual Machine.     * @throws MonitorException Thrown if monitoring errors occur.     */    public abstract void detach(MonitoredVm vm) throws MonitorException;     /**     * Add a HostListener. The given listener is added to the list     * of HostListener objects to be notified of MonitoredHost related events.     *     * @param listener the HostListener to add.     * @throws MonitorException Thrown if monitoring errors occur.     */    public abstract void addHostListener(HostListener listener)                         throws MonitorException;     /**     * Remove a HostListener. The given listener is removed from the list     * of HostListener objects to be notified of MonitoredHost related events.     *     * @param listener the HostListener to add.     * @throws MonitorException Thrown if monitoring errors occur.     */    public abstract void removeHostListener(HostListener listener)                         throws MonitorException;     /**     * Return the current set of active Java Virtual Machines for this     * MonitoredHost. The returned Set contains {@link Integer} instances     * holding the local virtual machine identifier, or <em>lvmid</em>     * for each instrumented Java Virtual Machine currently available.     *     * @return Set - the current set of active Java Virtual Machines associated     *               with this MonitoredHost, or the empty set of none.     * @throws MonitorException Thrown if monitoring errors occur.     */    public abstract Set<Integer> activeVms() throws MonitorException;}