/*
 * Copyright 2002-2007 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.  Sun designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Sun 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 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.
 */

package javax.management.remote.rmi;


import com.sun.jmx.remote.security.MBeanServerFileAccessController;
import com.sun.jmx.remote.util.ClassLogger;
import com.sun.jmx.remote.util.EnvHelp;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.net.MalformedURLException;
import java.rmi.server.RMIClientSocketFactory;
import java.rmi.server.RMIServerSocketFactory;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Map;
import java.util.Set;

import javax.management.InstanceNotFoundException;
import javax.management.MBeanServer;

import javax.management.remote.JMXConnectionNotification;
import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectorServer;
import javax.management.remote.JMXServiceURL;
import javax.management.remote.MBeanServerForwarder;

import javax.naming.InitialContext;
import javax.naming.NamingException;

/**
 * <p>A JMX API connector server that creates RMI-based connections
 * from remote clients.  Usually, such connector servers are made
 * using {@link javax.management.remote.JMXConnectorServerFactory
 * JMXConnectorServerFactory}.  However, specialized applications can
 * use this class directly, for example with an {@link RMIServerImpl}
 * object.</p>
 *
 * @since 1.5
 */
public class RMIConnectorServer extends JMXConnectorServer {
    /**
     * <p>Name of the attribute that specifies whether the {@link
     * RMIServer} stub that represents an RMI connector server should
     * override an existing stub at the same address.  The value
     * associated with this attribute, if any, should be a string that
     * is equal, ignoring case, to <code>"true"</code> or
     * <code>"false"</code>.  The default value is false.</p>
     */
    public static final String JNDI_REBIND_ATTRIBUTE =
        "jmx.remote.jndi.rebind";

    /**
     * <p>Name of the attribute that specifies the {@link
     * RMIClientSocketFactory} for the RMI objects created in
     * conjunction with this connector. The value associated with this
     * attribute must be of type <code>RMIClientSocketFactory</code> and can
     * only be specified in the <code>Map</code> argument supplied when
     * creating a connector server.</p>
     */
    public static final String RMI_CLIENT_SOCKET_FACTORY_ATTRIBUTE =
        "jmx.remote.rmi.client.socket.factory";

    /**
     * <p>Name of the attribute that specifies the {@link
     * RMIServerSocketFactory} for the RMI objects created in
     * conjunction with this connector. The value associated with this
     * attribute must be of type <code>RMIServerSocketFactory</code> and can
     * only be specified in the <code>Map</code> argument supplied when
     * creating a connector server.</p>
     */
    public static final String RMI_SERVER_SOCKET_FACTORY_ATTRIBUTE =
        "jmx.remote.rmi.server.socket.factory";

    /**
     * <p>Makes an <code>RMIConnectorServer</code>.
     * This is equivalent to calling {@link #RMIConnectorServer(
     * JMXServiceURL,Map,RMIServerImpl,MBeanServer)
     * RMIConnectorServer(directoryURL,environment,null,null)}</p>
     *
     * @param url the URL defining how to create the connector server.
     * Cannot be null.
     *
     * @param environment attributes governing the creation and
     * storing of the RMI object.  Can be null, which is equivalent to
     * an empty Map.
     *
     * @exception IllegalArgumentException if <code>url</code> is null.
     *
     * @exception MalformedURLException if <code>url</code> does not
     * conform to the syntax for an RMI connector, or if its protocol
     * is not recognized by this implementation. Only "rmi" and "iiop"
     * are valid when this constructor is used.
     *
     * @exception IOException if the connector server cannot be created
     * for some reason or if it is inevitable that its {@link #start()
     * start} method will fail.
     */
    public RMIConnectorServer(JMXServiceURL url, Map<String,?> environment)
            throws IOException {
        this(url, environment, (MBeanServer) null);
    }

