/**
   * Creates and exports a registry (using an inherited channel, if any, as specified below), and
   * binds the specified name to the specified proxy in that registry.
   *
   * <p>First, the registry is exported as follows:
   *
   * <ul>
   *   <li>If the <code>System.inheritedChannel</code> method returns a <code>ServerSocketChannel
   *       </code> instance, the registry is exported with an <code>RMIServerSocketFactory</code>
   *       whose <code>createServerSocket</code> method returns a <code>ServerSocket</code> for the
   *       inherited <code>ServerSocketChannel</code> that delays accepting requests until the
   *       specified proxy is bound in the registry.
   *   <li>If the <code>System.inheritedChannel</code> method returns <code>null</code>, then the
   *       registry is exported with an <code>RMIServerSocketFactory</code> whose <code>
   *       createServerSocket</code> method returns a <code>ServerSocket</code> constructed with the
   *       specified port that delays accepting requests until the specified proxy is bound in the
   *       registry. In this case, if the port is <code>0</code>, then an <code>
   *       IllegalArgumentException</code> is thrown.
   *   <li>Otherwise, if the <code>System.inheritedChannel</code> returns an instance of any other
   *       type, an <code>IOException</code> is thrown.
   * </ul>
   *
   * <p>Once the registry is exported, the registry's <code>bind</code> method is invoked with the
   * specified name and proxy as arguments.
   *
   * @param obj the proxy for a remote object
   * @param name the name for the remote object in the registry
   * @param port a port to export the registry on if there is no inherited channel
   * @throws IllegalArgumentException if the inherited channel is <code>null</code> and the port is
   *     <code>0</code>
   * @throws IllegalStateException if this method was called previously
   * @throws IOException if the inherited channel is not an instance of <code>ServerSocketChannel
   *     </code> or <code>null</code>
   * @throws RemoteException if the registry could not be exported
   */
  public static void initializeWithInheritedChannel(Remote proxy, String name, int port)
      throws IOException {
    /*
     * Only allow this method to be invoked once.
     */
    synchronized (InitializeRegistry.class) {
      if (initialized) {
        throw new IllegalStateException("already invoked");
      }
      initialized = true;
    }

    Channel channel = System.inheritedChannel();
    ServerSocket serverSocket = null;

    /*
     * Handle inherited channel, if any.
     */
    if (channel instanceof ServerSocketChannel) {
      /*
       * Service launched from inetd.  Get server socket from
       * inherited server socket channel.
       */
      serverSocket = ((ServerSocketChannel) channel).socket();

    } else if (channel instanceof SocketChannel) {
      throw new IllegalArgumentException("got a Socket Channel instead");
    } else if (channel == null) {
      /*
       * Service launched from the command line.  In this case, the
       * port specified for the registry must be nonzero
       */
      if (port == 0) {
        throw new IllegalArgumentException("port must be nonzero");
      }
      serverSocket = new ServerSocket(port);

    } else {
      throw new IOException(
          "unexpected channel returned from inheritedChannel: " + channel.toString());
    }

    /*
     * Create server socket factory for registry to delay accepting
     * calls until a service is bound in the registry.
     */
    RMIServerSocketFactory ssf = new RegistryServerSocketFactory(serverSocket);

    /*
     * Create/export registry and bind name to proxy in registry.
     */
    Registry registry = LocateRegistry.createRegistry(port, null, ssf);
    try {
      registry.bind(name, proxy);
    } catch (RemoteException impossible) {
      throw new AssertionError(impossible);
    } catch (AlreadyBoundException impossible) {
      throw new AssertionError(impossible);
    }

    /*
     * Notify registry's socket factory that the service proxy is
     * bound in the registry, so that the registry can accept
     * incoming requests to look up the service.
     */
    synchronized (lock) {
      serviceAvailable = true;
      lock.notifyAll();
    }
  }