    public void processEvent(XMLSecEvent xmlSecEvent, OutputProcessorChain outputProcessorChain) throws XMLStreamException, XMLSecurityException {
        try {
            final String bstId;
            final X509Certificate[] x509Certificates;
            String reference = null;
            Key key = null;
            TokenType tokenType = WSSecurityTokenConstants.X509V3Token;
            XMLSecurityConstants.Action action = getAction();
            if (WSSConstants.SIGNATURE.equals(action)
                    || WSSConstants.SAML_TOKEN_SIGNED.equals(action)
                    || WSSConstants.SIGNATURE_WITH_DERIVED_KEY.equals(action)) {
                String tokenId = 
                    outputProcessorChain.getSecurityContext().get(WSSConstants.PROP_USE_THIS_TOKEN_ID_FOR_SIGNATURE);
                SecurityTokenProvider<OutboundSecurityToken> signatureTokenProvider = null;
                GenericOutboundSecurityToken securityToken = null;
                if (tokenId != null && !WSSConstants.SIGNATURE_WITH_DERIVED_KEY.equals(getAction())) {
                    signatureTokenProvider = 
                        outputProcessorChain.getSecurityContext().getSecurityTokenProvider(tokenId);
                    if (signatureTokenProvider != null) {
                        securityToken = 
                            (GenericOutboundSecurityToken)signatureTokenProvider.getSecurityToken();
                        if (securityToken != null) {
                            key = securityToken.getSecretKey(getSecurityProperties().getSignatureAlgorithm());
                            reference = securityToken.getSha1Identifier();
                            if (securityToken.getTokenType() != null) {
                                tokenType = securityToken.getTokenType();
                            }
                        }
                    }
                }
                if (key == null) {
                    bstId = IDGenerator.generateID(null);
                    String alias = ((WSSSecurityProperties) getSecurityProperties()).getSignatureUser();
                    WSPasswordCallback pwCb = new WSPasswordCallback(alias, WSPasswordCallback.Usage.SIGNATURE);
                    WSSUtils.doPasswordCallback(((WSSSecurityProperties)getSecurityProperties()).getCallbackHandler(), pwCb);
                    String password = pwCb.getPassword();
                    byte[] secretKey = pwCb.getKey();
                    if (password == null && secretKey == null) {
                        throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_SIGNATURE, "noPassword", alias);
                    }
                    if (password != null) {
                        key = ((WSSSecurityProperties) getSecurityProperties()).getSignatureCrypto().getPrivateKey(alias, password);
                        CryptoType cryptoType = new CryptoType(CryptoType.TYPE.ALIAS);
                        cryptoType.setAlias(alias);
                        x509Certificates = ((WSSSecurityProperties) getSecurityProperties()).getSignatureCrypto().getX509Certificates(cryptoType);
                        if (x509Certificates == null || x509Certificates.length == 0) {
                            throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_SIGNATURE, "noUserCertsFound", alias);
                        }
                    } else {
                        x509Certificates = null;
                        String algoFamily = JCEAlgorithmMapper.getJCEKeyAlgorithmFromURI(getSecurityProperties().getSignatureAlgorithm());
                        key = new SecretKeySpec(secretKey, algoFamily);
                    } 
                } else {
                    bstId = tokenId;
                    x509Certificates = null;
                }
            } else if (WSSConstants.ENCRYPT.equals(action) ||
                    WSSConstants.ENCRYPT_WITH_DERIVED_KEY.equals(action)) {
                X509Certificate x509Certificate = getReqSigCert(outputProcessorChain.getSecurityContext());
                if (((WSSSecurityProperties) getSecurityProperties()).isUseReqSigCertForEncryption()) {
                    if (x509Certificate == null) {
                        throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_ENCRYPTION, "noCert");
                    }
                    x509Certificates = new X509Certificate[1];
                    x509Certificates[0] = x509Certificate;
                } else if (getSecurityProperties().getEncryptionUseThisCertificate() != null) {
                    x509Certificate = getSecurityProperties().getEncryptionUseThisCertificate();
                    x509Certificates = new X509Certificate[1];
                    x509Certificates[0] = x509Certificate;
                } else {
                    CryptoType cryptoType = new CryptoType(CryptoType.TYPE.ALIAS);
                    WSSSecurityProperties securityProperties = ((WSSSecurityProperties) getSecurityProperties());
                    cryptoType.setAlias(securityProperties.getEncryptionUser());
                    Crypto crypto = securityProperties.getEncryptionCrypto();
                    x509Certificates = crypto.getX509Certificates(cryptoType);
                    if (x509Certificates == null || x509Certificates.length == 0) {
                        throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_ENCRYPTION, "noUserCertsFound",
                                ((WSSSecurityProperties) getSecurityProperties()).getEncryptionUser());
                    }
                }
                WSSSecurityProperties securityProperties = ((WSSSecurityProperties) getSecurityProperties());
                if (securityProperties.isEnableRevocation()) {
                    Crypto crypto = securityProperties.getEncryptionCrypto();
                    crypto.verifyTrust(x509Certificates, true);
                }
                key = null;
                bstId = IDGenerator.generateID(null);
            } else {
                bstId = IDGenerator.generateID(null);
                x509Certificates = null;
                key = null;
            }
            final GenericOutboundSecurityToken binarySecurityToken =
                    new GenericOutboundSecurityToken(bstId, tokenType, key, x509Certificates);
            binarySecurityToken.setSha1Identifier(reference);
            final SecurityTokenProvider<OutboundSecurityToken> binarySecurityTokenProvider =
                    new SecurityTokenProvider<OutboundSecurityToken>() {
                @Override
                public OutboundSecurityToken getSecurityToken() throws WSSecurityException {
                    return binarySecurityToken;
                }
                @Override
                public String getId() {
                    return bstId;
                }
            };
            if (WSSConstants.SIGNATURE.equals(action)
                    || WSSConstants.SAML_TOKEN_SIGNED.equals(action)) {
                outputProcessorChain.getSecurityContext().put(WSSConstants.PROP_USE_THIS_TOKEN_ID_FOR_SIGNATURE, bstId);
                boolean includeSignatureToken = 
                    ((WSSSecurityProperties) getSecurityProperties()).isIncludeSignatureToken();
                if ((includeSignatureToken 
                    || WSSecurityTokenConstants.KeyIdentifier_SecurityTokenDirectReference.equals(getSecurityProperties().getSignatureKeyIdentifier()))
                    && !WSSecurityTokenConstants.KerberosToken.equals(tokenType)) {
                    FinalBinarySecurityTokenOutputProcessor finalBinarySecurityTokenOutputProcessor = new FinalBinarySecurityTokenOutputProcessor(binarySecurityToken);
                    finalBinarySecurityTokenOutputProcessor.setXMLSecurityProperties(getSecurityProperties());
                    finalBinarySecurityTokenOutputProcessor.setAction(getAction());
                    finalBinarySecurityTokenOutputProcessor.addBeforeProcessor(WSSSignatureOutputProcessor.class.getName());
                    finalBinarySecurityTokenOutputProcessor.init(outputProcessorChain);
                    binarySecurityToken.setProcessor(finalBinarySecurityTokenOutputProcessor);
                }
            } else if (WSSConstants.ENCRYPT.equals(action)) {
                outputProcessorChain.getSecurityContext().put(WSSConstants.PROP_USE_THIS_TOKEN_ID_FOR_ENCRYPTED_KEY, bstId);
                if (WSSecurityTokenConstants.KeyIdentifier_SecurityTokenDirectReference.equals(((WSSSecurityProperties) getSecurityProperties()).getEncryptionKeyIdentifier())) {
                    FinalBinarySecurityTokenOutputProcessor finalBinarySecurityTokenOutputProcessor = new FinalBinarySecurityTokenOutputProcessor(binarySecurityToken);
                    finalBinarySecurityTokenOutputProcessor.setXMLSecurityProperties(getSecurityProperties());
                    finalBinarySecurityTokenOutputProcessor.setAction(getAction());
                    finalBinarySecurityTokenOutputProcessor.addAfterProcessor(EncryptEndingOutputProcessor.class.getName());
                    finalBinarySecurityTokenOutputProcessor.init(outputProcessorChain);
                    binarySecurityToken.setProcessor(finalBinarySecurityTokenOutputProcessor);
                }
            } else if (WSSConstants.SIGNATURE_WITH_DERIVED_KEY.equals(action)
                    || WSSConstants.ENCRYPT_WITH_DERIVED_KEY.equals(action)) {
                WSSConstants.DerivedKeyTokenReference derivedKeyTokenReference = ((WSSSecurityProperties) getSecurityProperties()).getDerivedKeyTokenReference();
                switch (derivedKeyTokenReference) {
                    case DirectReference:
                        outputProcessorChain.getSecurityContext().put(WSSConstants.PROP_USE_THIS_TOKEN_ID_FOR_DERIVED_KEY, bstId);
                        break;
                    case EncryptedKey:
                        outputProcessorChain.getSecurityContext().put(WSSConstants.PROP_USE_THIS_TOKEN_ID_FOR_ENCRYPTED_KEY, bstId);
                        break;
                    case SecurityContextToken:
                        outputProcessorChain.getSecurityContext().put(WSSConstants.PROP_USE_THIS_TOKEN_ID_FOR_SECURITYCONTEXTTOKEN, bstId);
                        break;
                }
            }
            outputProcessorChain.getSecurityContext().registerSecurityTokenProvider(bstId, binarySecurityTokenProvider);
        } finally {
            outputProcessorChain.removeProcessor(this);
        }
        outputProcessorChain.processEvent(xmlSecEvent);
    }

    public void processEvent(XMLSecEvent xmlSecEvent, OutputProcessorChain outputProcessorChain) throws XMLStreamException, XMLSecurityException {
        try {
            final String bstId;
            final X509Certificate[] x509Certificates;
            String reference = null;
            Key key = null;
            TokenType tokenType = WSSecurityTokenConstants.X509V3Token;
            XMLSecurityConstants.Action action = getAction();
            if (WSSConstants.SIGNATURE.equals(action)
                    || WSSConstants.SAML_TOKEN_SIGNED.equals(action)
                    || WSSConstants.SIGNATURE_WITH_DERIVED_KEY.equals(action)) {
                String tokenId = 
                    outputProcessorChain.getSecurityContext().get(WSSConstants.PROP_USE_THIS_TOKEN_ID_FOR_SIGNATURE);
                SecurityTokenProvider<OutboundSecurityToken> signatureTokenProvider = null;
                GenericOutboundSecurityToken securityToken = null;
                if (tokenId != null && !WSSConstants.SIGNATURE_WITH_DERIVED_KEY.equals(getAction())) {
                    signatureTokenProvider = 
                        outputProcessorChain.getSecurityContext().getSecurityTokenProvider(tokenId);
                    if (signatureTokenProvider != null) {
                        securityToken = 
                            (GenericOutboundSecurityToken)signatureTokenProvider.getSecurityToken();
                        if (securityToken != null) {
                            key = securityToken.getSecretKey(getSecurityProperties().getSignatureAlgorithm());
                            reference = securityToken.getSha1Identifier();
                            tokenType = securityToken.getTokenType();
                        }
                    }
                }
                if (key == null) {
                    bstId = IDGenerator.generateID(null);
                    String alias = ((WSSSecurityProperties) getSecurityProperties()).getSignatureUser();
                    WSPasswordCallback pwCb = new WSPasswordCallback(alias, WSPasswordCallback.Usage.SIGNATURE);
                    WSSUtils.doPasswordCallback(((WSSSecurityProperties)getSecurityProperties()).getCallbackHandler(), pwCb);
                    String password = pwCb.getPassword();
                    byte[] secretKey = pwCb.getKey();
                    if (password == null && secretKey == null) {
                        throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_SIGNATURE, "noPassword", alias);
                    }
                    if (password != null) {
                        key = ((WSSSecurityProperties) getSecurityProperties()).getSignatureCrypto().getPrivateKey(alias, password);
                        CryptoType cryptoType = new CryptoType(CryptoType.TYPE.ALIAS);
                        cryptoType.setAlias(alias);
                        x509Certificates = ((WSSSecurityProperties) getSecurityProperties()).getSignatureCrypto().getX509Certificates(cryptoType);
                        if (x509Certificates == null || x509Certificates.length == 0) {
                            throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_SIGNATURE, "noUserCertsFound", alias);
                        }
                    } else {
                        x509Certificates = null;
                        String algoFamily = JCEAlgorithmMapper.getJCEKeyAlgorithmFromURI(getSecurityProperties().getSignatureAlgorithm());
                        key = new SecretKeySpec(secretKey, algoFamily);
                    }
                    tokenType = null;
                } else {
                    bstId = tokenId;
                    x509Certificates = null;
                }
            } else if (WSSConstants.ENCRYPT.equals(action) ||
                    WSSConstants.ENCRYPT_WITH_DERIVED_KEY.equals(action)) {
                X509Certificate x509Certificate = getReqSigCert(outputProcessorChain.getSecurityContext());
                if (((WSSSecurityProperties) getSecurityProperties()).isUseReqSigCertForEncryption()) {
                    if (x509Certificate == null) {
                        throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_ENCRYPTION, "noCert");
                    }
                    x509Certificates = new X509Certificate[1];
                    x509Certificates[0] = x509Certificate;
                } else if (getSecurityProperties().getEncryptionUseThisCertificate() != null) {
                    x509Certificate = getSecurityProperties().getEncryptionUseThisCertificate();
                    x509Certificates = new X509Certificate[1];
                    x509Certificates[0] = x509Certificate;
                } else {
                    CryptoType cryptoType = new CryptoType(CryptoType.TYPE.ALIAS);
                    WSSSecurityProperties securityProperties = ((WSSSecurityProperties) getSecurityProperties());
                    cryptoType.setAlias(securityProperties.getEncryptionUser());
                    Crypto crypto = securityProperties.getEncryptionCrypto();
                    x509Certificates = crypto.getX509Certificates(cryptoType);
                    if (x509Certificates == null || x509Certificates.length == 0) {
                        throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_ENCRYPTION, "noUserCertsFound",
                                ((WSSSecurityProperties) getSecurityProperties()).getEncryptionUser());
                    }
                }
                WSSSecurityProperties securityProperties = ((WSSSecurityProperties) getSecurityProperties());
                if (securityProperties.isEnableRevocation()) {
                    Crypto crypto = securityProperties.getEncryptionCrypto();
                    crypto.verifyTrust(x509Certificates, true);
                }
                key = null;
                bstId = IDGenerator.generateID(null);
            } else {
                bstId = IDGenerator.generateID(null);
                x509Certificates = null;
                key = null;
            }
            final GenericOutboundSecurityToken binarySecurityToken =
                    new GenericOutboundSecurityToken(bstId, tokenType, key, x509Certificates);
            binarySecurityToken.setSha1Identifier(reference);
            final SecurityTokenProvider<OutboundSecurityToken> binarySecurityTokenProvider =
                    new SecurityTokenProvider<OutboundSecurityToken>() {
                @Override
                public OutboundSecurityToken getSecurityToken() throws WSSecurityException {
                    return binarySecurityToken;
                }
                @Override
                public String getId() {
                    return bstId;
                }
            };
            if (WSSConstants.SIGNATURE.equals(action)
                    || WSSConstants.SAML_TOKEN_SIGNED.equals(action)) {
                outputProcessorChain.getSecurityContext().put(WSSConstants.PROP_USE_THIS_TOKEN_ID_FOR_SIGNATURE, bstId);
                boolean includeSignatureToken = 
                    ((WSSSecurityProperties) getSecurityProperties()).isIncludeSignatureToken();
                if ((includeSignatureToken 
                    || WSSecurityTokenConstants.KeyIdentifier_SecurityTokenDirectReference.equals(getSecurityProperties().getSignatureKeyIdentifier()))
                    && !WSSecurityTokenConstants.KerberosToken.equals(tokenType)) {
                    FinalBinarySecurityTokenOutputProcessor finalBinarySecurityTokenOutputProcessor = new FinalBinarySecurityTokenOutputProcessor(binarySecurityToken);
                    finalBinarySecurityTokenOutputProcessor.setXMLSecurityProperties(getSecurityProperties());
                    finalBinarySecurityTokenOutputProcessor.setAction(getAction());
                    finalBinarySecurityTokenOutputProcessor.addBeforeProcessor(WSSSignatureOutputProcessor.class.getName());
                    finalBinarySecurityTokenOutputProcessor.init(outputProcessorChain);
                    binarySecurityToken.setProcessor(finalBinarySecurityTokenOutputProcessor);
                }
            } else if (WSSConstants.ENCRYPT.equals(action)) {
                outputProcessorChain.getSecurityContext().put(WSSConstants.PROP_USE_THIS_TOKEN_ID_FOR_ENCRYPTED_KEY, bstId);
                if (WSSecurityTokenConstants.KeyIdentifier_SecurityTokenDirectReference.equals(((WSSSecurityProperties) getSecurityProperties()).getEncryptionKeyIdentifier())) {
                    FinalBinarySecurityTokenOutputProcessor finalBinarySecurityTokenOutputProcessor = new FinalBinarySecurityTokenOutputProcessor(binarySecurityToken);
                    finalBinarySecurityTokenOutputProcessor.setXMLSecurityProperties(getSecurityProperties());
                    finalBinarySecurityTokenOutputProcessor.setAction(getAction());
                    finalBinarySecurityTokenOutputProcessor.addAfterProcessor(EncryptEndingOutputProcessor.class.getName());
                    finalBinarySecurityTokenOutputProcessor.init(outputProcessorChain);
                    binarySecurityToken.setProcessor(finalBinarySecurityTokenOutputProcessor);
                }
            } else if (WSSConstants.SIGNATURE_WITH_DERIVED_KEY.equals(action)
                    || WSSConstants.ENCRYPT_WITH_DERIVED_KEY.equals(action)) {
                WSSConstants.DerivedKeyTokenReference derivedKeyTokenReference = ((WSSSecurityProperties) getSecurityProperties()).getDerivedKeyTokenReference();
                switch (derivedKeyTokenReference) {
                    case DirectReference:
                        outputProcessorChain.getSecurityContext().put(WSSConstants.PROP_USE_THIS_TOKEN_ID_FOR_DERIVED_KEY, bstId);
                        break;
                    case EncryptedKey:
                        outputProcessorChain.getSecurityContext().put(WSSConstants.PROP_USE_THIS_TOKEN_ID_FOR_ENCRYPTED_KEY, bstId);
                        break;
                    case SecurityContextToken:
                        outputProcessorChain.getSecurityContext().put(WSSConstants.PROP_USE_THIS_TOKEN_ID_FOR_SECURITYCONTEXTTOKEN, bstId);
                        break;
                }
            }
            outputProcessorChain.getSecurityContext().registerSecurityTokenProvider(bstId, binarySecurityTokenProvider);
        } finally {
            outputProcessorChain.removeProcessor(this);
        }
        outputProcessorChain.processEvent(xmlSecEvent);
    }