    /**
     * <p>Makes an <code>RMIConnectorServer</code> for the given MBean
     * server.
     * This is equivalent to calling {@link #RMIConnectorServer(
     * JMXServiceURL,Map,RMIServerImpl,MBeanServer)
     * RMIConnectorServer(directoryURL,environment,null,mbeanServer)}</p>
     *
     * @param url the URL defining how to create the connector server.
     * Cannot be null.
     *
     * @param environment attributes governing the creation and
     * storing of the RMI object.  Can be null, which is equivalent to
     * an empty Map.
     *
     * @param mbeanServer the MBean server to which the new connector
     * server is attached, or null if it will be attached by being
     * registered as an MBean in the MBean server.
     *
     * @exception IllegalArgumentException if <code>url</code> is null.
     *
     * @exception MalformedURLException if <code>url</code> does not
     * conform to the syntax for an RMI connector, or if its protocol
     * is not recognized by this implementation. Only "rmi" and "iiop"
     * are valid when this constructor is used.
     *
     * @exception IOException if the connector server cannot be created
     * for some reason or if it is inevitable that its {@link #start()
     * start} method will fail.
     */
    public RMIConnectorServer(JMXServiceURL url, Map<String,?> environment,
                              MBeanServer mbeanServer)
            throws IOException {
        this(url, environment, (RMIServerImpl) null, mbeanServer);
    }

    /**
     * <p>Makes an <code>RMIConnectorServer</code> for the given MBean
     * server.</p>
     *
     * @param url the URL defining how to create the connector server.
     * Cannot be null.
     *
     * @param environment attributes governing the creation and
     * storing of the RMI object.  Can be null, which is equivalent to
     * an empty Map.
     *
     * @param rmiServerImpl An implementation of the RMIServer interface,
     *  consistent with the protocol type specified in <var>url</var>.
     *  If this parameter is non null, the protocol type specified by
     *  <var>url</var> is not constrained, and is assumed to be valid.
     *  Otherwise, only "rmi" and "iiop" will be recognized.
     *
     * @param mbeanServer the MBean server to which the new connector
     * server is attached, or null if it will be attached by being
     * registered as an MBean in the MBean server.
     *
     * @exception IllegalArgumentException if <code>url</code> is null.
     *
     * @exception MalformedURLException if <code>url</code> does not
     * conform to the syntax for an RMI connector, or if its protocol
     * is not recognized by this implementation. Only "rmi" and "iiop"
     * are recognized when <var>rmiServerImpl</var> is null.
     *
     * @exception IOException if the connector server cannot be created
     * for some reason or if it is inevitable that its {@link #start()
     * start} method will fail.
     *
     * @see #start
     */
    public RMIConnectorServer(JMXServiceURL url, Map<String,?> environment,
                              RMIServerImpl rmiServerImpl,
                              MBeanServer mbeanServer)
            throws IOException {
        super(mbeanServer);

        if (url == null) throw new
            IllegalArgumentException("Null JMXServiceURL");
        if (rmiServerImpl == null) {
            final String prt = url.getProtocol();
            if (prt == null || !(prt.equals("rmi") || prt.equals("iiop"))) {
                final String msg = "Invalid protocol type: " + prt;
                throw new MalformedURLException(msg);
            }
            final String urlPath = url.getURLPath();
            if (!urlPath.equals("")
                && !urlPath.equals("/")
                && !urlPath.startsWith("/jndi/")) {
                final String msg = "URL path must be empty or start with " +
                    "/jndi/";
                throw new MalformedURLException(msg);
            }
        }

        if (environment == null)
            this.attributes = Collections.emptyMap();
        else {
            EnvHelp.checkAttributes(environment);
            this.attributes = Collections.unmodifiableMap(environment);
        }

        this.address = url;
        this.rmiServerImpl = rmiServerImpl;
    }

