/**
  * Make this HTTPFEDispatcher terminate. Note that when the BackEnd receives the termination
  * notification (explicitly sent in case of a self-initiated shutdown or attached to the response
  * to the EXIT command), it closes the input connection. The InputManager gets an exception and,
  * since it has been killed, terminates.
  */
 public void shutdown() {
   terminator = Thread.currentThread();
   myLogger.log(
       Logger.INFO,
       "Dispatcher shutting down. Self-initiated = " + (terminator != myInputManager));
   if (terminator != myInputManager) {
     // Self-initiated shut down
     // If connected, explicitly notify the BackEnd.
     if (myDisconnectionManager.isReachable()) {
       JICPPacket pkt =
           new JICPPacket(JICPProtocol.COMMAND_TYPE, (byte) (JICPProtocol.DEFAULT_INFO), null);
       myLogger.log(Logger.INFO, "Pushing termination notification");
       try {
         deliver(pkt);
       } catch (IOException ioe) {
         // When the BackEnd receives the termination notification,
         // it just closes the connection --> we always have this exception
         myLogger.log(Logger.FINE, "BackEnd closed");
       }
     }
     // Kill the InputManager
     myInputManager.kill();
   }
 }
  /** Create a BackEnd in the fixed network and return a stub to communicate with it */
  public BackEnd getBackEnd(FrontEnd fe, Properties p) throws IMTPException {
    props = p;

    beAddrsText = props.getProperty(FrontEnd.REMOTE_BACK_END_ADDRESSES);
    backEndAddresses = parseBackEndAddresses(beAddrsText);

    // Host
    String host = props.getProperty("host");
    if (host == null) {
      host = "localhost";
    }
    // Port
    int port = JICPProtocol.DEFAULT_PORT;
    try {
      port = Integer.parseInt(props.getProperty("port"));
    } catch (NumberFormatException nfe) {
      // Use default
    }
    // Compose URL. Note that we build a JICPAddress just to avoid loading the HTTPAddress class.
    mediatorTA = JICPProtocol.getInstance().buildAddress(host, String.valueOf(port), null, null);

    // Mediator class
    String tmp = props.getProperty(JICPProtocol.MEDIATOR_CLASS_KEY);
    if (tmp != null) {
      myMediatorClass = tmp;
    } else {
      // Set the default mediator class since this must be propagated to the mediator.
      props.setProperty(JICPProtocol.MEDIATOR_CLASS_KEY, myMediatorClass);
    }

    // Read re-connection retry time
    long retryTime = JICPProtocol.DEFAULT_RETRY_TIME;
    try {
      retryTime = Long.parseLong(props.getProperty(JICPProtocol.RECONNECTION_RETRY_TIME_KEY));
    } catch (Exception e) {
      // Use default
    }

    // Read Max disconnection time
    maxDisconnectionTime = JICPProtocol.DEFAULT_MAX_DISCONNECTION_TIME;
    try {
      maxDisconnectionTime =
          Long.parseLong(props.getProperty(JICPProtocol.MAX_DISCONNECTION_TIME_KEY));
    } catch (Exception e) {
      // Use default
      props.setProperty(
          JICPProtocol.MAX_DISCONNECTION_TIME_KEY, String.valueOf(maxDisconnectionTime));
    }

    // Read Keep-alive time
    keepAliveTime = JICPProtocol.DEFAULT_KEEP_ALIVE_TIME;
    try {
      keepAliveTime = Long.parseLong(props.getProperty(JICPProtocol.KEEP_ALIVE_TIME_KEY));
    } catch (Exception e) {
      // Use default
      props.setProperty(JICPProtocol.KEEP_ALIVE_TIME_KEY, String.valueOf(keepAliveTime));
    }

    if (myLogger.isLoggable(Logger.CONFIG)) {
      myLogger.log(Logger.CONFIG, "Remote URL = http://" + host + ":" + port);
      myLogger.log(Logger.CONFIG, "Mediator class = " + myMediatorClass);
      myLogger.log(Logger.CONFIG, "Reconnection retry time = " + retryTime);
      myLogger.log(Logger.CONFIG, "Max disconnection time = " + maxDisconnectionTime);
      myLogger.log(Logger.CONFIG, "Keep-alive time = " + keepAliveTime);
    }

    myDisconnectionManager = new DisconnectionManager(retryTime, maxDisconnectionTime);
    myKeepAliveManager = new KeepAliveManager(keepAliveTime);
    myInputManager = new InputManager();

    // Read the owner if any
    owner = props.getProperty("owner");

    // Create the BackEnd stub and the FrontEnd skeleton
    myStub = new BackEndStub(this);
    mySkel = new FrontEndSkel(fe);

    // Start the InputManager
    myInputManager.start();

    // Create the remote BackEnd
    createBackEnd();

    return myStub;
  }