You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ws.apache.org by gi...@apache.org on 2011/09/18 15:51:36 UTC

svn commit: r1172285 [20/48] - in /webservices/wss4j/branches/swssf: ./ cxf-integration/ cxf-integration/src/ cxf-integration/src/main/ cxf-integration/src/main/java/ cxf-integration/src/main/java/org/ cxf-integration/src/main/java/org/swssf/ cxf-integ...

Added: webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/processor/output/EncryptOutputProcessor.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/processor/output/EncryptOutputProcessor.java?rev=1172285&view=auto
==============================================================================
--- webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/processor/output/EncryptOutputProcessor.java (added)
+++ webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/processor/output/EncryptOutputProcessor.java Sun Sep 18 13:51:23 2011
@@ -0,0 +1,363 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.swssf.impl.processor.output;
+
+import org.apache.commons.codec.binary.Base64OutputStream;
+import org.swssf.config.JCEAlgorithmMapper;
+import org.swssf.ext.*;
+import org.swssf.impl.EncryptionPartDef;
+import org.swssf.impl.util.TrimmerOutputStream;
+
+import javax.crypto.Cipher;
+import javax.crypto.CipherOutputStream;
+import javax.crypto.NoSuchPaddingException;
+import javax.xml.namespace.QName;
+import javax.xml.stream.XMLEventFactory;
+import javax.xml.stream.XMLEventWriter;
+import javax.xml.stream.XMLOutputFactory;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.events.*;
+import java.io.BufferedOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+import java.util.*;
+
+/**
+ * Processor to encrypt XML structures
+ *
+ * @author $Author$
+ * @version $Revision$ $Date$
+ */
+public class EncryptOutputProcessor extends AbstractOutputProcessor {
+
+    private List<SecurePart> secureParts;
+    private InternalEncryptionOutputProcessor activeInternalEncryptionOutputProcessor = null;
+
+    public EncryptOutputProcessor(SecurityProperties securityProperties, Constants.Action action) throws WSSecurityException {
+        super(securityProperties, action);
+        secureParts = securityProperties.getEncryptionSecureParts();
+    }
+
+    @Override
+    public void processEvent(XMLEvent xmlEvent, OutputProcessorChain outputProcessorChain) throws XMLStreamException, WSSecurityException {
+
+        if (xmlEvent.isStartElement()) {
+            StartElement startElement = xmlEvent.asStartElement();
+
+            //avoid double encryption when child elements matches too
+            if (activeInternalEncryptionOutputProcessor == null) {
+                //find an element which matches a user configured securePart
+                Iterator<SecurePart> securePartIterator = secureParts.iterator();
+                while (securePartIterator.hasNext()) {
+                    SecurePart securePart = securePartIterator.next();
+                    if (securePart.getIdToSign() == null) {
+                        if (startElement.getName().getLocalPart().equals(securePart.getName())
+                                && startElement.getName().getNamespaceURI().equals(securePart.getNamespace())) {
+
+                            logger.debug("Matched securePart for encryption");
+                            InternalEncryptionOutputProcessor internalEncryptionOutputProcessor = null;
+                            try {
+                                String tokenId = outputProcessorChain.getSecurityContext().get(Constants.PROP_USE_THIS_TOKEN_ID_FOR_ENCRYPTION);
+                                SecurityTokenProvider securityTokenProvider = outputProcessorChain.getSecurityContext().getSecurityTokenProvider(tokenId);
+                                EncryptionPartDef encryptionPartDef = new EncryptionPartDef();
+                                encryptionPartDef.setModifier(securePart.getModifier());
+                                encryptionPartDef.setEncRefId("ED-" + UUID.randomUUID().toString());
+                                encryptionPartDef.setKeyId(securityTokenProvider.getId());
+                                encryptionPartDef.setSymmetricKey(securityTokenProvider.getSecurityToken(null).getSecretKey(getSecurityProperties().getEncryptionSymAlgorithm(), null));
+                                outputProcessorChain.getSecurityContext().putAsList(EncryptionPartDef.class, encryptionPartDef);
+                                internalEncryptionOutputProcessor =
+                                        new InternalEncryptionOutputProcessor(
+                                                getSecurityProperties(),
+                                                getAction(),
+                                                encryptionPartDef,
+                                                startElement,
+                                                outputProcessorChain.getDocumentContext().getEncoding()
+                                        );
+                            } catch (NoSuchAlgorithmException e) {
+                                throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_ENCRYPTION, e);
+                            } catch (NoSuchPaddingException e) {
+                                throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_ENCRYPTION, e);
+                            } catch (InvalidKeyException e) {
+                                throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_ENCRYPTION, e);
+                            } catch (IOException e) {
+                                throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_ENCRYPTION, e);
+                            }
+
+                            activeInternalEncryptionOutputProcessor = internalEncryptionOutputProcessor;
+                            outputProcessorChain.addProcessor(internalEncryptionOutputProcessor);
+                            break;
+                        }
+                    }
+                }
+            }
+        }
+
+        outputProcessorChain.processEvent(xmlEvent);
+    }
+
+    /**
+     * Processor which handles the effective enryption of the data
+     */
+    class InternalEncryptionOutputProcessor extends AbstractOutputProcessor {
+
+        private EncryptionPartDef encryptionPartDef;
+        private CharacterEventGeneratorOutputStream characterEventGeneratorOutputStream;
+        private XMLEventWriter xmlEventWriter;
+        private OutputStream cipherOutputStream;
+
+        private StartElement startElement;
+        private int elementCounter = 0;
+        private boolean doEncryptedHeader = false;
+        private OutputProcessorChain subOutputProcessorChain;
+
+        InternalEncryptionOutputProcessor(SecurityProperties securityProperties, Constants.Action action, EncryptionPartDef encryptionPartDef,
+                                          StartElement startElement, String encoding)
+                throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IOException, XMLStreamException {
+
+            super(securityProperties, action);
+            this.getBeforeProcessors().add(EncryptEndingOutputProcessor.class.getName());
+            this.getBeforeProcessors().add(InternalEncryptionOutputProcessor.class.getName());
+            this.getAfterProcessors().add(EncryptOutputProcessor.class.getName());
+            this.encryptionPartDef = encryptionPartDef;
+            this.startElement = startElement;
+
+            //initialize the cipher
+            String jceAlgorithm = JCEAlgorithmMapper.translateURItoJCEID(securityProperties.getEncryptionSymAlgorithm());
+            Cipher symmetricCipher = Cipher.getInstance(jceAlgorithm);
+
+            //Should internally generate an IV
+            symmetricCipher.init(Cipher.ENCRYPT_MODE, encryptionPartDef.getSymmetricKey());
+            byte[] iv = symmetricCipher.getIV();
+
+            characterEventGeneratorOutputStream = new CharacterEventGeneratorOutputStream(encoding);
+            //Base64EncoderStream calls write every 78byte (line breaks). So we have to buffer again to get optimal performance
+            Base64OutputStream base64EncoderStream = new Base64OutputStream(new BufferedOutputStream(characterEventGeneratorOutputStream), true, 76, new byte[]{'\n'});
+            base64EncoderStream.write(iv);
+
+            //the trimmer output stream is needed to strip away the dummy wrapping element which must be added 
+            cipherOutputStream = new TrimmerOutputStream(new CipherOutputStream(base64EncoderStream, symmetricCipher), 8192, 3, 4);
+
+            //we create a new StAX writer for optimized namespace writing.
+            XMLOutputFactory xmlOutputFactory = XMLOutputFactory.newInstance();
+            xmlOutputFactory.setProperty(XMLOutputFactory.IS_REPAIRING_NAMESPACES, false);
+            //spec says (4.2): "The cleartext octet sequence obtained in step 3 is interpreted as UTF-8 encoded character data."
+            xmlEventWriter = xmlOutputFactory.createXMLEventWriter(cipherOutputStream, "UTF-8");
+            //we have to output a fake element to workaround text-only encryption:
+            xmlEventWriter.add(XMLEventFactory.newFactory().createStartElement(new QName("a"), null, null));
+        }
+
+        @Override
+        public void processEvent(XMLEvent xmlEvent, OutputProcessorChain outputProcessorChain) throws XMLStreamException, WSSecurityException {
+
+            if (xmlEvent.isStartElement()) {
+
+                StartElement startElement = xmlEvent.asStartElement();
+
+                if (startElement.getName().equals(this.startElement.getName()) && elementCounter == 0) {
+                    //if the user selected element encryption we have to encrypt the current element-event...
+                    if (encryptionPartDef.getModifier() == SecurePart.Modifier.Element) {
+                        subOutputProcessorChain = outputProcessorChain.createSubChain(this);
+                        processEventInternal(subOutputProcessorChain);
+                        //encrypt the current element event
+                        encryptEvent(xmlEvent);
+
+                    } //...the user selected content encryption, so we let pass this event as usual  
+                    else if (encryptionPartDef.getModifier() == SecurePart.Modifier.Content) {
+                        outputProcessorChain.processEvent(xmlEvent);
+                        subOutputProcessorChain = outputProcessorChain.createSubChain(this);
+                        processEventInternal(subOutputProcessorChain);
+                    }
+                } else {
+                    encryptEvent(xmlEvent);
+                }
+
+                elementCounter++;
+
+            } else if (xmlEvent.isEndElement()) {
+                elementCounter--;
+
+                EndElement endElement = xmlEvent.asEndElement();
+
+                if (endElement.getName().equals(this.startElement.getName()) && elementCounter == 0) {
+                    if (encryptionPartDef.getModifier() == SecurePart.Modifier.Element) {
+                        encryptEvent(xmlEvent);
+                        doFinalInternal(subOutputProcessorChain);
+                    } else {
+                        doFinalInternal(subOutputProcessorChain);
+                        outputAsEvent(subOutputProcessorChain, xmlEvent);
+                    }
+                    subOutputProcessorChain.removeProcessor(this);
+                    subOutputProcessorChain = null;
+                    //from now on encryption is possible again
+                    activeInternalEncryptionOutputProcessor = null;
+
+                } else {
+                    encryptEvent(xmlEvent);
+                }
+            } else {
+                //not an interesting start nor an interesting end element
+                //so encrypt this
+                encryptEvent(xmlEvent);
+
+                //push all buffered encrypted character events through the chain
+                Iterator<Characters> charactersIterator = characterEventGeneratorOutputStream.getCharactersBuffer().iterator();
+                while (charactersIterator.hasNext()) {
+                    Characters characters = charactersIterator.next();
+                    outputAsEvent(subOutputProcessorChain, characters);
+                    charactersIterator.remove();
+                }
+            }
+        }
+
+        private void encryptEvent(XMLEvent xmlEvent) throws XMLStreamException {
+            xmlEventWriter.add(xmlEvent);
+        }
+
+        /**
+         * Creates the Data structure around the cipher data
+         */
+        private void processEventInternal(OutputProcessorChain outputProcessorChain) throws XMLStreamException, WSSecurityException {
+            Map<QName, String> attributes = null;
+
+            //WSS 1.1 EncryptedHeader Element:
+            if (outputProcessorChain.getDocumentContext().getDocumentLevel() == 3
+                    && outputProcessorChain.getDocumentContext().isInSOAPHeader()) {
+                doEncryptedHeader = true;
+
+                attributes = new HashMap<QName, String>();
+
+                @SuppressWarnings("unchecked")
+                Iterator<Attribute> attributeIterator = this.startElement.getAttributes();
+                while (attributeIterator.hasNext()) {
+                    Attribute attribute = attributeIterator.next();
+                    if (!attribute.isNamespace() &&
+                            (Constants.NS_SOAP11.equals(attribute.getName().getNamespaceURI()) ||
+                                    Constants.NS_SOAP12.equals(attribute.getName().getNamespaceURI()))) {
+                        attributes.put(attribute.getName(), attribute.getValue());
+                    }
+                }
+                createStartElementAndOutputAsEvent(outputProcessorChain, Constants.TAG_wsse11_EncryptedHeader, attributes);
+            }
+
+            attributes = new HashMap<QName, String>();
+            attributes.put(Constants.ATT_NULL_Id, encryptionPartDef.getEncRefId());
+            attributes.put(Constants.ATT_NULL_Type, encryptionPartDef.getModifier().getModifier());
+            createStartElementAndOutputAsEvent(outputProcessorChain, Constants.TAG_xenc_EncryptedData, attributes);
+
+            attributes = new HashMap<QName, String>();
+            attributes.put(Constants.ATT_NULL_Algorithm, securityProperties.getEncryptionSymAlgorithm());
+            createStartElementAndOutputAsEvent(outputProcessorChain, Constants.TAG_xenc_EncryptionMethod, attributes);
+
+            createEndElementAndOutputAsEvent(outputProcessorChain, Constants.TAG_xenc_EncryptionMethod);
+            createStartElementAndOutputAsEvent(outputProcessorChain, Constants.TAG_dsig_KeyInfo, null);
+            createStartElementAndOutputAsEvent(outputProcessorChain, Constants.TAG_wsse_SecurityTokenReference, null);
+
+            attributes = new HashMap<QName, String>();
+            attributes.put(Constants.ATT_NULL_URI, "#" + encryptionPartDef.getKeyId());
+            createStartElementAndOutputAsEvent(outputProcessorChain, Constants.TAG_wsse_Reference, attributes);
+            createEndElementAndOutputAsEvent(outputProcessorChain, Constants.TAG_wsse_Reference);
+            createEndElementAndOutputAsEvent(outputProcessorChain, Constants.TAG_wsse_SecurityTokenReference);
+            createEndElementAndOutputAsEvent(outputProcessorChain, Constants.TAG_dsig_KeyInfo);
+            createStartElementAndOutputAsEvent(outputProcessorChain, Constants.TAG_xenc_CipherData, null);
+            createStartElementAndOutputAsEvent(outputProcessorChain, Constants.TAG_xenc_CipherValue, null);
+
+            /*
+            <xenc:EncryptedData xmlns:xenc="http://www.w3.org/2001/04/xmlenc#" Id="EncDataId-1612925417"
+                Type="http://www.w3.org/2001/04/xmlenc#Content">
+                <xenc:EncryptionMethod xmlns:xenc="http://www.w3.org/2001/04/xmlenc#"
+                    Algorithm="http://www.w3.org/2001/04/xmlenc#aes256-cbc" />
+                <ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
+                    <wsse:SecurityTokenReference xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
+                    <wsse:Reference xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
+                        URI="#EncKeyId-1483925398" />
+                    </wsse:SecurityTokenReference>
+                </ds:KeyInfo>
+                <xenc:CipherData xmlns:xenc="http://www.w3.org/2001/04/xmlenc#">
+                    <xenc:CipherValue xmlns:xenc="http://www.w3.org/2001/04/xmlenc#">
+                    ...
+                    </xenc:CipherValue>
+                </xenc:CipherData>
+            </xenc:EncryptedData>
+             */
+        }
+
+        private void doFinalInternal(OutputProcessorChain outputProcessorChain) throws XMLStreamException, WSSecurityException {
+
+            try {
+                xmlEventWriter.add(XMLEventFactory.newFactory().createEndElement(new QName("a"), null));
+                //close the event writer to flush all outstanding events to the encrypt stream
+                xmlEventWriter.close();
+                //call close to force a cipher.doFinal()
+                cipherOutputStream.close();
+            } catch (IOException e) {
+                throw new XMLStreamException(e);
+            }
+
+            //push all buffered encrypted character events through the chain
+            Iterator<Characters> charactersIterator = characterEventGeneratorOutputStream.getCharactersBuffer().iterator();
+            while (charactersIterator.hasNext()) {
+                Characters characters = charactersIterator.next();
+                outputAsEvent(outputProcessorChain, characters);
+                charactersIterator.remove();
+            }
+
+            createEndElementAndOutputAsEvent(outputProcessorChain, Constants.TAG_xenc_CipherValue);
+            createEndElementAndOutputAsEvent(outputProcessorChain, Constants.TAG_xenc_CipherData);
+            createEndElementAndOutputAsEvent(outputProcessorChain, Constants.TAG_xenc_EncryptedData);
+
+            if (doEncryptedHeader) {
+                createEndElementAndOutputAsEvent(outputProcessorChain, Constants.TAG_wsse11_EncryptedHeader);
+            }
+        }
+    }
+
+    /**
+     * Creates Character-XMLEvents from the byte stream
+     */
+    class CharacterEventGeneratorOutputStream extends OutputStream {
+
+        private List<Characters> charactersBuffer = new Vector<Characters>();
+        private String encoding;
+
+        CharacterEventGeneratorOutputStream(String encoding) {
+            this.encoding = encoding;
+        }
+
+        public List<Characters> getCharactersBuffer() {
+            return charactersBuffer;
+        }
+
+        @Override
+        public void write(int b) throws IOException {
+            charactersBuffer.add(createCharacters(new String(new byte[]{((byte) b)}, encoding)).asCharacters());
+        }
+
+        @Override
+        public void write(byte[] b) throws IOException {
+            charactersBuffer.add(createCharacters(new String(b, encoding)).asCharacters());
+        }
+
+        @Override
+        public void write(byte[] b, int off, int len) throws IOException {
+            charactersBuffer.add(createCharacters(new String(b, off, len, encoding)).asCharacters());
+        }
+    }
+}

