OpendsJmxConnector.java revision cf364c082dfe5ea566abc3c20bc5546a4629c5eb
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at legal-notices/CDDLv1_0.txt
* or http://forgerock.org/license/CDDLv1.0.html.
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at legal-notices/CDDLv1_0.txt.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information:
* Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*
*
* Copyright 2006-2008 Sun Microsystems, Inc.
* Portions Copyright 2015 ForgeRock AS
*/
package org.opends.server.protocols.jmx;
import java.io.IOException;
import java.util.Map;
import javax.management.ListenerNotFoundException;
import javax.management.MBeanServerConnection;
import javax.management.NotificationFilter;
import javax.management.NotificationListener;
import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectorFactory;
import javax.management.remote.JMXServiceURL;
import javax.security.auth.Subject;
/**
* Wrapper class for the JMX's RMI connector. This class has the exact same
* functionnalities but maintain inner variables which are used during the
* connection phase.
* <p>
* Note that the javadoc has been copied from the
* javax.management.remote.JMXConnector interface.
*/
public class OpendsJmxConnector implements JMXConnector
{
/**
* the wrapped JMX RMI connector.
*/
private JMXConnector jmxc;
/**
* the connection environment set at creation.
*/
private Map<String,Object> environment;
/**
* the JMX Service URL.
*/
private JMXServiceURL serviceURL;
/**
* the host to connect to.
*/
private String serverHostname;
/**
* Creates a connector client for the connector server at the
* given host and port. The resultant client is not connected until its
* connect method is called.
*
* @param serverHostname the target server hostname
*
* @param serverPort the target server port
*
* @param environment a set of attributes to determine how the
* connection is made. This parameter can be null. Keys in this
* map must be Strings. The appropriate type of each associated
* value depends on the attribute. The contents of
* <code>environment</code> are not changed by this call.
*
* @exception IOException if the connector client cannot be made
* because of a communication problem.
*
*/
public OpendsJmxConnector(String serverHostname, int serverPort,
Map<String,Object> environment) throws IOException
{
serviceURL = new JMXServiceURL(
"service:jmx:rmi:///jndi/rmi://" + serverHostname + ":" + serverPort
+ "/org.opends.server.protocols.jmx.client-unknown");
this.jmxc = JMXConnectorFactory.newJMXConnector(serviceURL, environment);
this.serverHostname = serverHostname;
this.environment = environment ;
}
// /**
// * Sets this connector's connection environment.
// *
// * @param environment the new connection env
// */
// public void setConnectionEnv(Map connectionEnv)
// {
// this.environment = environment;
// }
/**
* Returns the connection environment.
*
* @return Map the connection environment used by new connections
*/
public Map getConnectionEnv()
{
return environment;
}
/**
* Establishes the connection to the connector server. This method is
* equivalent to connect(null).
*
* @throws IOException
* if the connection could not be made because of a communication
* problem.
* @throws SecurityException
* if the connection could not be made for security reasons.
*/
public void connect() throws IOException, SecurityException
{
connect(null);
}
/**
* Establishes the connection to the connector server. If connect has
* already been called successfully on this object, calling it again has
* no effect. If, however, close() was called after connect, the new
* connect will throw an IOException. Otherwise, either connect has never
* been called on this object, or it has been called but produced an
* exception. Then calling connect will attempt to establish a connection
* to the connector server.
*
* @param env
* the properties of the connection. Properties in this map
* override properties in the map specified when the JMXConnector
* was created, if any. This parameter can be null, which is
* equivalent to an empty map.
* @throws IOException
* if the connection could not be made because of a communication
* problem.
* @throws SecurityException -
* if the connection could not be made for security reasons.
*/
public void connect(Map<String,?> env) throws IOException, SecurityException
{
// set the real target hostname
DirectoryRMIClientSocketFactory.setServerHostname(serverHostname);
// configure the thread-local connection environment
if (env != null)
{
// encode credentials if necessary
updateCredentials(env);
}
DirectoryRMIClientSocketFactory.setConnectionEnv(environment);
jmxc.connect(env);
}
/**
* Returns an MBeanServerConnection object representing a remote MBean
* server. For a given JMXConnector, two successful calls to this method
* will usually return the same MBeanServerConnection object, though this
* is not required. For each method in the returned
* MBeanServerConnection, calling the method causes the corresponding
* method to be called in the remote MBean server. The value returned by
* the MBean server method is the value returned to the client. If the
* MBean server method produces an Exception, the same Exception is seen
* by the client. If the MBean server method, or the attempt to call it,
* produces an Error, the Error is wrapped in a JMXServerErrorException,
* which is seen by the client. Calling this method is equivalent to
* calling getMBeanServerConnection(null) meaning that no delegation
* subject is specified and that all the operations called on the
* MBeanServerConnection must use the authenticated subject, if any.
*
* @return an object that implements the MBeanServerConnection interface
* by forwarding its methods to the remote MBean server.
* @throws IOException -
* if a valid MBeanServerConnection cannot be created, for
* instance because the connection to the remote MBean server has
* not yet been established (with the connect method), or it has
* been closed, or it has broken.
*/
public MBeanServerConnection getMBeanServerConnection() throws IOException
{
return jmxc.getMBeanServerConnection();
}
/**
* Returns an MBeanServerConnection object representing a remote MBean
* server on which operations are performed on behalf of the supplied
* delegation subject. For a given JMXConnector and Subject, two
* successful calls to this method will usually return the same
* MBeanServerConnection object, though this is not required. For each
* method in the returned MBeanServerConnection, calling the method
* causes the corresponding method to be called in the remote MBean
* server on behalf of the given delegation subject instead of the
* authenticated subject. The value returned by the MBean server method
* is the value returned to the client. If the MBean server method
* produces an Exception, the same Exception is seen by the client. If
* the MBean server method, or the attempt to call it, produces an Error,
* the Error is wrapped in a JMXServerErrorException, which is seen by
* the client.
*
* @param delegationSubject
* the Subject on behalf of which requests will be performed. Can
* be null, in which case requests will be performed on behalf of
* the authenticated Subject, if any.
* @return an object that implements the MBeanServerConnection interface
* by forwarding its methods to the remote MBean server on behalf
* of a given delegation subject.
* @throws IOException
* if a valid MBeanServerConnection cannot be created, for
* instance because the connection to the remote MBean server has
* not yet been established (with the connect method), or it has
* been closed, or it has broken.
*/
public MBeanServerConnection getMBeanServerConnection(
Subject delegationSubject) throws IOException
{
return jmxc.getMBeanServerConnection(delegationSubject);
}
/**
* Closes the client connection to its server. Any ongoing or new request
* using the MBeanServerConnection returned by getMBeanServerConnection()
* will get an IOException. If close has already been called successfully
* on this object, calling it again has no effect. If close has never
* been called, or if it was called but produced an exception, an attempt
* will be made to close the connection. This attempt can succeed, in
* which case close will return normally, or it can generate an
* exception. Closing a connection is a potentially slow operation. For
* example, if the server has crashed, the close operation might have to
* wait for a network protocol timeout. Callers that do not want to block
* in a close operation should do it in a separate thread.
*
* @throws IOException
* if the connection cannot be closed cleanly. If this exception
* is thrown, it is not known whether the server end of the
* connection has been cleanly closed.
*/
public void close() throws IOException
{
jmxc.close();
}
/**
* Adds a listener to be informed of changes in connection status. The
* listener will receive notifications of type JMXConnectionNotification.
* An implementation can send other types of notifications too. Any
* number of listeners can be added with this method. The same listener
* can be added more than once with the same or different values for the
* filter and handback. There is no special treatment of a duplicate
* entry. For example, if a listener is registered twice with no filter,
* then its handleNotification method will be called twice for each
* notification.
*
* @param listener
* a listener to receive connection status notifications.
* @param filter
* a filter to select which notifications are to be delivered to
* the listener, or null if all notifications are to be delivered.
* @param handback
* an object to be given to the listener along with each
* notification. Can be null.
* @throws NullPointerException
* if listener is null.
*/
public void addConnectionNotificationListener(
NotificationListener listener, NotificationFilter filter,
Object handback) throws NullPointerException
{
jmxc.addConnectionNotificationListener(listener, filter, handback);
}
/**
* Removes a listener from the list to be informed of changes in status.
* The listener must previously have been added. If there is more than
* one matching listener, all are removed.
*
* @param listener -
* a listener to receive connection status notifications.
* @throws NullPointerException
* if listener is null.
* @throws ListenerNotFoundException
* if the listener is not registered with this JMXConnector.
*/
public void removeConnectionNotificationListener(
NotificationListener listener) throws ListenerNotFoundException,
NullPointerException
{
jmxc.removeConnectionNotificationListener(listener);
}
/**
* Removes a listener from the list to be informed of changes in status.
* The listener must previously have been added with the same three
* parameters. If there is more than one matching listener, only one is
* removed.
*
* @param l
* a listener to receive connection status notifications.
* @param f
* a filter to select which notifications are to be delivered to
* the listener. Can be null. handback - an object to be given to
* the listener along with each notification. Can be null.
* @param handback
* an object to be given to the listener along with each
* notification. Can be null.
* @throws ListenerNotFoundException
* if the listener is not registered with this JMXConnector, or
* is not registered with the given filter and handback.
*/
public void removeConnectionNotificationListener(
NotificationListener l, NotificationFilter f, Object handback)
throws ListenerNotFoundException
{
jmxc.removeConnectionNotificationListener(l, f, handback);
}
/**
* Gets this connection's ID from the connector server. For a given
* connector server, every connection will have a unique id which does
* not change during the lifetime of the connection.
*
* @return the unique ID of this connection. This is the same as the ID
* that the connector server includes in its
* JMXConnectionNotifications. The package description describes
* the conventions for connection IDs.
* @throws IOException
* if the connection ID cannot be obtained, for instance because
* the connection is closed or broken.
*/
public String getConnectionId() throws IOException
{
return jmxc.getConnectionId();
}
/**
* Update if necessary the credentials of the given map using
* information coming from the map given when the connector was created.
* This method is called from the connect method when it has received
* a non null map holding potentially new credentials. It calls this
* method BEFORE actually trying to connect to the server.
*
* @param Map given to the connect method
*/
private void updateCredentials(Map env) throws IOException
{
// credential to update ??
if (!env.containsKey(JMXConnector.CREDENTIALS))
{
// NO : nothing to update
return;
}
else
{
Object cred = env.get(JMXConnector.CREDENTIALS);
environment.put(JMXConnector.CREDENTIALS, cred);
}
}
}