    /**
     * <p>Returns a client stub for this connector server.  A client
     * stub is a serializable object whose {@link
     * JMXConnector#connect(Map) connect} method can be used to make
     * one new connection to this connector server.</p>
     *
     * @param env client connection parameters of the same sort that
     * could be provided to {@link JMXConnector#connect(Map)
     * JMXConnector.connect(Map)}.  Can be null, which is equivalent
     * to an empty map.
     *
     * @return a client stub that can be used to make a new connection
     * to this connector server.
     *
     * @exception UnsupportedOperationException if this connector
     * server does not support the generation of client stubs.
     *
     * @exception IllegalStateException if the JMXConnectorServer is
     * not started (see {@link #isActive()}).
     *
     * @exception IOException if a communications problem means that a
     * stub cannot be created.
     **/
    public JMXConnector toJMXConnector(Map<String,?> env) throws IOException {
        // The serialized for of rmiServerImpl is automatically
        // a RMI server stub.
        if (!isActive()) throw new
            IllegalStateException("Connector is not active");

        // Merge maps
        Map<String, Object> usemap = new HashMap<String, Object>(
                (this.attributes==null)?Collections.<String, Object>emptyMap():
                    this.attributes);

        if (env != null) {
            EnvHelp.checkAttributes(env);
            usemap.putAll(env);
        }

        usemap = EnvHelp.filterAttributes(usemap);

        final RMIServer stub=(RMIServer)rmiServerImpl.toStub();

        return new RMIConnector(stub, usemap);
    }

