/**
   * Make the actual CORBA call.
   *
   * @param serverName Name of the server as known in the COS Naming Service.
   * @param reload Flag indicating whether object reference should be refreshed (true) or any
   *     previously-cached version should be used (false).
   * @param header Header message to send.
   * @param message Body message to send.
   * @return Response that caller should return.
   * @exception Exception Thrown on any errors.
   */
  private String makeClientCall(String serverName, boolean reload, String header, String message)
      throws Exception {
    ORB orb = null;

    // If the alternate ip and port are provided
    if (StringUtils.hasValue(orbAgentAddr) && StringUtils.hasValue(orbAgentPort)) {
      // Key to store the orb in a static map for access the next time around
      String key = orbAgentAddr + ":" + orbAgentPort;

      synchronized (orbStore) {
        orb = (ORB) orbStore.get(key);

        if (orb == null) {
          Properties props = new Properties();
          props.put(ORB_AGENT_ADDR_PROP, orbAgentAddr);
          props.put(ORB_AGENT_PORT_PROP, orbAgentPort);
          orb = new CorbaPortabilityLayer(new String[0], props, null, serverName).getORB();

          orbStore.put(key, orb);
        } else {
          if (Debug.isLevelEnabled(Debug.IO_STATUS))
            Debug.log(
                Debug.IO_STATUS,
                "Using cached orb with properties "
                    + "ORBagentAddr = ["
                    + orbAgentAddr
                    + "] ORBagentPort = ["
                    + orbAgentPort
                    + "]");
        }
      }
    } else {
      if (Debug.isLevelEnabled(Debug.IO_STATUS))
        Debug.log(Debug.IO_STATUS, "Using the default orb ..");

      orb = Supervisor.getSupervisor().getCPL().getORB();
    }

    ObjectLocator ob_loc = new ObjectLocator(orb);

    if (reload) {
      ob_loc.removeFromCache(serverName);
      if (StringUtils.hasValue(orbAgentAddr) && StringUtils.hasValue(orbAgentPort))
        ob_loc.removeFromCache(serverName, orbAgentAddr, orbAgentPort);
    }

    RequestHandler rh = null;
    // The key corresponding to secondary install object references depends on host address and port
    // too.
    if (StringUtils.hasValue(orbAgentAddr) && StringUtils.hasValue(orbAgentPort))
      rh = RequestHandlerHelper.narrow(ob_loc.find(serverName, orbAgentAddr, orbAgentPort));
    else rh = RequestHandlerHelper.narrow(ob_loc.find(serverName));

    if (rh == null) {
      throw new Exception("Object named [" + serverName + "] is not of IDL type RequestHandler.");
    }

    // Make sure that the header contains any available customer context information.
    header = CustomerContext.getInstance().propagate(header);

    if (Debug.isLevelEnabled(Debug.IO_STATUS))
      Debug.log(Debug.IO_STATUS, "Header value:\n" + header);

    ThreadMonitor.ThreadInfo tmti =
        ThreadMonitor.start(
            "Message-processor ["
                + getName()
                + "] making CORBA client call with header:\n"
                + header);

    try {
      if (isAsync) {
        rh.processAsync(header, message);

        return (message);
      } else {
        org.omg.CORBA.StringHolder response = new org.omg.CORBA.StringHolder("");

        rh.processSync(header, message, response);

        return (response.value);
      }
    } finally {
      ThreadMonitor.stop(tmti);
    }
  }