@Override
  public void addContent(Request notifyRequest, SubscriptionRequest request)
      throws ParseException, InvalidArgumentException {
    String content = new String(request.getRequest().getRawContent(), StandardCharsets.UTF_8);

    UserPresence presence = presenceService.getPresence(request.getUser());

    if (isEmpty(content)) {
      ContentTypeHeader contentTypeHeader =
          headerFactory.createContentTypeHeader("multipart", "mixed");
      contentTypeHeader.setParameter(MultipartMimeContentImpl.BOUNDARY, SIPR_BOUNDARY);

      notifyRequest.setContent(
          getInitialMultipartContent(contentTypeHeader, presence).toString(), contentTypeHeader);
    } else {
      String eventResponse = getEventResponse(presence, content);
      presenceService.savePresence(presence);

      ContentTypeHeader eventHeader = getAsFeatureEventHeader();
      notifyRequest.setContent(eventResponse, eventHeader);
      sender.sendNotifyToAllSubscribers(request, eventHeader, eventResponse);
    }
  }
    /**
     * Process a request from a distant contact
     *
     * @param requestEvent the <tt>RequestEvent</tt> containing the newly received request.
     * @return <tt>true</tt> if the specified event has been handled by this processor and shouldn't
     *     be offered to other processors registered for the same method; <tt>false</tt>, otherwise
     */
    @Override
    public boolean processRequest(RequestEvent requestEvent) {
      synchronized (messageProcessors) {
        for (SipMessageProcessor listener : messageProcessors)
          if (!listener.processMessage(requestEvent)) return true;
      }

      // get the content
      String content = null;
      Request req = requestEvent.getRequest();
      try {

        content = new String(req.getRawContent(), getCharset(req));
      } catch (UnsupportedEncodingException ex) {
        if (logger.isDebugEnabled()) logger.debug("failed to convert the message charset");
        content = new String(requestEvent.getRequest().getRawContent());
      }

      // who sent this request ?
      FromHeader fromHeader = (FromHeader) requestEvent.getRequest().getHeader(FromHeader.NAME);

      if (fromHeader == null) {
        logger.error("received a request without a from header");
        return false;
      }

      Contact from =
          opSetPersPresence.resolveContactID(fromHeader.getAddress().getURI().toString());

      ContentTypeHeader ctheader = (ContentTypeHeader) req.getHeader(ContentTypeHeader.NAME);

      String ctype = null;
      String cencoding = null;

      if (ctheader == null) {
        ctype = DEFAULT_MIME_TYPE;
      } else {
        ctype = ctheader.getContentType() + "/" + ctheader.getContentSubType();
        cencoding = ctheader.getParameter("charset");
      }

      if (cencoding == null) cencoding = DEFAULT_MIME_ENCODING;

      Message newMessage = createMessage(content, ctype, cencoding, null);

      if (from == null) {
        if (logger.isDebugEnabled())
          logger.debug(
              "received a message from an unknown contact: "
                  + fromHeader.getAddress().getURI().toString());
        // create the volatile contact
        from = opSetPersPresence.createVolatileContact(fromHeader.getAddress().getURI().toString());
      }

      // answer ok
      try {
        Response ok =
            sipProvider.getMessageFactory().createResponse(Response.OK, requestEvent.getRequest());
        SipStackSharing.getOrCreateServerTransaction(requestEvent).sendResponse(ok);
      } catch (ParseException exc) {
        logger.error("failed to build the response", exc);
      } catch (SipException exc) {
        logger.error("failed to send the response : " + exc.getMessage(), exc);
      } catch (InvalidArgumentException exc) {
        if (logger.isDebugEnabled())
          logger.debug("Invalid argument for createResponse : " + exc.getMessage(), exc);
      }

      // fire an event
      MessageReceivedEvent msgReceivedEvt =
          new MessageReceivedEvent(newMessage, from, System.currentTimeMillis());
      fireMessageEvent(msgReceivedEvt);

      return true;
    }
  /**
   * Construct a <tt>Request</tt> represent a new message.
   *
   * @param to the <tt>Contact</tt> to send <tt>message</tt> to
   * @param message the <tt>Message</tt> to send.
   * @return a Message Request destined to the contact
   * @throws OperationFailedException if an error occurred during the creation of the request
   */
  Request createMessageRequest(Contact to, Message message) throws OperationFailedException {
    Address toAddress = null;
    try {
      toAddress = sipProvider.parseAddressString(to.getAddress());
    } catch (ParseException exc) {
      // Shouldn't happen
      logger.error("An unexpected error occurred while" + "constructing the address", exc);
      throw new OperationFailedException(
          "An unexpected error occurred while" + "constructing the address",
          OperationFailedException.INTERNAL_ERROR,
          exc);
    }

    // Call ID
    CallIdHeader callIdHeader = this.sipProvider.getDefaultJainSipProvider().getNewCallId();

    // CSeq
    CSeqHeader cSeqHeader = null;

    try {
      // protect seqN
      synchronized (this) {
        cSeqHeader = this.sipProvider.getHeaderFactory().createCSeqHeader(seqN++, Request.MESSAGE);
      }
    } catch (InvalidArgumentException ex) {
      // Shouldn't happen
      logger.error("An unexpected error occurred while" + "constructing the CSeqHeadder", ex);
      throw new OperationFailedException(
          "An unexpected error occurred while" + "constructing the CSeqHeadder",
          OperationFailedException.INTERNAL_ERROR,
          ex);
    } catch (ParseException exc) {
      // shouldn't happen
      logger.error("An unexpected error occurred while" + "constructing the CSeqHeadder", exc);
      throw new OperationFailedException(
          "An unexpected error occurred while" + "constructing the CSeqHeadder",
          OperationFailedException.INTERNAL_ERROR,
          exc);
    }

    // FromHeader and ToHeader
    String localTag = SipMessageFactory.generateLocalTag();
    FromHeader fromHeader = null;
    ToHeader toHeader = null;
    try {
      // FromHeader
      fromHeader =
          this.sipProvider
              .getHeaderFactory()
              .createFromHeader(sipProvider.getOurSipAddress(toAddress), localTag);

      // ToHeader
      toHeader = this.sipProvider.getHeaderFactory().createToHeader(toAddress, null);
    } catch (ParseException ex) {
      // these two should never happen.
      logger.error(
          "An unexpected error occurred while" + "constructing the FromHeader or ToHeader", ex);
      throw new OperationFailedException(
          "An unexpected error occurred while" + "constructing the FromHeader or ToHeader",
          OperationFailedException.INTERNAL_ERROR,
          ex);
    }

    // ViaHeaders
    ArrayList<ViaHeader> viaHeaders = this.sipProvider.getLocalViaHeaders(toAddress);

    // MaxForwards
    MaxForwardsHeader maxForwards = this.sipProvider.getMaxForwardsHeader();

    // Content params
    ContentTypeHeader contTypeHeader;
    ContentLengthHeader contLengthHeader;
    try {
      contTypeHeader =
          this.sipProvider
              .getHeaderFactory()
              .createContentTypeHeader(getType(message), getSubType(message));

      if (!DEFAULT_MIME_ENCODING.equalsIgnoreCase(message.getEncoding()))
        contTypeHeader.setParameter("charset", message.getEncoding());

      contLengthHeader =
          this.sipProvider.getHeaderFactory().createContentLengthHeader(message.getSize());
    } catch (ParseException ex) {
      // these two should never happen.
      logger.error("An unexpected error occurred while" + "constructing the content headers", ex);
      throw new OperationFailedException(
          "An unexpected error occurred while" + "constructing the content headers",
          OperationFailedException.INTERNAL_ERROR,
          ex);
    } catch (InvalidArgumentException exc) {
      // these two should never happen.
      logger.error(
          "An unexpected error occurred while" + "constructing the content length header", exc);
      throw new OperationFailedException(
          "An unexpected error occurred while" + "constructing the content length header",
          OperationFailedException.INTERNAL_ERROR,
          exc);
    }

    Request req;
    try {
      req =
          this.sipProvider
              .getMessageFactory()
              .createRequest(
                  toHeader.getAddress().getURI(),
                  Request.MESSAGE,
                  callIdHeader,
                  cSeqHeader,
                  fromHeader,
                  toHeader,
                  viaHeaders,
                  maxForwards,
                  contTypeHeader,
                  message.getRawData());
    } catch (ParseException ex) {
      // shouldn't happen
      logger.error("Failed to create message Request!", ex);
      throw new OperationFailedException(
          "Failed to create message Request!", OperationFailedException.INTERNAL_ERROR, ex);
    }

    req.addHeader(contLengthHeader);

    return req;
  }
  public void onPublishEvent(RequestEvent event, ActivityContextInterface aci) {

    if (isTraceable(TraceLevel.FINEST)) {
      finest("onPublishEvent: PublishSbb received request:\n" + event.getRequest());
    }

    Request request = event.getRequest();
    ServerTransaction st = event.getServerTransaction();
    String sipAddress =
        getCanonicalAddress(((ToHeader) request.getHeader(ToHeader.NAME)).getAddress().getURI());

    // Check that the resource identified by the request-URI is one that this server is responsible
    // for
    //  This will be achieved by checking that the resource has been registered with the Registrar
    try {
      if (getLocationService().getRegistration(sipAddress) == null) {
        sendErrorResponse(
            Response.NOT_FOUND,
            "Presentity identified by Request-URI '"
                + sipAddress
                + "' not registered with Registrar",
            st,
            request);
        return;
      }
    } catch (CreateException e) {
      warn("Error creating location service: ", e);
    }

    // Check that the event package is correct - should be 'presence'
    if (request.getHeader(EventHeader.NAME) != null) {
      String eventType = ((EventHeader) request.getHeader(EventHeader.NAME)).getEventType();
      if (!eventType.equals("presence")) {
        sendErrorResponse(
            Response.BAD_EVENT,
            "PUBLISH request received with incorrect event package, package was '"
                + eventType
                + "', expected 'presence'",
            st,
            request);
        return;
      }
    }

    // Check for and validate SIP-If-Match header
    String eTag = null;
    String newETag = (new Integer((int) (Math.random() * 10000))).toString();

    if ((SIPIfMatchHeader) request.getHeader(SIPIfMatchHeader.NAME) != null) {

      // Found a SIP-If-Match header, retrieve E-Tag
      SIPIfMatchHeader sipIfMatchHeader =
          (SIPIfMatchHeader) request.getHeader(SIPIfMatchHeader.NAME);
      eTag = sipIfMatchHeader.getETag();
      if (isTraceable(TraceLevel.FINEST)) {
        finest("onPublishEvent: found E-Tag: " + eTag);
      }
      // Check that the entity-tag matches an entity-tag stored by the server
      if (!entityTagIsKnownByServer(sipAddress, eTag)) {
        if (isTraceable(TraceLevel.FINEST)) {
          finest("onPublishEvent: E-Tag '" + eTag + "' not recognised by server");
        }
        sendErrorResponse(
            Response.CONDITIONAL_REQUEST_FAILED,
            "Entity-tag is not known to this server, value of entity-tag is: " + eTag,
            st,
            request);
        return;
      }
    }

    // Validate requested Expiry time
    long expiryTime = validateExpireTime(request);
    // Check for correct media type
    if (request.getContent() != null && request.getHeader(ContentTypeHeader.NAME) != null) {
      ContentTypeHeader contentTypeHeader =
          (ContentTypeHeader) request.getHeader(ContentTypeHeader.NAME);
      if (!contentTypeHeader.getContentType().equalsIgnoreCase("application")
          || (!contentTypeHeader.getContentSubType().equalsIgnoreCase("pidf+xml"))) {
        sendErrorResponse(Response.UNSUPPORTED_MEDIA_TYPE, "Uncrecognised media type", st, request);
        return;
      }
    }

    // Process the PUBLISH request
    String body = request.toString();
    if (expiryTime == 0) {
      // this is a request to remove all stored presence information associated with this entity-tag
      if (eTag == null) {
        // this is a mal-formed request - can't remove presence information if it was never
        // published in the first place!
        sendErrorResponse(
            Response.BAD_REQUEST,
            "Received request to remove presence information, but no entity-tag was provided",
            st,
            request);
        return;
      } else {
        updatePresenceState(
            sipAddress, newETag, eTag, body, System.currentTimeMillis(), new Long(expiryTime));
      }
    } else {
      // this is either an initial request, or a request to modify or refresh a previous publication
      // get the body of PUBLISH request, if it has one

      if (eTag == null) {
        // this an initial request, make sure there's a body containing some presence info
        if (request.getContent() != null) {
          updatePresenceState(
              sipAddress,
              newETag,
              null,
              body,
              System.currentTimeMillis(),
              System.currentTimeMillis() + (expiryTime * 1000));
        } else {
          sendErrorResponse(
              Response.BAD_REQUEST,
              "Received initial PUBLISH request, but no presence information was provided",
              st,
              request);
          return;
        }
      } else {
        // this is either a request to refresh the publication (no body), or to modify or refresh
        // the published presence info
        updatePresenceState(
            sipAddress,
            newETag,
            eTag,
            (body != null ? body.toString() : null),
            System.currentTimeMillis(),
            System.currentTimeMillis() + (expiryTime * 1000));
      }
    }

    // if this point is reached, all processing has been successfully undertaken, so return a 200 OK
    // response
    sendOkResponse(st, request, (int) expiryTime, newETag);
  }
  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();
    }
  }
  /**
   * Starts the process of handling a new sip subscription
   *
   * @param event
   * @param aci
   * @param eventPackage
   * @param eventId
   * @param expires
   * @param entityManager
   * @param childSbb
   */
  public void newSipSubscription(
      RequestEvent event,
      ActivityContextInterface aci,
      String eventPackage,
      String eventId,
      int expires,
      SubscriptionControlDataSource dataSource,
      ImplementedSubscriptionControlSbbLocalObject childSbb) {

    // get subscription data from request
    Address fromAddress = ((FromHeader) event.getRequest().getHeader(FromHeader.NAME)).getAddress();
    String subscriber = fromAddress.getURI().toString();
    String subscriberDisplayName = fromAddress.getDisplayName();

    Notifier notifier = new Notifier(event.getRequest().getRequestURI().toString());

    // get content
    String content = null;
    String contentType = null;
    String contentSubtype = null;
    ContentTypeHeader contentTypeHeader =
        (ContentTypeHeader) event.getRequest().getHeader(ContentTypeHeader.NAME);
    if (contentTypeHeader != null) {
      contentType = contentTypeHeader.getContentType();
      contentSubtype = contentTypeHeader.getContentSubType();
      content = new String(event.getRequest().getRawContent());
    }

    // create dialog if does not exists
    Dialog dialog = event.getDialog();
    if (dialog == null) {
      try {
        dialog =
            sipSubscriptionHandler.sbb.getSipProvider().getNewDialog(event.getServerTransaction());
      } catch (Exception e) {
        tracer.severe("Can't create dialog", e);
        // cleanup
        try {
          Response response =
              sipSubscriptionHandler
                  .sbb
                  .getMessageFactory()
                  .createResponse(Response.SERVER_INTERNAL_ERROR, event.getRequest());
          response = sipSubscriptionHandler.addContactHeader(response);
          event.getServerTransaction().sendResponse(response);
        } catch (Exception f) {
          tracer.severe("Can't send RESPONSE", f);
        }
        return;
      }
    }

    // if dialog id is null (cause it's a new dialog and no response was sent yet) then build it
    // manually
    String dialogId =
        dialog.getDialogId() != null
            ? dialog.getDialogId()
            : ((SIPRequest) event.getRequest()).getDialogId(true, dialog.getLocalTag());
    SubscriptionKey key = new SubscriptionKey(dialogId, eventPackage, eventId);

    if (sipSubscriptionHandler.sbb.getConfiguration().getEventListSupportOn()) {
      // we need to find out if the notifier is a resource list
      int rlsResponse =
          sipSubscriptionHandler
              .sbb
              .getEventListSubscriptionHandler()
              .validateSubscribeRequest(subscriber, notifier, eventPackage, event);

      switch (rlsResponse) {
        case Response.NOT_FOUND:
          // the notifier is not a resource list, proceed with normal authorization means
          authorizeNewSipSubscription(
              event,
              aci,
              subscriber,
              subscriberDisplayName,
              notifier,
              key,
              expires,
              content,
              contentType,
              contentSubtype,
              false,
              dataSource,
              childSbb);
          break;
        case Response.OK:
          // the notifier is a resource list
          authorizeNewSipSubscription(
              event,
              aci,
              subscriber,
              subscriberDisplayName,
              notifier,
              key,
              expires,
              content,
              contentType,
              contentSubtype,
              true,
              dataSource,
              childSbb);
          break;
        default:
          // the rls request validation returned an error
          try {
            Response response =
                sipSubscriptionHandler
                    .sbb
                    .getMessageFactory()
                    .createResponse(rlsResponse, event.getRequest());
            response = sipSubscriptionHandler.addContactHeader(response);
            response.addHeader(
                sipSubscriptionHandler.sbb.getHeaderFactory().createRequireHeader("eventlist"));
            event.getServerTransaction().sendResponse(response);
          } catch (Exception f) {
            tracer.severe("Can't send RESPONSE", f);
          }
          return;
      }
    } else {
      authorizeNewSipSubscription(
          event,
          aci,
          subscriber,
          subscriberDisplayName,
          notifier,
          key,
          expires,
          content,
          contentType,
          contentSubtype,
          false,
          dataSource,
          childSbb);
    }
  }
  /**
   * Implements {@link MethodProcessor#processRequest(RequestEvent)}. Handles only NOTIFY requests
   * because they are the only requests concerning event package subscribers and if the processing
   * of a given request requires event package-specific handling, delivers the request to the
   * matching Subscription instance. Examples of such event package-specific handling include
   * handling the termination of an existing Subscription and processing the bodies of the NOTIFY
   * requests for active Subscriptions.
   *
   * @param requestEvent a <tt>RequestEvent</tt> specifying the SIP <tt>Request</tt> to be processed
   * @return <tt>true</tt> if the SIP <tt>Request</tt> specified by <tt>requestEvent</tt> was
   *     processed; otherwise, <tt>false</tt>
   */
  @Override
  public boolean processRequest(RequestEvent requestEvent) {
    Request request = requestEvent.getRequest();

    EventHeader eventHeader = (EventHeader) request.getHeader(EventHeader.NAME);
    if ((eventHeader == null) || !eventPackage.equalsIgnoreCase(eventHeader.getEventType())) {
      /*
       * We are not concerned by this request, perhaps another listener
       * is. So don't send a 489 / Bad event answer here.
       */
      return false;
    }

    if (!Request.NOTIFY.equals(request.getMethod())) return false;

    if (logger.isDebugEnabled()) logger.debug("notify received");

    SubscriptionStateHeader sstateHeader =
        (SubscriptionStateHeader) request.getHeader(SubscriptionStateHeader.NAME);
    // notify must contain one (rfc3265)
    if (sstateHeader == null) {
      logger.error("no subscription state in this request");
      return false;
    }
    String sstate = sstateHeader.getState();

    ServerTransaction serverTransaction = getOrCreateServerTransaction(requestEvent);

    // first handle the case of a contact still pending
    // it's possible if the NOTIFY arrives before the OK
    CallIdHeader callIdHeader = (CallIdHeader) request.getHeader(CallIdHeader.NAME);
    String callId = callIdHeader.getCallId();
    Subscription subscription = getSubscription(callId);

    // see if the notify correspond to an existing subscription
    if ((subscription == null) && !SubscriptionStateHeader.TERMINATED.equalsIgnoreCase(sstate)) {
      if (logger.isDebugEnabled()) logger.debug("subscription not found for callId " + callId);

      // send a 481 response (rfc3625)
      Response response;
      try {
        response =
            protocolProvider
                .getMessageFactory()
                .createResponse(Response.CALL_OR_TRANSACTION_DOES_NOT_EXIST, request);
      } catch (ParseException e) {
        logger.error("failed to create the 481 response", e);
        return false;
      }

      try {
        serverTransaction.sendResponse(response);
      } catch (SipException e) {
        logger.error("failed to send the response", e);
      } catch (InvalidArgumentException e) {
        // should not happen
        logger.error("invalid argument provided while trying to send the response", e);
      }
      return true;
    }

    // if we don't understand the content
    ContentTypeHeader ctheader = (ContentTypeHeader) request.getHeader(ContentTypeHeader.NAME);
    if ((ctheader != null) && !ctheader.getContentSubType().equalsIgnoreCase(contentSubType)) {
      // send a 415 response (rfc3261)
      Response response;
      try {
        response =
            protocolProvider
                .getMessageFactory()
                .createResponse(Response.UNSUPPORTED_MEDIA_TYPE, request);
      } catch (ParseException e) {
        logger.error("failed to create the OK response", e);
        return false;
      }

      // we want PIDF
      AcceptHeader acceptHeader;
      try {
        acceptHeader =
            protocolProvider.getHeaderFactory().createAcceptHeader("application", contentSubType);
      } catch (ParseException e) {
        // should not happen
        logger.error("failed to create the accept header", e);
        return false;
      }
      response.setHeader(acceptHeader);

      try {
        serverTransaction.sendResponse(response);
      } catch (SipException e) {
        logger.error("failed to send the response", e);
      } catch (InvalidArgumentException e) {
        // should not happen
        logger.error("invalid argument provided while trying" + " to send the response", e);
      }
    }

    // if the presentity doesn't want of us anymore
    if (SubscriptionStateHeader.TERMINATED.equalsIgnoreCase(sstate)) {
      // if we requested this end of subscription, subscription == null
      if (subscription != null) {
        removeSubscription(callId, subscription);
        subscription.processTerminatedRequest(requestEvent, sstateHeader.getReasonCode());
      }
    }

    // send an OK response
    Response response;
    try {
      response = protocolProvider.getMessageFactory().createResponse(Response.OK, request);
    } catch (ParseException e) {
      logger.error("failed to create the OK response", e);
      return false;
    }

    try {
      serverTransaction.sendResponse(response);
    } catch (SipException e) {
      logger.error("failed to send the response", e);
    } catch (InvalidArgumentException e) {
      // should not happen
      logger.error("invalid argument provided while trying to send the response", e);
    }

    // transform the presence document in new presence status
    if (subscription != null)
      subscription.processActiveRequest(requestEvent, request.getRawContent());

    return true;
  }