/**
     * Stop the registered lifecycles, optionally calling destroy on them.
     *
     * @param destroy true if {@link Destroyable}'s should also be destroyed.
     */
    public void stopLifeCycles(boolean destroy) {
      for (LifeCycle l : _lifeCycles) {
        try {
          if (l.isStarted()) {
            l.stop();
          }

          if ((l instanceof Destroyable) && destroy) ((Destroyable) l).destroy();
        } catch (Exception e) {
          debug(e);
        }
      }
    }
    @Override
    public void run() {
      if (serverSocket == null) {
        return;
      }

      while (serverSocket != null) {
        Socket socket = null;
        try {
          socket = serverSocket.accept();

          LineNumberReader lin =
              new LineNumberReader(new InputStreamReader(socket.getInputStream()));
          String receivedKey = lin.readLine();
          if (!key.equals(receivedKey)) {
            System.err.println("Ignoring command with incorrect key");
            continue;
          }

          OutputStream out = socket.getOutputStream();

          String cmd = lin.readLine();
          debug("command=%s", cmd);
          if ("stop".equalsIgnoreCase(cmd)) // historic, for backward compatibility
          {
            // Stop the lifecycles, only if they are registered with the ShutdownThread, only
            // destroying if vm is exiting
            debug("Issuing stop...");

            for (LifeCycle l : _lifeCycles) {
              try {
                if (l.isStarted() && ShutdownThread.isRegistered(l)) {
                  l.stop();
                }

                if ((l instanceof Destroyable) && exitVm) ((Destroyable) l).destroy();
              } catch (Exception e) {
                debug(e);
              }
            }

            // Stop accepting any more commands
            stopInput(socket);

            // Reply to client
            debug("Informing client that we are stopped.");
            informClient(out, "Stopped\r\n");

            // Stop the output and close the monitor socket
            stopOutput(socket);

            if (exitVm) {
              // Kill JVM
              debug("Killing JVM");
              System.exit(0);
            }
          } else if ("forcestop".equalsIgnoreCase(cmd)) {
            debug("Issuing force stop...");

            // Ensure that objects are stopped, destroyed only if vm is forcibly exiting
            stopLifeCycles(exitVm);

            // Stop accepting any more commands
            stopInput(socket);

            // Reply to client
            debug("Informing client that we are stopped.");
            informClient(out, "Stopped\r\n");

            // Stop the output and close the monitor socket
            stopOutput(socket);

            // Honour any pre-setup config to stop the jvm when this command is given
            if (exitVm) {
              // Kill JVM
              debug("Killing JVM");
              System.exit(0);
            }
          } else if ("stopexit".equalsIgnoreCase(cmd)) {
            debug("Issuing stop and exit...");
            // Make sure that objects registered with the shutdown thread will be stopped
            stopLifeCycles(true);

            // Stop accepting any more input
            stopInput(socket);

            // Reply to client
            debug("Informing client that we are stopped.");
            informClient(out, "Stopped\r\n");

            // Stop the output and close the monitor socket
            stopOutput(socket);

            debug("Killing JVM");
            System.exit(0);
          } else if ("exit".equalsIgnoreCase(cmd)) {
            debug("Killing JVM");
            System.exit(0);
          } else if ("status".equalsIgnoreCase(cmd)) {
            // Reply to client
            informClient(out, "OK\r\n");
          }
        } catch (Exception e) {
          debug(e);
          System.err.println(e.toString());
        } finally {
          close(socket);
          socket = null;
        }
      }
    }