/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.karaf.management;

import org.apache.karaf.jaas.config.KeystoreManager;
import org.apache.karaf.management.internal.MBeanInvocationHandler;
import org.osgi.framework.BundleContext;

import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Proxy;
import java.net.BindException;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketAddress;
import java.net.SocketException;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.channels.ServerSocketChannel;
import java.rmi.AccessException;
import java.rmi.AlreadyBoundException;
import java.rmi.NotBoundException;
import java.rmi.Remote;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.RMIClientSocketFactory;
import java.rmi.server.RMIServerSocketFactory;
import java.rmi.server.UnicastRemoteObject;
import java.security.GeneralSecurityException;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Map;

import javax.management.JMException;
import javax.management.MBeanServer;
import javax.management.ObjectName;
import javax.management.remote.JMXConnectorServer;
import javax.management.remote.JMXConnectorServerFactory;
import javax.management.remote.JMXServiceURL;
import javax.management.remote.rmi.RMIConnectorServer;
import javax.management.remote.rmi.RMIJRMPServerImpl;
import javax.net.ServerSocketFactory;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLParameters;
import javax.net.ssl.SSLServerSocket;
import javax.net.ssl.SSLServerSocketFactory;
import javax.rmi.ssl.SslRMIClientSocketFactory;

public class ConnectorServerFactory {

    private enum AuthenticatorType {NONE, PASSWORD, CERTIFICATE}

    private MBeanServer server;
    private KarafMBeanServerGuard guard;
    private String serviceUrl;
    private boolean jmxmpEnabled;
    private String jmxmpServiceUrl;
    private String rmiServerHost;
    private Map<String, Object> environment;
    private Map<String, Object> jmxmpEnvironment;
    private ObjectName objectName;
    private ObjectName jmxmpObjectName;
    private boolean threaded = false;
    private boolean daemon = false;
    private JMXConnectorServer connectorServer;
    private Remote remoteServerStub;
    private RMIJRMPServerImpl rmiServer;
    private JMXConnectorServer jmxmpConnectorServer;

    private long keyStoreAvailabilityTimeout = 5000;
    private AuthenticatorType authenticatorType = AuthenticatorType.PASSWORD;
    private boolean secured;
    private KeystoreManager keystoreManager;
    private String algorithm;
    private String secureProtocol;
    private String[] enabledProtocols;
    private String[] enabledCipherSuites;
    private String keyStore;
    private String trustStore;
    private String keyAlias;

    private int port = Registry.REGISTRY_PORT;
    private String host;
    private Registry registry;
    private boolean locate;
    private boolean create = true;
    private boolean locallyCreated;
    private BundleContext bundleContext;

    public MBeanServer getServer() {
        return server;
    }

    public void setServer(MBeanServer server) {
        this.server = server;
    }

    public KarafMBeanServerGuard getGuard() {
        return guard;
    }

    public void setGuard(KarafMBeanServerGuard guard) {
        this.guard = guard;
    }

    public String getServiceUrl() {
        return serviceUrl;
    }

    public void setServiceUrl(String serviceUrl) {
        this.serviceUrl = serviceUrl;
    }

    public boolean isJmxmpEnabled() {
        return this.jmxmpEnabled;
    }

    public void setJmxmpEnabled(boolean jmxmpEnabled) {
        this.jmxmpEnabled = jmxmpEnabled;
    }

    public String getJmxmpServiceUrl() {
        return jmxmpServiceUrl;
    }

    public void setJmxmpServiceUrl(String jmxmpServiceUrl) {
        this.jmxmpServiceUrl = jmxmpServiceUrl;
    }

    public String getRmiServerHost() {
        return this.rmiServerHost;
    }

    public void setRmiServerHost(String rmiServerHost) {
        this.rmiServerHost = rmiServerHost;
    }

    public Map<String, Object> getEnvironment() {
        return environment;
    }

    public void setEnvironment(Map<String, Object> environment) {
        this.environment = environment;
    }

    public Map<String, Object> getJmxmpEnvironment() {
        return this.jmxmpEnvironment;
    }

    public void setJmxmpEnvironment(Map<String,Object> jmxmpEnvironment) {
        this.jmxmpEnvironment = jmxmpEnvironment;
    }

    public ObjectName getObjectName() {
        return objectName;
    }

    public void setObjectName(ObjectName objectName) {
        this.objectName = objectName;
    }

    public ObjectName getJmxmpObjectName() {
        return this.jmxmpObjectName;
    }