Propchange: webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/processor/output/EncryptOutputProcessor.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Added: webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/processor/output/EncryptedKeyOutputProcessor.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/processor/output/EncryptedKeyOutputProcessor.java?rev=1172285&view=auto
==============================================================================
--- webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/processor/output/EncryptedKeyOutputProcessor.java (added)
+++ webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/processor/output/EncryptedKeyOutputProcessor.java Sun Sep 18 13:51:23 2011
@@ -0,0 +1,273 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.swssf.impl.processor.output;
+
+import org.apache.commons.codec.binary.Base64;
+import org.swssf.config.JCEAlgorithmMapper;
+import org.swssf.crypto.Crypto;
+import org.swssf.ext.*;
+import org.swssf.impl.securityToken.ProcessorInfoSecurityToken;
+
+import javax.crypto.*;
+import javax.xml.namespace.QName;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.events.StartElement;
+import javax.xml.stream.events.XMLEvent;
+import java.security.InvalidKeyException;
+import java.security.Key;
+import java.security.NoSuchAlgorithmException;
+import java.security.PublicKey;
+import java.security.cert.X509Certificate;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.UUID;
+
+/**
+ * @author $Author$
+ * @version $Revision$ $Date$
+ */
+public class EncryptedKeyOutputProcessor extends AbstractOutputProcessor {
+
+    public EncryptedKeyOutputProcessor(SecurityProperties securityProperties, Constants.Action action) throws WSSecurityException {
+        super(securityProperties, action);
+    }
+
+    @Override
+    public void processEvent(XMLEvent xmlEvent, OutputProcessorChain outputProcessorChain) throws XMLStreamException, WSSecurityException {
+        try {
+
+            String tokenId = outputProcessorChain.getSecurityContext().get(Constants.PROP_USE_THIS_TOKEN_ID_FOR_ENCRYPTED_KEY);
+            if (tokenId == null) {
+                throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_ENCRYPTION);
+            }
+            SecurityTokenProvider wrappingSecurityTokenProvider = outputProcessorChain.getSecurityContext().getSecurityTokenProvider(tokenId);
+            if (wrappingSecurityTokenProvider == null) {
+                throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_ENCRYPTION);
+            }
+            final SecurityToken wrappingSecurityToken = wrappingSecurityTokenProvider.getSecurityToken(null);
+            if (wrappingSecurityToken == null) {
+                throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_ENCRYPTION);
+            }
+
+            //prepare the symmetric session key for all encryption parts
+            String keyAlgorithm = JCEAlgorithmMapper.getJCERequiredKeyFromURI(securityProperties.getEncryptionSymAlgorithm());
+            int keyLength = JCEAlgorithmMapper.getKeyLengthFromURI(securityProperties.getEncryptionSymAlgorithm());
+            KeyGenerator keyGen = null;
+            try {
+                keyGen = KeyGenerator.getInstance(keyAlgorithm);
+            } catch (NoSuchAlgorithmException e) {
+                throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_ENCRYPTION, e);
+            }
+            keyGen.init(keyLength);
+
+            final Key symmetricKey = keyGen.generateKey();
+
+            final String ekId = "EK-" + UUID.randomUUID().toString();
+
+            final ProcessorInfoSecurityToken encryptedKeySecurityToken = new ProcessorInfoSecurityToken() {
+
+                private OutputProcessor outputProcessor;
+
+                public String getId() {
+                    return ekId;
+                }
+
+                public void setProcessor(OutputProcessor outputProcessor) {
+                    this.outputProcessor = outputProcessor;
+                }
+
+                public Object getProcessor() {
+                    return outputProcessor;
+                }
+
+                public boolean isAsymmetric() {
+                    return false;
+                }
+
+                public Key getSecretKey(String algorithmURI, Constants.KeyUsage keyUsage) throws WSSecurityException {
+                    return symmetricKey;
+                }
+
+                public PublicKey getPublicKey(Constants.KeyUsage keyUsage) throws WSSecurityException {
+                    return null;
+                }
+
+                public X509Certificate[] getX509Certificates() throws WSSecurityException {
+                    return null;
+                }
+
+                public void verify() throws WSSecurityException {
+                }
+
+                public SecurityToken getKeyWrappingToken() {
+                    return wrappingSecurityToken;
+                }
+
+                public String getKeyWrappingTokenAlgorithm() {
+                    return null;
+                }
+
+                public Constants.TokenType getTokenType() {
+                    return null;
+                }
+            };
+
+            final SecurityTokenProvider encryptedKeySecurityTokenProvider = new SecurityTokenProvider() {
+                public SecurityToken getSecurityToken(Crypto crypto) throws WSSecurityException {
+                    return encryptedKeySecurityToken;
+                }
+
+                public String getId() {
+                    return ekId;
+                }
+            };
+
+            FinalEncryptedKeyOutputProcessor finalEncryptedKeyOutputProcessor = new FinalEncryptedKeyOutputProcessor(getSecurityProperties(), getAction(), encryptedKeySecurityToken);
+            switch (getAction()) {
+                case ENCRYPT:
+                    outputProcessorChain.getSecurityContext().put(Constants.PROP_USE_THIS_TOKEN_ID_FOR_ENCRYPTION, ekId);
+                    if (wrappingSecurityToken.getProcessor() != null) {
+                        finalEncryptedKeyOutputProcessor.getBeforeProcessors().add(wrappingSecurityToken.getProcessor());
+                    } else {
+                        finalEncryptedKeyOutputProcessor.getAfterProcessors().add(EncryptEndingOutputProcessor.class.getName());
+                    }
+                    break;
+                case SIGNATURE_WITH_DERIVED_KEY:
+                    outputProcessorChain.getSecurityContext().put(Constants.PROP_USE_THIS_TOKEN_ID_FOR_DERIVED_KEY, ekId);
+                    if (wrappingSecurityToken.getProcessor() != null) {
+                        finalEncryptedKeyOutputProcessor.getBeforeProcessors().add(wrappingSecurityToken.getProcessor());
+                    } else {
+                        finalEncryptedKeyOutputProcessor.getBeforeProcessors().add(SignatureOutputProcessor.class.getName());
+                    }
+                    break;
+                case ENCRYPT_WITH_DERIVED_KEY:
+                    outputProcessorChain.getSecurityContext().put(Constants.PROP_USE_THIS_TOKEN_ID_FOR_DERIVED_KEY, ekId);
+                    if (wrappingSecurityToken.getProcessor() != null) {
+                        finalEncryptedKeyOutputProcessor.getBeforeProcessors().add(wrappingSecurityToken.getProcessor());
+                    } else {
+                        finalEncryptedKeyOutputProcessor.getAfterProcessors().add(EncryptEndingOutputProcessor.class.getName());
+                    }
+                    break;
+            }
+            outputProcessorChain.getSecurityContext().registerSecurityTokenProvider(ekId, encryptedKeySecurityTokenProvider);
+            encryptedKeySecurityToken.setProcessor(finalEncryptedKeyOutputProcessor);
+            outputProcessorChain.addProcessor(finalEncryptedKeyOutputProcessor);
+        } finally {
+            outputProcessorChain.removeProcessor(this);
+        }
+        outputProcessorChain.processEvent(xmlEvent);
+    }
+
+    class FinalEncryptedKeyOutputProcessor extends AbstractOutputProcessor {
+
+        private SecurityToken securityToken;
+
+        FinalEncryptedKeyOutputProcessor(SecurityProperties securityProperties, Constants.Action action, SecurityToken securityToken) throws WSSecurityException {
+            super(securityProperties, action);
+            this.getAfterProcessors().add(FinalEncryptedKeyOutputProcessor.class.getName());
+            this.securityToken = securityToken;
+        }
+
+        /*
+       <xenc:EncryptedKey xmlns:xenc="http://www.w3.org/2001/04/xmlenc#" Id="EncKeyId-1483925398">
+           <xenc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-1_5" />
+           <ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
+               <wsse:SecurityTokenReference xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
+                   <wsse:KeyIdentifier EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary" ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509SubjectKeyIdentifier">
+                       pHoiKNGY2YsLBKxwIV+jURt858M=
+                   </wsse:KeyIdentifier>
+               </wsse:SecurityTokenReference>
+           </ds:KeyInfo>
+           <xenc:CipherData>
+               <xenc:CipherValue>
+                   Khsa9SN3ALNXOgGDKOqihvfwGsXb9QN/q4Fpi9uuThgz+3D4oRSMkrGSPCqwG13vddvHywGAA/XNbWNT+5Xivz3lURCDCc2H/92YlXXo/crQNJnPlLrLZ81bGOzbNo7lnYQBLp/77K7b1bhldZAeV9ZfEW7DjbOMZ+k1dnDCu3A=
+               </xenc:CipherValue>
+           </xenc:CipherData>
+           <xenc:ReferenceList>
+               <xenc:DataReference URI="#EncDataId-1612925417" />
+           </xenc:ReferenceList>
+       </xenc:EncryptedKey>
+        */
+
+        @Override
+        public void processEvent(XMLEvent xmlEvent, OutputProcessorChain outputProcessorChain) throws XMLStreamException, WSSecurityException {
+            outputProcessorChain.processEvent(xmlEvent);
+            if (xmlEvent.isStartElement()) {
+                StartElement startElement = xmlEvent.asStartElement();
+                if (outputProcessorChain.getDocumentContext().isInSecurityHeader() && startElement.getName().equals(Constants.TAG_wsse_Security)) {
+                    OutputProcessorChain subOutputProcessorChain = outputProcessorChain.createSubChain(this);
+
+                    X509Certificate x509Certificate = securityToken.getKeyWrappingToken().getX509Certificates()[0];
+
+                    Map<QName, String> attributes = new HashMap<QName, String>();
+                    attributes.put(Constants.ATT_NULL_Id, securityToken.getId());
+                    createStartElementAndOutputAsEvent(subOutputProcessorChain, Constants.TAG_xenc_EncryptedKey, attributes);
+
+                    attributes = new HashMap<QName, String>();
+                    attributes.put(Constants.ATT_NULL_Algorithm, getSecurityProperties().getEncryptionKeyTransportAlgorithm());
+                    createStartElementAndOutputAsEvent(subOutputProcessorChain, Constants.TAG_xenc_EncryptionMethod, attributes);
+                    createEndElementAndOutputAsEvent(subOutputProcessorChain, Constants.TAG_xenc_EncryptionMethod);
+                    createStartElementAndOutputAsEvent(subOutputProcessorChain, Constants.TAG_dsig_KeyInfo, null);
+                    createSecurityTokenReferenceStructureForEncryptedKey(subOutputProcessorChain, securityToken, getSecurityProperties().getEncryptionKeyIdentifierType(), getSecurityProperties().isUseSingleCert());
+                    createEndElementAndOutputAsEvent(subOutputProcessorChain, Constants.TAG_dsig_KeyInfo);
+                    createStartElementAndOutputAsEvent(subOutputProcessorChain, Constants.TAG_xenc_CipherData, null);
+                    createStartElementAndOutputAsEvent(subOutputProcessorChain, Constants.TAG_xenc_CipherValue, null);
+
+                    try {
+                        //encrypt the symmetric session key with the public key from the receiver:
+                        String jceid = JCEAlgorithmMapper.translateURItoJCEID(getSecurityProperties().getEncryptionKeyTransportAlgorithm());
+                        Cipher cipher = Cipher.getInstance(jceid);
+                        cipher.init(Cipher.ENCRYPT_MODE, x509Certificate);
+
+                        byte[] ephemeralKey = securityToken.getSecretKey(null, null).getEncoded();
+
+                        int blockSize = cipher.getBlockSize();
+                        if (blockSize > 0 && blockSize < ephemeralKey.length) {
+                            throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, "unsupportedKeyTransp", "public key algorithm too weak to encrypt symmetric key"
+                            );
+                        }
+                        byte[] encryptedEphemeralKey = cipher.doFinal(ephemeralKey);
+
+                        createCharactersAndOutputAsEvent(subOutputProcessorChain, new Base64(76, new byte[]{'\n'}).encodeToString(encryptedEphemeralKey));
+
+                    } catch (NoSuchPaddingException e) {
+                        throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_ENCRYPTION, e);
+                    } catch (NoSuchAlgorithmException e) {
+                        throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_ENCRYPTION, e);
+                    } catch (InvalidKeyException e) {
+                        throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_ENCRYPTION, e);
+                    } catch (BadPaddingException e) {
+                        throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_ENCRYPTION, e);
+                    } catch (IllegalBlockSizeException e) {
+                        throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_ENCRYPTION, e);
+                    }
+
+                    createEndElementAndOutputAsEvent(subOutputProcessorChain, Constants.TAG_xenc_CipherValue);
+                    createEndElementAndOutputAsEvent(subOutputProcessorChain, Constants.TAG_xenc_CipherData);
+
+                    if (getAction() == Constants.Action.ENCRYPT) {
+                        createReferenceListStructure(subOutputProcessorChain);
+                    }
+                    createEndElementAndOutputAsEvent(subOutputProcessorChain, Constants.TAG_xenc_EncryptedKey);
+                    outputProcessorChain.removeProcessor(this);
+                }
+            }
+        }
+    }
+}