    /**
     * <p>Activates the connector server, that is starts listening for
     * client connections.  Calling this method when the connector
     * server is already active has no effect.  Calling this method
     * when the connector server has been stopped will generate an
     * <code>IOException</code>.</p>
     *
     * <p>The behavior of this method when called for the first time
     * depends on the parameters that were supplied at construction,
     * as described below.</p>
     *
     * <p>First, an object of a subclass of {@link RMIServerImpl} is
     * required, to export the connector server through RMI:</p>
     *
     * <ul>
     *
     * <li>If an <code>RMIServerImpl</code> was supplied to the
     * constructor, it is used.
     *
     * <li>Otherwise, if the protocol part of the
     * <code>JMXServiceURL</code> supplied to the constructor was
     * <code>iiop</code>, an object of type {@link RMIIIOPServerImpl}
     * is created.
     *
     * <li>Otherwise, if the <code>JMXServiceURL</code>
     * was null, or its protocol part was <code>rmi</code>, an object
     * of type {@link RMIJRMPServerImpl} is created.
     *
     * <li>Otherwise, the implementation can create an
     * implementation-specific {@link RMIServerImpl} or it can throw
     * {@link MalformedURLException}.
     *
     * </ul>
     *
     * <p>If the given address includes a JNDI directory URL as
     * specified in the package documentation for {@link
     * javax.management.remote.rmi}, then this
     * <code>RMIConnectorServer</code> will bootstrap by binding the
     * <code>RMIServerImpl</code> to the given address.</p>
     *
     * <p>If the URL path part of the <code>JMXServiceURL</code> was
     * empty or a single slash (<code>/</code>), then the RMI object
     * will not be bound to a directory.  Instead, a reference to it
     * will be encoded in the URL path of the RMIConnectorServer
     * address (returned by {@link #getAddress()}).  The encodings for
     * <code>rmi</code> and <code>iiop</code> are described in the
     * package documentation for {@link
     * javax.management.remote.rmi}.</p>
     *
     * <p>The behavior when the URL path is neither empty nor a JNDI
     * directory URL, or when the protocol is neither <code>rmi</code>
     * nor <code>iiop</code>, is implementation defined, and may
     * include throwing {@link MalformedURLException} when the
     * connector server is created or when it is started.</p>
     *
     * @exception IllegalStateException if the connector server has
     * not been attached to an MBean server.
     * @exception IOException if the connector server cannot be
     * started.
     */
    public synchronized void start() throws IOException {
        final boolean tracing = logger.traceOn();

        if (state == STARTED) {
            if (tracing) logger.trace("start", "already started");
            return;
        } else if (state == STOPPED) {
            if (tracing) logger.trace("start", "already stopped");
            throw new IOException("The server has been stopped.");
        }

        if (getMBeanServer() == null)
            throw new IllegalStateException("This connector server is not " +
                                            "attached to an MBean server");

        // Check the internal access file property to see
        // if an MBeanServerForwarder is to be provided
        //
        if (attributes != null) {
            // Check if access file property is specified
            //
            String accessFile =
                (String) attributes.get("jmx.remote.x.access.file");
            if (accessFile != null) {
                // Access file property specified, create an instance
                // of the MBeanServerFileAccessController class
                //
                MBeanServerForwarder mbsf = null;
                try {
                    mbsf = new MBeanServerFileAccessController(accessFile);
                } catch (IOException e) {
                    throw EnvHelp.initCause(
                        new IllegalArgumentException(e.getMessage()), e);
                }
                // Set the MBeanServerForwarder
                //
                setMBeanServerForwarder(mbsf);
            }
        }

        try {
            if (tracing) logger.trace("start", "setting default class loader");
            defaultClassLoader =
                EnvHelp.resolveServerClassLoader(attributes, getMBeanServer());
        } catch (InstanceNotFoundException infc) {
            IllegalArgumentException x = new
                IllegalArgumentException("ClassLoader not found: "+infc);
            throw EnvHelp.initCause(x,infc);
        }

        if (tracing) logger.trace("start", "setting RMIServer object");
        final RMIServerImpl rmiServer;

        if (rmiServerImpl != null)
            rmiServer = rmiServerImpl;
        else
            rmiServer = newServer();

        rmiServer.setMBeanServer(getMBeanServer());
        rmiServer.setDefaultClassLoader(defaultClassLoader);
        rmiServer.setRMIConnectorServer(this);
        rmiServer.export();

        try {
            if (tracing) logger.trace("start", "getting RMIServer object to export");
            final RMIServer objref = objectToBind(rmiServer, attributes);

            if (address != null && address.getURLPath().startsWith("/jndi/")) {
                final String jndiUrl = address.getURLPath().substring(6);

                if (tracing)
                    logger.trace("start", "Using external directory: " + jndiUrl);

                final boolean rebind = EnvHelp.computeBooleanFromString(
                    attributes,
                    JNDI_REBIND_ATTRIBUTE);

                if (tracing)
                    logger.trace("start", JNDI_REBIND_ATTRIBUTE + "=" + rebind);

                try {
                    if (tracing) logger.trace("start", "binding to " + jndiUrl);

                    final Hashtable usemap = EnvHelp.mapToHashtable(attributes);

                    bind(jndiUrl, usemap, objref, rebind);

                    boundJndiUrl = jndiUrl;
                } catch (NamingException e) {
                    // fit e in the nested exception if we are on 1.4
                    throw newIOException("Cannot bind to URL ["+jndiUrl+"]: "
                                         + e, e);
                }
            } else {
                // if jndiURL is null, we must encode the stub into the URL.
                if (tracing) logger.trace("start", "Encoding URL");

                encodeStubInAddress(objref, attributes);

                if (tracing) logger.trace("start", "Encoded URL: " + this.address);
            }
        } catch (Exception e) {
            try {
                rmiServer.close();
            } catch (Exception x) {
                // OK: we are already throwing another exception
            }
            if (e instanceof RuntimeException)
                throw (RuntimeException) e;
            else if (e instanceof IOException)
                throw (IOException) e;
            else
                throw newIOException("Got unexpected exception while " +
                                     "starting the connector server: "
                                     + e, e);
        }

        rmiServerImpl = rmiServer;

        synchronized(openedServers) {
            openedServers.add(this);
        }

        state = STARTED;

        if (tracing) {
            logger.trace("start", "Connector Server Address = " + address);
            logger.trace("start", "started.");
        }
    }

