/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* 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.
*/
/**
* 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 {
}
/**
* Names of JMX configuration properties.
**/
public static interface PropertyNames {
"com.sun.management.jmxremote.port";
"com.sun.management.jmxremote.rmi.port";
"com.sun.management.config.file";
"com.sun.management.jmxremote.local.only";
"com.sun.management.jmxremote.ssl";
"com.sun.management.jmxremote.registry.ssl";
"com.sun.management.jmxremote.authenticate";
"com.sun.management.jmxremote.password.file";
"com.sun.management.jmxremote.access.file";
"com.sun.management.jmxremote.ssl.enabled.cipher.suites";
"com.sun.management.jmxremote.ssl.enabled.protocols";
"com.sun.management.jmxremote.ssl.need.client.auth";
"com.sun.management.jmxremote.ssl.config.file";
}
/**
* JMXConnectorServer associated data.
*/
private static class JMXConnectorServerData {
public JMXConnectorServerData(
this.jmxConnectorServer = jmxConnectorServer;
this.jmxRemoteURL = 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>
*/
int port,
throws RemoteException {
synchronized (this) {
if (firstExported == null) {
firstExported = obj;
}
}
final UnicastServerRef ref;
} else {
}
}
// Nothing special to be done for this case
throws NoSuchObjectException {
}
}
/**
* 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 {
environment = env;
}
final JMXAuthenticator authenticator =
return subject;
}
throw new SecurityException(
"Access denied! No matching entries found in " +
"authenticated Subject is null");
}
return;
}
}
}
throw new SecurityException(
"Access denied! No entries found in the access file [" +
accessFile + "] for any of the authenticated identities " +
}
throws IOException {
Properties p = new Properties();
return p;
}
return p;
}
}
// The variable below is here to support stop functionality
// It would be overriten if you call startRemoteCommectionServer second
// time. It's OK for now as logic in Agent.java forbids mutiple agents
public static void unexportRegistry() {
// Remove the entry from registry
try {
}
} catch(NoSuchObjectException ex) {
// This exception can appears only if we attempt
// to unexportRegistry second time. So it's safe
// to ignore it without additional messages.
}
}
/**
* 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 #startRemoteConnectorServer
* (java.lang.String, java.util.Properties)}.
*
* This method is used by some jtreg tests.
**/
// Load a new management properties
return null;
}
}
/**
* This method is used by some jtreg tests.
*
* @see #startRemoteConnectorServer
* (String portStr, Properties props)
*/
}
/**
* Initializes and starts a JMX Connector Server for remote
* monitoring and management.
**/
public static synchronized JMXConnectorServer startRemoteConnectorServer(String portStr, Properties props) {
// Get port number
final int port;
try {
} catch (NumberFormatException x) {
}
if (port < 0) {
}
// User can specify a port to be used to export rmi object,
// in order to simplify firewall rules
// if port is not specified random one will be allocated.
int rmiPort = 0;
try {
if (rmiPortStr != null) {
}
} catch (NumberFormatException x) {
}
if (rmiPort < 0) {
}
// Do we use authentication?
final String useAuthenticationStr =
final boolean useAuthentication =
// Do we use SSL?
final boolean useSsl =
// Do we use RMI Registry SSL?
final String useRegistrySslStr =
final boolean useRegistrySsl =
final String enabledCipherSuites =
if (enabledCipherSuites != null) {
for (int i = 0; i < tokens; i++) {
}
}
final String enabledProtocols =
if (enabledProtocols != null) {
for (int i = 0; i < tokens; i++) {
}
}
final String sslNeedClientAuthStr =
final boolean sslNeedClientAuth =
// Read SSL config file name
final String sslConfigFileName =
// Initialize settings when authentication is active
if (useAuthentication) {
// Get non-default login configuration
if (loginConfigName == null) {
// Get password file
}
// Get access file
}
loginConfigName)) : "\n\t" +
accessFileName) : "") +
"");
}
try {
} catch (Exception e) {
}
try {
// Export remote connector address and associated configuration
// properties to the instrumentation buffer.
} 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.
}
return cs;
}
/*
* Creates and starts a RMI Connector Server for "local" monitoring
* and management.
*/
// Ensure cryptographically strong random number generater used
// to choose the object number - see java.rmi.server.ObjID
// This RMI server should not keep the VM alive
// The local connector server need only be available via the
// loopback connection.
try {
} catch (UnknownHostException x) {
}
// localhost unknown or (somehow) didn't resolve to
// a loopback address.
localhost = "127.0.0.1";
}
try {
// Do we accept connections from local interfaces only?
props = new Properties();
}
if (useLocalOnly) {
new LocalRMIServerSocketFactory());
}
return server;
} catch (Exception e) {
}
}
throw new AgentConfigurationError(PASSWORD_FILE_NOT_SET);
}
}
}
try {
}
}
} catch (IOException e) {
throw new AgentConfigurationError(PASSWORD_FILE_READ_FAILED,
e, passwordFileName);
}
}
throw new AgentConfigurationError(ACCESS_FILE_NOT_SET);
}
}
}
}
throw new AgentConfigurationError(FILE_NOT_SET);
}
}
}
try {
"jmxremote.ConnectorBootstrap.file.readonly",
throw new AgentConfigurationError(
}
}
} catch (IOException e) {
throw new AgentConfigurationError(
}
}
/**
* Compute the full path name for a default file.
* @param basename basename (with extension) of the default file.
* @return ${JRE}/lib/management/${basename}
**/
}
boolean sslNeedClientAuth) {
if (sslConfigFileName == null) {
return new SslRMIServerSocketFactory(
} else {
try {
// Load the SSL keystore properties from the config file
Properties p = new Properties();
try {
} finally {
}
p.getProperty("javax.net.ssl.keyStore");
p.getProperty("javax.net.ssl.trustStore");
char[] keyStorePasswd = null;
}
char[] trustStorePasswd = null;
}
try {
} finally {
}
}
if (trustStore != null) {
try {
} finally {
}
}
return new SslRMIServerSocketFactory(
ctx,
} catch (Exception e) {
}
}
}
int port,
int rmiPort,
boolean useSsl,
boolean useRegistrySsl,
boolean sslNeedClientAuth,
boolean useAuthentication,
throws IOException, MalformedURLException {
/* Make sure we use non-guessable RMI object IDs. Otherwise
* attackers could hijack open connections by guessing their
* IDs. */
if (useAuthentication) {
if (loginConfigName != null) {
}
if (passwordFileName != null) {
}
}
}
if (useSsl || useRegistrySsl) {
csf = new SslRMIClientSocketFactory();
}
if (useSsl) {
csf);
ssf);
}
try {
connServer.start();
} catch (IOException e) {
if (connServer == null) {
throw new AgentConfigurationError(CONNECTOR_SERVER_IO_ERROR,
} else {
throw new AgentConfigurationError(CONNECTOR_SERVER_IO_ERROR,
}
}
if (useRegistrySsl) {
registry =
} else {
registry =
new SingleEntryRegistry(port,
}
int registryPort =
/* Our exporter remembers the first object it was asked to
export, which will be an RMIServerImpl appropriate for
publication in our special registry. We could
alternatively have constructed the RMIServerImpl explicitly
and then constructed an RMIConnectorServer passing it as a
parameter, but that's quite a bit more verbose and pulls in
lots of knowledge of the RMI connector. */
}
/**
* This class cannot be instantiated.
**/
private ConnectorBootstrap() {
}
"ConnectorBootstrap");
}