提交 62acf0ec 编写于 作者: L lmalvent

4981215: Publishing a port number for management console to access

Reviewed-by: emcmanus, dfuchs
上级 5d53bf09
/* /*
* Copyright 2004 Sun Microsystems, Inc. All Rights Reserved. * Copyright 2004-2008 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -25,12 +25,13 @@ ...@@ -25,12 +25,13 @@
package sun.management; package sun.management;
import java.io.IOException;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.util.ArrayList; import java.util.HashMap;
import java.util.List;
import java.util.Iterator; import java.util.Iterator;
import java.util.Set; import java.util.List;
import java.io.IOException; import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import sun.misc.Perf; import sun.misc.Perf;
import sun.management.counter.Units; import sun.management.counter.Units;
...@@ -48,6 +49,37 @@ public class ConnectorAddressLink { ...@@ -48,6 +49,37 @@ public class ConnectorAddressLink {
private static final String CONNECTOR_ADDRESS_COUNTER = private static final String CONNECTOR_ADDRESS_COUNTER =
"sun.management.JMXConnectorServer.address"; "sun.management.JMXConnectorServer.address";
/*
* The format of the jvmstat counters representing the properties of
* a given out-of-the-box JMX remote connector will be as follows:
*
* sun.management.JMXConnectorServer.<counter>.<key>=<value>
*
* where:
*
* counter = index computed by this class which uniquely identifies
* an out-of-the-box JMX remote connector running in this
* Java virtual machine.
* key/value = a given key/value pair in the map supplied to the
* exportRemote() method.
*
* For example,
*
* sun.management.JMXConnectorServer.0.remoteAddress=service:jmx:rmi:///jndi/rmi://myhost:5000/jmxrmi
* sun.management.JMXConnectorServer.0.authenticate=false
* sun.management.JMXConnectorServer.0.ssl=false
* sun.management.JMXConnectorServer.0.sslRegistry=false
* sun.management.JMXConnectorServer.0.sslNeedClientAuth=false
*/
private static final String REMOTE_CONNECTOR_COUNTER_PREFIX =
"sun.management.JMXConnectorServer.";
/*
* JMX remote connector counter (it will be incremented every
* time a new out-of-the-box JMX remote connector is created).
*/
private static AtomicInteger counter = new AtomicInteger();
/** /**
* Exports the specified connector address to the instrumentation buffer * Exports the specified connector address to the instrumentation buffer
* so that it can be read by this or other Java virtual machines running * so that it can be read by this or other Java virtual machines running
...@@ -60,22 +92,22 @@ public class ConnectorAddressLink { ...@@ -60,22 +92,22 @@ public class ConnectorAddressLink {
throw new IllegalArgumentException("address not specified"); throw new IllegalArgumentException("address not specified");
} }
Perf perf = Perf.getPerf(); Perf perf = Perf.getPerf();
perf.createString(CONNECTOR_ADDRESS_COUNTER, 1, Units.STRING.intValue(), address); perf.createString(
CONNECTOR_ADDRESS_COUNTER, 1, Units.STRING.intValue(), address);
} }
/** /**
* Imports the connector address from the instrument buffer * Imports the connector address from the instrument buffer
* of the specified Java virtual machine. * of the specified Java virtual machine.
* *
* @param vmid an identifier that uniquely identifies a local * @param vmid an identifier that uniquely identifies a local Java virtual
* Java virtual machine, or <code>0</code> to indicate * machine, or <code>0</code> to indicate the current Java virtual machine.
* the current Java virtual machine.
* *
* @return the value of the connector address, or <code>null</code> * @return the value of the connector address, or <code>null</code> if the
* if the target VM has not exported a connector address. * target VM has not exported a connector address.
* *
* @throws IOException An I/O error occurred while trying to acquire * @throws IOException An I/O error occurred while trying to acquire the
* the instrumentation buffer. * instrumentation buffer.
*/ */
public static String importFrom(int vmid) throws IOException { public static String importFrom(int vmid) throws IOException {
Perf perf = Perf.getPerf(); Perf perf = Perf.getPerf();
...@@ -85,14 +117,65 @@ public class ConnectorAddressLink { ...@@ -85,14 +117,65 @@ public class ConnectorAddressLink {
} catch (IllegalArgumentException iae) { } catch (IllegalArgumentException iae) {
throw new IOException(iae.getMessage()); throw new IOException(iae.getMessage());
} }
List counters = (new PerfInstrumentation(bb)).findByPattern(CONNECTOR_ADDRESS_COUNTER); List counters =
new PerfInstrumentation(bb).findByPattern(CONNECTOR_ADDRESS_COUNTER);
Iterator i = counters.iterator(); Iterator i = counters.iterator();
if (i.hasNext()) { if (i.hasNext()) {
Counter c = (Counter)i.next(); Counter c = (Counter) i.next();
return (String)c.getValue(); return (String) c.getValue();
} else { } else {
return null; return null;
} }
} }
/**
* Exports the specified remote connector address and associated
* configuration properties to the instrumentation buffer so that
* it can be read by this or other Java virtual machines running
* on the same system.
*
* @param properties The remote connector address properties.
*/
public static void exportRemote(Map<String, String> properties) {
final int index = counter.getAndIncrement();
Perf perf = Perf.getPerf();
for (Map.Entry<String, String> entry : properties.entrySet()) {
perf.createString(REMOTE_CONNECTOR_COUNTER_PREFIX + index + "." +
entry.getKey(), 1, Units.STRING.intValue(), entry.getValue());
}
}
/**
* Imports the remote connector address and associated
* configuration properties from the instrument buffer
* of the specified Java virtual machine.
*
* @param vmid an identifier that uniquely identifies a local Java virtual
* machine, or <code>0</code> to indicate the current Java virtual machine.
*
* @return a map containing the remote connector's properties, or an empty
* map if the target VM has not exported the remote connector's properties.
*
* @throws IOException An I/O error occurred while trying to acquire the
* instrumentation buffer.
*/
public static Map<String, String> importRemoteFrom(int vmid) throws IOException {
Perf perf = Perf.getPerf();
ByteBuffer bb;
try {
bb = perf.attach(vmid, "r");
} catch (IllegalArgumentException iae) {
throw new IOException(iae.getMessage());
}
List counters = new PerfInstrumentation(bb).getAllCounters();
Map<String, String> properties = new HashMap<String, String>();
for (Object c : counters) {
String name = ((Counter) c).getName();
if (name.startsWith(REMOTE_CONNECTOR_COUNTER_PREFIX) &&
!name.equals(CONNECTOR_ADDRESS_COUNTER)) {
properties.put(name, ((Counter) c).getValue().toString());
}
}
return properties;
}
} }
/* /*
* Copyright 2003-2005 Sun Microsystems, Inc. All Rights Reserved. * Copyright 2003-2008 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -39,6 +39,7 @@ import java.rmi.NoSuchObjectException; ...@@ -39,6 +39,7 @@ import java.rmi.NoSuchObjectException;
import java.rmi.Remote; import java.rmi.Remote;
import java.rmi.RemoteException; import java.rmi.RemoteException;
import java.rmi.registry.Registry; import java.rmi.registry.Registry;
import java.rmi.server.RemoteObject;
import java.rmi.server.RMIClientSocketFactory; import java.rmi.server.RMIClientSocketFactory;
import java.rmi.server.RMIServerSocketFactory; import java.rmi.server.RMIServerSocketFactory;
import java.rmi.server.UnicastRemoteObject; import java.rmi.server.UnicastRemoteObject;
...@@ -70,12 +71,14 @@ import javax.rmi.ssl.SslRMIServerSocketFactory; ...@@ -70,12 +71,14 @@ import javax.rmi.ssl.SslRMIServerSocketFactory;
import javax.security.auth.Subject; import javax.security.auth.Subject;
import sun.rmi.server.UnicastRef;
import sun.rmi.server.UnicastServerRef; import sun.rmi.server.UnicastServerRef;
import sun.rmi.server.UnicastServerRef2; import sun.rmi.server.UnicastServerRef2;
import sun.management.Agent; import sun.management.Agent;
import sun.management.AgentConfigurationError; import sun.management.AgentConfigurationError;
import static sun.management.AgentConfigurationError.*; import static sun.management.AgentConfigurationError.*;
import sun.management.ConnectorAddressLink;
import sun.management.FileSystem; import sun.management.FileSystem;
import sun.management.snmp.util.MibLogger; import sun.management.snmp.util.MibLogger;
...@@ -92,20 +95,22 @@ public final class ConnectorBootstrap { ...@@ -92,20 +95,22 @@ public final class ConnectorBootstrap {
* Default values for JMX configuration properties. * Default values for JMX configuration properties.
**/ **/
public static interface DefaultValues { public static interface DefaultValues {
public static final String PORT="0";
public static final String CONFIG_FILE_NAME="management.properties"; public static final String PORT = "0";
public static final String USE_SSL="true"; public static final String CONFIG_FILE_NAME = "management.properties";
public static final String USE_REGISTRY_SSL="false"; public static final String USE_SSL = "true";
public static final String USE_AUTHENTICATION="true"; public static final String USE_REGISTRY_SSL = "false";
public static final String PASSWORD_FILE_NAME="jmxremote.password"; public static final String USE_AUTHENTICATION = "true";
public static final String ACCESS_FILE_NAME="jmxremote.access"; public static final String PASSWORD_FILE_NAME = "jmxremote.password";
public static final String SSL_NEED_CLIENT_AUTH="false"; public static final String ACCESS_FILE_NAME = "jmxremote.access";
public static final String SSL_NEED_CLIENT_AUTH = "false";
} }
/** /**
* Names of JMX configuration properties. * Names of JMX configuration properties.
**/ **/
public static interface PropertyNames { public static interface PropertyNames {
public static final String PORT = public static final String PORT =
"com.sun.management.jmxremote.port"; "com.sun.management.jmxremote.port";
public static final String CONFIG_FILE_NAME = public static final String CONFIG_FILE_NAME =
...@@ -132,6 +137,21 @@ public final class ConnectorBootstrap { ...@@ -132,6 +137,21 @@ public final class ConnectorBootstrap {
"com.sun.management.jmxremote.ssl.config.file"; "com.sun.management.jmxremote.ssl.config.file";
} }
/**
* JMXConnectorServer associated data.
*/
private static class JMXConnectorServerData {
public JMXConnectorServerData(
JMXConnectorServer jmxConnectorServer,
JMXServiceURL jmxRemoteURL) {
this.jmxConnectorServer = jmxConnectorServer;
this.jmxRemoteURL = jmxRemoteURL;
}
JMXConnectorServer jmxConnectorServer;
JMXServiceURL jmxRemoteURL;
}
/** /**
* <p>Prevents our RMI server objects from keeping the JVM alive.</p> * <p>Prevents our RMI server objects from keeping the JVM alive.</p>
* *
...@@ -151,6 +171,7 @@ public final class ConnectorBootstrap { ...@@ -151,6 +171,7 @@ public final class ConnectorBootstrap {
* works). Hence the somewhat misleading name of this class.</p> * works). Hence the somewhat misleading name of this class.</p>
*/ */
private static class PermanentExporter implements RMIExporter { private static class PermanentExporter implements RMIExporter {
public Remote exportObject(Remote obj, public Remote exportObject(Remote obj,
int port, int port,
RMIClientSocketFactory csf, RMIClientSocketFactory csf,
...@@ -158,15 +179,17 @@ public final class ConnectorBootstrap { ...@@ -158,15 +179,17 @@ public final class ConnectorBootstrap {
throws RemoteException { throws RemoteException {
synchronized (this) { synchronized (this) {
if (firstExported == null) if (firstExported == null) {
firstExported = obj; firstExported = obj;
} }
}
final UnicastServerRef ref; final UnicastServerRef ref;
if (csf == null && ssf == null) if (csf == null && ssf == null) {
ref = new UnicastServerRef(port); ref = new UnicastServerRef(port);
else } else {
ref = new UnicastServerRef2(port, csf, ssf); ref = new UnicastServerRef2(port, csf, ssf);
}
return ref.exportObject(obj, null, true); return ref.exportObject(obj, null, true);
} }
...@@ -175,7 +198,6 @@ public final class ConnectorBootstrap { ...@@ -175,7 +198,6 @@ public final class ConnectorBootstrap {
throws NoSuchObjectException { throws NoSuchObjectException {
return UnicastRemoteObject.unexportObject(obj, force); return UnicastRemoteObject.unexportObject(obj, force);
} }
Remote firstExported; Remote firstExported;
} }
...@@ -202,19 +224,21 @@ public final class ConnectorBootstrap { ...@@ -202,19 +224,21 @@ public final class ConnectorBootstrap {
} }
private void checkAccessFileEntries(Subject subject) { private void checkAccessFileEntries(Subject subject) {
if (subject == null) if (subject == null) {
throw new SecurityException( throw new SecurityException(
"Access denied! No matching entries found in " + "Access denied! No matching entries found in " +
"the access file [" + accessFile + "] as the " + "the access file [" + accessFile + "] as the " +
"authenticated Subject is null"); "authenticated Subject is null");
}
final Set principals = subject.getPrincipals(); final Set principals = subject.getPrincipals();
for (Iterator i = principals.iterator(); i.hasNext(); ) { for (Iterator i = principals.iterator(); i.hasNext();) {
final Principal p = (Principal) i.next(); final Principal p = (Principal) i.next();
if (properties.containsKey(p.getName())) if (properties.containsKey(p.getName())) {
return; return;
} }
}
final Set<String> principalsStr = new HashSet<String>(); final Set<String> principalsStr = new HashSet<String>();
for (Iterator i = principals.iterator(); i.hasNext(); ) { for (Iterator i = principals.iterator(); i.hasNext();) {
final Principal p = (Principal) i.next(); final Principal p = (Principal) i.next();
principalsStr.add(p.getName()); principalsStr.add(p.getName());
} }
...@@ -227,14 +251,14 @@ public final class ConnectorBootstrap { ...@@ -227,14 +251,14 @@ public final class ConnectorBootstrap {
private static Properties propertiesFromFile(String fname) private static Properties propertiesFromFile(String fname)
throws IOException { throws IOException {
Properties p = new Properties(); Properties p = new Properties();
if (fname == null) if (fname == null) {
return p; return p;
}
FileInputStream fin = new FileInputStream(fname); FileInputStream fin = new FileInputStream(fname);
p.load(fin); p.load(fin);
fin.close(); fin.close();
return p; return p;
} }
private final Map<String, Object> environment; private final Map<String, Object> environment;
private final Properties properties; private final Properties properties;
private final String accessFile; private final String accessFile;
...@@ -251,22 +275,23 @@ public final class ConnectorBootstrap { ...@@ -251,22 +275,23 @@ public final class ConnectorBootstrap {
// Load a new management properties // Load a new management properties
final Properties props = Agent.loadManagementProperties(); final Properties props = Agent.loadManagementProperties();
if (props == null) return null; if (props == null) {
return null;
}
final String portStr = props.getProperty(PropertyNames.PORT); final String portStr = props.getProperty(PropertyNames.PORT);
// System.out.println("initializing: {port=" + portStr + ", // System.out.println("initializing: {port=" + portStr + ",
// properties="+props+"}"); // properties="+props+"}");
return initialize(portStr,props); return initialize(portStr, props);
} }
/** /**
* Initializes and starts a JMX Connector Server for remote * Initializes and starts a JMX Connector Server for remote
* monitoring and management. * monitoring and management.
**/ **/
public static synchronized public static synchronized JMXConnectorServer initialize(String portStr, Properties props) {
JMXConnectorServer initialize(String portStr, Properties props) {
// Get port number // Get port number
final int port; final int port;
...@@ -307,7 +332,7 @@ public final class ConnectorBootstrap { ...@@ -307,7 +332,7 @@ public final class ConnectorBootstrap {
StringTokenizer st = new StringTokenizer(enabledCipherSuites, ","); StringTokenizer st = new StringTokenizer(enabledCipherSuites, ",");
int tokens = st.countTokens(); int tokens = st.countTokens();
enabledCipherSuitesList = new String[tokens]; enabledCipherSuitesList = new String[tokens];
for (int i = 0 ; i < tokens; i++) { for (int i = 0; i < tokens; i++) {
enabledCipherSuitesList[i] = st.nextToken(); enabledCipherSuitesList[i] = st.nextToken();
} }
} }
...@@ -319,7 +344,7 @@ public final class ConnectorBootstrap { ...@@ -319,7 +344,7 @@ public final class ConnectorBootstrap {
StringTokenizer st = new StringTokenizer(enabledProtocols, ","); StringTokenizer st = new StringTokenizer(enabledProtocols, ",");
int tokens = st.countTokens(); int tokens = st.countTokens();
enabledProtocolsList = new String[tokens]; enabledProtocolsList = new String[tokens];
for (int i = 0 ; i < tokens; i++) { for (int i = 0; i < tokens; i++) {
enabledProtocolsList[i] = st.nextToken(); enabledProtocolsList[i] = st.nextToken();
} }
} }
...@@ -374,39 +399,49 @@ public final class ConnectorBootstrap { ...@@ -374,39 +399,49 @@ public final class ConnectorBootstrap {
sslNeedClientAuth + sslNeedClientAuth +
"\n\t" + PropertyNames.USE_AUTHENTICATION + "=" + "\n\t" + PropertyNames.USE_AUTHENTICATION + "=" +
useAuthentication + useAuthentication +
(useAuthentication ? (useAuthentication ? (loginConfigName == null ? ("\n\t" + PropertyNames.PASSWORD_FILE_NAME + "=" +
(loginConfigName == null ? passwordFileName) : ("\n\t" + PropertyNames.LOGIN_CONFIG_NAME + "=" +
("\n\t" + PropertyNames.PASSWORD_FILE_NAME + "=" +
passwordFileName) :
("\n\t" + PropertyNames.LOGIN_CONFIG_NAME + "=" +
loginConfigName)) : "\n\t" + loginConfigName)) : "\n\t" +
Agent.getText("jmxremote.ConnectorBootstrap.initialize.noAuthentication")) + Agent.getText("jmxremote.ConnectorBootstrap.initialize.noAuthentication")) +
(useAuthentication ? (useAuthentication ? ("\n\t" + PropertyNames.ACCESS_FILE_NAME + "=" +
("\n\t" + PropertyNames.ACCESS_FILE_NAME + "=" +
accessFileName) : "") + accessFileName) : "") +
""); "");
} }
final MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); final MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
JMXConnectorServer cs = null; JMXConnectorServer cs = null;
JMXServiceURL url = null;
try { try {
cs = exportMBeanServer(mbs, port, useSsl, useRegistrySsl, final JMXConnectorServerData data = exportMBeanServer(
mbs, port, useSsl, useRegistrySsl,
sslConfigFileName, enabledCipherSuitesList, sslConfigFileName, enabledCipherSuitesList,
enabledProtocolsList, sslNeedClientAuth, enabledProtocolsList, sslNeedClientAuth,
useAuthentication, loginConfigName, useAuthentication, loginConfigName,
passwordFileName, accessFileName); passwordFileName, accessFileName);
cs = data.jmxConnectorServer;
final JMXServiceURL url = cs.getAddress(); url = data.jmxRemoteURL;
log.config("initialize", log.config("initialize",
Agent.getText("jmxremote.ConnectorBootstrap.initialize.ready", Agent.getText("jmxremote.ConnectorBootstrap.initialize.ready",
new JMXServiceURL(url.getProtocol(), url.toString()));
url.getHost(),
url.getPort(),
"/jndi/rmi://"+url.getHost()+":"+port+"/"+
"jmxrmi").toString()));
} catch (Exception e) { } catch (Exception e) {
throw new AgentConfigurationError(AGENT_EXCEPTION, e, e.toString()); throw new AgentConfigurationError(AGENT_EXCEPTION, e, e.toString());
} }
try {
// Export remote connector address and associated configuration
// properties to the instrumentation buffer.
Map<String, String> properties = new HashMap<String, String>();
properties.put("remoteAddress", url.toString());
properties.put("authenticate", useAuthenticationStr);
properties.put("ssl", useSslStr);
properties.put("sslRegistry", useRegistrySslStr);
properties.put("sslNeedClientAuth", sslNeedClientAuthStr);
ConnectorAddressLink.exportRemote(properties);
} catch (Exception e) {
// Remote connector server started but unable to export remote
// connector address and associated configuration properties to
// the instrumentation buffer - non-fatal error.
log.debug("initialize", e);
}
return cs; return cs;
} }
...@@ -452,7 +487,7 @@ public final class ConnectorBootstrap { ...@@ -452,7 +487,7 @@ public final class ConnectorBootstrap {
} }
private static void checkPasswordFile(String passwordFileName) { private static void checkPasswordFile(String passwordFileName) {
if (passwordFileName == null || passwordFileName.length()==0) { if (passwordFileName == null || passwordFileName.length() == 0) {
throw new AgentConfigurationError(PASSWORD_FILE_NOT_SET); throw new AgentConfigurationError(PASSWORD_FILE_NOT_SET);
} }
File file = new File(passwordFileName); File file = new File(passwordFileName);
...@@ -468,9 +503,9 @@ public final class ConnectorBootstrap { ...@@ -468,9 +503,9 @@ public final class ConnectorBootstrap {
try { try {
if (fs.supportsFileSecurity(file)) { if (fs.supportsFileSecurity(file)) {
if (!fs.isAccessUserOnly(file)) { if (!fs.isAccessUserOnly(file)) {
final String msg=Agent.getText("jmxremote.ConnectorBootstrap.initialize.password.readonly", final String msg = Agent.getText("jmxremote.ConnectorBootstrap.initialize.password.readonly",
passwordFileName); passwordFileName);
log.config("initialize",msg); log.config("initialize", msg);
throw new AgentConfigurationError(PASSWORD_FILE_ACCESS_NOT_RESTRICTED, throw new AgentConfigurationError(PASSWORD_FILE_ACCESS_NOT_RESTRICTED,
passwordFileName); passwordFileName);
} }
...@@ -482,7 +517,7 @@ public final class ConnectorBootstrap { ...@@ -482,7 +517,7 @@ public final class ConnectorBootstrap {
} }
private static void checkAccessFile(String accessFileName) { private static void checkAccessFile(String accessFileName) {
if (accessFileName == null || accessFileName.length()==0) { if (accessFileName == null || accessFileName.length() == 0) {
throw new AgentConfigurationError(ACCESS_FILE_NOT_SET); throw new AgentConfigurationError(ACCESS_FILE_NOT_SET);
} }
File file = new File(accessFileName); File file = new File(accessFileName);
...@@ -619,7 +654,7 @@ public final class ConnectorBootstrap { ...@@ -619,7 +654,7 @@ public final class ConnectorBootstrap {
} }
} }
private static JMXConnectorServer exportMBeanServer( private static JMXConnectorServerData exportMBeanServer(
MBeanServer mbs, MBeanServer mbs,
int port, int port,
boolean useSsl, boolean useSsl,
...@@ -697,14 +732,20 @@ public final class ConnectorBootstrap { ...@@ -697,14 +732,20 @@ public final class ConnectorBootstrap {
} }
final Registry registry; final Registry registry;
if (useRegistrySsl) if (useRegistrySsl) {
registry = registry =
new SingleEntryRegistry(port, csf, ssf, new SingleEntryRegistry(port, csf, ssf,
"jmxrmi", exporter.firstExported); "jmxrmi", exporter.firstExported);
else } else {
registry = registry =
new SingleEntryRegistry(port, new SingleEntryRegistry(port,
"jmxrmi", exporter.firstExported); "jmxrmi", exporter.firstExported);
}
JMXServiceURL remoteURL = new JMXServiceURL(
"service:jmx:rmi:///jndi/rmi://" + url.getHost() + ":" +
((UnicastRef) ((RemoteObject) registry).getRef()).getLiveRef().getPort() +
"/jmxrmi");
/* Our exporter remembers the first object it was asked to /* Our exporter remembers the first object it was asked to
export, which will be an RMIServerImpl appropriate for export, which will be an RMIServerImpl appropriate for
...@@ -714,7 +755,7 @@ public final class ConnectorBootstrap { ...@@ -714,7 +755,7 @@ public final class ConnectorBootstrap {
parameter, but that's quite a bit more verbose and pulls in parameter, but that's quite a bit more verbose and pulls in
lots of knowledge of the RMI connector. */ lots of knowledge of the RMI connector. */
return connServer; return new JMXConnectorServerData(connServer, remoteURL);
} }
/** /**
...@@ -726,5 +767,4 @@ public final class ConnectorBootstrap { ...@@ -726,5 +767,4 @@ public final class ConnectorBootstrap {
// XXX Revisit: should probably clone this MibLogger.... // XXX Revisit: should probably clone this MibLogger....
private static final MibLogger log = private static final MibLogger log =
new MibLogger(ConnectorBootstrap.class); new MibLogger(ConnectorBootstrap.class);
} }
/*
* Copyright 2008 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.
*
* 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.
*/
/*
* @test
* @bug 4981215
* @summary Tests that the jvmstat counters published by the out-of-the-box
* management agent for the JMX connection details are correct.
* @author Luis-Miguel Alventosa
* @run clean JvmstatCountersTest
* @run build JvmstatCountersTest
* @run main/othervm JvmstatCountersTest 1
* @run main/othervm -Dcom.sun.management.jmxremote JvmstatCountersTest 2
* @run main/othervm -Dcom.sun.management.jmxremote.port=0 -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false JvmstatCountersTest 3
* @run main/othervm JvmstatCountersTest 4
*/
import java.io.*;
import java.lang.management.*;
import java.util.*;
import javax.management.*;
import javax.management.remote.*;
import com.sun.tools.attach.*;
import sun.management.ConnectorAddressLink;
public class JvmstatCountersTest {
public static void checkAddress(String address) throws IOException {
System.out.println("Address = " + address);
JMXServiceURL url = new JMXServiceURL(address);
JMXConnector jmxc = JMXConnectorFactory.connect(url);
MBeanServerConnection mbsc = jmxc.getMBeanServerConnection();
System.out.println("MBean Count = " + mbsc.getMBeanCount());
}
public static void checkKey(Map<String, String> data, int index,
String key, String expectedValue) throws Exception {
String counter = "sun.management.JMXConnectorServer." + index + "." + key;
if (!data.containsKey(counter)) {
System.out.println("Test FAILED! Missing counter " + counter);
throw new IllegalArgumentException("Test case failed");
}
String value = data.get(counter);
if (key.equals("remoteAddress")) {
checkAddress(value);
} else if (!expectedValue.equals(value)) {
System.out.println("Test FAILED! Invalid counter " +
counter + "=" + value);
throw new IllegalArgumentException("Test case failed");
}
System.out.println("OK: " + counter + "=" + value);
}
public static void main(String args[]) throws Exception {
String localAddress = ConnectorAddressLink.importFrom(0);
Map<String, String> remoteData = ConnectorAddressLink.importRemoteFrom(0);
final int testCase = Integer.parseInt(args[0]);
switch (testCase) {
case 1:
if (localAddress == null && remoteData.isEmpty()) {
System.out.println("Test PASSED! The OOTB management " +
"agent didn't publish any jvmstat counter.");
} else {
System.out.println("Test FAILED! The OOTB management " +
"agent unexpectedly published jvmstat counters.");
throw new IllegalArgumentException("Test case 1 failed");
}
break;
case 2:
if (localAddress == null) {
System.out.println("Test FAILED! The OOTB management " +
"agent didn't publish the local connector.");
throw new IllegalArgumentException("Test case 2 failed");
}
checkAddress(localAddress);
if (!remoteData.isEmpty()) {
System.out.println("Test FAILED! The OOTB management " +
"agent shouldn't publish the remote connector.");
throw new IllegalArgumentException("Test case 2 failed");
}
System.out.println("Test PASSED! The OOTB management " +
"agent only publishes the local connector through " +
"a jvmstat counter.");
break;
case 3:
if (localAddress == null) {
System.out.println("Test FAILED! The OOTB management " +
"agent didn't publish the local connector.");
throw new IllegalArgumentException("Test case 3 failed");
}
checkAddress(localAddress);
if (remoteData.isEmpty()) {
System.out.println("Test FAILED! The OOTB management " +
"agent didnn't publish the remote connector.");
throw new IllegalArgumentException("Test case 3 failed");
}
for (String key : remoteData.keySet()) {
if (!key.startsWith("sun.management.JMXConnectorServer.0.")) {
System.out.println("Test FAILED! The OOTB management " +
"agent shouldn't publish anything which isn't " +
"related to the remote connector.");
throw new IllegalArgumentException("Test case 3 failed");
}
}
checkKey(remoteData, 0, "remoteAddress", null);
checkKey(remoteData, 0, "authenticate", "false");
checkKey(remoteData, 0, "ssl", "false");
checkKey(remoteData, 0, "sslRegistry", "false");
checkKey(remoteData, 0, "sslNeedClientAuth", "false");
System.out.println("Test PASSED! The OOTB management " +
"agent publishes both the local and remote " +
"connector info through jvmstat counters.");
break;
case 4:
if (localAddress != null || !remoteData.isEmpty()) {
System.out.println("Test FAILED! The OOTB management " +
"agent unexpectedly published jvmstat counters.");
throw new IllegalArgumentException("Test case 4 failed");
}
RuntimeMXBean rt = ManagementFactory.getRuntimeMXBean();
String name = rt.getName();
System.out.println("name = " + name);
String vmid = name.substring(0, name.indexOf("@"));
System.out.println("vmid = " + vmid);
VirtualMachine vm = VirtualMachine.attach(vmid);
String agent = vm.getSystemProperties().getProperty("java.home") +
File.separator + "lib" + File.separator + "management-agent.jar";
vm.loadAgent(agent, "com.sun.management.jmxremote.port=0,com.sun.management.jmxremote.authenticate=false,com.sun.management.jmxremote.ssl=false");
vm.detach();
String localAddress2 = ConnectorAddressLink.importFrom(0);
if (localAddress2 == null) {
System.out.println("Test FAILED! The OOTB management " +
"agent didn't publish the local connector.");
throw new IllegalArgumentException("Test case 4 failed");
}
checkAddress(localAddress2);
Map<String, String> remoteData2 = ConnectorAddressLink.importRemoteFrom(0);
if (remoteData2.isEmpty()) {
System.out.println("Test FAILED! The OOTB management " +
"agent didnn't publish the remote connector.");
throw new IllegalArgumentException("Test case 4 failed");
}
for (String key : remoteData2.keySet()) {
if (!key.startsWith("sun.management.JMXConnectorServer.0.")) {
System.out.println("Test FAILED! The OOTB management " +
"agent shouldn't publish anything which isn't " +
"related to the remote connector.");
throw new IllegalArgumentException("Test case 4 failed");
}
}
checkKey(remoteData2, 0, "remoteAddress", null);
checkKey(remoteData2, 0, "authenticate", "false");
checkKey(remoteData2, 0, "ssl", "false");
checkKey(remoteData2, 0, "sslRegistry", "false");
checkKey(remoteData2, 0, "sslNeedClientAuth", "false");
System.out.println("Test PASSED! The OOTB management agent " +
"publishes both the local and remote connector " +
"info through jvmstat counters when the agent is " +
"loaded through the Attach API.");
}
System.out.println("Bye! Bye!");
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册