    /**
     * <p>Deactivates the connector server, that is, stops listening for
     * client connections.  Calling this method will also close all
     * client connections that were made by this server.  After this
     * method returns, whether normally or with an exception, the
     * connector server will not create any new client
     * connections.</p>
     *
     * <p>Once a connector server has been stopped, it cannot be started
     * again.</p>
     *
     * <p>Calling this method when the connector server has already
     * been stopped has no effect.  Calling this method when the
     * connector server has not yet been started will disable the
     * connector server object permanently.</p>
     *
     * <p>If closing a client connection produces an exception, that
     * exception is not thrown from this method.  A {@link
     * JMXConnectionNotification} is emitted from this MBean with the
     * connection ID of the connection that could not be closed.</p>
     *
     * <p>Closing a connector server is a potentially slow operation.
     * For example, if a client machine with an open connection 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.</p>
     *
     * <p>This method calls the method {@link RMIServerImpl#close()
     * close} on the connector server's <code>RMIServerImpl</code>
     * object.</p>
     *
     * <p>If the <code>RMIServerImpl</code> was bound to a JNDI
     * directory by the {@link #start() start} method, it is unbound
     * from the directory by this method.</p>
     *
     * @exception IOException if the server cannot be closed cleanly,
     * or if the <code>RMIServerImpl</code> cannot be unbound from the
     * directory.  When this exception is thrown, the server has
     * already attempted to close all client connections, if
     * appropriate; to call {@link RMIServerImpl#close()}; and to
     * unbind the <code>RMIServerImpl</code> from its directory, if
     * appropriate.  All client connections are closed except possibly
     * those that generated exceptions when the server attempted to
     * close them.
     */
    public void stop() throws IOException {
        final boolean tracing = logger.traceOn();

        synchronized (this) {
            if (state == STOPPED) {
                if (tracing) logger.trace("stop","already stopped.");
                return;
            } else if (state == CREATED) {
                if (tracing) logger.trace("stop","not started yet.");
            }

            if (tracing) logger.trace("stop", "stopping.");
            state = STOPPED;
        }

        synchronized(openedServers) {
            openedServers.remove(this);
        }

        IOException exception = null;

        // rmiServerImpl can be null if stop() called without start()
        if (rmiServerImpl != null) {
            try {
                if (tracing) logger.trace("stop", "closing RMI server.");
                rmiServerImpl.close();
            } catch (IOException e) {
                if (tracing) logger.trace("stop", "failed to close RMI server: " + e);
                if (logger.debugOn()) logger.debug("stop",e);
                exception = e;
            }
        }

        if (boundJndiUrl != null) {
            try {
                if (tracing)
                    logger.trace("stop",
                          "unbind from external directory: " + boundJndiUrl);

                final Hashtable usemap = EnvHelp.mapToHashtable(attributes);

                InitialContext ctx =
                    new InitialContext(usemap);

                ctx.unbind(boundJndiUrl);

                ctx.close();
            } catch (NamingException e) {
                if (tracing) logger.trace("stop", "failed to unbind RMI server: "+e);
                if (logger.debugOn()) logger.debug("stop",e);
                // fit e in as the nested exception if we are on 1.4
                if (exception == null)
                    exception = newIOException("Cannot bind to URL: " + e, e);
            }
        }

        if (exception != null) throw exception;

        if (tracing) logger.trace("stop", "stopped");
    }

    public synchronized boolean isActive() {
        return (state == STARTED);
    }

    public JMXServiceURL getAddress() {
        if (!isActive())
            return null;
        return address;
    }

    public Map<String,?> getAttributes() {
        Map<String, ?> map = EnvHelp.filterAttributes(attributes);
        return Collections.unmodifiableMap(map);
    }

    public synchronized
        void setMBeanServerForwarder(MBeanServerForwarder mbsf) {
        super.setMBeanServerForwarder(mbsf);
        if (rmiServerImpl != null)
            rmiServerImpl.setMBeanServer(getMBeanServer());
    }

    /* We repeat the definitions of connection{Opened,Closed,Failed}
       here so that they are accessible to other classes in this package
       even though they have protected access.  */

