/* * 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 * trunk/opends/resource/legal-notices/OpenDS.LICENSE * or https://OpenDS.dev.java.net/OpenDS.LICENSE. * 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 * trunk/opends/resource/legal-notices/OpenDS.LICENSE. 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. */ 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 = null; /** * the connection environment set at creation. */ private Map<String,Object> environment = null; /** * the JMX Service URL. */ private JMXServiceURL serviceURL = null; /** * the host to connect to. */ private String serverHostname = null; /** * 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 { this.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); } } }