/**
  * Get a free connection
  *
  * @return
  * @throws IllegalStateException - Thrown if a connection cannot be created.
  * @since 1.0.0
  */
 public IREMConnection getFreeConnection() throws IllegalStateException {
   Thread thread = Thread.currentThread();
   if (thread instanceof REMCallbackThread) {
     // The current thread is a call back thread, so just reuse the connection.
     // But this thread could actually be trying to access another registry.
     // So if this thread is for this registry, use it, if not for this registry, create a new
     // connection.
     // But if for this registry AND is already in a transaction, we need a fresh connection.
     REMCallbackThread callbackThread = (REMCallbackThread) thread;
     if (callbackThread.registry == this && !callbackThread.inTransaction()) {
       // This way any calls out to the remote vm will be on same thread as callback caller
       // on remote vm because that thread is waiting on this connection for commands.
       IREMConnection c = (callbackThread).getConnection();
       if (c.isConnected()) return c;
       else
         throw new IllegalStateException(
             ProxyRemoteMessages.REMProxyFactoryRegistry_CallbackConnectionNotWorking_EXC_);
     }
   }
   synchronized (fConnectionPool) {
     if (!fConnectionPool.isEmpty()) return (IREMConnection) fConnectionPool.pop();
     // else we need to allocate one.
     return createConnection();
   }
 }
 /** Free the connection */
 public void returnConnection(IREMConnection connection) {
   if (connection.isConnected()) {
     Thread thread = Thread.currentThread();
     if (!(thread instanceof REMCallbackThread)
         || ((REMCallbackThread) thread).getConnection() != connection) {
       // We are not a callback thread, or we are but the connection is not for the thread, then
       // the connection
       // can be returned.
       synchronized (fConnectionPool) {
         if (fConnectionPool.size() < NUMBER_FREE_CONNECTIONS) fConnectionPool.push(connection);
         else connection.close(); // We don't need to maintain more than five free connections.
       }
     }
   }
 }
 /** Release this connection. This means close it out. */
 public void closeConnection(IREMConnection connection) {
   connection.close();
 }
  protected void registryTerminated(boolean wait) {
    if (processListener != null) {
      // Remove listener cause we are now going to terminate process and don't want premature
      // terminate notice.
      // Sometimes in shutdown we are called and the debug plugin may of already been shutdown. In
      // that case the db
      // will be null and there is nothing remove listener from.
      DebugPlugin db = DebugPlugin.getDefault();
      if (db != null) db.removeDebugEventListener(processListener);
      processListener = null;
    }

    Job tjob = null;
    if (waitRegistrationThread != null) {
      synchronized (waitRegistrationThread) {
        // Still waiting. close it out.
        WaitForRegistrationThread wThread = waitRegistrationThread;
        waitRegistrationThread = null;
        wThread.notifyAll();
      }
    }
    if (fServerPort != 0) {
      IREMConnection closeCon = null; // The connection we will use to close the remote vm.
      synchronized (fConnectionPool) {
        // Now we walk through all of the free connections and close them properly.
        Iterator itr = fConnectionPool.iterator();
        if (itr.hasNext()) closeCon = (IREMConnection) itr.next();
        while (itr.hasNext()) {
          IREMConnection con = (IREMConnection) itr.next();
          con.close();
        }
      }

      // Now we terminate the server.
      if (closeCon == null)
        try {
          closeCon =
              getFreeConnection(); // There weren't any free connections, so get a new one so that
                                   // we can close it.
        } catch (IllegalStateException e) {
          // Do nothing, don't want to stop termination just because we can't get a connection.
        }
      if (closeCon != null) {
        closeCon
            .terminateServer(); // We got a connection to terminate (process may of terminated
                                // early, so we would not have a conn then).
      }
      fConnectionPool.clear();
      fServerPort = 0;

      if (fProcess != null && !fRegistryController.inShutDown()) {
        tjob = new TerminateProcess(fProcess);
        tjob.setSystem(true);
        tjob.schedule();
        fProcess = null;
      }
    }

    if (fCallbackServer != null) {
      fCallbackServer.requestShutdown();
      fCallbackServer = null;
    }

    fConnectionPool.clear();
    fRegistryController.deregisterRegistry(fRegistryKey); // De-register this registry.

    if (wait && tjob != null) {
      try {
        tjob.join();
      } catch (InterruptedException e) {
        // It timed out, so we'll just go on.
      }
    }
  }