Propchange: webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/processor/output/EncryptedKeyOutputProcessor.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Added: webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/processor/output/FinalOutputProcessor.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/processor/output/FinalOutputProcessor.java?rev=1172285&view=auto
==============================================================================
--- webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/processor/output/FinalOutputProcessor.java (added)
+++ webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/processor/output/FinalOutputProcessor.java Sun Sep 18 13:51:23 2011
@@ -0,0 +1,69 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.swssf.impl.processor.output;
+
+import org.swssf.ext.*;
+
+import javax.xml.stream.XMLEventWriter;
+import javax.xml.stream.XMLOutputFactory;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.events.XMLEvent;
+import java.io.OutputStream;
+
+/**
+ * Processor which outputs the XMLEvents to an outputStream
+ * This Processor can be extended to allow to write to a StAX writer instead of directly to an output stream
+ *
+ * @author $Author$
+ * @version $Revision$ $Date$
+ */
+public class FinalOutputProcessor extends AbstractOutputProcessor {
+
+    private XMLEventWriter xmlEventWriter;
+    private static final XMLOutputFactory xmlOutputFactory = XMLOutputFactory.newInstance();
+
+    static {
+        xmlOutputFactory.setProperty(XMLOutputFactory.IS_REPAIRING_NAMESPACES, false);
+    }
+
+    public FinalOutputProcessor(OutputStream outputStream, String encoding, SecurityProperties securityProperties, Constants.Action action) throws WSSecurityException {
+        super(securityProperties, action);
+        setPhase(Constants.Phase.POSTPROCESSING);
+        try {
+            xmlEventWriter = xmlOutputFactory.createXMLEventWriter(outputStream, encoding);
+        } catch (XMLStreamException e) {
+            throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, e);
+        }
+    }
+
+    @Override
+    public void processEvent(XMLEvent xmlEvent, OutputProcessorChain outputProcessorChain) throws XMLStreamException, WSSecurityException {
+        xmlEventWriter.add(xmlEvent);
+    }
+
+    @Override
+    public void doFinal(OutputProcessorChain outputProcessorChain) throws WSSecurityException {
+        try {
+            xmlEventWriter.flush();
+            xmlEventWriter.close();
+        } catch (XMLStreamException e) {
+            throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, e);
+        }
+    }
+}

