0N/A/*
2362N/A * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved.
0N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0N/A *
0N/A * This code is free software; you can redistribute it and/or modify it
0N/A * under the terms of the GNU General Public License version 2 only, as
0N/A * published by the Free Software Foundation. Oracle designates this
0N/A * particular file as subject to the "Classpath" exception as provided
0N/A * by Oracle in the LICENSE file that accompanied this code.
0N/A *
0N/A * This code is distributed in the hope that it will be useful, but WITHOUT
0N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0N/A * version 2 for more details (a copy is included in the LICENSE file that
0N/A * accompanied this code).
0N/A *
0N/A * You should have received a copy of the GNU General Public License version
0N/A * 2 along with this work; if not, write to the Free Software Foundation,
2362N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
2362N/A *
2362N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
0N/A * or visit www.oracle.com if you need additional information or have any
0N/A * questions.
0N/A */
0N/A
0N/Apackage sun.jvmstat.monitor;
0N/A
0N/Aimport java.util.*;
0N/Aimport java.net.*;
0N/Aimport java.lang.reflect.*;
0N/A
0N/Aimport sun.jvmstat.monitor.event.HostListener;
0N/A
0N/A/**
0N/A * An abstraction for a host that contains instrumented Java Virtual
0N/A * Machines. The class provides abstract factory methods for creating
0N/A * concrete instances of this class and factory methods for creating
0N/A * {@link MonitoredVm} instances. Concrete implementations of this class
0N/A * provide methods for managing the communications protocols and provide
0N/A * for event notification.
0N/A *
0N/A * @author Brian Doherty
0N/A * @since 1.5
0N/A *
0N/A * @see HostIdentifier
0N/A * @see VmIdentifier
0N/A * @see MonitoredVm
0N/A * @see HostListener
0N/A */
0N/Apublic abstract class MonitoredHost {
0N/A private static Map<HostIdentifier, MonitoredHost> monitoredHosts =
0N/A new HashMap<HostIdentifier, MonitoredHost>();
0N/A
0N/A /*
0N/A * The monitoring implementation override mechanism. The value of
0N/A * this property is used as the class name for the concrete MonitoredHost
0N/A * subclass that implements the monitoring APIs. Setting this property
0N/A * will cause the remaining override mechanisms to be ignored. When
0N/A * this mechanism is used, the HostIdentifier scheme name, which
0N/A * indicates the communications protocol, is not used to locate a
0N/A * the protocol specific package. However, the HostIdentifier is
0N/A * still passed to the corresponding single arg constructor.
0N/A * This property is not expected to be set in normal circumstances.
0N/A */
0N/A private static final String IMPL_OVERRIDE_PROP_NAME =
0N/A "sun.jvmstat.monitor.MonitoredHost";
0N/A
0N/A /*
0N/A * The monitoring package name override mechanism. The value
0N/A * the this property is used as base package name for the
0N/A * monitoring implementation package. This property is not
0N/A * expected to be set under normal circumstances.
0N/A */
0N/A private static final String IMPL_PKG_PROP_NAME =
0N/A "sun.jvmstat.monitor.package";
0N/A private static final String IMPL_PACKAGE =
0N/A System.getProperty(IMPL_PKG_PROP_NAME, "sun.jvmstat.perfdata");
0N/A
0N/A /*
0N/A * The default optimized local protocol override mechanism. The value
0N/A * of this property is used to construct the default package name
0N/A * for the default optimized local protocol as follows:
0N/A * <IMPL_PACKAGE>.monitor.<LOCAL_PROTOCOL>
0N/A * This property is not expected to be set under normal circumstances.
0N/A */
0N/A private static final String LOCAL_PROTOCOL_PROP_NAME =
0N/A "sun.jvmstat.monitor.local";
0N/A private static final String LOCAL_PROTOCOL =
0N/A System.getProperty(LOCAL_PROTOCOL_PROP_NAME, "local");
0N/A
0N/A /*
0N/A * The default remote protocol override mechanism. The value of
0N/A * this property is used to construct the default package name
0N/A * 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;
}