@SuppressWarnings("unchecked")
  public Packet secureResponse(Packet retPacket, Subject serviceSubject, Map sharedState)
      throws XWSSecurityException {

    boolean isSCIssueMessage = (sharedState.get("IS_SC_ISSUE") != null) ? true : false;
    boolean isSCCancelMessage = (sharedState.get("IS_SC_CANCEL") != null) ? true : false;
    boolean isTrustMessage = (sharedState.get("IS_TRUST_MESSAGE") != null) ? true : false;

    Packet packet = (Packet) sharedState.get("VALIDATE_REQ_PACKET");
    Boolean thereWasAFaultSTR = (Boolean) sharedState.get("THERE_WAS_A_FAULT");
    boolean thereWasAFault = (thereWasAFaultSTR != null) ? thereWasAFaultSTR.booleanValue() : false;

    if (thereWasAFault) {
      return retPacket;
    }

    /* TODO:this piece of code present since payload should be read once*/
    if (!optimized) {
      try {
        SOAPMessage sm = retPacket.getMessage().readAsSOAPMessage();
        Message newMsg = Messages.create(sm);
        retPacket.setMessage(newMsg);
      } catch (SOAPException ex) {
        throw new WebServiceException(ex);
      }
    }

    // ---------------OUTBOUND SECURITY PROCESSING----------
    ProcessingContext ctx = initializeOutgoingProcessingContext(retPacket, isSCIssueMessage);
    ctx.setExtraneousProperty("SessionManager", sessionManager);
    Message msg = retPacket.getMessage();

    try {

      if (ctx.getSecurityPolicy() != null && ((MessagePolicy) ctx.getSecurityPolicy()).size() > 0) {
        if (!optimized) {
          SOAPMessage soapMessage = msg.readAsSOAPMessage();
          soapMessage = secureOutboundMessage(soapMessage, ctx);
          msg = Messages.create(soapMessage);
        } else {
          msg = secureOutboundMessage(msg, ctx);
        }
      }
    } catch (WssSoapFaultException ex) {
      sharedState.put("THERE_WAS_A_FAULT", Boolean.valueOf(true));
      msg = Messages.create(getSOAPFault(ex));
    } catch (SOAPException se) {
      // internal error
      log.log(Level.SEVERE, LogStringsMessages.WSITPVD_0029_ERROR_SECURING_OUTBOUND_MSG(), se);
      throw new WebServiceException(
          LogStringsMessages.WSITPVD_0029_ERROR_SECURING_OUTBOUND_MSG(), se);
    } finally {
      if (isSCCancel(retPacket)) {
        removeContext(packet);
      }
    }
    resetCachedOperation(retPacket);
    retPacket.setMessage(msg);
    return retPacket;
  }
  protected final Message createSoapFaultMessage(
      RuntimeContext rc, boolean attachSequenceFaultElement) {
    try {
      // TODO P1 where to set soap fault code?
      SOAPFault soapFault = rc.soapVersion.saajSoapFactory.createFault();

      // common SOAP1.1 and SOAP1.2 Fault settings
      if (faultReasonText != null) {
        soapFault.setFaultString(faultReasonText, java.util.Locale.ENGLISH);
      }

      soapFault.setFaultCode(getCode().asQName(rc.soapVersion));

      // SOAP version-specific SOAP Fault settings
      switch (rc.soapVersion) {
        case SOAP_11:
          break;
        case SOAP_12:
          soapFault.appendFaultSubcode(getSubcode(rc.rmVersion));
          soapFault.addDetail().setValue(getDetailValue());
          break;
        default:
          throw new RxRuntimeException(
              "Unsupported SOAP version: '" + rc.soapVersion.toString() + "'");
      }

      Message soapFaultMessage = Messages.create(soapFault);

      if (attachSequenceFaultElement && rc.soapVersion == SOAPVersion.SOAP_11) {
        soapFaultMessage
            .getHeaders()
            .add(
                rc.protocolHandler.createSequenceFaultElementHeader(
                    getSubcode(rc.rmVersion), getDetailValue()));
      }

      return soapFaultMessage;

    } catch (SOAPException ex) {
      throw new RxRuntimeException("Error creating a SOAP fault", ex);
    }
  }
  // The packet has the Message with RST/SCT inside it
  // TODO: Need to inspect if it is really a Issue or a Cancel
  private Packet invokeSecureConversationContract(
      Packet packet, ProcessingContext ctx, boolean isSCTIssue) {

    IssuedTokenContext ictx = new IssuedTokenContextImpl();
    ictx.getOtherProperties().put("SessionManager", sessionManager);
    Message msg = packet.getMessage();
    Message retMsg = null;
    String retAction = null;

    try {

      // Set the requestor authenticated Subject in the IssuedTokenContext
      Subject subject = SubjectAccessor.getRequesterSubject(ctx);
      ictx.setRequestorSubject(subject);

      WSTrustElementFactory wsscEleFac = WSTrustElementFactory.newInstance(wsscVer);
      JAXBElement rstEle =
          msg.readPayloadAsJAXB(WSTrustElementFactory.getContext(wsTrustVer).createUnmarshaller());
      BaseSTSRequest rst = wsscEleFac.createRSTFrom(rstEle);

      URI requestType = ((RequestSecurityToken) rst).getRequestType();
      BaseSTSResponse rstr = null;
      WSSCContract scContract = WSSCFactory.newWSSCContract(wsscVer);
      scContract.setWSSCServerConfig(
          (Iterator)
              packet.invocationProperties.get(
                  com.sun.xml.ws.security.impl.policy.Constants
                      .SUN_SECURE_SERVER_CONVERSATION_POLICY_NS));
      if (requestType.toString().equals(wsTrustVer.getIssueRequestTypeURI())) {
        List<PolicyAssertion> policies = getOutBoundSCP(packet.getMessage());
        rstr = scContract.issue(rst, ictx, (SecureConversationToken) policies.get(0));
        retAction = wsscVer.getSCTResponseAction();
        SecurityContextToken sct = (SecurityContextToken) ictx.getSecurityToken();
        String sctId = sct.getIdentifier().toString();

        Session session = sessionManager.getSession(sctId);
        if (session == null) {
          log.log(Level.SEVERE, LogStringsMessages.WSITPVD_0044_ERROR_SESSION_CREATION());
          throw new WSSecureConversationException(
              LogStringsMessages.WSITPVD_0044_ERROR_SESSION_CREATION());
        }

        // Put it here for RM to pick up
        packet.invocationProperties.put(Session.SESSION_ID_KEY, sctId);

        packet.invocationProperties.put(Session.SESSION_KEY, session.getUserData());

        IssuedTokenContext itctx = session.getSecurityInfo().getIssuedTokenContext();
        // add the subject of requestor
        itctx.setRequestorSubject(ictx.getRequestorSubject());
        // ((ProcessingContextImpl)ctx).getIssuedTokenContextMap().put(sctId, itctx);

      } else if (requestType.toString().equals(wsTrustVer.getRenewRequestTypeURI())) {
        List<PolicyAssertion> policies = getOutBoundSCP(packet.getMessage());
        retAction = wsscVer.getSCTRenewResponseAction();
        rstr = scContract.renew(rst, ictx, (SecureConversationToken) policies.get(0));
      } else if (requestType.toString().equals(wsTrustVer.getCancelRequestTypeURI())) {
        retAction = wsscVer.getSCTCancelResponseAction();
        rstr = scContract.cancel(rst, ictx);
      } else {
        log.log(
            Level.SEVERE,
            LogStringsMessages.WSITPVD_0045_UNSUPPORTED_OPERATION_EXCEPTION(requestType));
        throw new UnsupportedOperationException(
            LogStringsMessages.WSITPVD_0045_UNSUPPORTED_OPERATION_EXCEPTION(requestType));
      }

      // construct the complete message here containing the RSTR and the
      // correct Action headers if any and return the message.
      retMsg =
          Messages.create(
              WSTrustElementFactory.getContext(wsTrustVer).createMarshaller(),
              wsscEleFac.toJAXBElement(rstr),
              soapVersion);

    } catch (javax.xml.bind.JAXBException ex) {
      log.log(Level.SEVERE, LogStringsMessages.WSITPVD_0001_PROBLEM_MAR_UNMAR(), ex);
      throw new RuntimeException(LogStringsMessages.WSITPVD_0001_PROBLEM_MAR_UNMAR(), ex);
    } catch (com.sun.xml.wss.XWSSecurityException ex) {
      log.log(Level.SEVERE, LogStringsMessages.WSITPVD_0046_ERROR_INVOKE_SC_CONTRACT(), ex);
      throw new RuntimeException(LogStringsMessages.WSITPVD_0046_ERROR_INVOKE_SC_CONTRACT(), ex);
    } catch (WSSecureConversationException ex) {
      log.log(Level.SEVERE, LogStringsMessages.WSITPVD_0046_ERROR_INVOKE_SC_CONTRACT(), ex);
      throw new RuntimeException(LogStringsMessages.WSITPVD_0046_ERROR_INVOKE_SC_CONTRACT(), ex);
    }

    // SecurityContextToken sct = (SecurityContextToken)ictx.getSecurityToken();
    // String sctId = sct.getIdentifier().toString();
    // ((ProcessingContextImpl)ctx).getIssuedTokenContextMap().put(sctId, ictx);

    Packet retPacket = addAddressingHeaders(packet, retMsg, retAction);
    if (isSCTIssue) {
      List<PolicyAssertion> policies = getOutBoundSCP(packet.getMessage());

      if (!policies.isEmpty()) {
        retPacket.invocationProperties.put(SC_ASSERTION, (PolicyAssertion) policies.get(0));
      }
    }

    return retPacket;
  }
  public Packet validateRequest(
      Packet packet, Subject clientSubject, Subject serviceSubject, Map<Object, Object> sharedState)
      throws XWSSecurityException {

    Message msg = packet.getMessage();

    boolean isSCIssueMessage = false;
    boolean isSCCancelMessage = false;
    boolean isTrustMessage = false;
    String msgId = null;
    String action = null;

    boolean thereWasAFault = false;

    // Do Security Processing for Incoming Message

    // ---------------INBOUND SECURITY VERIFICATION----------
    ProcessingContext ctx = initializeInboundProcessingContext(packet);

    // update the client subject passed to the AuthModule itself.
    ctx.setExtraneousProperty(MessageConstants.AUTH_SUBJECT, clientSubject);
    ctx.setExtraneousProperty(
        ProcessingContext.OPERATION_RESOLVER,
        new PolicyResolverImpl(
            inMessagePolicyMap,
            inProtocolPM,
            cachedOperation(packet),
            pipeConfig,
            addVer,
            false,
            rmVer));
    ctx.setExtraneousProperty("SessionManager", sessionManager);
    try {
      if (!optimized) {
        SOAPMessage soapMessage = msg.readAsSOAPMessage();
        soapMessage = verifyInboundMessage(soapMessage, ctx);
        msg = Messages.create(soapMessage);
      } else {
        msg = verifyInboundMessage(msg, ctx);
      }
    } catch (WssSoapFaultException ex) {
      log.log(Level.SEVERE, LogStringsMessages.WSITPVD_0035_ERROR_VERIFY_INBOUND_MSG(), ex);
      thereWasAFault = true;
      SOAPFaultException sfe = SOAPUtil.getSOAPFaultException(ex, soapFactory, soapVersion);
      msg = Messages.create(sfe, soapVersion);
    } catch (XWSSecurityException xwse) {
      log.log(Level.SEVERE, LogStringsMessages.WSITPVD_0035_ERROR_VERIFY_INBOUND_MSG(), xwse);
      thereWasAFault = true;
      SOAPFaultException sfe = SOAPUtil.getSOAPFaultException(xwse, soapFactory, soapVersion);
      msg = Messages.create(sfe, soapVersion);

    } catch (XWSSecurityRuntimeException xwse) {
      log.log(Level.SEVERE, LogStringsMessages.WSITPVD_0035_ERROR_VERIFY_INBOUND_MSG(), xwse);
      thereWasAFault = true;
      SOAPFaultException sfe = SOAPUtil.getSOAPFaultException(xwse, soapFactory, soapVersion);
      msg = Messages.create(sfe, soapVersion);

    } catch (WebServiceException xwse) {
      log.log(Level.SEVERE, LogStringsMessages.WSITPVD_0035_ERROR_VERIFY_INBOUND_MSG(), xwse);
      thereWasAFault = true;
      SOAPFaultException sfe = SOAPUtil.getSOAPFaultException(xwse, soapFactory, soapVersion);
      msg = Messages.create(sfe, soapVersion);

    } catch (SOAPException se) {
      // internal error
      log.log(Level.SEVERE, LogStringsMessages.WSITPVD_0035_ERROR_VERIFY_INBOUND_MSG(), se);
      thereWasAFault = true;
      SOAPFaultException sfe = SOAPUtil.getSOAPFaultException(se, soapFactory, soapVersion);
      msg = Messages.create(sfe, soapVersion);
    } catch (Exception ex) {
      // NPE's from server need to be handled as well
      log.log(Level.SEVERE, LogStringsMessages.WSITPVD_0035_ERROR_VERIFY_INBOUND_MSG(), ex);
      thereWasAFault = true;
      SOAPFaultException sfe = SOAPUtil.getSOAPFaultException(ex, soapFactory, soapVersion);
      msg = Messages.create(sfe, soapVersion);
    }

    if (thereWasAFault) {
      sharedState.put("THERE_WAS_A_FAULT", Boolean.valueOf(thereWasAFault));
      if (this.isAddressingEnabled()) {
        if (optimized) {
          packet.setMessage(((JAXBFilterProcessingContext) ctx).getPVMessage());
        }
        Packet ret =
            packet.createServerResponse(
                msg, this.addVer, this.soapVersion, this.addVer.getDefaultFaultAction());
        return ret;
      } else {
        packet.setMessage(msg);
        return packet;
      }
    }

    packet.setMessage(msg);

    if (isAddressingEnabled()) {
      action = getAction(packet);
      if (wsscVer.getSCTRequestAction().equals(action)
          || wsscVer.getSCTRenewRequestAction().equals(action)) {
        isSCIssueMessage = true;
        sharedState.put("IS_SC_ISSUE", TRUE);
        if (wsscConfig != null) {
          packet.invocationProperties.put(
              com.sun.xml.ws.security.impl.policy.Constants
                  .SUN_SECURE_SERVER_CONVERSATION_POLICY_NS,
              wsscConfig.iterator());
        }
      } else if (wsscVer.getSCTCancelRequestAction().equals(action)) {
        isSCCancelMessage = true;
        sharedState.put("IS_SC_CANCEL", TRUE);
      } else if (wsTrustVer.getIssueRequestAction().equals(action)
          || wsTrustVer.getValidateRequestAction().equals(action)) {
        isTrustMessage = true;
        sharedState.put("IS_TRUST_MESSAGE", TRUE);
        sharedState.put("TRUST_REQUEST_ACTION", action);
        // packet.getMessage().getHeaders().getTo(addVer, pipeConfig.getBinding().getSOAPVersion());

        if (trustConfig != null) {
          packet.invocationProperties.put(
              com.sun.xml.ws.security.impl.policy.Constants.SUN_TRUST_SERVER_SECURITY_POLICY_NS,
              trustConfig.iterator());
        }

        // set the SecurityEnvironment
        packet.invocationProperties.put(WSTrustConstants.SECURITY_ENVIRONMENT, secEnv);
        packet.invocationProperties.put(WSTrustConstants.WST_VERSION, this.wsTrustVer);
        IssuedTokenContext ictx = ((ProcessingContextImpl) ctx).getTrustContext();
        if (ictx != null && ictx.getAuthnContextClass() != null) {
          packet.invocationProperties.put(
              WSTrustConstants.AUTHN_CONTEXT_CLASS, ictx.getAuthnContextClass());
        }
      }

      if (isSCIssueMessage) {
        List<PolicyAssertion> policies = getInBoundSCP(packet.getMessage());
        if (!policies.isEmpty()) {
          packet.invocationProperties.put(SC_ASSERTION, (PolicyAssertion) policies.get(0));
        }
      }
    }

    if (!isSCIssueMessage) {
      WSDLBoundOperation cachedOperation = cacheOperation(msg, packet);
      if (cachedOperation == null) {
        if (addVer != null) {
          cachedOperation = getWSDLOpFromAction(packet, true);
          packet.invocationProperties.put("WSDL_BOUND_OPERATION", cachedOperation);
        }
      }
    }

    sharedState.put("VALIDATE_REQ_PACKET", packet);

    Packet retPacket = null;

    if (isSCIssueMessage || isSCCancelMessage) {
      // -------put application message on hold and invoke SC contract--------
      retPacket = invokeSecureConversationContract(packet, ctx, isSCIssueMessage);
      // if this is SC message we need to secure it in ValidateRequest Itself
      retPacket = secureResponse(retPacket, serviceSubject, sharedState);
    } else {
      updateSCSessionInfo(packet);
      retPacket = packet;
    }

    return retPacket;
  }