Propchange: webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/processor/output/FinalOutputProcessor.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Added: webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/processor/output/SAMLTokenOutputProcessor.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/processor/output/SAMLTokenOutputProcessor.java?rev=1172285&view=auto
==============================================================================
--- webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/processor/output/SAMLTokenOutputProcessor.java (added)
+++ webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/processor/output/SAMLTokenOutputProcessor.java Sun Sep 18 13:51:23 2011
@@ -0,0 +1,332 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.swssf.impl.processor.output;
+
+import org.opensaml.common.SAMLVersion;
+import org.swssf.crypto.Crypto;
+import org.swssf.ext.*;
+import org.swssf.impl.saml.OpenSAMLUtil;
+import org.swssf.impl.saml.SAMLAssertionWrapper;
+import org.swssf.impl.saml.SAMLCallback;
+import org.swssf.impl.saml.SAMLKeyInfo;
+import org.swssf.impl.saml.bean.KeyInfoBean;
+import org.swssf.impl.saml.bean.SubjectBean;
+import org.swssf.impl.securityToken.ProcessorInfoSecurityToken;
+import org.swssf.impl.securityToken.SAMLSecurityToken;
+import org.w3c.dom.*;
+
+import javax.xml.namespace.QName;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.events.StartElement;
+import javax.xml.stream.events.XMLEvent;
+import java.security.Key;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.security.cert.X509Certificate;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+
+/**
+ * @author $Author$
+ * @version $Revision$ $Date$
+ */
+public class SAMLTokenOutputProcessor extends AbstractOutputProcessor {
+
+    public SAMLTokenOutputProcessor(SecurityProperties securityProperties, Constants.Action action) throws WSSecurityException {
+        super(securityProperties, action);
+    }
+
+    @Override
+    public void processEvent(XMLEvent xmlEvent, final OutputProcessorChain outputProcessorChain) throws XMLStreamException, WSSecurityException {
+
+        try {
+            final SAMLCallback samlCallback = new SAMLCallback();
+            Utils.doPasswordCallback(getSecurityProperties().getCallbackHandler(), samlCallback);
+            SAMLAssertionWrapper samlAssertionWrapper = new SAMLAssertionWrapper(samlCallback);
+
+            boolean senderVouches = false;
+            List<String> methods = samlAssertionWrapper.getConfirmationMethods();
+            if (methods != null && methods.size() > 0) {
+                String confirmMethod = methods.get(0);
+                if (OpenSAMLUtil.isMethodSenderVouches(confirmMethod)) {
+                    senderVouches = true;
+                }
+            }
+
+            final String securityTokenReferenceId = "STRSAMLId-" + UUID.randomUUID().toString();
+            final String binarySecurityTokenId = "BST-" + UUID.randomUUID().toString();
+            final String tokenId = samlAssertionWrapper.getId();
+
+            PrivateKey privateKey = null;
+            X509Certificate[] certificates = null;
+
+            if (senderVouches) {
+                // prepare to sign the SAML token
+                certificates = samlCallback.getIssuerCrypto().getCertificates(samlCallback.getIssuerKeyName());
+                if (certificates == null) {
+                    throw new WSSecurityException(
+                            "No issuer certs were found to sign the SAML Assertion using issuer name: "
+                                    + samlCallback.getIssuerKeyName()
+                    );
+                }
+                try {
+                    privateKey = samlCallback.getIssuerCrypto().getPrivateKey(samlCallback.getIssuerKeyName(), samlCallback.getIssuerKeyPassword());
+                } catch (Exception ex) {
+                    throw new WSSecurityException(ex.getMessage(), ex);
+                }
+            } else {
+                SubjectBean subjectBean = samlCallback.getSubject();
+                if (subjectBean != null) {
+                    KeyInfoBean keyInfoBean = subjectBean.getKeyInfo();
+                    if (keyInfoBean != null) {
+                        X509Certificate x509Certificate = keyInfoBean.getCertificate();
+                        if (x509Certificate != null) {
+                            String alias = getSecurityProperties().getSignatureCrypto().getAliasForX509Cert(x509Certificate);
+                            if (alias == null) {
+                                throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, "aliasIsNull");
+                            }
+                            WSPasswordCallback wsPasswordCallback = new WSPasswordCallback(alias, WSPasswordCallback.Usage.SIGNATURE);
+                            Utils.doPasswordCallback(getSecurityProperties().getCallbackHandler(), wsPasswordCallback);
+                            certificates = getSecurityProperties().getSignatureCrypto().getCertificates(alias);
+                            privateKey = getSecurityProperties().getSignatureCrypto().getPrivateKey(alias, wsPasswordCallback.getPassword());
+                        }
+                    }
+                }
+            }
+
+            final SAMLKeyInfo samlKeyInfo = new SAMLKeyInfo(certificates);
+            samlKeyInfo.setPublicKey(certificates[0].getPublicKey());
+            samlKeyInfo.setPrivateKey(privateKey);
+
+            final X509Certificate[] x509Certificates;
+            if (certificates != null && certificates.length > 0) {
+                x509Certificates = certificates;
+            } else {
+                x509Certificates = null;
+            }
+
+            final PrivateKey secretKey = privateKey;
+
+            final SecurityToken securityToken;
+            SecurityTokenProvider securityTokenProvider;
+            if (senderVouches) {
+                securityToken = new ProcessorInfoSecurityToken() {
+
+                    private OutputProcessor outputProcessor;
+
+                    public void setProcessor(OutputProcessor outputProcessor) {
+                        this.outputProcessor = outputProcessor;
+                    }
+
+                    public String getId() {
+                        return binarySecurityTokenId;
+                    }
+
+                    public Object getProcessor() {
+                        return outputProcessor;
+                    }
+
+                    public boolean isAsymmetric() {
+                        return true;
+                    }
+
+                    public Key getSecretKey(String algorithmURI, Constants.KeyUsage keyUsage) throws WSSecurityException {
+                        return secretKey;
+                    }
+
+                    public PublicKey getPublicKey(Constants.KeyUsage keyUsage) throws WSSecurityException {
+                        return x509Certificates[0].getPublicKey();
+                    }
+
+                    public X509Certificate[] getX509Certificates() throws WSSecurityException {
+                        return x509Certificates;
+                    }
+
+                    public void verify() throws WSSecurityException {
+                    }
+
+                    public SecurityToken getKeyWrappingToken() {
+                        return null;
+                    }
+
+                    public String getKeyWrappingTokenAlgorithm() {
+                        return null;
+                    }
+
+                    public Constants.TokenType getTokenType() {
+                        //todo pkiPathToken etc?
+                        return Constants.TokenType.X509V3Token;
+                    }
+                };
+            } else {
+                securityToken = null;
+            }
+
+            final FinalSAMLTokenOutputProcessor finalSAMLTokenOutputProcessor = new FinalSAMLTokenOutputProcessor(getSecurityProperties(), getAction(), securityToken, samlAssertionWrapper, securityTokenReferenceId, binarySecurityTokenId, senderVouches);
+
+            if (senderVouches) {
+
+                securityTokenProvider = new SecurityTokenProvider() {
+                    public SecurityToken getSecurityToken(Crypto crypto) throws WSSecurityException {
+                        return securityToken;
+                    }
+
+                    public String getId() {
+                        return binarySecurityTokenId;
+                    }
+                };
+
+                outputProcessorChain.getSecurityContext().registerSecurityTokenProvider(binarySecurityTokenId, securityTokenProvider);
+                outputProcessorChain.getSecurityContext().put(Constants.PROP_USE_THIS_TOKEN_ID_FOR_SIGNATURE, binarySecurityTokenId);
+                outputProcessorChain.getSecurityContext().put(Constants.PROP_APPEND_SIGNATURE_ON_THIS_ID, securityTokenReferenceId);
+            } else {
+                securityTokenProvider = new SecurityTokenProvider() {
+                    public SecurityToken getSecurityToken(Crypto crypto) throws WSSecurityException {
+                        return new SAMLSecurityToken(samlCallback.getSamlVersion(), samlKeyInfo, outputProcessorChain.getSecurityContext(), crypto, getSecurityProperties().getCallbackHandler(), tokenId, finalSAMLTokenOutputProcessor);
+                    }
+
+                    public String getId() {
+                        return tokenId;
+                    }
+                };
+
+                outputProcessorChain.getSecurityContext().registerSecurityTokenProvider(tokenId, securityTokenProvider);
+                outputProcessorChain.getSecurityContext().put(Constants.PROP_USE_THIS_TOKEN_ID_FOR_SIGNATURE, tokenId);
+                outputProcessorChain.getSecurityContext().put(Constants.PROP_APPEND_SIGNATURE_ON_THIS_ID, tokenId);
+            }
+
+
+            switch (getAction()) {
+                case SAML_TOKEN_SIGNED:
+                    if (senderVouches) {
+                        SecurePart securePart = new SecurePart(Constants.SOAPMESSAGE_NS10_STRTransform, null, SecurePart.Modifier.Element, tokenId, securityTokenReferenceId);
+                        outputProcessorChain.getSecurityContext().putAsList(SecurePart.class, securePart);
+                    }
+                    break;
+                case SAML_TOKEN_UNSIGNED:
+                    break;
+            }
+            outputProcessorChain.addProcessor(finalSAMLTokenOutputProcessor);
+        } finally {
+            outputProcessorChain.removeProcessor(this);
+        }
+        outputProcessorChain.processEvent(xmlEvent);
+    }
+
+    class FinalSAMLTokenOutputProcessor extends AbstractOutputProcessor {
+
+        private SecurityToken securityToken;
+        private SAMLAssertionWrapper samlAssertionWrapper;
+        private String securityTokenReferenceId;
+        private String binarySecurityTokenReferenceId;
+        private boolean senderVouches = false;
+
+        FinalSAMLTokenOutputProcessor(SecurityProperties securityProperties, Constants.Action action, SecurityToken securityToken, SAMLAssertionWrapper samlAssertionWrapper, String securityTokenReferenceId, String binarySecurityTokenReferenceId, boolean senderVouches)
+                throws WSSecurityException {
+            super(securityProperties, action);
+            this.getAfterProcessors().add(UsernameTokenOutputProcessor.class.getName());
+            this.getAfterProcessors().add(SAMLTokenOutputProcessor.class.getName());
+            this.samlAssertionWrapper = samlAssertionWrapper;
+            this.securityTokenReferenceId = securityTokenReferenceId;
+            this.senderVouches = senderVouches;
+            this.binarySecurityTokenReferenceId = binarySecurityTokenReferenceId;
+            this.securityToken = securityToken;
+        }
+
+        @Override
+        public void processEvent(XMLEvent xmlEvent, OutputProcessorChain outputProcessorChain) throws XMLStreamException, WSSecurityException {
+            outputProcessorChain.processEvent(xmlEvent);
+            if (xmlEvent.isStartElement()) {
+                StartElement startElement = xmlEvent.asStartElement();
+                if (outputProcessorChain.getDocumentContext().isInSecurityHeader() && startElement.getName().equals(Constants.TAG_wsse_Security)) {
+                    OutputProcessorChain subOutputProcessorChain = outputProcessorChain.createSubChain(this);
+                    if (senderVouches && getSecurityProperties().getSignatureKeyIdentifierType() == Constants.KeyIdentifierType.BST_DIRECT_REFERENCE) {
+                        outputBinarySecurityToken(outputProcessorChain, binarySecurityTokenReferenceId, securityToken.getX509Certificates(), getSecurityProperties().isUseSingleCert());
+                    }
+                    outputSamlAssertion(samlAssertionWrapper.toDOM(null), subOutputProcessorChain);
+                    if (senderVouches) {
+                        outputSecurityTokenReference(subOutputProcessorChain, samlAssertionWrapper, securityTokenReferenceId, samlAssertionWrapper.getId());
+                    }
+                    outputProcessorChain.removeProcessor(this);
+                }
+            }
+        }
+    }
+
+    private void outputSecurityTokenReference(OutputProcessorChain outputProcessorChain, SAMLAssertionWrapper samlAssertionWrapper, String referenceId, String tokenId) throws XMLStreamException, WSSecurityException {
+        Map<QName, String> attributes = new HashMap<QName, String>();
+        if (samlAssertionWrapper.getSAMLVersion() == SAMLVersion.VERSION_11) {
+            attributes.put(Constants.ATT_wsse11_TokenType, Constants.NS_SAML11_TOKEN_PROFILE_TYPE);
+        } else {
+            attributes.put(Constants.ATT_wsse11_TokenType, Constants.NS_SAML20_TOKEN_PROFILE_TYPE);
+        }
+        attributes.put(Constants.ATT_wsu_Id, referenceId);
+        createStartElementAndOutputAsEvent(outputProcessorChain, Constants.TAG_wsse_SecurityTokenReference, attributes);
+        attributes = new HashMap<QName, String>();
+        if (samlAssertionWrapper.getSAMLVersion() == SAMLVersion.VERSION_11) {
+            attributes.put(Constants.ATT_NULL_ValueType, Constants.NS_SAML10_TYPE);
+        } else {
+            attributes.put(Constants.ATT_NULL_ValueType, Constants.NS_SAML20_TYPE);
+        }
+        createStartElementAndOutputAsEvent(outputProcessorChain, Constants.TAG_wsse_KeyIdentifier, attributes);
+        createCharactersAndOutputAsEvent(outputProcessorChain, tokenId);
+        createEndElementAndOutputAsEvent(outputProcessorChain, Constants.TAG_wsse_KeyIdentifier);
+        createEndElementAndOutputAsEvent(outputProcessorChain, Constants.TAG_wsse_SecurityTokenReference);
+    }
+
+    private void outputBinarySecurityToken(OutputProcessorChain outputProcessorChain, String referenceId, X509Certificate[] x509Certificates, boolean useSingleCertificate) throws XMLStreamException, WSSecurityException {
+        createBinarySecurityTokenStructure(outputProcessorChain, referenceId, x509Certificates, useSingleCertificate);
+    }
+
+    //todo serialize directly from SAML XMLObject?
+    private void outputSamlAssertion(Element element, OutputProcessorChain outputProcessorChain) throws XMLStreamException, WSSecurityException {
+
+        Map<QName, String> attributes = new HashMap<QName, String>();
+        Map<QName, String> namespaces = new HashMap<QName, String>();
+        NamedNodeMap namedNodeMap = element.getAttributes();
+        for (int i = 0; i < namedNodeMap.getLength(); i++) {
+            Attr attribute = (Attr) namedNodeMap.item(i);
+            if ("xmlns".equals(attribute.getPrefix()) || "xmlns".equals(attribute.getLocalName())) {
+                namespaces.put(new QName(attribute.getNamespaceURI(), attribute.getLocalName(), attribute.getPrefix()), attribute.getValue());
+            } else if (attribute.getPrefix() == null) {
+                attributes.put(new QName(attribute.getNamespaceURI(), attribute.getLocalName()), attribute.getValue());
+            } else {
+                attributes.put(new QName(attribute.getNamespaceURI(), attribute.getLocalName(), attribute.getPrefix()), attribute.getValue());
+            }
+        }
+
+        QName elementName = new QName(element.getNamespaceURI(), element.getLocalName(), element.getPrefix());
+        createStartElementAndOutputAsEvent(outputProcessorChain, elementName, namespaces, attributes);
+        NodeList childNodes = element.getChildNodes();
+        for (int i = 0; i < childNodes.getLength(); i++) {
+            Node childNode = childNodes.item(i);
+            switch (childNode.getNodeType()) {
+                case Node.ELEMENT_NODE:
+                    outputSamlAssertion((Element) childNode, outputProcessorChain);
+                    break;
+                case Node.TEXT_NODE:
+                    createCharactersAndOutputAsEvent(outputProcessorChain, ((Text) childNode).getData());
+                    break;
+            }
+        }
+        createEndElementAndOutputAsEvent(outputProcessorChain, elementName);
+    }
+}

