/**
  * Send response with a result for a specific request message
  *
  * @param requestID the id of request to be responsed
  * @param result the result of invoked operation
  * @param destination the target endpoint
  */
 private void sendResponse(int requestID, Object result, String destination) {
   Response response =
       new Response(messageCount.incrementAndGet(), requestID, this.endpoint, result);
   XMLBuilder build = new XMLBuilder();
   String responseMessage = build.toXML(response);
   serviceProvider.sendMessage(responseMessage, destination);
 }
  /**
   * Send request to invoke a service with specific waiting time
   *
   * @param service the service name
   * @param destination the target endpoint
   * @param reply requires reply or not
   * @param responseTime the max time for waiting a reply
   * @param opName the invoked operation name
   * @param params parameters for the operation
   * @return the service result
   */
  public Object sendRequest(
      String service,
      String destination,
      boolean reply,
      long responseTime,
      String opName,
      Object... params) {
    try {
      int messageID = messageCount.incrementAndGet();
      Request request = new Request(messageID, this.endpoint, service, opName, params);
      XMLBuilder build = new XMLBuilder();
      String requestMessage = build.toXML(request);

      serviceProvider.sendMessage(requestMessage, destination);

      if (DEBUG) System.out.println("The request message is: \n" + requestMessage);

      if (reply) {
        synchronized (this) {
          if (responseTime == -1) {
            while (!results.containsKey(messageID)) {
              this.wait();
            }
          } else {
            long startTime = System.currentTimeMillis();
            while (!results.containsKey(messageID)) {
              this.wait(responseTime * Time.scale);
              long endTime = System.currentTimeMillis();
              if ((endTime - startTime) / Time.scale >= responseTime) {
                results.put(messageID, new TimeOutError());
              }
            }
          }
        }

        Object result = results.get(messageID);
        results.remove(messageID);
        return result != NullObject ? result : null;
      }
      return null;
    } catch (Exception e) {
      e.printStackTrace();
      return null;
    }
  }