提交 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;
...@@ -46,36 +47,67 @@ import sun.management.counter.perf.PerfInstrumentation; ...@@ -46,36 +47,67 @@ import sun.management.counter.perf.PerfInstrumentation;
public class ConnectorAddressLink { 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
* on the same system. * on the same system.
* *
* @param address The connector address. * @param address The connector address.
*/ */
public static void export(String address) { public static void export(String address) {
if (address == null || address.length() == 0) { if (address == null || address.length() == 0) {
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,24 +179,25 @@ public final class ConnectorBootstrap { ...@@ -158,24 +179,25 @@ 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);
} }
// Nothing special to be done for this case // Nothing special to be done for this case
public boolean unexportObject(Remote obj, boolean force) public boolean unexportObject(Remote obj, boolean force)
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());
} }
...@@ -225,16 +249,16 @@ public final class ConnectorBootstrap { ...@@ -225,16 +249,16 @@ 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;
...@@ -280,21 +305,21 @@ public final class ConnectorBootstrap { ...@@ -280,21 +305,21 @@ public final class ConnectorBootstrap {
} }
// Do we use authentication? // Do we use authentication?
final String useAuthenticationStr = final String useAuthenticationStr =
props.getProperty(PropertyNames.USE_AUTHENTICATION, props.getProperty(PropertyNames.USE_AUTHENTICATION,
DefaultValues.USE_AUTHENTICATION); DefaultValues.USE_AUTHENTICATION);
final boolean useAuthentication = final boolean useAuthentication =
Boolean.valueOf(useAuthenticationStr).booleanValue(); Boolean.valueOf(useAuthenticationStr).booleanValue();
// Do we use SSL? // Do we use SSL?
final String useSslStr = final String useSslStr =
props.getProperty(PropertyNames.USE_SSL, props.getProperty(PropertyNames.USE_SSL,
DefaultValues.USE_SSL); DefaultValues.USE_SSL);
final boolean useSsl = final boolean useSsl =
Boolean.valueOf(useSslStr).booleanValue(); Boolean.valueOf(useSslStr).booleanValue();
// Do we use RMI Registry SSL? // Do we use RMI Registry SSL?
final String useRegistrySslStr = final String useRegistrySslStr =
props.getProperty(PropertyNames.USE_REGISTRY_SSL, props.getProperty(PropertyNames.USE_REGISTRY_SSL,
DefaultValues.USE_REGISTRY_SSL); DefaultValues.USE_REGISTRY_SSL);
final boolean useRegistrySsl = final boolean useRegistrySsl =
...@@ -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,12 +344,12 @@ public final class ConnectorBootstrap { ...@@ -319,12 +344,12 @@ 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();
} }
} }
final String sslNeedClientAuthStr = final String sslNeedClientAuthStr =
props.getProperty(PropertyNames.SSL_NEED_CLIENT_AUTH, props.getProperty(PropertyNames.SSL_NEED_CLIENT_AUTH,
DefaultValues.SSL_NEED_CLIENT_AUTH); DefaultValues.SSL_NEED_CLIENT_AUTH);
final boolean sslNeedClientAuth = final boolean sslNeedClientAuth =
...@@ -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,24 +732,30 @@ public final class ConnectorBootstrap { ...@@ -697,24 +732,30 @@ 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
publication in our special registry. We could publication in our special registry. We could
alternatively have constructed the RMIServerImpl explicitly alternatively have constructed the RMIServerImpl explicitly
and then constructed an RMIConnectorServer passing it as a and then constructed an RMIConnectorServer passing it as a
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.
先完成此消息的编辑!
想要评论请 注册