Propchange: webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/processor/output/SAMLTokenOutputProcessor.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Added: webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/processor/output/SecurityContextTokenOutputProcessor.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/processor/output/SecurityContextTokenOutputProcessor.java?rev=1172285&view=auto
==============================================================================
--- webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/processor/output/SecurityContextTokenOutputProcessor.java (added)
+++ webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/processor/output/SecurityContextTokenOutputProcessor.java Sun Sep 18 13:51:23 2011
@@ -0,0 +1,186 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.swssf.impl.processor.output;
+
+import org.swssf.crypto.Crypto;
+import org.swssf.ext.*;
+import org.swssf.impl.securityToken.ProcessorInfoSecurityToken;
+
+import javax.xml.namespace.QName;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.events.StartElement;
+import javax.xml.stream.events.XMLEvent;
+import java.security.Key;
+import java.security.PublicKey;
+import java.security.cert.X509Certificate;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.UUID;
+
+/**
+ * @author $Author$
+ * @version $Revision$ $Date$
+ */
+public class SecurityContextTokenOutputProcessor extends AbstractOutputProcessor {
+
+    public SecurityContextTokenOutputProcessor(SecurityProperties securityProperties, Constants.Action action) throws WSSecurityException {
+        super(securityProperties, action);
+    }
+
+    @Override
+    public void processEvent(XMLEvent xmlEvent, OutputProcessorChain outputProcessorChain) throws XMLStreamException, WSSecurityException {
+        try {
+            String tokenId = outputProcessorChain.getSecurityContext().get(Constants.PROP_USE_THIS_TOKEN_ID_FOR_SECURITYCONTEXTTOKEN);
+            if (tokenId == null) {
+                throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_ENCRYPTION);
+            }
+            SecurityTokenProvider wrappingSecurityTokenProvider = outputProcessorChain.getSecurityContext().getSecurityTokenProvider(tokenId);
+            if (wrappingSecurityTokenProvider == null) {
+                throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_ENCRYPTION);
+            }
+            final SecurityToken wrappingSecurityToken = wrappingSecurityTokenProvider.getSecurityToken(null);
+            if (wrappingSecurityToken == null) {
+                throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_ENCRYPTION);
+            }
+
+            final String wsuId = "SCT-" + UUID.randomUUID().toString();
+            final String identifier = UUID.randomUUID().toString();
+
+            final ProcessorInfoSecurityToken securityContextSecurityToken = new ProcessorInfoSecurityToken() {
+
+                private OutputProcessor outputProcessor;
+
+                public String getId() {
+                    return wsuId;
+                }
+
+                public void setProcessor(OutputProcessor outputProcessor) {
+                    this.outputProcessor = outputProcessor;
+                }
+
+                public Object getProcessor() {
+                    return outputProcessor;
+                }
+
+                public boolean isAsymmetric() {
+                    return wrappingSecurityToken.isAsymmetric();
+                }
+
+                public Key getSecretKey(String algorithmURI, Constants.KeyUsage keyUsage) throws WSSecurityException {
+                    return wrappingSecurityToken.getSecretKey(algorithmURI, keyUsage);
+                }
+
+                public PublicKey getPublicKey(Constants.KeyUsage keyUsage) throws WSSecurityException {
+                    return wrappingSecurityToken.getPublicKey(keyUsage);
+                }
+
+                public X509Certificate[] getX509Certificates() throws WSSecurityException {
+                    return wrappingSecurityToken.getX509Certificates();
+                }
+
+                public void verify() throws WSSecurityException {
+                    wrappingSecurityToken.verify();
+                }
+
+                public SecurityToken getKeyWrappingToken() {
+                    return wrappingSecurityToken;
+                }
+
+                public String getKeyWrappingTokenAlgorithm() {
+                    return null;
+                }
+
+                public Constants.TokenType getTokenType() {
+                    return Constants.TokenType.SecurityContextToken;
+                }
+            };
+
+            SecurityTokenProvider securityContextSecurityTokenProvider = new SecurityTokenProvider() {
+                public SecurityToken getSecurityToken(Crypto crypto) throws WSSecurityException {
+                    return securityContextSecurityToken;
+                }
+
+                public String getId() {
+                    return wsuId;
+                }
+            };
+
+            FinalSecurityContextTokenOutputProcessor finalSecurityContextTokenOutputProcessor = new FinalSecurityContextTokenOutputProcessor(getSecurityProperties(), getAction(), securityContextSecurityToken, identifier);
+            switch (getAction()) {
+                case SIGNATURE_WITH_DERIVED_KEY:
+                    outputProcessorChain.getSecurityContext().put(Constants.PROP_USE_THIS_TOKEN_ID_FOR_DERIVED_KEY, wsuId);
+                    if (wrappingSecurityToken.getProcessor() != null) {
+                        finalSecurityContextTokenOutputProcessor.getBeforeProcessors().add(wrappingSecurityToken.getProcessor());
+                    } else {
+                        finalSecurityContextTokenOutputProcessor.getBeforeProcessors().add(SignatureOutputProcessor.class.getName());
+                    }
+                    break;
+                case ENCRYPT_WITH_DERIVED_KEY:
+                    outputProcessorChain.getSecurityContext().put(Constants.PROP_USE_THIS_TOKEN_ID_FOR_DERIVED_KEY, wsuId);
+                    if (wrappingSecurityToken.getProcessor() != null) {
+                        finalSecurityContextTokenOutputProcessor.getBeforeProcessors().add(wrappingSecurityToken.getProcessor());
+                    } else {
+                        finalSecurityContextTokenOutputProcessor.getAfterProcessors().add(EncryptEndingOutputProcessor.class.getName());
+                    }
+                    break;
+            }
+
+            outputProcessorChain.getSecurityContext().registerSecurityTokenProvider(wsuId, securityContextSecurityTokenProvider);
+            securityContextSecurityToken.setProcessor(finalSecurityContextTokenOutputProcessor);
+            outputProcessorChain.addProcessor(finalSecurityContextTokenOutputProcessor);
+
+        } finally {
+            outputProcessorChain.removeProcessor(this);
+        }
+        outputProcessorChain.processEvent(xmlEvent);
+    }
+
+    class FinalSecurityContextTokenOutputProcessor extends AbstractOutputProcessor {
+
+        private SecurityToken securityToken;
+        private String identifier;
+
+        FinalSecurityContextTokenOutputProcessor(SecurityProperties securityProperties, Constants.Action action, SecurityToken securityToken, String identifier) throws WSSecurityException {
+            super(securityProperties, action);
+            this.securityToken = securityToken;
+            this.identifier = identifier;
+        }
+
+        @Override
+        public void processEvent(XMLEvent xmlEvent, OutputProcessorChain outputProcessorChain) throws XMLStreamException, WSSecurityException {
+            outputProcessorChain.processEvent(xmlEvent);
+            if (xmlEvent.isStartElement()) {
+                StartElement startElement = xmlEvent.asStartElement();
+                if (outputProcessorChain.getDocumentContext().isInSecurityHeader() && startElement.getName().equals(Constants.TAG_wsse_Security)) {
+                    OutputProcessorChain subOutputProcessorChain = outputProcessorChain.createSubChain(this);
+
+                    Map<QName, String> attributes = new HashMap<QName, String>();
+                    attributes.put(Constants.ATT_wsu_Id, securityToken.getId());
+                    createStartElementAndOutputAsEvent(subOutputProcessorChain, Constants.TAG_wsc0502_SecurityContextToken, attributes);
+                    createStartElementAndOutputAsEvent(subOutputProcessorChain, Constants.TAG_wsc0502_Identifier, null);
+                    createCharactersAndOutputAsEvent(subOutputProcessorChain, identifier);
+                    createEndElementAndOutputAsEvent(subOutputProcessorChain, Constants.TAG_wsc0502_Identifier);
+                    createEndElementAndOutputAsEvent(subOutputProcessorChain, Constants.TAG_wsc0502_SecurityContextToken);
+
+                    outputProcessorChain.removeProcessor(this);
+                }
+            }
+        }
+    }
+}

