/**
   * Creates a new SUBSCRIBE request in the form of a <tt>ClientTransaction</tt> with the parameters
   * of a specific <tt>Subscription</tt>.
   *
   * @param subscription the <tt>Subscription</tt> to be described in a SUBSCRIBE request
   * @param dialog the <tt>Dialog</tt> with which this request should be associated
   * @param expires the subscription duration of the SUBSCRIBE request to be created
   * @return a new <tt>ClientTransaction</tt> initialized with a new SUBSCRIBE request which matches
   *     the parameters of the specified <tt>Subscription</tt> and is associated with the specified
   *     <tt>Dialog</tt>
   * @throws OperationFailedException if the message could not be generated
   */
  private ClientTransaction createSubscription(
      Subscription subscription, Dialog dialog, int expires) throws OperationFailedException {
    Request req = messageFactory.createRequest(dialog, Request.SUBSCRIBE);

    // Address
    Address toAddress = dialog.getRemoteTarget();
    // no Contact field
    if (toAddress == null) toAddress = dialog.getRemoteParty();

    // MaxForwards
    MaxForwardsHeader maxForwards = protocolProvider.getMaxForwardsHeader();
    req.setHeader(maxForwards);

    /*
     * Create the transaction and then add the via header as recommended by
     * the jain-sip documentation at
     * http://snad.ncsl.nist.gov/proj/iptel/jain-sip-1.2/javadoc
     * /javax/sip/Dialog.html#createRequest(String).
     */
    ClientTransaction transac = null;
    try {
      transac = protocolProvider.getDefaultJainSipProvider().getNewClientTransaction(req);
    } catch (TransactionUnavailableException ex) {
      logger.error(
          "Failed to create subscriptionTransaction.\n"
              + "This is most probably a network connection error.",
          ex);
      throw new OperationFailedException(
          "Failed to create the subscription transaction",
          OperationFailedException.NETWORK_FAILURE);
    }

    populateSubscribeRequest(req, subscription, expires);

    return transac;
  }
  public void sendSubscribe(String localURL, String buddyURI, boolean EXPIRED) {
    try {
      logger.debug("Sending SUBSCRIBE in progress to the buddy: " + buddyURI);
      int proxyPort = imUA.getProxyPort();
      String proxyAddress = imUA.getProxyAddress();
      String imProtocol = imUA.getIMProtocol();
      SipStack sipStack = imUA.getSipStack();
      SipProvider sipProvider = imUA.getSipProvider();
      MessageFactory messageFactory = imUA.getMessageFactory();
      HeaderFactory headerFactory = imUA.getHeaderFactory();
      AddressFactory addressFactory = imUA.getAddressFactory();

      // Request-URI:
      // URI requestURI=addressFactory.createURI(buddyURI);
      SipURI requestURI = addressFactory.createSipURI(null, proxyAddress);
      requestURI.setPort(proxyPort);
      requestURI.setTransportParam(imProtocol);

      // Call-Id:
      CallIdHeader callIdHeader = null;

      // CSeq:
      CSeqHeader cseqHeader = null;

      // To header:
      ToHeader toHeader = null;

      // From Header:
      FromHeader fromHeader = null;

      // Via header
      String branchId = Utils.generateBranchId();
      ViaHeader viaHeader =
          headerFactory.createViaHeader(
              imUA.getIMAddress(), imUA.getIMPort(), imProtocol, branchId);
      Vector viaList = new Vector();
      viaList.addElement(viaHeader);

      PresenceManager presenceManager = imUA.getPresenceManager();
      Presentity presentity = presenceManager.getPresentity(buddyURI);
      Dialog dialog = null;
      if (presentity != null) dialog = presentity.getDialog();

      if (dialog != null) {

        // We have to remove the subscriber and the Presentity related
        // with this Buddy...
        presenceManager.removePresentity(buddyURI);
        Subscriber subscriber = presenceManager.getSubscriber(buddyURI);
        if (subscriber == null) {
          // It means that the guy does not have us in his buddy list
          // nothing to do!!!
        } else {
          presenceManager.removeSubscriber(buddyURI);
        }

        Address localAddress = dialog.getLocalParty();
        Address remoteAddress = dialog.getRemoteParty();

        fromHeader = headerFactory.createFromHeader(localAddress, dialog.getLocalTag());
        toHeader = headerFactory.createToHeader(remoteAddress, dialog.getRemoteTag());

        long cseq = dialog.getLocalSeqNumber();
        cseqHeader = headerFactory.createCSeqHeader(cseq, "MESSAGE");

        callIdHeader = dialog.getCallId();
      } else {
        String localTag = Utils.generateTag();

        Address toAddress = addressFactory.createAddress(buddyURI);
        Address fromAddress = addressFactory.createAddress(localURL);

        fromHeader = headerFactory.createFromHeader(fromAddress, localTag);
        toHeader = headerFactory.createToHeader(toAddress, null);

        // CSeq:
        cseqHeader = headerFactory.createCSeqHeader(1L, "SUBSCRIBE");

        callIdCounter++;
        // Call-ID:
        callIdHeader =
            (CallIdHeader)
                headerFactory.createCallIdHeader("nist-sip-im-subscribe-callId" + callIdCounter);
      }

      // MaxForwards header:
      MaxForwardsHeader maxForwardsHeader = headerFactory.createMaxForwardsHeader(70);

      Request request =
          messageFactory.createRequest(
              requestURI,
              "SUBSCRIBE",
              callIdHeader,
              cseqHeader,
              fromHeader,
              toHeader,
              viaList,
              maxForwardsHeader);

      RouteHeader rh = this.imUA.getRouteToProxy();
      request.setHeader(rh);

      // Contact header:
      SipURI sipURI = addressFactory.createSipURI(null, imUA.getIMAddress());
      sipURI.setPort(imUA.getIMPort());
      sipURI.setTransportParam(imUA.getIMProtocol());
      Address contactAddress = addressFactory.createAddress(sipURI);
      ContactHeader contactHeader = headerFactory.createContactHeader(contactAddress);
      request.setHeader(contactHeader);

      ExpiresHeader expiresHeader = null;
      if (EXPIRED) {
        expiresHeader = headerFactory.createExpiresHeader(0);
      } else {
        expiresHeader = headerFactory.createExpiresHeader(presenceManager.getExpiresTime());
      }
      request.setHeader(expiresHeader);

      // WE have to add a new Header: "Event"
      Header eventHeader = headerFactory.createHeader("Event", "presence");
      request.setHeader(eventHeader);

      // Add Acceptw Header
      Header acceptHeader = headerFactory.createHeader("Accept", "application/pidf+xml");
      request.setHeader(acceptHeader);

      // ProxyAuthorization header if not null:
      ProxyAuthorizationHeader proxyAuthHeader = imUA.getProxyAuthorizationHeader();
      if (proxyAuthHeader != null) request.setHeader(proxyAuthHeader);

      ClientTransaction clientTransaction = sipProvider.getNewClientTransaction(request);

      if (dialog != null) {
        dialog.sendRequest(clientTransaction);
      } else {
        clientTransaction.sendRequest();
      }

      logger.debug("IMSubscribeProcessing, sendSubscribe(), SUBSCRIBE sent:\n" + request);
    } catch (Exception ex) {
      ex.printStackTrace();
    }
  }
  public void sendMessage(
      String localSipURL, String remoteSipURL, String text, ChatSession chatSession) {
    try {
      DebugIM.println("IMMessageProcessing, ChatSession:" + chatSession);
      DebugIM.println("Sending a MESSAGE in progress to " + remoteSipURL);

      SipProvider sipProvider = imUA.getSipProvider();
      MessageFactory messageFactory = imUA.getMessageFactory();
      HeaderFactory headerFactory = imUA.getHeaderFactory();
      AddressFactory addressFactory = imUA.getAddressFactory();

      String proxyAddress = imUA.getProxyAddress();
      SipURI requestURI = null;
      if (proxyAddress != null) {
        requestURI = addressFactory.createSipURI(null, proxyAddress);
        requestURI.setPort(imUA.getProxyPort());
        requestURI.setTransportParam(imUA.getIMProtocol());
      } else {
        requestURI = (SipURI) addressFactory.createURI(remoteSipURL);
        requestURI.setTransportParam(imUA.getIMProtocol());
      }

      // Call-Id:
      CallIdHeader callIdHeader = null;

      // CSeq:
      CSeqHeader cseqHeader = null;

      // To header:
      ToHeader toHeader = null;

      // From Header:
      FromHeader fromHeader = null;

      //  Via header
      String branchId = Utils.generateBranchId();
      ViaHeader viaHeader =
          headerFactory.createViaHeader(
              imUA.getIMAddress(), imUA.getIMPort(), imUA.getIMProtocol(), branchId);
      Vector viaList = new Vector();
      viaList.addElement(viaHeader);

      // MaxForwards header:
      MaxForwardsHeader maxForwardsHeader = headerFactory.createMaxForwardsHeader(70);
      Dialog dialog = chatSession.getDialog();
      if (chatSession.isEstablishedSession()) {
        DebugIM.println(
            "DEBUG, IMMessageProcessing, sendMessage(), we get"
                + " the DIALOG from the ChatSession");

        Address localAddress = dialog.getLocalParty();
        Address remoteAddress = dialog.getRemoteParty();
        //  if (dialog.isServer()) {
        // We received the first MESSAGE
        fromHeader = headerFactory.createFromHeader(localAddress, dialog.getLocalTag());
        toHeader = headerFactory.createToHeader(remoteAddress, dialog.getRemoteTag());
        //  }
        //  else {

        //   }
        int cseq = dialog.getLocalSequenceNumber();
        DebugIM.println("the cseq number got from the dialog:" + cseq);
        cseqHeader = headerFactory.createCSeqHeader(cseq, "MESSAGE");

        callIdHeader = dialog.getCallId();

      } else {
        DebugIM.println(
            "DEBUG, IMMessageProcessing, sendMessage(), the "
                + " session has not been established yet! We create the first message");

        // To header:
        Address toAddress = addressFactory.createAddress(remoteSipURL);

        // From Header:
        Address fromAddress = addressFactory.createAddress(localSipURL);

        // We have to initiate the dialog: means to create the From tag
        String localTag = Utils.generateTag();
        fromHeader = headerFactory.createFromHeader(fromAddress, localTag);
        toHeader = headerFactory.createToHeader(toAddress, null);

        // CSeq:
        cseqHeader = headerFactory.createCSeqHeader(1, "MESSAGE");

        // Call-ID:
        callIdCounter++;
        callIdHeader =
            (CallIdHeader)
                headerFactory.createCallIdHeader("nist-sip-im-message-callId" + callIdCounter);
      }

      // Content-Type:
      ContentTypeHeader contentTypeHeader = headerFactory.createContentTypeHeader("text", "plain");
      contentTypeHeader.setParameter("charset", "UTF-8");

      Request request =
          messageFactory.createRequest(
              requestURI,
              "MESSAGE",
              callIdHeader,
              cseqHeader,
              fromHeader,
              toHeader,
              viaList,
              maxForwardsHeader,
              contentTypeHeader,
              text);

      // Contact header:
      SipURI sipURI = addressFactory.createSipURI(null, imUA.getIMAddress());
      sipURI.setPort(imUA.getIMPort());
      sipURI.setTransportParam(imUA.getIMProtocol());
      Address contactAddress = addressFactory.createAddress(sipURI);
      ContactHeader contactHeader = headerFactory.createContactHeader(contactAddress);
      request.setHeader(contactHeader);

      // ProxyAuthorization header if not null:
      ProxyAuthorizationHeader proxyAuthHeader = imUA.getProxyAuthorizationHeader();
      if (proxyAuthHeader != null) request.setHeader(proxyAuthHeader);

      ClientTransaction clientTransaction = sipProvider.getNewClientTransaction(request);

      if (chatSession.isEstablishedSession()) {
        dialog.sendRequest(clientTransaction);
        DebugIM.println(
            "IMessageProcessing, sendMessage(), MESSAGE sent" + " using the dialog:\n" + request);
      } else {
        clientTransaction.sendRequest();
        DebugIM.println(
            "IMessageProcessing, sendMessage(), MESSAGE sent"
                + " using a new client transaction:\n"
                + request);
      }

    } catch (Exception ex) {
      ex.printStackTrace();
    }
  }