    protected void connectionOpened(String connectionId, String message,
                                    Object userData) {
        super.connectionOpened(connectionId, message, userData);
    }

    protected void connectionClosed(String connectionId, String message,
                                    Object userData) {
        super.connectionClosed(connectionId, message, userData);
    }

    protected void connectionFailed(String connectionId, String message,
                                    Object userData) {
        super.connectionFailed(connectionId, message, userData);
    }

    /**
     * Bind a stub to a registry.
     * @param jndiUrl URL of the stub in the registry, extracted
     *        from the <code>JMXServiceURL</code>.
     * @param attributes A Hashtable containing environment parameters,
     *        built from the Map specified at this object creation.
     * @param rmiServer The object to bind in the registry
     * @param rebind true if the object must be rebound.
     **/
    void bind(String jndiUrl, Hashtable attributes,
              RMIServer rmiServer, boolean rebind)
        throws NamingException, MalformedURLException {
        // if jndiURL is not null, we nust bind the stub to a
        // directory.
        InitialContext ctx =
            new InitialContext(attributes);

        if (rebind)
            ctx.rebind(jndiUrl, rmiServer);
        else
            ctx.bind(jndiUrl, rmiServer);
        ctx.close();
    }

    /**
     * Creates a new RMIServerImpl.
     **/
    RMIServerImpl newServer() throws IOException {
        final boolean iiop = isIiopURL(address,true);
        final int port;
        if (address == null)
            port = 0;
        else
            port = address.getPort();
        if (iiop)
            return newIIOPServer(attributes);
        else
            return newJRMPServer(attributes, port);
    }

    /**
     * Encode a stub into the JMXServiceURL.
     * @param rmiServer The stub object to encode in the URL
     * @param attributes A Map containing environment parameters,
     *        built from the Map specified at this object creation.
     **/
    private void encodeStubInAddress(RMIServer rmiServer, Map attributes)
            throws IOException {

        final String protocol, host;
        final int port;

        if (address == null) {
            if (rmiServer instanceof javax.rmi.CORBA.Stub)
                protocol = "iiop";
            else
                protocol = "rmi";
            host = null; // will default to local host name
            port = 0;
        } else {
            protocol = address.getProtocol();
            host = (address.getHost().equals("")) ? null : address.getHost();
            port = address.getPort();
        }

        final String urlPath = encodeStub(rmiServer, attributes);

        address = new JMXServiceURL(protocol, host, port, urlPath);
    }

    static boolean isIiopURL(JMXServiceURL directoryURL, boolean strict)
        throws MalformedURLException {
        String protocol = directoryURL.getProtocol();
        if (protocol.equals("rmi"))
            return false;
        else if (protocol.equals("iiop"))
            return true;
        else if (strict) {

            throw new MalformedURLException("URL must have protocol " +
                                            "\"rmi\" or \"iiop\": \"" +
                                            protocol + "\"");
        }
        return false;
    }

    /**
     * Returns the IOR of the given rmiServer.
     **/
    static String encodeStub(RMIServer rmiServer, Map env) throws IOException {
        if (rmiServer instanceof javax.rmi.CORBA.Stub)
            return "/ior/" + encodeIIOPStub(rmiServer, env);
        else
            return "/stub/" + encodeJRMPStub(rmiServer, env);
    }

    static String encodeJRMPStub(RMIServer rmiServer, Map env)
            throws IOException {
        ByteArrayOutputStream bout = new ByteArrayOutputStream();
        ObjectOutputStream oout = new ObjectOutputStream(bout);
        oout.writeObject(rmiServer);
        oout.close();
        byte[] bytes = bout.toByteArray();
        return byteArrayToBase64(bytes);
    }

    static String encodeIIOPStub(RMIServer rmiServer, Map env)
            throws IOException {
        try {
            javax.rmi.CORBA.Stub stub =
                (javax.rmi.CORBA.Stub) rmiServer;
            return stub._orb().object_to_string(stub);
        } catch (org.omg.CORBA.BAD_OPERATION x) {
            throw newIOException(x.getMessage(), x);
        }
    }

