/**
   * Dispatch a serialized command to the BackEnd and get back a serialized response. Mutual
   * exclusion with itself to preserve dispatching order
   */
  public synchronized byte[] dispatch(byte[] payload, boolean flush) throws ICPException {
    // Note that we don't even try to dispatch packets while the
    // device is not reachable to preserve dispatching order.
    // If dispatching succeeded in fact this command would overcome
    // any postponed command waiting to be flushed.
    if (myDisconnectionManager.isReachable()) {
      // The following check preserves dispatching order when the
      // device has just reconnected but flushing has not started yet
      if (waitingForFlush && !flush) {
        throw new ICPException("Upsetting dispatching order");
      }
      waitingForFlush = false;

      int sid = outCnt;
      outCnt = (outCnt + 1) & 0x0f;
      myLogger.log(Logger.FINE, "Issuing outgoing command " + sid);
      try {
        JICPPacket pkt =
            new JICPPacket(JICPProtocol.COMMAND_TYPE, JICPProtocol.DEFAULT_INFO, payload);
        pkt.setSessionID((byte) sid);
        pkt = deliver(pkt);
        myLogger.log(Logger.FINE, "Response received " + pkt.getSessionID());
        if (pkt.getType() == JICPProtocol.ERROR_TYPE) {
          // Communication OK, but there was a JICP error on the peer
          throw new ICPException(new String(pkt.getData()));
        }
        return pkt.getData();
      } catch (IOException ioe) {
        // Can't reach the BackEnd. Assume we are unreachable
        myLogger.log(Logger.WARNING, "IOException on output connection", ioe);
        myDisconnectionManager.setUnreachable(false);
        throw new ICPException("Dispatching error.", ioe);
      }
    } else {
      throw new ICPException("Unreachable");
    }
  }
 /**
  * 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();
   }
 }
  /**
   * Send the CREATE_MEDIATOR command with the necessary parameter in order to create the BackEnd in
   * the fixed network. Executed - at bootstrap time by the thread that creates the
   * FrontEndContainer. - To re-attach to the platform after a fault of the BackEnd
   */
  private synchronized void createBackEnd() throws IMTPException {
    StringBuffer sb = BackEndStub.encodeCreateMediatorRequest(props);
    if (myMediatorID != null) {
      // This is a request to re-create my expired back-end
      BackEndStub.appendProp(sb, JICPProtocol.MEDIATOR_ID_KEY, myMediatorID);
      BackEndStub.appendProp(sb, "outcnt", String.valueOf(outCnt));
      BackEndStub.appendProp(sb, "lastsid", String.valueOf(lastSid));
    }
    JICPPacket pkt =
        new JICPPacket(
            JICPProtocol.CREATE_MEDIATOR_TYPE,
            JICPProtocol.DEFAULT_INFO,
            null,
            sb.toString().getBytes());

    // Try first with the current transport address, then with the various backup addresses
    for (int i = -1; i < backEndAddresses.length; i++) {

      if (i >= 0) {
        // Set the mediator address to a new address..
        String addr = backEndAddresses[i];
        int colonPos = addr.indexOf(':');
        String host = addr.substring(0, colonPos);
        String port = addr.substring(colonPos + 1, addr.length());
        mediatorTA = new JICPAddress(host, port, myMediatorID, "");
      }

      try {
        HTTPClientConnection hc = (HTTPClientConnection) getConnection(mediatorTA);
        myLogger.log(
            Logger.INFO,
            "Creating BackEnd on "
                + hc.getProtocol()
                + mediatorTA.getHost()
                + ":"
                + mediatorTA.getPort());
        pkt = deliver(pkt);

        String replyMsg = new String(pkt.getData());
        if (pkt.getType() != JICPProtocol.ERROR_TYPE) {
          // BackEnd creation successful
          BackEndStub.parseCreateMediatorResponse(replyMsg, props);
          myMediatorID = props.getProperty(JICPProtocol.MEDIATOR_ID_KEY);
          // Complete the mediator address with the mediator ID
          mediatorTA =
              new JICPAddress(mediatorTA.getHost(), mediatorTA.getPort(), myMediatorID, null);
          myDisconnectionManager.setReachable();
          myKeepAliveManager.update();
          myLogger.log(Logger.INFO, "BackEnd OK. Mediator ID is " + myMediatorID);
          return;
        } else {
          myLogger.log(Logger.WARNING, "Mediator error: " + replyMsg);
        }
      } catch (IOException ioe) {
        // Ignore it, and try the next address...
        myLogger.log(Logger.WARNING, "Connection error", ioe);
      }
    }

    // No address succeeded!
    throw new IMTPException("Error creating the BackEnd.");
  }