| /* |
| * 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; |
| } |