    /**
     * Object that we will bind to the registry.
     * This object is a stub connected to our RMIServerImpl.
     **/
    private static RMIServer objectToBind(RMIServerImpl rmiServer, Map env)
        throws IOException {
        return RMIConnector.
            connectStub((RMIServer)rmiServer.toStub(),env);
    }

    private static RMIServerImpl newJRMPServer(Map<String, ?> env, int port)
            throws IOException {
        RMIClientSocketFactory csf = (RMIClientSocketFactory)
            env.get(RMI_CLIENT_SOCKET_FACTORY_ATTRIBUTE);
        RMIServerSocketFactory ssf = (RMIServerSocketFactory)
            env.get(RMI_SERVER_SOCKET_FACTORY_ATTRIBUTE);
        return new RMIJRMPServerImpl(port, csf, ssf, env);
    }

    private static RMIServerImpl newIIOPServer(Map<String, ?> env)
            throws IOException {
        return new RMIIIOPServerImpl(env);
    }

    private static String byteArrayToBase64(byte[] a) {
        int aLen = a.length;
        int numFullGroups = aLen/3;
        int numBytesInPartialGroup = aLen - 3*numFullGroups;
        int resultLen = 4*((aLen + 2)/3);
        final StringBuilder result = new StringBuilder(resultLen);

        // Translate all full groups from byte array elements to Base64
        int inCursor = 0;
        for (int i=0; i<numFullGroups; i++) {
            int byte0 = a[inCursor++] & 0xff;
            int byte1 = a[inCursor++] & 0xff;
            int byte2 = a[inCursor++] & 0xff;
            result.append(intToAlpha[byte0 >> 2]);
            result.append(intToAlpha[(byte0 << 4)&0x3f | (byte1 >> 4)]);
            result.append(intToAlpha[(byte1 << 2)&0x3f | (byte2 >> 6)]);
            result.append(intToAlpha[byte2 & 0x3f]);
        }

        // Translate partial group if present
        if (numBytesInPartialGroup != 0) {
            int byte0 = a[inCursor++] & 0xff;
            result.append(intToAlpha[byte0 >> 2]);
            if (numBytesInPartialGroup == 1) {
                result.append(intToAlpha[(byte0 << 4) & 0x3f]);
                result.append("==");
            } else {
                // assert numBytesInPartialGroup == 2;
                int byte1 = a[inCursor++] & 0xff;
                result.append(intToAlpha[(byte0 << 4)&0x3f | (byte1 >> 4)]);
                result.append(intToAlpha[(byte1 << 2)&0x3f]);
                result.append('=');
            }
        }
        // assert inCursor == a.length;
        // assert result.length() == resultLen;
        return result.toString();
    }

    /**
     * This array is a lookup table that translates 6-bit positive integer
     * index values into their "Base64 Alphabet" equivalents as specified
     * in Table 1 of RFC 2045.
     */
    private static final char intToAlpha[] = {
        'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
        'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
        'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
        'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
        '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'
    };

    /**
     * Construct a new IOException with a nested exception.
     * The nested exception is set only if JDK >= 1.4
     */
    private static IOException newIOException(String message,
                                              Throwable cause) {
        final IOException x = new IOException(message);
        return EnvHelp.initCause(x,cause);
    }


    // Private variables
    // -----------------

    private static ClassLogger logger =
        new ClassLogger("javax.management.remote.rmi", "RMIConnectorServer");

    private JMXServiceURL address;
    private RMIServerImpl rmiServerImpl;
    private final Map<String, ?> attributes;
    private ClassLoader defaultClassLoader = null;

    private String boundJndiUrl;

    // state
    private static final int CREATED = 0;
    private static final int STARTED = 1;
    private static final int STOPPED = 2;

    private int state = CREATED;
    private final static Set<RMIConnectorServer> openedServers =
            new HashSet<RMIConnectorServer>();
}