Propchange: webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/processor/output/SecurityContextTokenOutputProcessor.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Added: webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/processor/output/SecurityHeaderOutputProcessor.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/processor/output/SecurityHeaderOutputProcessor.java?rev=1172285&view=auto
==============================================================================
--- webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/processor/output/SecurityHeaderOutputProcessor.java (added)
+++ webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/processor/output/SecurityHeaderOutputProcessor.java Sun Sep 18 13:51:23 2011
@@ -0,0 +1,139 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.swssf.impl.processor.output;
+
+import org.swssf.ext.*;
+
+import javax.xml.namespace.QName;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.events.EndElement;
+import javax.xml.stream.events.StartElement;
+import javax.xml.stream.events.XMLEvent;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Processor to build the Security Header structure
+ *
+ * @author $Author$
+ * @version $Revision$ $Date$
+ */
+public class SecurityHeaderOutputProcessor extends AbstractOutputProcessor {
+
+    public SecurityHeaderOutputProcessor(SecurityProperties securityProperties, Constants.Action action) throws WSSecurityException {
+        super(securityProperties, action);
+        setPhase(Constants.Phase.PREPROCESSING);
+    }
+
+    @Override
+    public void processEvent(XMLEvent xmlEvent, OutputProcessorChain outputProcessorChain) throws XMLStreamException, WSSecurityException {
+
+        boolean eventHandled = false;
+        int level = outputProcessorChain.getDocumentContext().getDocumentLevel();
+
+        String soapMessageVersion = outputProcessorChain.getDocumentContext().getSOAPMessageVersionNamespace();
+
+        if (xmlEvent.isStartElement()) {
+            StartElement startElement = xmlEvent.asStartElement();
+
+            if (level == 1 && soapMessageVersion == null) {
+                throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, "notASOAPMessage");
+            } else if (level == 1 && soapMessageVersion != null) {
+                //set correct namespace on secure parts
+                List<SecurePart> securePartList = securityProperties.getEncryptionSecureParts();
+                for (int i = 0; i < securePartList.size(); i++) {
+                    SecurePart securePart = securePartList.get(i);
+                    if (securePart.getName().equals("Body") && securePart.getNamespace().equals("*")) {
+                        securePart.setNamespace(soapMessageVersion);
+                        break;
+                    }
+                }
+                securePartList = securityProperties.getSignatureSecureParts();
+                for (int j = 0; j < securePartList.size(); j++) {
+                    SecurePart securePart = securePartList.get(j);
+                    if (securePart.getName().equals("Body") && securePart.getNamespace().equals("*")) {
+                        securePart.setNamespace(soapMessageVersion);
+                    }
+                }
+            } else if (level == 3 && startElement.getName().equals(Constants.TAG_wsse_Security)) {
+                if (Utils.isResponsibleActorOrRole(startElement, soapMessageVersion, getSecurityProperties().getActor())) {
+                    outputProcessorChain.getDocumentContext().setInSecurityHeader(true);
+                    //remove this processor. its no longer needed.
+                    outputProcessorChain.removeProcessor(this);
+                }
+            } else if (level == 2
+                    && startElement.getName().getLocalPart().equals(Constants.TAG_soap_Body_LocalName)
+                    && startElement.getName().getNamespaceURI().equals(soapMessageVersion)) {
+                //hmm it seems we don't have a soap header in the current document
+                //so output one and add securityHeader
+
+                //create subchain and output soap-header and securityHeader
+                OutputProcessorChain subOutputProcessorChain = outputProcessorChain.createSubChain(this);
+                createStartElementAndOutputAsEvent(subOutputProcessorChain,
+                        new QName(soapMessageVersion, Constants.TAG_soap_Header_LocalName, Constants.PREFIX_SOAPENV), null);
+                buildSecurityHeader(soapMessageVersion, subOutputProcessorChain);
+                createEndElementAndOutputAsEvent(subOutputProcessorChain,
+                        new QName(soapMessageVersion, Constants.TAG_soap_Header_LocalName, Constants.PREFIX_SOAPENV));
+
+                //output current soap-header event
+                outputProcessorChain.processEvent(xmlEvent);
+                //remove this processor. its no longer needed.
+                outputProcessorChain.removeProcessor(this);
+
+                eventHandled = true;
+            }
+        } else if (xmlEvent.isEndElement()) {
+            EndElement endElement = xmlEvent.asEndElement();
+            if (level == 2 && endElement.getName().equals(Constants.TAG_wsse_Security)) {
+                outputProcessorChain.getDocumentContext().setInSecurityHeader(false);
+            } else if (level == 1 && endElement.getName().getLocalPart().equals(Constants.TAG_soap_Header_LocalName)
+                    && endElement.getName().getNamespaceURI().equals(soapMessageVersion)) {
+                OutputProcessorChain subOutputProcessorChain = outputProcessorChain.createSubChain(this);
+                buildSecurityHeader(soapMessageVersion, subOutputProcessorChain);
+                //output current soap-header event
+                outputProcessorChain.processEvent(xmlEvent);
+                //remove this processor. its no longer needed.
+                outputProcessorChain.removeProcessor(this);
+
+                eventHandled = true;
+            }
+        }
+
+        if (!eventHandled) {
+            outputProcessorChain.processEvent(xmlEvent);
+        }
+    }
+
+    private void buildSecurityHeader(String soapMessageVersion, OutputProcessorChain subOutputProcessorChain) throws XMLStreamException, WSSecurityException {
+        Map<QName, String> attributes = new HashMap<QName, String>();
+        final String actor = getSecurityProperties().getActor();
+        if (actor != null && !"".equals(actor)) {
+            if (Constants.NS_SOAP11.equals(soapMessageVersion)) {
+                attributes.put(Constants.ATT_soap11_Actor, actor);
+            } else {
+                attributes.put(Constants.ATT_soap12_Role, actor);
+            }
+        }
+        subOutputProcessorChain.getDocumentContext().setInSecurityHeader(true);
+        createStartElementAndOutputAsEvent(subOutputProcessorChain, Constants.TAG_wsse_Security, attributes);
+        createEndElementAndOutputAsEvent(subOutputProcessorChain, Constants.TAG_wsse_Security);
+        subOutputProcessorChain.getDocumentContext().setInSecurityHeader(false);
+    }
+}

