/* * Copyright (c) 2003, 2008, 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.management.jmxremote; import java.io.BufferedInputStream;import java.io.File;import java.io.FileInputStream;import java.io.InputStream;import java.io.IOException; import java.net.InetAddress;import java.net.MalformedURLException;import java.net.UnknownHostException; import java.rmi.NoSuchObjectException;import java.rmi.Remote;import java.rmi.RemoteException;import java.rmi.registry.Registry;import java.rmi.server.RemoteObject;import java.rmi.server.RMIClientSocketFactory;import java.rmi.server.RMIServerSocketFactory;import java.rmi.server.UnicastRemoteObject; import java.security.KeyStore;import java.security.Principal; import java.util.HashMap;import java.util.HashSet;import java.util.Iterator;import java.util.Map;import java.util.Properties;import java.util.Set;import java.util.StringTokenizer; import java.lang.management.ManagementFactory; import javax.net.ssl.*; import javax.management.MBeanServer;import javax.management.remote.JMXAuthenticator;import javax.management.remote.JMXConnectorServer;import javax.management.remote.JMXConnectorServerFactory;import javax.management.remote.JMXServiceURL;import javax.management.remote.rmi.RMIConnectorServer; import javax.rmi.ssl.SslRMIClientSocketFactory;import javax.rmi.ssl.SslRMIServerSocketFactory; import javax.security.auth.Subject; import sun.rmi.server.UnicastRef;import sun.rmi.server.UnicastServerRef;import sun.rmi.server.UnicastServerRef2; import sun.management.Agent;import sun.management.AgentConfigurationError;import static sun.management.AgentConfigurationError.*;import sun.management.ConnectorAddressLink;import sun.management.FileSystem;import com.sun.jmx.remote.util.ClassLogger; import com.sun.jmx.remote.internal.RMIExporter;import com.sun.jmx.remote.security.JMXPluggableAuthenticator; /** * This class initializes and starts the RMIConnectorServer for JSR 163 * JMX Monitoring. **/public final class ConnectorBootstrap { /** * Default values for JMX configuration properties. **/ public static interface DefaultValues { public static final String PORT = "0"; public static final String CONFIG_FILE_NAME = "management.properties"; public static final String USE_SSL = "true"; public static final String USE_LOCAL_ONLY = "true"; public static final String USE_REGISTRY_SSL = "false"; public static final String USE_AUTHENTICATION = "true"; public static final String PASSWORD_FILE_NAME = "jmxremote.password"; public static final String ACCESS_FILE_NAME = "jmxremote.access"; public static final String SSL_NEED_CLIENT_AUTH = "false"; } /** * Names of JMX configuration properties. **/ public static interface PropertyNames { public static final String PORT = "com.sun.management.jmxremote.port"; public static final String CONFIG_FILE_NAME = "com.sun.management.config.file"; public static final String USE_LOCAL_ONLY = "com.sun.management.jmxremote.local.only"; public static final String USE_SSL = "com.sun.management.jmxremote.ssl"; public static final String USE_REGISTRY_SSL = "com.sun.management.jmxremote.registry.ssl"; public static final String USE_AUTHENTICATION = "com.sun.management.jmxremote.authenticate"; public static final String PASSWORD_FILE_NAME = "com.sun.management.jmxremote.password.file"; public static final String ACCESS_FILE_NAME = "com.sun.management.jmxremote.access.file"; public static final String LOGIN_CONFIG_NAME = "com.sun.management.jmxremote.login.config"; public static final String SSL_ENABLED_CIPHER_SUITES = "com.sun.management.jmxremote.ssl.enabled.cipher.suites"; public static final String SSL_ENABLED_PROTOCOLS = "com.sun.management.jmxremote.ssl.enabled.protocols"; public static final String SSL_NEED_CLIENT_AUTH = "com.sun.management.jmxremote.ssl.need.client.auth"; public static final String SSL_CONFIG_FILE_NAME = "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>We use a private interface in Sun's JMX Remote API implementation * that allows us to specify how to export RMI objects. We do so using * UnicastServerRef, a class in Sun's RMI implementation. This is all * non-portable, of course, so this is only valid because we are inside * Sun's JRE.</p> * * <p>Objects are exported using {@link * UnicastServerRef#exportObject(Remote, Object, boolean)}. The * boolean parameter is called <code>permanent</code> and means * both that the object is not eligible for Distributed Garbage * Collection, and that its continued existence will not prevent * the JVM from exiting. It is the latter semantics we want (we * already have the former because of the way the JMX Remote API * works). Hence the somewhat misleading name of this class.</p> */ private static class PermanentExporter implements RMIExporter { public Remote exportObject(Remote obj, int port, RMIClientSocketFactory csf, RMIServerSocketFactory ssf) throws RemoteException { synchronized (this) { if (firstExported == null) { firstExported = obj; } } final UnicastServerRef ref; if (csf == null && ssf == null) { ref = new UnicastServerRef(port); } else { ref = new UnicastServerRef2(port, csf, ssf); } return ref.exportObject(obj, null, true); } // Nothing special to be done for this case public boolean unexportObject(Remote obj, boolean force) throws NoSuchObjectException { return UnicastRemoteObject.unexportObject(obj, force); } Remote firstExported; } /** * This JMXAuthenticator wraps the JMXPluggableAuthenticator and verifies * that at least one of the principal names contained in the authenticated * Subject is present in the access file. */ private static class AccessFileCheckerAuthenticator implements JMXAuthenticator { public AccessFileCheckerAuthenticator(Map<String, Object> env) throws IOException { environment = env; accessFile = (String) env.get("jmx.remote.x.access.file"); properties = propertiesFromFile(accessFile); } public Subject authenticate(Object credentials) { final JMXAuthenticator authenticator = new JMXPluggableAuthenticator(environment); final Subject subject = authenticator.authenticate(credentials); checkAccessFileEntries(subject); return subject; } private void checkAccessFileEntries(Subject subject) { if (subject == null) { throw new SecurityException( "Access denied! No matching entries found in " + "the access file [" + accessFile + "] as the " + "authenticated Subject is null"); } final Set principals = subject.getPrincipals(); for (Iterator i = principals.iterator(); i.hasNext();) { final Principal p = (Principal) i.next(); if (properties.containsKey(p.getName())) { return; } } final Set<String> principalsStr = new HashSet<String>(); for (Iterator i = principals.iterator(); i.hasNext();) { final Principal p = (Principal) i.next(); principalsStr.add(p.getName()); } throw new SecurityException( "Access denied! No entries found in the access file [" + accessFile + "] for any of the authenticated identities " + principalsStr); } private static Properties propertiesFromFile(String fname) throws IOException { Properties p = new Properties(); if (fname == null) { return p; } FileInputStream fin = new FileInputStream(fname); p.load(fin); fin.close(); return p; } private final Map<String, Object> environment; private final Properties properties; private final String accessFile; } /** * Initializes and starts the JMX Connector Server. * If the com.sun.management.jmxremote.port property is not defined, * simply return. Otherwise, attempts to load the config file, and * then calls {@link #initialize(java.lang.String, java.util.Properties)}. * **/ public static synchronized JMXConnectorServer initialize() { // Load a new management properties final Properties props = Agent.loadManagementProperties(); if (props == null) { return null; } final String portStr = props.getProperty(PropertyNames.PORT); // System.out.println("initializing: {port=" + portStr + ", // properties="+props+"}"); return initialize(portStr, props); } /** * Initializes and starts a JMX Connector Server for remote * monitoring and management. **/ public static synchronized JMXConnectorServer initialize(String portStr, Properties props) { // Get port number final int port; try { port = Integer.parseInt(portStr); } catch (NumberFormatException x) { throw new AgentConfigurationError(INVALID_JMXREMOTE_PORT, x, portStr); } if (port < 0) { throw new AgentConfigurationError(INVALID_JMXREMOTE_PORT, portStr); } // Do we use authentication? final String useAuthenticationStr = props.getProperty(PropertyNames.USE_AUTHENTICATION, DefaultValues.USE_AUTHENTICATION); final boolean useAuthentication = Boolean.valueOf(useAuthenticationStr).booleanValue(); // Do we use SSL? final String useSslStr = props.getProperty(PropertyNames.USE_SSL, DefaultValues.USE_SSL); final boolean useSsl = Boolean.valueOf(useSslStr).booleanValue(); // Do we use RMI Registry SSL? final String useRegistrySslStr = props.getProperty(PropertyNames.USE_REGISTRY_SSL, DefaultValues.USE_REGISTRY_SSL); final boolean useRegistrySsl = Boolean.valueOf(useRegistrySslStr).booleanValue(); final String enabledCipherSuites = props.getProperty(PropertyNames.SSL_ENABLED_CIPHER_SUITES); String enabledCipherSuitesList[] = null; if (enabledCipherSuites != null) { StringTokenizer st = new StringTokenizer(enabledCipherSuites, ","); int tokens = st.countTokens(); enabledCipherSuitesList = new String[tokens]; for (int i = 0; i < tokens; i++) { enabledCipherSuitesList[i] = st.nextToken(); } } final String enabledProtocols = props.getProperty(PropertyNames.SSL_ENABLED_PROTOCOLS); String enabledProtocolsList[] = null; if (enabledProtocols != null) { StringTokenizer st = new StringTokenizer(enabledProtocols, ","); int tokens = st.countTokens(); enabledProtocolsList = new String[tokens]; for (int i = 0; i < tokens; i++) { enabledProtocolsList[i] = st.nextToken(); } } final String sslNeedClientAuthStr = props.getProperty(PropertyNames.SSL_NEED_CLIENT_AUTH, DefaultValues.SSL_NEED_CLIENT_AUTH); final boolean sslNeedClientAuth = Boolean.valueOf(sslNeedClientAuthStr).booleanValue(); // Read SSL config file name final String sslConfigFileName = props.getProperty(PropertyNames.SSL_CONFIG_FILE_NAME); String loginConfigName = null; String passwordFileName = null; String accessFileName = null; // Initialize settings when authentication is active if (useAuthentication) { // Get non-default login configuration loginConfigName = props.getProperty(PropertyNames.LOGIN_CONFIG_NAME); if (loginConfigName == null) { // Get password file passwordFileName = props.getProperty(PropertyNames.PASSWORD_FILE_NAME, getDefaultFileName(DefaultValues.PASSWORD_FILE_NAME)); checkPasswordFile(passwordFileName); } // Get access file accessFileName = props.getProperty(PropertyNames.ACCESS_FILE_NAME, getDefaultFileName(DefaultValues.ACCESS_FILE_NAME)); checkAccessFile(accessFileName); } if (log.debugOn()) { log.debug("initialize", Agent.getText("jmxremote.ConnectorBootstrap.initialize") + "\n\t" + PropertyNames.PORT + "=" + port + "\n\t" + PropertyNames.USE_SSL + "=" + useSsl + "\n\t" + PropertyNames.USE_REGISTRY_SSL + "=" + useRegistrySsl + "\n\t" + PropertyNames.SSL_CONFIG_FILE_NAME + "=" + sslConfigFileName + "\n\t" + PropertyNames.SSL_ENABLED_CIPHER_SUITES + "=" + enabledCipherSuites + "\n\t" + PropertyNames.SSL_ENABLED_PROTOCOLS + "=" + enabledProtocols + "\n\t" + PropertyNames.SSL_NEED_CLIENT_AUTH + "=" + sslNeedClientAuth + "\n\t" + PropertyNames.USE_AUTHENTICATION + "=" + useAuthentication + (useAuthentication ? (loginConfigName == null ? ("\n\t" + PropertyNames.PASSWORD_FILE_NAME + "=" + passwordFileName) : ("\n\t" + PropertyNames.LOGIN_CONFIG_NAME + "=" + loginConfigName)) : "\n\t" + Agent.getText("jmxremote.ConnectorBootstrap.initialize.noAuthentication")) + (useAuthentication ? ("\n\t" + PropertyNames.ACCESS_FILE_NAME + "=" + accessFileName) : "") + ""); } final MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); JMXConnectorServer cs = null; JMXServiceURL url = null; try { final JMXConnectorServerData data = exportMBeanServer( mbs, port, useSsl, useRegistrySsl, sslConfigFileName, enabledCipherSuitesList, enabledProtocolsList, sslNeedClientAuth, useAuthentication, loginConfigName, passwordFileName, accessFileName); cs = data.jmxConnectorServer; url = data.jmxRemoteURL; log.config("initialize", Agent.getText("jmxremote.ConnectorBootstrap.initialize.ready", url.toString())); } catch (Exception e) { 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; } /* * Creates and starts a RMI Connector Server for "local" monitoring * and management. */ public static JMXConnectorServer startLocalConnectorServer() { // Ensure cryptographically strong random number generater used // to choose the object number - see java.rmi.server.ObjID System.setProperty("java.rmi.server.randomIDs", "true"); // This RMI server should not keep the VM alive Map<String, Object> env = new HashMap<String, Object>(); env.put(RMIExporter.EXPORTER_ATTRIBUTE, new PermanentExporter()); // The local connector server need only be available via the // loopback connection. String localhost = "localhost"; InetAddress lh = null; try { lh = InetAddress.getByName(localhost); localhost = lh.getHostAddress(); } catch (UnknownHostException x) { } // localhost unknown or (somehow) didn't resolve to // a loopback address. if (lh == null || !lh.isLoopbackAddress()) { localhost = "127.0.0.1"; } MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); try { JMXServiceURL url = new JMXServiceURL("rmi", localhost, 0); // Do we accept connections from local interfaces only? Properties props = Agent.getManagementProperties(); if (props == null) { props = new Properties(); } String useLocalOnlyStr = props.getProperty( PropertyNames.USE_LOCAL_ONLY, DefaultValues.USE_LOCAL_ONLY); boolean useLocalOnly = Boolean.valueOf(useLocalOnlyStr).booleanValue(); if (useLocalOnly) { env.put(RMIConnectorServer.RMI_SERVER_SOCKET_FACTORY_ATTRIBUTE, new LocalRMIServerSocketFactory()); } JMXConnectorServer server = JMXConnectorServerFactory.newJMXConnectorServer(url, env, mbs); server.start(); return server; } catch (Exception e) { throw new AgentConfigurationError(AGENT_EXCEPTION, e, e.toString());Lines 1–500 of 785. Load more
/* * Copyright (c) 2003, 2008, 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.management.jmxremote; import java.io.BufferedInputStream; import java.io.File; import java.io.FileInputStream; import java.io.InputStream; import java.io.IOException; import java.net.InetAddress; import java.net.MalformedURLException; import java.net.UnknownHostException; import java.rmi.NoSuchObjectException; import java.rmi.Remote; import java.rmi.RemoteException; import java.rmi.registry.Registry; import java.rmi.server.RemoteObject; import java.rmi.server.RMIClientSocketFactory; import java.rmi.server.RMIServerSocketFactory; import java.rmi.server.UnicastRemoteObject; import java.security.KeyStore; import java.security.Principal; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.Map; import java.util.Properties; import java.util.Set; import java.util.StringTokenizer; import java.lang.management.ManagementFactory; import javax.net.ssl.*; import javax.management.MBeanServer; import javax.management.remote.JMXAuthenticator; import javax.management.remote.JMXConnectorServer; import javax.management.remote.JMXConnectorServerFactory; import javax.management.remote.JMXServiceURL; import javax.management.remote.rmi.RMIConnectorServer; import javax.rmi.ssl.SslRMIClientSocketFactory; import javax.rmi.ssl.SslRMIServerSocketFactory; import javax.security.auth.Subject; import sun.rmi.server.UnicastRef; import sun.rmi.server.UnicastServerRef; import sun.rmi.server.UnicastServerRef2; import sun.management.Agent; import sun.management.AgentConfigurationError; import static sun.management.AgentConfigurationError.*; import sun.management.ConnectorAddressLink; import sun.management.FileSystem; import com.sun.jmx.remote.util.ClassLogger; import com.sun.jmx.remote.internal.RMIExporter; import com.sun.jmx.remote.security.JMXPluggableAuthenticator; /** * This class initializes and starts the RMIConnectorServer for JSR 163 * JMX Monitoring. **/ public final class ConnectorBootstrap { /** * Default values for JMX configuration properties. **/ public static interface DefaultValues { public static final String PORT = "0"; public static final String CONFIG_FILE_NAME = "management.properties"; public static final String USE_SSL = "true"; public static final String USE_LOCAL_ONLY = "true"; public static final String USE_REGISTRY_SSL = "false"; public static final String USE_AUTHENTICATION = "true"; public static final String PASSWORD_FILE_NAME = "jmxremote.password"; public static final String ACCESS_FILE_NAME = "jmxremote.access"; public static final String SSL_NEED_CLIENT_AUTH = "false"; } /** * Names of JMX configuration properties. **/ public static interface PropertyNames { public static final String PORT = "com.sun.management.jmxremote.port"; public static final String CONFIG_FILE_NAME = "com.sun.management.config.file"; public static final String USE_LOCAL_ONLY = "com.sun.management.jmxremote.local.only"; public static final String USE_SSL = "com.sun.management.jmxremote.ssl"; public static final String USE_REGISTRY_SSL = "com.sun.management.jmxremote.registry.ssl"; public static final String USE_AUTHENTICATION = "com.sun.management.jmxremote.authenticate"; public static final String PASSWORD_FILE_NAME = "com.sun.management.jmxremote.password.file"; public static final String ACCESS_FILE_NAME = "com.sun.management.jmxremote.access.file"; public static final String LOGIN_CONFIG_NAME = "com.sun.management.jmxremote.login.config"; public static final String SSL_ENABLED_CIPHER_SUITES = "com.sun.management.jmxremote.ssl.enabled.cipher.suites"; public static final String SSL_ENABLED_PROTOCOLS = "com.sun.management.jmxremote.ssl.enabled.protocols"; public static final String SSL_NEED_CLIENT_AUTH = "com.sun.management.jmxremote.ssl.need.client.auth"; public static final String SSL_CONFIG_FILE_NAME = "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>We use a private interface in Sun's JMX Remote API implementation * that allows us to specify how to export RMI objects. We do so using * UnicastServerRef, a class in Sun's RMI implementation. This is all * non-portable, of course, so this is only valid because we are inside * Sun's JRE.</p> * * <p>Objects are exported using {@link * UnicastServerRef#exportObject(Remote, Object, boolean)}. The * boolean parameter is called <code>permanent</code> and means * both that the object is not eligible for Distributed Garbage * Collection, and that its continued existence will not prevent * the JVM from exiting. It is the latter semantics we want (we * already have the former because of the way the JMX Remote API * works). Hence the somewhat misleading name of this class.</p> */ private static class PermanentExporter implements RMIExporter { public Remote exportObject(Remote obj, int port, RMIClientSocketFactory csf, RMIServerSocketFactory ssf) throws RemoteException { synchronized (this) { if (firstExported == null) { firstExported = obj; } } final UnicastServerRef ref; if (csf == null && ssf == null) { ref = new UnicastServerRef(port); } else { ref = new UnicastServerRef2(port, csf, ssf); } return ref.exportObject(obj, null, true); } // Nothing special to be done for this case public boolean unexportObject(Remote obj, boolean force) throws NoSuchObjectException { return UnicastRemoteObject.unexportObject(obj, force); } Remote firstExported; } /** * This JMXAuthenticator wraps the JMXPluggableAuthenticator and verifies * that at least one of the principal names contained in the authenticated * Subject is present in the access file. */ private static class AccessFileCheckerAuthenticator implements JMXAuthenticator { public AccessFileCheckerAuthenticator(Map<String, Object> env) throws IOException { environment = env; accessFile = (String) env.get("jmx.remote.x.access.file"); properties = propertiesFromFile(accessFile); } public Subject authenticate(Object credentials) { final JMXAuthenticator authenticator = new JMXPluggableAuthenticator(environment); final Subject subject = authenticator.authenticate(credentials); checkAccessFileEntries(subject); return subject; } private void checkAccessFileEntries(Subject subject) { if (subject == null) { throw new SecurityException( "Access denied! No matching entries found in " + "the access file [" + accessFile + "] as the " + "authenticated Subject is null"); } final Set principals = subject.getPrincipals(); for (Iterator i = principals.iterator(); i.hasNext();) { final Principal p = (Principal) i.next(); if (properties.containsKey(p.getName())) { return; } } final Set<String> principalsStr = new HashSet<String>(); for (Iterator i = principals.iterator(); i.hasNext();) { final Principal p = (Principal) i.next(); principalsStr.add(p.getName()); } throw new SecurityException( "Access denied! No entries found in the access file [" + accessFile + "] for any of the authenticated identities " + principalsStr); } private static Properties propertiesFromFile(String fname) throws IOException { Properties p = new Properties(); if (fname == null) { return p; } FileInputStream fin = new FileInputStream(fname); p.load(fin); fin.close(); return p; } private final Map<String, Object> environment; private final Properties properties; private final String accessFile; } /** * Initializes and starts the JMX Connector Server. * If the com.sun.management.jmxremote.port property is not defined, * simply return. Otherwise, attempts to load the config file, and * then calls {@link #initialize(java.lang.String, java.util.Properties)}. * **/ public static synchronized JMXConnectorServer initialize() { // Load a new management properties final Properties props = Agent.loadManagementProperties(); if (props == null) { return null; } final String portStr = props.getProperty(PropertyNames.PORT); // System.out.println("initializing: {port=" + portStr + ", // properties="+props+"}"); return initialize(portStr, props); } /** * Initializes and starts a JMX Connector Server for remote * monitoring and management. **/ public static synchronized JMXConnectorServer initialize(String portStr, Properties props) { // Get port number final int port; try { port = Integer.parseInt(portStr); } catch (NumberFormatException x) { throw new AgentConfigurationError(INVALID_JMXREMOTE_PORT, x, portStr); } if (port < 0) { throw new AgentConfigurationError(INVALID_JMXREMOTE_PORT, portStr); } // Do we use authentication? final String useAuthenticationStr = props.getProperty(PropertyNames.USE_AUTHENTICATION, DefaultValues.USE_AUTHENTICATION); final boolean useAuthentication = Boolean.valueOf(useAuthenticationStr).booleanValue(); // Do we use SSL? final String useSslStr = props.getProperty(PropertyNames.USE_SSL, DefaultValues.USE_SSL); final boolean useSsl = Boolean.valueOf(useSslStr).booleanValue(); // Do we use RMI Registry SSL? final String useRegistrySslStr = props.getProperty(PropertyNames.USE_REGISTRY_SSL, DefaultValues.USE_REGISTRY_SSL); final boolean useRegistrySsl = Boolean.valueOf(useRegistrySslStr).booleanValue(); final String enabledCipherSuites = props.getProperty(PropertyNames.SSL_ENABLED_CIPHER_SUITES); String enabledCipherSuitesList[] = null; if (enabledCipherSuites != null) { StringTokenizer st = new StringTokenizer(enabledCipherSuites, ","); int tokens = st.countTokens(); enabledCipherSuitesList = new String[tokens]; for (int i = 0; i < tokens; i++) { enabledCipherSuitesList[i] = st.nextToken(); } } final String enabledProtocols = props.getProperty(PropertyNames.SSL_ENABLED_PROTOCOLS); String enabledProtocolsList[] = null; if (enabledProtocols != null) { StringTokenizer st = new StringTokenizer(enabledProtocols, ","); int tokens = st.countTokens(); enabledProtocolsList = new String[tokens]; for (int i = 0; i < tokens; i++) { enabledProtocolsList[i] = st.nextToken(); } } final String sslNeedClientAuthStr = props.getProperty(PropertyNames.SSL_NEED_CLIENT_AUTH, DefaultValues.SSL_NEED_CLIENT_AUTH); final boolean sslNeedClientAuth = Boolean.valueOf(sslNeedClientAuthStr).booleanValue(); // Read SSL config file name final String sslConfigFileName = props.getProperty(PropertyNames.SSL_CONFIG_FILE_NAME); String loginConfigName = null; String passwordFileName = null; String accessFileName = null; // Initialize settings when authentication is active if (useAuthentication) { // Get non-default login configuration loginConfigName = props.getProperty(PropertyNames.LOGIN_CONFIG_NAME); if (loginConfigName == null) { // Get password file passwordFileName = props.getProperty(PropertyNames.PASSWORD_FILE_NAME, getDefaultFileName(DefaultValues.PASSWORD_FILE_NAME)); checkPasswordFile(passwordFileName); } // Get access file accessFileName = props.getProperty(PropertyNames.ACCESS_FILE_NAME, getDefaultFileName(DefaultValues.ACCESS_FILE_NAME)); checkAccessFile(accessFileName); } if (log.debugOn()) { log.debug("initialize", Agent.getText("jmxremote.ConnectorBootstrap.initialize") + "\n\t" + PropertyNames.PORT + "=" + port + "\n\t" + PropertyNames.USE_SSL + "=" + useSsl + "\n\t" + PropertyNames.USE_REGISTRY_SSL + "=" + useRegistrySsl + "\n\t" + PropertyNames.SSL_CONFIG_FILE_NAME + "=" + sslConfigFileName + "\n\t" + PropertyNames.SSL_ENABLED_CIPHER_SUITES + "=" + enabledCipherSuites + "\n\t" + PropertyNames.SSL_ENABLED_PROTOCOLS + "=" + enabledProtocols + "\n\t" + PropertyNames.SSL_NEED_CLIENT_AUTH + "=" + sslNeedClientAuth + "\n\t" + PropertyNames.USE_AUTHENTICATION + "=" + useAuthentication + (useAuthentication ? (loginConfigName == null ? ("\n\t" + PropertyNames.PASSWORD_FILE_NAME + "=" + passwordFileName) : ("\n\t" + PropertyNames.LOGIN_CONFIG_NAME + "=" + loginConfigName)) : "\n\t" + Agent.getText("jmxremote.ConnectorBootstrap.initialize.noAuthentication")) + (useAuthentication ? ("\n\t" + PropertyNames.ACCESS_FILE_NAME + "=" + accessFileName) : "") + ""); } final MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); JMXConnectorServer cs = null; JMXServiceURL url = null; try { final JMXConnectorServerData data = exportMBeanServer( mbs, port, useSsl, useRegistrySsl, sslConfigFileName, enabledCipherSuitesList, enabledProtocolsList, sslNeedClientAuth, useAuthentication, loginConfigName, passwordFileName, accessFileName); cs = data.jmxConnectorServer; url = data.jmxRemoteURL; log.config("initialize", Agent.getText("jmxremote.ConnectorBootstrap.initialize.ready", url.toString())); } catch (Exception e) { 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; } /* * Creates and starts a RMI Connector Server for "local" monitoring * and management. */ public static JMXConnectorServer startLocalConnectorServer() { // Ensure cryptographically strong random number generater used // to choose the object number - see java.rmi.server.ObjID System.setProperty("java.rmi.server.randomIDs", "true"); // This RMI server should not keep the VM alive Map<String, Object> env = new HashMap<String, Object>(); env.put(RMIExporter.EXPORTER_ATTRIBUTE, new PermanentExporter()); // The local connector server need only be available via the // loopback connection. String localhost = "localhost"; InetAddress lh = null; try { lh = InetAddress.getByName(localhost); localhost = lh.getHostAddress(); } catch (UnknownHostException x) { } // localhost unknown or (somehow) didn't resolve to // a loopback address. if (lh == null || !lh.isLoopbackAddress()) { localhost = "127.0.0.1"; } MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); try { JMXServiceURL url = new JMXServiceURL("rmi", localhost, 0); // Do we accept connections from local interfaces only? Properties props = Agent.getManagementProperties(); if (props == null) { props = new Properties(); } String useLocalOnlyStr = props.getProperty( PropertyNames.USE_LOCAL_ONLY, DefaultValues.USE_LOCAL_ONLY); boolean useLocalOnly = Boolean.valueOf(useLocalOnlyStr).booleanValue(); if (useLocalOnly) { env.put(RMIConnectorServer.RMI_SERVER_SOCKET_FACTORY_ATTRIBUTE, new LocalRMIServerSocketFactory()); } JMXConnectorServer server = JMXConnectorServerFactory.newJMXConnectorServer(url, env, mbs); server.start(); return server; } catch (Exception e) { throw new AgentConfigurationError(AGENT_EXCEPTION, e, e.toString());