/**
   * Starts the common RMI registry. In order to provide RMI stub for remote client, the JMX RMI
   * connector should be register into an RMI registry. Each server will maintain its own private
   * one.
   *
   * @throws Exception if the registry cannot be started
   */
  private void startCommonRegistry() throws Exception {
    int registryPort = jmxConnectionHandler.getListenPort();

    //
    // create our local RMI registry if it does not exist already
    if (debugEnabled()) {
      TRACER.debugVerbose("start or reach an RMI registry on port %d", registryPort);
    }
    try {
      //
      // TODO Not yet implemented: If the host has several interfaces
      if (registry == null) {
        rmiSsf = new OpendsRmiServerSocketFactory();
        registry = LocateRegistry.createRegistry(registryPort, null, rmiSsf);
      }
    } catch (RemoteException re) {
      //
      // is the registry already created ?
      if (debugEnabled()) {
        TRACER.debugWarning("cannot create the RMI registry -> already done ?");
      }
      try {
        //
        // get a 'remote' reference on the registry
        Registry reg = LocateRegistry.getRegistry(registryPort);

        //
        // 'ping' the registry
        reg.list();
        registry = reg;
      } catch (Exception e) {
        if (debugEnabled()) {
          //
          // no 'valid' registry found on the specified port
          TRACER.debugError("exception thrown while pinging the RMI registry");

          //
          // throw the original exception
          TRACER.debugCaught(DebugLogLevel.ERROR, re);
        }
        throw re;
      }

      //
      // here the registry is ok even though
      // it was not created by this call
      if (debugEnabled()) {
        TRACER.debugWarning("RMI was registry already started");
      }
    }
  }
  /**
   * Starts a secure RMI connector, with a client that doesn't have to present a certificate, on the
   * local MBean server. This method assumes that the common registry was successfully started.
   *
   * <p>If the connector is already started, this method simply returns without doing anything.
   *
   * @throws Exception if an error occurs
   */
  private void startConnectorNoClientCertificate() throws Exception {
    try {
      //
      // Environment map
      HashMap<String, Object> env = new HashMap<String, Object>();

      // ---------------------
      // init an ssl context
      // ---------------------
      DirectoryRMIClientSocketFactory rmiClientSockeyFactory = null;
      DirectoryRMIServerSocketFactory rmiServerSockeyFactory = null;
      if (jmxConnectionHandler.isUseSSL()) {
        if (debugEnabled()) {
          TRACER.debugVerbose("SSL connection");
        }

        // ---------------------
        // SERVER SIDE
        // ---------------------
        //
        // Get a Server socket factory
        KeyManager[] keyManagers;
        KeyManagerProvider provider =
            DirectoryServer.getKeyManagerProvider(jmxConnectionHandler.getKeyManagerProviderDN());
        if (provider == null) {
          keyManagers = new NullKeyManagerProvider().getKeyManagers();
        } else {
          String nickname = jmxConnectionHandler.getSSLServerCertNickname();
          if (nickname == null) {
            keyManagers = provider.getKeyManagers();
          } else {
            keyManagers = SelectableCertificateKeyManager.wrap(provider.getKeyManagers(), nickname);
          }
        }

        SSLContext ctx = SSLContext.getInstance("TLSv1");
        ctx.init(keyManagers, null, null);
        SSLSocketFactory ssf = ctx.getSocketFactory();

        //
        // set the Server socket factory in the JMX map
        rmiServerSockeyFactory = new DirectoryRMIServerSocketFactory(ssf, false);
        env.put("jmx.remote.rmi.server.socket.factory", rmiServerSockeyFactory);

        // ---------------------
        // CLIENT SIDE : Rmi stores the client stub in the
        // registry
        // ---------------------
        // Set the Client socket factory in the JMX map
        rmiClientSockeyFactory = new DirectoryRMIClientSocketFactory(false);
        env.put("jmx.remote.rmi.client.socket.factory", rmiClientSockeyFactory);
      } else {
        if (debugEnabled()) {
          TRACER.debugVerbose("UNSECURE CONNECTION");
        }
      }

      //
      // specify the rmi JMX authenticator to be used
      if (debugEnabled()) {
        TRACER.debugVerbose("Add RmiAuthenticator into JMX map");
      }
      rmiAuthenticator = new RmiAuthenticator(jmxConnectionHandler);

      env.put(JMXConnectorServer.AUTHENTICATOR, rmiAuthenticator);

      //
      // Create the JMX Service URL
      String uri = "org.opends.server.protocols.jmx.client-unknown";
      String serviceUrl =
          "service:jmx:rmi:///jndi/rmi://"
              + registryClientAddress
              + ":"
              + jmxConnectionHandler.getListenPort()
              + "/"
              + uri;
      JMXServiceURL url = new JMXServiceURL(serviceUrl);

      //
      // Create and start the connector
      if (debugEnabled()) {
        TRACER.debugVerbose("Create and start the JMX RMI connector");
      }
      OpendsRMIJRMPServerImpl opendsRmiConnectorServer =
          new OpendsRMIJRMPServerImpl(
              jmxConnectionHandler.getRmiPort(),
              rmiClientSockeyFactory,
              rmiServerSockeyFactory,
              env);
      jmxRmiConnectorNoClientCertificate =
          new RMIConnectorServer(url, env, opendsRmiConnectorServer, mbs);
      jmxRmiConnectorNoClientCertificate.start();

      //
      // Register the connector into the RMI registry
      // TODO Should we do that?
      ObjectName name = new ObjectName(jmxRmiConnectorNoClientCertificateName);
      mbs.registerMBean(jmxRmiConnectorNoClientCertificate, name);
      rmiVersion = opendsRmiConnectorServer.getVersion();

      if (debugEnabled()) {
        TRACER.debugVerbose("JMX RMI connector Started");
      }

    } catch (Exception e) {
      if (debugEnabled()) {
        TRACER.debugCaught(DebugLogLevel.ERROR, e);
      }
      throw e;
    }
  }