    public void setJmxmpObjectName(ObjectName jmxmpObjectName) {
        this.jmxmpObjectName = jmxmpObjectName;
    }

    public boolean isThreaded() {
        return threaded;
    }

    public void setThreaded(boolean threaded) {
        this.threaded = threaded;
    }

    public boolean isDaemon() {
        return daemon;
    }

    public void setDaemon(boolean daemon) {
        this.daemon = daemon;
    }

    public String getAuthenticatorType() {
        return this.authenticatorType.name().toLowerCase();
    }

    /**
     * Authenticator type to use. Acceptable values are "none", "password", and "certificate"
     *
     * @param value The authenticator type: "none", "password", "certificate".
     */
    public void setAuthenticatorType(String value) {
        this.authenticatorType = AuthenticatorType.valueOf(value.toUpperCase());
    }

    /**
     * Use this param to allow KeyStoreManager to wait for expected keystores to be loaded by other bundle
     *
     * @param keyStoreAvailabilityTimeout The keystore timeout.
     */
    public void setKeyStoreAvailabilityTimeout(long keyStoreAvailabilityTimeout) {
        this.keyStoreAvailabilityTimeout = keyStoreAvailabilityTimeout;
    }

    public boolean isSecured() {
        return this.secured;
    }

    public void setSecured(boolean secured) {
        this.secured = secured;
    }

    public void setKeystoreManager(KeystoreManager keystoreManager) {
        this.keystoreManager = keystoreManager;
    }

    public KeystoreManager getKeystoreManager() {
        return this.keystoreManager;
    }

    public String getKeyStore() {
        return this.keyStore;
    }

    public void setKeyStore(String keyStore) {
        this.keyStore = keyStore;
    }

    public String getTrustStore() {
        return this.trustStore;
    }

    public void setTrustStore(String trustStore) {
        this.trustStore = trustStore;
    }

    public String getKeyAlias() {
        return this.keyAlias;
    }

    public void setKeyAlias(String keyAlias) {
        this.keyAlias = keyAlias;
    }

    public String getAlgorithm() {
        return this.algorithm;
    }

    /**
     * Algorithm to use.
     * As different JVMs have different implementations available, the default algorithm can be used by supplying the value "Default".
     *
     * @param algorithm the algorithm to use, or "Default" to use the default from {@link javax.net.ssl.KeyManagerFactory#getDefaultAlgorithm()}
     */
    public void setAlgorithm(String algorithm) {
        if ("default".equalsIgnoreCase(algorithm)) {
            this.algorithm = KeyManagerFactory.getDefaultAlgorithm();
        } else {
            this.algorithm = algorithm;
        }
    }

    public String getSecureProtocol() {
        return this.secureProtocol;
    }

    public void setSecureProtocol(String secureProtocol) {
        this.secureProtocol = secureProtocol;
    }


    private boolean isClientAuth() {
        return this.authenticatorType.equals(AuthenticatorType.CERTIFICATE);
    }

    /**
     * @return the create
     */
    public boolean isCreate() {
        return create;
    }

    /**
     * @param create the create to set
     */
    public void setCreate(boolean create) {
        this.create = create;
    }

    /**
     * @return the locate
     */
    public boolean isLocate() {
        return locate;
    }

    /**
     * @param locate the locate to set
     */
    public void setLocate(boolean locate) {
        this.locate = locate;
    }

    /**
     * @return the port
     */
    public int getPort() {
        return port;
    }

    /**
     * @param port the port to set
     */
    public void setPort(int port) {
        this.port = port;
    }

    public String getHost() {
        return host;
    }

    public void setHost(String host) {
        this.host = host;
    }

    public void setBundleContext(BundleContext bundleContext) {
        this.bundleContext = bundleContext;
    }

    public void init() throws Exception {

        JMXServiceURL url = new JMXServiceURL(this.serviceUrl);

        if (registry == null && locate) {
            try {
                Registry reg = LocateRegistry.getRegistry(host, getPort());
                reg.list();
                registry = reg;
            } catch (RemoteException e) {
                // ignore
            }
        }
        if (registry == null && create) {
            registry = new JmxRegistry(getPort(), getBindingName(url));
            locallyCreated = true;
        }
        if (registry != null) {
            // register the registry as an OSGi service
            Hashtable<String, Object> props = new Hashtable<>();
            props.put("port", getPort());
            props.put("host", getHost());
            bundleContext.registerService(Registry.class, registry, props);
        }

        if (this.server == null) {
            throw new IllegalArgumentException("server must be set");
        }
        if ( isClientAuth() ) {
            this.secured = true;
        }

        if ( this.secured ) {
            setupSsl();
        } else {
            setupKarafRMIServerSocketFactory();
        }

        if ( ! AuthenticatorType.PASSWORD.equals( this.authenticatorType ) ) {
            this.environment.remove( "jmx.remote.authenticator" );
        }

        MBeanInvocationHandler handler = new MBeanInvocationHandler(server, guard);
        MBeanServer guardedServer = (MBeanServer) Proxy.newProxyInstance(server.getClass().getClassLoader(), new Class[]{ MBeanServer.class }, handler);

        rmiServer = new RMIJRMPServerImpl(url.getPort(), null, null, environment);

        // Create the connector server now.
        this.connectorServer = new RMIConnectorServer(url, environment, rmiServer, guardedServer);

        if (this.objectName != null) {
            this.server.registerMBean(this.connectorServer, this.objectName);
        }

        if (jmxmpEnabled) {
            JMXServiceURL jmxmpUrl = new JMXServiceURL(this.jmxmpServiceUrl);
            this.jmxmpConnectorServer = JMXConnectorServerFactory.newJMXConnectorServer(jmxmpUrl, this.jmxmpEnvironment, guardedServer);
            if (this.jmxmpObjectName != null) {
                this.server.registerMBean(this.jmxmpConnectorServer, this.jmxmpObjectName);
            }
        }

        try {
            if (this.threaded) {
                Thread connectorThread = new Thread(() -> {
                    try {
                        Thread.currentThread().setContextClassLoader(ConnectorServerFactory.class.getClassLoader());
                        connectorServer.start();
                        remoteServerStub = rmiServer.toStub();
                        if (jmxmpEnabled && jmxmpConnectorServer != null) {
                            jmxmpConnectorServer.start();
                        }
                    } catch (IOException ex) {
                        if (ex.getCause() instanceof BindException){
                            // we want just the port message
                            int endIndex = ex.getMessage().indexOf("nested exception is");
                            // check to make sure we do not get an index out of range
                            if (endIndex > ex.getMessage().length() || endIndex < 0){
                                endIndex = ex.getMessage().length();
                            }
                            throw new RuntimeException("\n" + ex.getMessage().substring(0, endIndex) +
                                                    "\nYou may have started two containers.  If you need to start a second container or the default ports are already in use " +
                                                    "update the config file etc/org.apache.karaf.management.cfg and change the Registry Port and Server Port to unused ports");
                        }
                        throw new RuntimeException("Could not start JMX connector server", ex);
                    }
                });
                connectorThread.setName("JMX Connector Thread [" + this.serviceUrl + "]");
                connectorThread.setDaemon(this.daemon);
                connectorThread.start();
            } else {
                this.connectorServer.start();
                remoteServerStub = rmiServer.toStub();
                if (jmxmpEnabled && jmxmpConnectorServer != null) {
                    jmxmpConnectorServer.start();
                }
            }
        } catch (Exception ex) {
            if (this.objectName != null) {
                doUnregister(this.objectName);
            }
            if (jmxmpEnabled && this.jmxmpObjectName != null) {
                doUnregister(this.jmxmpObjectName);
            }
            throw ex;
        }
    }

    protected static String getBindingName(final JMXServiceURL jmxServiceURL) {
        final String urlPath = jmxServiceURL.getURLPath();

        try {
            if (urlPath.startsWith("/jndi/")) {
                return new URI(urlPath.substring(6)).getPath()
                        .replaceAll("^/+", "").replaceAll("/+$", "");
            }
        } catch (URISyntaxException e) {
            // ignore
        }

        return "jmxrmi"; // use the default
    }

    public void destroy() throws Exception {
        try {
            if (this.connectorServer != null) {
                this.connectorServer.stop();
            }
            if (this.jmxmpEnabled && this.jmxmpConnectorServer != null) {
                this.jmxmpConnectorServer.stop();
            }

            if (registry != null && locallyCreated) {
                Registry reg = registry;
                registry = null;
                UnicastRemoteObject.unexportObject(reg, true);

                // clear TCPEndpointCache
                try {
                    Class<?> cls = getClass().getClassLoader().loadClass("sun.rmi.transport.tcp.TCPEndpoint");
                    Field localEndpointsField = cls.getDeclaredField("localEndpoints");
                    Field ssfField = cls.getDeclaredField("ssf");
                    localEndpointsField.setAccessible(true);
                    ssfField.setAccessible(true);
                    Object localEndpoints = localEndpointsField.get(null);
                    if (localEndpoints != null) {
                        Map<Object, Object> map = (Map<Object, Object>) localEndpoints;
                        for (Iterator<Object> it = map.keySet().iterator(); it.hasNext(); ) {
                            Object key = it.next();
                            Object ssf = ssfField.get(key);
                            if (ssf != null && ssf.getClass().getPackage().getName().equals("org.apache.karaf.management")) {
                                it.remove();
                            }
                        }
                    }
                } catch (Exception ignored) {
                }
            }
        } finally {
            if (this.objectName != null) {
                doUnregister(this.objectName);
            }
            if (this.jmxmpEnabled && this.jmxmpObjectName != null) {
                doUnregister(this.jmxmpObjectName);
            }
        }
    }

    protected void doUnregister(ObjectName objectName) {
        try {
            if (this.objectName != null && this.server.isRegistered(objectName)) {
                this.server.unregisterMBean(objectName);
            }
            if (this.jmxmpObjectName != null && this.server.isRegistered(jmxmpObjectName)) {
                this.server.unregisterMBean(jmxmpObjectName);
            }
        } catch (JMException ex) {
            // Ignore
        }
    }

    private void setupSsl() throws GeneralSecurityException {
        SSLServerSocketFactory sssf = keystoreManager.createSSLServerFactory(null, secureProtocol, algorithm, keyStore, keyAlias, trustStore,keyStoreAvailabilityTimeout);
        RMIServerSocketFactory rssf = new KarafSslRMIServerSocketFactory(sssf, isClientAuth(), getRmiServerHost(), getEnabledProtocols(),
                                                                         getEnabledCipherSuites());
        RMIClientSocketFactory rcsf = new SslRMIClientSocketFactory();
        environment.put(RMIConnectorServer.RMI_SERVER_SOCKET_FACTORY_ATTRIBUTE, rssf);
        environment.put(RMIConnectorServer.RMI_CLIENT_SOCKET_FACTORY_ATTRIBUTE, rcsf);
        //@TODO secure RMI connector as well?
        //env.put("com.sun.jndi.rmi.factory.socket", rcsf);
    }

    private void setupKarafRMIServerSocketFactory() {
        RMIServerSocketFactory rssf = new KarafRMIServerSocketFactory(getRmiServerHost());
        environment.put(RMIConnectorServer.RMI_SERVER_SOCKET_FACTORY_ATTRIBUTE, rssf);
    }

    private static class KarafSslRMIServerSocketFactory implements RMIServerSocketFactory {
        private SSLServerSocketFactory sssf;
        private boolean clientAuth;
        private String rmiServerHost;
        private String[] enabledProtocols;
        private String[] enabledCipherSuites;

        public KarafSslRMIServerSocketFactory(SSLServerSocketFactory sssf, boolean clientAuth, String rmiServerHost,
                                              String[] enabledProtocols,
                                              String[] enabledCipherSuites) {
            this.sssf = sssf;
            this.clientAuth = clientAuth;
            this.rmiServerHost = rmiServerHost;
            this.enabledProtocols = enabledProtocols;
            this.enabledCipherSuites = enabledCipherSuites;
        }

        public ServerSocket createServerSocket(int port) throws IOException {
            InetAddress host = InetAddress.getByName(rmiServerHost);
            if (host.isLoopbackAddress()) {
                final SSLServerSocket ss = (SSLServerSocket) sssf.createServerSocket(port, 50);
                ss.setNeedClientAuth(clientAuth);
                if (this.enabledProtocols != null && this.enabledProtocols.length > 0) {
                    ss.setEnabledProtocols(this.enabledProtocols);
                }
                if (this.enabledCipherSuites != null && this.enabledCipherSuites.length > 0) {
                    ss.setEnabledCipherSuites(this.enabledCipherSuites);
                }
                return new LocalOnlySSLServerSocket(ss);
            } else {
                final SSLServerSocket ss = (SSLServerSocket) sssf.createServerSocket(port, 50, InetAddress.getByName(rmiServerHost));
                ss.setNeedClientAuth(clientAuth);
                if (this.enabledProtocols != null && this.enabledProtocols.length > 0) {
                    ss.setEnabledProtocols(this.enabledProtocols);
                }
                if (this.enabledCipherSuites != null && this.enabledCipherSuites.length > 0) {
                    ss.setEnabledCipherSuites(this.enabledCipherSuites);
                }
                return ss;
            }
        }
    }

    private static class KarafRMIServerSocketFactory implements RMIServerSocketFactory {
        private String rmiServerHost;

        public KarafRMIServerSocketFactory(String rmiServerHost) {
            this.rmiServerHost = rmiServerHost;
        }

        public ServerSocket createServerSocket(int port) throws IOException {
            InetAddress host = InetAddress.getByName(rmiServerHost);
            if (host.isLoopbackAddress()) {
                final ServerSocket ss = ServerSocketFactory.getDefault().createServerSocket(port, 50);
                return new LocalOnlyServerSocket(ss);
            } else {
                final ServerSocket ss = ServerSocketFactory.getDefault().createServerSocket(port, 50, InetAddress.getByName(rmiServerHost));
                return ss;
            }
        }
    }

    private static class LocalOnlyServerSocket extends ServerSocket {

        private final ServerSocket ss;

        public LocalOnlyServerSocket(ServerSocket ss) throws IOException {
            this.ss = ss;
        }

        @Override
        public void bind(SocketAddress endpoint) throws IOException {
            ss.bind(endpoint);
        }

        @Override
        public void bind(SocketAddress endpoint, int backlog) throws IOException {
            ss.bind(endpoint, backlog);
        }

        @Override
        public InetAddress getInetAddress() {
            return ss.getInetAddress();
        }

        @Override
        public int getLocalPort() {
            return ss.getLocalPort();
        }

        @Override
        public SocketAddress getLocalSocketAddress() {
            return ss.getLocalSocketAddress();
        }

        @Override
        public Socket accept() throws IOException {
            return checkLocal(ss.accept());
        }

        @Override
        public void close() throws IOException {
            ss.close();
        }

        @Override
        public ServerSocketChannel getChannel() {
            return ss.getChannel();
        }

        @Override
        public boolean isBound() {
            return ss.isBound();
        }

        @Override
        public boolean isClosed() {
            return ss.isClosed();
        }

        @Override
        public void setSoTimeout(int timeout) throws SocketException {
            ss.setSoTimeout(timeout);
        }

        @Override
        public int getSoTimeout() throws IOException {
            return ss.getSoTimeout();
        }

        @Override
        public void setReuseAddress(boolean on) throws SocketException {
            ss.setReuseAddress(on);
        }

        @Override
        public boolean getReuseAddress() throws SocketException {
            return ss.getReuseAddress();
        }

        @Override
        public String toString() {
            return ss.toString();
        }

        @Override
        public void setReceiveBufferSize(int size) throws SocketException {
            ss.setReceiveBufferSize(size);
        }

        @Override
        public int getReceiveBufferSize() throws SocketException {
            return ss.getReceiveBufferSize();
        }

        @Override
        public void setPerformancePreferences(int connectionTime, int latency, int bandwidth) {
            ss.setPerformancePreferences(connectionTime, latency, bandwidth);
        }
    }

    private static class LocalOnlySSLServerSocket extends SSLServerSocket {

        private final SSLServerSocket ss;

        public LocalOnlySSLServerSocket(SSLServerSocket ss) throws IOException {
            this.ss = ss;
        }

        @Override
        public void bind(SocketAddress endpoint) throws IOException {
            ss.bind(endpoint);
        }

        @Override
        public void bind(SocketAddress endpoint, int backlog) throws IOException {
            ss.bind(endpoint, backlog);
        }

        @Override
        public InetAddress getInetAddress() {
            return ss.getInetAddress();
        }

        @Override
        public int getLocalPort() {
            return ss.getLocalPort();
        }

        @Override
        public SocketAddress getLocalSocketAddress() {
            return ss.getLocalSocketAddress();
        }

        @Override
        public Socket accept() throws IOException {
            return checkLocal(ss.accept());
        }

        @Override
        public void close() throws IOException {
            ss.close();
        }

        @Override
        public ServerSocketChannel getChannel() {
            return ss.getChannel();
        }

        @Override
        public boolean isBound() {
            return ss.isBound();
        }

        @Override
        public boolean isClosed() {
            return ss.isClosed();
        }

        @Override
        public void setSoTimeout(int timeout) throws SocketException {
            ss.setSoTimeout(timeout);
        }

        @Override
        public int getSoTimeout() throws IOException {
            return ss.getSoTimeout();
        }

        @Override
        public void setReuseAddress(boolean on) throws SocketException {
            ss.setReuseAddress(on);
        }

        @Override
        public boolean getReuseAddress() throws SocketException {
            return ss.getReuseAddress();
        }

        @Override
        public String toString() {
            return ss.toString();
        }

        @Override
        public void setReceiveBufferSize(int size) throws SocketException {
            ss.setReceiveBufferSize(size);
        }

        @Override
        public int getReceiveBufferSize() throws SocketException {
            return ss.getReceiveBufferSize();
        }

        @Override
        public void setPerformancePreferences(int connectionTime, int latency, int bandwidth) {
            ss.setPerformancePreferences(connectionTime, latency, bandwidth);
        }
        public String[] getEnabledCipherSuites() {
            return ss.getEnabledCipherSuites();
        }

        public void setEnabledCipherSuites(String[] strings) {
            ss.setEnabledCipherSuites(strings);
        }

        public String[] getSupportedCipherSuites() {
            return ss.getSupportedCipherSuites();
        }

        public String[] getSupportedProtocols() {
            return ss.getSupportedProtocols();
        }

        public String[] getEnabledProtocols() {
            return ss.getEnabledProtocols();
        }

        public void setEnabledProtocols(String[] strings) {
            ss.setEnabledProtocols(strings);
        }

        public void setNeedClientAuth(boolean b) {
            ss.setNeedClientAuth(b);
        }

        public boolean getNeedClientAuth() {
            return ss.getNeedClientAuth();
        }

        public void setWantClientAuth(boolean b) {
            ss.setWantClientAuth(b);
        }

        public boolean getWantClientAuth() {
            return ss.getWantClientAuth();
        }

        public void setUseClientMode(boolean b) {
            ss.setUseClientMode(b);
        }

        public boolean getUseClientMode() {
            return ss.getUseClientMode();
        }

        public void setEnableSessionCreation(boolean b) {
            ss.setEnableSessionCreation(b);
        }

        public boolean getEnableSessionCreation() {
            return ss.getEnableSessionCreation();
        }

        public SSLParameters getSSLParameters() {
            return ss.getSSLParameters();
        }

        public void setSSLParameters(SSLParameters sslParameters) {
            ss.setSSLParameters(sslParameters);
        }
    }

    private static Socket checkLocal(Socket socket) throws IOException {
        InetAddress addr = socket.getInetAddress();
        if (addr != null) {
            if (addr.isLoopbackAddress()) {
                return socket;
            } else {
                try {
                    Enumeration<NetworkInterface> nis = NetworkInterface.getNetworkInterfaces();
                    while (nis.hasMoreElements()) {
                        NetworkInterface ni = nis.nextElement();
                        Enumeration<InetAddress> ads = ni.getInetAddresses();
                        while (ads.hasMoreElements()) {
                            InetAddress ad = ads.nextElement();
                            if (ad.equals(addr)) {
                                return socket;
                            }
                        }
                    }
                } catch (SocketException e) {
                    // Ignore
                }
            }
        }
        try {
            socket.close();
        } catch (Exception e) {
            // Ignore
        }
        throw new IOException("Only connections from clients running on the host where the RMI remote objects have been exported are accepted.");
    }

    public String[] getEnabledProtocols() {
        return enabledProtocols;
    }

    public void setEnabledProtocols(String[] enabledProtocols) {
        this.enabledProtocols = enabledProtocols;
    }

    public String[] getEnabledCipherSuites() {
        return enabledCipherSuites;
    }

    public void setEnabledCipherSuites(String[] enabledCipherSuites) {
        this.enabledCipherSuites = enabledCipherSuites;
    }

    /*
     * Better to use the internal API than re-invent the wheel.
     */
    @SuppressWarnings("restriction")
    private class JmxRegistry extends sun.rmi.registry.RegistryImpl {
        private final String lookupName;

        JmxRegistry(final int port, final String lookupName) throws RemoteException {
            super(port);
            this.lookupName = lookupName;
        }

        @Override
        public Remote lookup(String s) throws RemoteException, NotBoundException {
            return lookupName.equals(s) ? remoteServerStub : null;
        }

        @Override
        public void bind(String s, Remote remote) throws RemoteException, AlreadyBoundException, AccessException {
        }

        @Override
        public void unbind(String s) throws RemoteException, NotBoundException, AccessException {
        }

        @Override
        public void rebind(String s, Remote remote) throws RemoteException, AccessException {
        }

        @Override
        public String[] list() throws RemoteException {
            return new String[] {lookupName};
        }
    }

}
