/**
   * @param context JAXBFilterProcessingContext
   * @return errorCode
   * @throws XWSSecurityException
   */
  public static int sign(JAXBFilterProcessingContext context) throws XWSSecurityException {
    try {
      SignaturePolicy signaturePolicy = (SignaturePolicy) context.getSecurityPolicy();
      ((NamespaceContextEx) context.getNamespaceContext()).addSignatureNS();
      WSSPolicy keyBinding = (WSSPolicy) signaturePolicy.getKeyBinding();
      if (logger.isLoggable(Level.FINEST)) {
        logger.log(Level.FINEST, "KeyBinding is " + keyBinding);
      }

      Key signingKey = null;

      SignatureElementFactory signFactory = new SignatureElementFactory();

      KeyInfo keyInfo = null;
      SecurityHeader securityHeader = context.getSecurityHeader();

      // Get the Signing key and KeyInfo from TokenProcessor
      TokenProcessor tokenProcessor = new TokenProcessor(signaturePolicy, context);
      BuilderResult builderResult = tokenProcessor.process();
      signingKey = builderResult.getDataProtectionKey();
      keyInfo = builderResult.getKeyInfo();

      if (keyInfo != null || !keyBinding.isOptional()) {
        SignedInfo signedInfo = signFactory.constructSignedInfo(context);
        JAXBSignContext signContext = new JAXBSignContext(signingKey);
        signContext.setURIDereferencer(DSigResolver.getInstance());
        XMLSignature signature =
            signFactory.constructSignature(signedInfo, keyInfo, signaturePolicy.getUUID());
        signContext.put(MessageConstants.WSS_PROCESSING_CONTEXT, context);
        NamespaceAndPrefixMapper npMapper =
            new NamespaceAndPrefixMapper(
                context.getNamespaceContext(), context.getDisableIncPrefix());
        signContext.put(NamespaceAndPrefixMapper.NS_PREFIX_MAPPER, npMapper);
        signContext.putNamespacePrefix(MessageConstants.DSIG_NS, MessageConstants.DSIG_PREFIX);
        signature.sign(signContext);

        JAXBSignatureHeaderElement jaxBSign =
            new JAXBSignatureHeaderElement(
                (com.sun.xml.ws.security.opt.crypto.dsig.Signature) signature,
                context.getSOAPVersion());
        securityHeader.add(jaxBSign);

        // For SignatureConfirmation
        List scList = (ArrayList) context.getExtraneousProperty("SignatureConfirmation");
        if (scList != null) {
          scList.add(Base64.encode(signature.getSignatureValue().getValue()));
        }
      }
      // End SignatureConfirmation specific code

    } catch (XWSSecurityException xe) {
      logger.log(Level.SEVERE, LogStringsMessages.WSS_1701_SIGN_FAILED(), xe);
      throw xe;
    } catch (Exception ex) {
      logger.log(Level.SEVERE, LogStringsMessages.WSS_1701_SIGN_FAILED(), ex);
      throw new XWSSecurityException(ex);
    }
    return 0;
  }
  /**
   * Validate a signed document with the given public key
   *
   * @param signedDoc
   * @param publicKey
   * @return
   * @throws MarshalException
   * @throws XMLSignatureException
   */
  @SuppressWarnings("unchecked")
  public static boolean validate(Document signedDoc, Key publicKey)
      throws MarshalException, XMLSignatureException {
    if (signedDoc == null) throw logger.nullArgumentError("Signed Document");

    propagateIDAttributeSetup(signedDoc.getDocumentElement(), signedDoc.getDocumentElement());

    NodeList nl = signedDoc.getElementsByTagNameNS(XMLSignature.XMLNS, "Signature");

    if (nl == null || nl.getLength() == 0) {
      throw logger.nullValueError("Cannot find Signature element");
    }

    if (publicKey == null) throw logger.nullValueError("Public Key");

    for (int i = 0; i < nl.getLength(); i++) {
      DOMValidateContext valContext = new DOMValidateContext(publicKey, nl.item(i));
      XMLSignature signature = fac.unmarshalXMLSignature(valContext);

      boolean coreValidity = signature.validate(valContext);

      if (!coreValidity) {
        if (logger.isTraceEnabled()) {
          boolean sv = signature.getSignatureValue().validate(valContext);
          logger.trace("Signature validation status: " + sv);

          List<Reference> references = signature.getSignedInfo().getReferences();
          for (Reference ref : references) {
            logger.trace(
                "[Ref id="
                    + ref.getId()
                    + ":uri="
                    + ref.getURI()
                    + "]validity status:"
                    + ref.validate(valContext));
          }
        }

        return false;
      }
    }

    return true;
  }