Propchange: webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/processor/output/SecurityHeaderOutputProcessor.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Added: webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/processor/output/SignatureConfirmationOutputProcessor.java
URL: http://svn.apache.org/viewvc/webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/processor/output/SignatureConfirmationOutputProcessor.java?rev=1172285&view=auto
==============================================================================
--- webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/processor/output/SignatureConfirmationOutputProcessor.java (added)
+++ webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/processor/output/SignatureConfirmationOutputProcessor.java Sun Sep 18 13:51:23 2011
@@ -0,0 +1,83 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.swssf.impl.processor.output;
+
+import org.apache.commons.codec.binary.Base64;
+import org.swssf.ext.*;
+import org.swssf.securityEvent.SecurityEvent;
+import org.swssf.securityEvent.SignatureTokenSecurityEvent;
+
+import javax.xml.namespace.QName;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.events.StartElement;
+import javax.xml.stream.events.XMLEvent;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+
+/**
+ * @author $Author$
+ * @version $Revision$ $Date$
+ */
+public class SignatureConfirmationOutputProcessor extends AbstractOutputProcessor {
+
+    public SignatureConfirmationOutputProcessor(SecurityProperties securityProperties, Constants.Action action) throws WSSecurityException {
+        super(securityProperties, action);
+        getBeforeProcessors().add(SignatureOutputProcessor.class.getName());
+        getBeforeProcessors().add(EncryptOutputProcessor.class.getName());
+    }
+
+    @Override
+    public void processEvent(XMLEvent xmlEvent, OutputProcessorChain outputProcessorChain) throws XMLStreamException, WSSecurityException {
+        outputProcessorChain.processEvent(xmlEvent);
+        if (xmlEvent.isStartElement()) {
+            StartElement startElement = xmlEvent.asStartElement();
+            if (outputProcessorChain.getDocumentContext().isInSecurityHeader() && startElement.getName().equals(Constants.TAG_wsse_Security)) {
+                OutputProcessorChain subOutputProcessorChain = outputProcessorChain.createSubChain(this);
+
+                boolean aSignatureFound = false;
+
+                List<SecurityEvent> requestSecurityEvents = outputProcessorChain.getSecurityContext().getAsList(SecurityEvent.class);
+                for (int i = 0; i < requestSecurityEvents.size(); i++) {
+                    SecurityEvent securityEvent = requestSecurityEvents.get(i);
+                    if (securityEvent.getSecurityEventType() == SecurityEvent.Event.SignatureToken) {
+                        aSignatureFound = true;
+                        SignatureTokenSecurityEvent signatureTokenSecurityEvent = (SignatureTokenSecurityEvent) securityEvent;
+
+                        Map<QName, String> attributes = new HashMap<QName, String>();
+                        attributes.put(Constants.ATT_wsu_Id, "SigConf-" + UUID.randomUUID().toString());
+                        attributes.put(Constants.ATT_NULL_Value, new Base64(76, new byte[]{'\n'}).encodeToString(signatureTokenSecurityEvent.getSignatureValue()));
+                        createStartElementAndOutputAsEvent(subOutputProcessorChain, Constants.TAG_wsse11_SignatureConfirmation, attributes);
+                        createEndElementAndOutputAsEvent(subOutputProcessorChain, Constants.TAG_wsse11_SignatureConfirmation);
+                    }
+                }
+
+                if (!aSignatureFound) {
+                    Map<QName, String> attributes = new HashMap<QName, String>();
+                    attributes.put(Constants.ATT_wsu_Id, "SigConf-" + UUID.randomUUID().toString());
+                    createStartElementAndOutputAsEvent(subOutputProcessorChain, Constants.TAG_wsse11_SignatureConfirmation, attributes);
+                    createEndElementAndOutputAsEvent(subOutputProcessorChain, Constants.TAG_wsse11_SignatureConfirmation);
+                }
+
+                outputProcessorChain.removeProcessor(this);
+            }
+        }
+    }
+}

Propchange: webservices/wss4j/branches/swssf/streaming-ws-security/src/main/java/org/swssf/impl/processor/output/SignatureConfirmationOutputProcessor.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision