camel-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From davscl...@apache.org
Subject [2/3] CAMEL-7618: Enhancement for xmlsecurity Component: Detached XML Signatures. Thanks to Franz Forsthofer for the patch.
Date Tue, 22 Jul 2014 09:26:34 GMT
http://git-wip-us.apache.org/repos/asf/camel/blob/12241987/components/camel-xmlsecurity/src/main/java/org/apache/camel/component/xmlsecurity/processor/XmlVerifierProcessor.java
----------------------------------------------------------------------
diff --git a/components/camel-xmlsecurity/src/main/java/org/apache/camel/component/xmlsecurity/processor/XmlVerifierProcessor.java b/components/camel-xmlsecurity/src/main/java/org/apache/camel/component/xmlsecurity/processor/XmlVerifierProcessor.java
index 88863c0..37e2cc7 100644
--- a/components/camel-xmlsecurity/src/main/java/org/apache/camel/component/xmlsecurity/processor/XmlVerifierProcessor.java
+++ b/components/camel-xmlsecurity/src/main/java/org/apache/camel/component/xmlsecurity/processor/XmlVerifierProcessor.java
@@ -34,10 +34,12 @@ import javax.xml.crypto.dsig.XMLSignatureException;
 import javax.xml.crypto.dsig.XMLSignatureFactory;
 import javax.xml.crypto.dsig.dom.DOMValidateContext;
 import javax.xml.crypto.dsig.keyinfo.KeyInfo;
+import javax.xml.parsers.DocumentBuilder;
 import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.validation.Schema;
 
 import org.w3c.dom.Document;
-import org.w3c.dom.Node;
+import org.w3c.dom.Element;
 import org.w3c.dom.NodeList;
 import org.xml.sax.SAXException;
 
@@ -49,19 +51,19 @@ import org.apache.camel.component.xmlsecurity.api.XmlSignatureChecker;
 import org.apache.camel.component.xmlsecurity.api.XmlSignatureFormatException;
 import org.apache.camel.component.xmlsecurity.api.XmlSignatureHelper;
 import org.apache.camel.component.xmlsecurity.api.XmlSignatureInvalidException;
+import org.apache.camel.processor.validation.DefaultValidationErrorHandler;
+import org.apache.camel.processor.validation.ValidatorErrorHandler;
 import org.apache.camel.util.IOHelper;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-
 /**
  * XML signature verifier. Assumes that the input XML contains exactly one
  * Signature element.
  */
 public class XmlVerifierProcessor extends XmlSignatureProcessor {
 
-    private static final Logger LOG = LoggerFactory
-        .getLogger(XmlVerifierProcessor.class);
+    private static final Logger LOG = LoggerFactory.getLogger(XmlVerifierProcessor.class);
 
     private final XmlVerifierConfiguration config;
 
@@ -75,8 +77,7 @@ public class XmlVerifierProcessor extends XmlSignatureProcessor {
     }
 
     @Override
-    public void process(Exchange exchange) throws Exception {
-
+    public void process(Exchange exchange) throws Exception { //NOPMD
         InputStream stream = exchange.getIn().getMandatoryBody(InputStream.class);
         try {
             // lets setup the out message before we invoke the signing
@@ -94,13 +95,10 @@ public class XmlVerifierProcessor extends XmlSignatureProcessor {
         }
     }
 
-    protected void verify(InputStream input, final Message out)
-        throws Exception {
-
+    @SuppressWarnings("unchecked")
+    protected void verify(InputStream input, final Message out) throws Exception { //NOPMD
         LOG.debug("Verification of XML signature document started");
-        final Document doc = parseInput(input);
-
-        Node signatureNode = getSignatureNode(doc);
+        final Document doc = parseInput(input, out);
 
         XMLSignatureFactory fac;
         // Try to install the Santuario Provider - fall back to the JDK provider if this does
@@ -116,10 +114,10 @@ public class XmlVerifierProcessor extends XmlSignatureProcessor {
             throw new IllegalStateException("Wrong configuration. Key selector is missing.");
         }
 
-        DOMValidateContext valContext = new DOMValidateContext(selector, signatureNode);
+        DOMValidateContext valContext = new DOMValidateContext(selector, doc);
         valContext.setProperty("javax.xml.crypto.dsig.cacheReference", Boolean.TRUE);
         valContext.setProperty("org.jcp.xml.dsig.validateManifests", Boolean.TRUE);
-        
+
         if (getConfiguration().getSecureValidation() == Boolean.TRUE) {
             valContext.setProperty("org.apache.jcp.xml.dsig.secureValidation", Boolean.TRUE);
             valContext.setProperty("org.jcp.xml.dsig.secureValidation", Boolean.TRUE);
@@ -128,75 +126,52 @@ public class XmlVerifierProcessor extends XmlSignatureProcessor {
 
         setCryptoContextProperties(valContext);
 
-        final XMLSignature signature = fac.unmarshalXMLSignature(valContext);
+        NodeList signatureNodes = getSignatureNodes(doc);
 
-        executeApplicationCheck(out, doc, signature);
+        List<XMLObject> collectedObjects = new ArrayList<XMLObject>(3);
+        List<Reference> collectedReferences = new ArrayList<Reference>(3);
+        int totalCount = signatureNodes.getLength();
+        for (int i = 0; i < totalCount; i++) {
 
-        boolean coreValidity;
-        try {
-            coreValidity = signature.validate(valContext);
-        } catch (XMLSignatureException se) {
-            throw getConfiguration().getValidationFailedHandler().onXMLSignatureException(se);
-        }
-        // Check core validation status
-        boolean goon = coreValidity;
-        if (!coreValidity) {
-            goon = handleSignatureValidationFailed(valContext, signature);
-        }
-        if (goon) {
-            LOG.debug("XML signature verified");
-            map2Message(signature, out, doc);
-        } else {
-            throw new XmlSignatureInvalidException("");
-        }
-    }
-
-    private void executeApplicationCheck(final Message out, final Document doc,
-                                         final XMLSignature signature) throws Exception {
-        if (getConfiguration().getXmlSignatureChecker() != null) {
-            XmlSignatureChecker.Input checkerInput = new XmlSignatureChecker.Input() {
+            Element signatureNode = (Element) signatureNodes.item(i);
 
-                @Override
-                public SignedInfo getSignedInfo() {
-                    return signature.getSignedInfo();
-                }
+            valContext.setNode(signatureNode);
+            final XMLSignature signature = fac.unmarshalXMLSignature(valContext);
 
-                @Override
-                public SignatureValue getSignatureValue() {
-                    return signature.getSignatureValue();
-                }
-
-                @SuppressWarnings("unchecked")
-                @Override
-                public List<? extends XMLObject> getObjects() {
-                    return signature.getObjects();
-                }
-
-                @Override
-                public Document getMessageBodyDocument() {
-                    return doc;
-                }
-
-                @Override
-                public Message getMessage() {
-                    return out;
-                }
+            if (getConfiguration().getXmlSignatureChecker() != null) {
+                XmlSignatureChecker.Input checkerInput = new CheckerInputBuilder().message(out).messageBodyDocument(doc)
+                        .keyInfo(signature.getKeyInfo()).currentCountOfSignatures(i + 1).currentSignatureElement(signatureNode)
+                        .objects(signature.getObjects()).signatureValue(signature.getSignatureValue())
+                        .signedInfo(signature.getSignedInfo()).totalCountOfSignatures(totalCount)
+                        .xmlSchemaValidationExecuted(getSchemaResourceUri(out) != null).build();
+                getConfiguration().getXmlSignatureChecker().checkBeforeCoreValidation(checkerInput);
+            }
 
-                @Override
-                public KeyInfo getKeyInfo() {
-                    return signature.getKeyInfo();
-                }
-            };
-            getConfiguration().getXmlSignatureChecker().checkBeforeCoreValidation(checkerInput);
+            boolean coreValidity;
+            try {
+                coreValidity = signature.validate(valContext);
+            } catch (XMLSignatureException se) {
+                throw getConfiguration().getValidationFailedHandler().onXMLSignatureException(se);
+            }
+            // Check core validation status
+            boolean goon = coreValidity;
+            if (!coreValidity) {
+                goon = handleSignatureValidationFailed(valContext, signature);
+            }
+            if (goon) {
+                LOG.debug("XML signature {} verified", i + 1);
+            } else {
+                throw new XmlSignatureInvalidException("XML signature validation failed");
+            }
+            collectedObjects.addAll((List<XMLObject>) signature.getObjects());
+            collectedReferences.addAll((List<Reference>) signature.getSignedInfo().getReferences());
         }
+        map2Message(collectedReferences, collectedObjects, out, doc);
     }
 
-    private void map2Message(XMLSignature signature, Message out,
-                             final Document messageBodyDocument) throws Exception {
-        @SuppressWarnings("unchecked")
-        final List<Reference> refs = new ArrayList<Reference>(signature.getSignedInfo().getReferences());
-        @SuppressWarnings("unchecked")
-        final List<XMLObject> objs = new ArrayList<XMLObject>(signature.getObjects());
+    private void map2Message(final List<Reference> refs, final List<XMLObject> objs, Message out, final Document messageBodyDocument)
+        throws Exception { //NOPMD
+
         XmlSignature2Message.Input refsAndObjects = new XmlSignature2Message.Input() {
 
             @Override
@@ -237,28 +212,21 @@ public class XmlVerifierProcessor extends XmlSignatureProcessor {
         getConfiguration().getXmlSignature2Message().mapToMessage(refsAndObjects, out);
     }
 
-    private Node getSignatureNode(Document doc) throws IOException,
-        ParserConfigurationException, XmlSignatureFormatException {
+    private NodeList getSignatureNodes(Document doc) throws IOException, ParserConfigurationException, XmlSignatureFormatException {
 
         // Find Signature element
         NodeList nl = doc.getElementsByTagNameNS(XMLSignature.XMLNS, "Signature");
         if (nl.getLength() == 0) {
             throw new XmlSignatureFormatException(
-                "Message is not a correct XML signature document: 'Signature' element is missing. Check the sent message.");
+                    "Message is not a correct XML signature document: 'Signature' element is missing. Check the sent message.");
         }
 
-        if (nl.getLength() != 1) {
-            throw new XmlSignatureFormatException(
-                "XML signature document is not supported; it contains more than one signature element. Check the sent message.");
-        }
-        Node signatureNode = nl.item(0);
-        LOG.debug("Signature element found");
-        return signatureNode;
+        LOG.debug("{} signature elements found", nl.getLength());
+        return nl;
     }
 
     @SuppressWarnings("unchecked")
-    protected boolean handleSignatureValidationFailed(DOMValidateContext valContext, 
-                                                      XMLSignature signature) throws Exception {
+    protected boolean handleSignatureValidationFailed(DOMValidateContext valContext, XMLSignature signature) throws Exception { //NOPMD
         ValidationFailedHandler handler = getConfiguration().getValidationFailedHandler();
         LOG.debug("handleSignatureValidationFailed called");
         try {
@@ -288,8 +256,7 @@ public class XmlVerifierProcessor extends XmlSignatureProcessor {
                     for (XMLStructure xs : content) {
                         if (xs instanceof Manifest) {
                             Manifest man = (Manifest) xs;
-                            for (Reference ref : (List<Reference>) man
-                                .getReferences()) {
+                            for (Reference ref : (List<Reference>) man.getReferences()) {
                                 boolean refValid = ref.validate(valContext);
                                 if (!refValid) {
                                     handler.manifestReferenceValidationFailed(ref);
@@ -308,18 +275,146 @@ public class XmlVerifierProcessor extends XmlSignatureProcessor {
 
     }
 
-    protected Document parseInput(InputStream is)
-        throws XmlSignatureFormatException, ParserConfigurationException,
-        IOException {
+    protected Document parseInput(InputStream is, Message message) throws Exception { //NOPMD
         try {
-            Document doc = 
-                XmlSignatureHelper.newDocumentBuilder(getConfiguration().getDisallowDoctypeDecl()).parse(is);
+            ValidatorErrorHandler errorHandler = new DefaultValidationErrorHandler();
+            Schema schema = getSchema(message);
+            DocumentBuilder db = XmlSignatureHelper.newDocumentBuilder(getConfiguration().getDisallowDoctypeDecl(), schema);
+            db.setErrorHandler(errorHandler);
+            Document doc = db.parse(is);
+            errorHandler.handleErrors(message.getExchange(), schema, null); // throws ValidationException
             return doc;
         } catch (SAXException e) {
-            throw new XmlSignatureFormatException(
-                "Message has wrong format, it is not a XML signature document. Check the sent message.",
-                 e
-            );
+            throw new XmlSignatureFormatException("Message has wrong format, it is not a XML signature document. Check the sent message.",
+                    e);
+        }
+    }
+
+    static class CheckerInputBuilder {
+
+        private boolean xmlSchemaValidationExecuted;
+
+        private int totalCountOfSignatures;
+
+        private SignedInfo signedInfo;
+
+        private SignatureValue signatureValue;
+
+        private List<? extends XMLObject> objects;
+
+        private Document messageBodyDocument;
+
+        private Message message;
+
+        private KeyInfo keyInfo;
+
+        private Element currentSignatureElement;
+
+        private int currentCountOfSignatures;
+
+        CheckerInputBuilder xmlSchemaValidationExecuted(boolean xmlSchemaValidationExecuted) {
+            this.xmlSchemaValidationExecuted = xmlSchemaValidationExecuted;
+            return this;
+        }
+
+        CheckerInputBuilder totalCountOfSignatures(int totalCountOfSignatures) {
+            this.totalCountOfSignatures = totalCountOfSignatures;
+            return this;
+        }
+
+        CheckerInputBuilder signedInfo(SignedInfo signedInfo) {
+            this.signedInfo = signedInfo;
+            return this;
+        }
+
+        CheckerInputBuilder signatureValue(SignatureValue signatureValue) {
+            this.signatureValue = signatureValue;
+            return this;
+        }
+
+        CheckerInputBuilder objects(List<? extends XMLObject> objects) {
+            this.objects = objects;
+            return this;
+        }
+
+        CheckerInputBuilder messageBodyDocument(Document messageBodyDocument) {
+            this.messageBodyDocument = messageBodyDocument;
+            return this;
+        }
+
+        CheckerInputBuilder message(Message message) {
+            this.message = message;
+            return this;
+        }
+
+        CheckerInputBuilder keyInfo(KeyInfo keyInfo) {
+            this.keyInfo = keyInfo;
+            return this;
+        }
+
+        CheckerInputBuilder currentSignatureElement(Element currentSignatureElement) {
+            this.currentSignatureElement = currentSignatureElement;
+            return this;
+        }
+
+        CheckerInputBuilder currentCountOfSignatures(int currentCountOfSignatures) {
+            this.currentCountOfSignatures = currentCountOfSignatures;
+            return this;
+        }
+
+        XmlSignatureChecker.Input build() {
+            return new XmlSignatureChecker.Input() {
+
+                @Override
+                public boolean isXmlSchemaValidationExecuted() {
+                    return xmlSchemaValidationExecuted;
+                }
+
+                @Override
+                public int getTotalCountOfSignatures() {
+                    return totalCountOfSignatures;
+                }
+
+                @Override
+                public SignedInfo getSignedInfo() {
+                    return signedInfo;
+                }
+
+                @Override
+                public SignatureValue getSignatureValue() {
+                    return signatureValue;
+                }
+
+                @Override
+                public List<? extends XMLObject> getObjects() {
+                    return objects;
+                }
+
+                @Override
+                public Document getMessageBodyDocument() {
+                    return messageBodyDocument;
+                }
+
+                @Override
+                public Message getMessage() {
+                    return message;
+                }
+
+                @Override
+                public KeyInfo getKeyInfo() {
+                    return keyInfo;
+                }
+
+                @Override
+                public Element getCurrentSignatureElement() {
+                    return currentSignatureElement;
+                }
+
+                @Override
+                public int getCurrentCountOfSignatures() {
+                    return currentCountOfSignatures;
+                }
+            };
         }
     }
 }

http://git-wip-us.apache.org/repos/asf/camel/blob/12241987/components/camel-xmlsecurity/src/test/java/org/apache/camel/component/xmlsecurity/SpringXmlSignatureTest.java
----------------------------------------------------------------------
diff --git a/components/camel-xmlsecurity/src/test/java/org/apache/camel/component/xmlsecurity/SpringXmlSignatureTest.java b/components/camel-xmlsecurity/src/test/java/org/apache/camel/component/xmlsecurity/SpringXmlSignatureTest.java
index aef1fba..628a532 100644
--- a/components/camel-xmlsecurity/src/test/java/org/apache/camel/component/xmlsecurity/SpringXmlSignatureTest.java
+++ b/components/camel-xmlsecurity/src/test/java/org/apache/camel/component/xmlsecurity/SpringXmlSignatureTest.java
@@ -61,4 +61,12 @@ public class SpringXmlSignatureTest extends XmlSignatureTest {
         return new RouteBuilder[] {};
     }
 
+    @Override
+    XmlSignerEndpoint getDetachedSignerEndpoint() {
+        XmlSignerEndpoint endpoint = (XmlSignerEndpoint) context()
+                .getEndpoint(
+                        "xmlsecurity:sign://detached?keyAccessor=#accessorRsa&xpathsToIdAttributes=#xpathsToIdAttributes&"//
+                        + "schemaResourceUri=org/apache/camel/component/xmlsecurity/Test.xsd&clearHeaders=false");
+        return endpoint;
+    }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/camel/blob/12241987/components/camel-xmlsecurity/src/test/java/org/apache/camel/component/xmlsecurity/XmlSignatureTest.java
----------------------------------------------------------------------
diff --git a/components/camel-xmlsecurity/src/test/java/org/apache/camel/component/xmlsecurity/XmlSignatureTest.java b/components/camel-xmlsecurity/src/test/java/org/apache/camel/component/xmlsecurity/XmlSignatureTest.java
index 07bcd66..2562763 100644
--- a/components/camel-xmlsecurity/src/test/java/org/apache/camel/component/xmlsecurity/XmlSignatureTest.java
+++ b/components/camel-xmlsecurity/src/test/java/org/apache/camel/component/xmlsecurity/XmlSignatureTest.java
@@ -17,6 +17,7 @@
 package org.apache.camel.component.xmlsecurity;
 
 import java.io.ByteArrayOutputStream;
+import java.io.IOException;
 import java.io.InputStream;
 import java.io.PrintWriter;
 import java.io.UnsupportedEncodingException;
@@ -33,6 +34,7 @@ import java.security.cert.Certificate;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashMap;
+import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 import java.util.TreeMap;
@@ -46,13 +48,22 @@ import javax.xml.crypto.XMLCryptoContext;
 import javax.xml.crypto.XMLStructure;
 import javax.xml.crypto.dsig.CanonicalizationMethod;
 import javax.xml.crypto.dsig.SignatureMethod;
+import javax.xml.crypto.dsig.XMLSignature;
 import javax.xml.crypto.dsig.keyinfo.KeyInfo;
 import javax.xml.crypto.dsig.keyinfo.KeyInfoFactory;
 import javax.xml.crypto.dsig.keyinfo.KeyValue;
 import javax.xml.crypto.dsig.spec.XPathFilterParameterSpec;
 import javax.xml.crypto.dsig.spec.XPathType;
+import javax.xml.namespace.NamespaceContext;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.xpath.XPath;
+import javax.xml.xpath.XPathConstants;
+import javax.xml.xpath.XPathExpression;
+import javax.xml.xpath.XPathExpressionException;
+import javax.xml.xpath.XPathFactory;
 
 import org.w3c.dom.Node;
+import org.xml.sax.SAXException;
 
 import org.apache.camel.CamelContext;
 import org.apache.camel.Exchange;
@@ -83,16 +94,16 @@ import org.apache.camel.component.xmlsecurity.util.ValidationFailedHandlerIgnore
 import org.apache.camel.component.xmlsecurity.util.XmlSignature2Message2MessageWithTimestampProperty;
 import org.apache.camel.impl.DefaultCamelContext;
 import org.apache.camel.impl.JndiRegistry;
+import org.apache.camel.processor.validation.SchemaValidationException;
 import org.apache.camel.test.junit4.CamelTestSupport;
 import org.junit.Before;
 import org.junit.Test;
 
 
-
 public class XmlSignatureTest extends CamelTestSupport {
-    
+
     private static String payload = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
-        + "<root xmlns=\"http://test/test\"><test>Test Message</test></root>";
+            + "<root xmlns=\"http://test/test\"><test>Test Message</test></root>";
     private KeyPair keyPair;
 
     @Override
@@ -111,12 +122,14 @@ public class XmlSignatureTest extends CamelTestSupport {
         registry.bind("keyAccessorDefault", getDefaultKeyAccessor());
         registry.bind("keySelectorDefault", getDefaultKeySelector());
         registry.bind("envelopingSignatureChecker", getEnvelopingXmlSignatureChecker());
-        registry.bind("xmlSignature2MessageWithTimestampProperty",
-                      getXmlSignature2MessageWithTimestampdProperty());
-        registry.bind("validationFailedHandlerIgnoreManifestFailures",
-                      getValidationFailedHandlerIgnoreManifestFailures());
+        registry.bind("xmlSignature2MessageWithTimestampProperty", getXmlSignature2MessageWithTimestampdProperty());
+        registry.bind("validationFailedHandlerIgnoreManifestFailures", getValidationFailedHandlerIgnoreManifestFailures());
         registry.bind("signatureProperties", getSignatureProperties());
         registry.bind("nodesearchxpath", getNodeSerachXPath());
+        Map<String, String> namespaceMap = Collections.singletonMap("ns", "http://test");
+        List<XPathFilterParameterSpec> xpaths = Collections
+                .singletonList(XmlSignatureHelper.getXpathFilter("/ns:root/a/@ID", namespaceMap));
+        registry.bind("xpathsToIdAttributes", xpaths);
 
         return registry;
     }
@@ -126,36 +139,28 @@ public class XmlSignatureTest extends CamelTestSupport {
         return new RouteBuilder[] {new RouteBuilder() {
             public void configure() throws Exception {
                 // START SNIPPET: enveloping XML signature
-                onException(XmlSignatureException.class).handled(true).to(
-                    "mock:exception");
-                from("direct:enveloping")
-                    .to("xmlsecurity:sign://enveloping?keyAccessor=#accessor")
-                    .to("xmlsecurity:verify://enveloping?keySelector=#selector")
-                    .to("mock:result");
+                onException(XmlSignatureException.class).handled(true).to("mock:exception");
+                from("direct:enveloping").to("xmlsecurity:sign://enveloping?keyAccessor=#accessor")
+                        .to("xmlsecurity:verify://enveloping?keySelector=#selector").to("mock:result");
                 // END SNIPPET: enveloping XML signature
             }
         }, new RouteBuilder() {
             public void configure() throws Exception {
                 // START SNIPPET: enveloping XML signature with plain text
                 // message body
-                onException(XmlSignatureException.class).handled(true).to(
-                    "mock:exception");
-                from("direct:plaintext")
-                    .to("xmlsecurity:sign://plaintext?keyAccessor=#accessor&plainText=true&plainTextEncoding=UTF-8")
-                    .to("xmlsecurity:verify://plaintext?keySelector=#selector")
-                    .to("mock:result");
+                onException(XmlSignatureException.class).handled(true).to("mock:exception");
+                from("direct:plaintext").to("xmlsecurity:sign://plaintext?keyAccessor=#accessor&plainText=true&plainTextEncoding=UTF-8")
+                        .to("xmlsecurity:verify://plaintext?keySelector=#selector").to("mock:result");
                 // END SNIPPET: enveloping XML signature with plain text message
                 // body
             }
         }, new RouteBuilder() {
             public void configure() throws Exception {
                 // START SNIPPET: enveloped XML signature
-                onException(XmlSignatureException.class).handled(true).to(
-                    "mock:exception");
+                onException(XmlSignatureException.class).handled(true).to("mock:exception");
                 from("direct:enveloped")
-                    .to("xmlsecurity:sign://enveloped?keyAccessor=#accessor&parentLocalName=root&parentNamespace=http://test/test")
-                    .to("xmlsecurity:verify://enveloped?keySelector=#selector")
-                    .to("mock:result");
+                        .to("xmlsecurity:sign://enveloped?keyAccessor=#accessor&parentLocalName=root&parentNamespace=http://test/test")
+                        .to("xmlsecurity:verify://enveloped?keySelector=#selector").to("mock:result");
                 // END SNIPPET: enveloped XML signature
             }
         }, new RouteBuilder() {
@@ -164,83 +169,74 @@ public class XmlSignatureTest extends CamelTestSupport {
                 // we can set the configuration properties explicitly on the
                 // endpoint instances.
                 context.getEndpoint("xmlsecurity:sign://canonicalization?canonicalizationMethod=#canonicalizationMethod1",
-                                    XmlSignerEndpoint.class).setKeyAccessor(getKeyAccessor(keyPair.getPrivate()));
+                        XmlSignerEndpoint.class).setKeyAccessor(getKeyAccessor(keyPair.getPrivate()));
                 context.getEndpoint("xmlsecurity:sign://canonicalization?canonicalizationMethod=#canonicalizationMethod1",
-                                    XmlSignerEndpoint.class).setSignatureAlgorithm(
-                                        "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256");
-                context.getEndpoint("xmlsecurity:verify://canonicalization",
-                                    XmlVerifierEndpoint.class).setKeySelector(KeySelector.singletonKeySelector(keyPair.getPublic()));
-                from("direct:canonicalization")
-                    .to("xmlsecurity:sign://canonicalization?canonicalizationMethod=#canonicalizationMethod1",
-                        "xmlsecurity:verify://canonicalization",
-                        "mock:result");
+                        XmlSignerEndpoint.class).setSignatureAlgorithm("http://www.w3.org/2001/04/xmldsig-more#rsa-sha256");
+                context.getEndpoint("xmlsecurity:verify://canonicalization", XmlVerifierEndpoint.class).setKeySelector(
+                        KeySelector.singletonKeySelector(keyPair.getPublic()));
+                from("direct:canonicalization").to("xmlsecurity:sign://canonicalization?canonicalizationMethod=#canonicalizationMethod1",
+                        "xmlsecurity:verify://canonicalization", "mock:result");
                 // END SNIPPET: canonicalization
             }
         }, new RouteBuilder() {
             public void configure() throws Exception {
                 // START SNIPPET: signature and digest algorithm
                 from("direct:signaturedigestalgorithm")
-                    .to("xmlsecurity:sign://signaturedigestalgorithm?keyAccessor=#accessor"
-                        + "&signatureAlgorithm=http://www.w3.org/2001/04/xmldsig-more#rsa-sha512&digestAlgorithm=http://www.w3.org/2001/04/xmlenc#sha512",
-                        "xmlsecurity:verify://signaturedigestalgorithm?keySelector=#selector")
-                    .to("mock:result");
+                        .to("xmlsecurity:sign://signaturedigestalgorithm?keyAccessor=#accessor"
+                                + "&signatureAlgorithm=http://www.w3.org/2001/04/xmldsig-more#rsa-sha512&digestAlgorithm=http://www.w3.org/2001/04/xmlenc#sha512",
+                                "xmlsecurity:verify://signaturedigestalgorithm?keySelector=#selector").to("mock:result");
                 // END SNIPPET: signature and digest algorithm
             }
         }, new RouteBuilder() {
             public void configure() throws Exception {
                 // START SNIPPET: transforms XPath2
-                from("direct:transformsXPath2")
-                    .to("xmlsecurity:sign://transformsXPath2?keyAccessor=#accessor&transformMethods=#transformsXPath2",
-                        "xmlsecurity:verify://transformsXPath2?keySelector=#selector")
-                    .to("mock:result");
+                from("direct:transformsXPath2").to(
+                        "xmlsecurity:sign://transformsXPath2?keyAccessor=#accessor&transformMethods=#transformsXPath2",
+                        "xmlsecurity:verify://transformsXPath2?keySelector=#selector").to("mock:result");
                 // END SNIPPET: transform XPath
             }
         }, new RouteBuilder() {
             public void configure() throws Exception {
                 // START SNIPPET: transforms XSLT,XPath
-                onException(XmlSignatureException.class).handled(false)
-                .to("mock:exception");
-                from("direct:transformsXsltXPath")
-                    .to("xmlsecurity:sign://transformsXsltXPath?keyAccessor=#accessor&transformMethods=#transformsXsltXPath",
-                        "xmlsecurity:verify://transformsXsltXPath?keySelector=#selector")
-                    .to("mock:result");
+                onException(XmlSignatureException.class).handled(false).to("mock:exception");
+                from("direct:transformsXsltXPath").to(
+                        "xmlsecurity:sign://transformsXsltXPath?keyAccessor=#accessor&transformMethods=#transformsXsltXPath",
+                        "xmlsecurity:verify://transformsXsltXPath?keySelector=#selector").to("mock:result");
                 // END SNIPPET: transforms XSLT,XPath
             }
         }, new RouteBuilder() {
             public void configure() throws Exception {
                 // START SNIPPET: transforms XSLT,XPath - secure Validation disabled
                 from("direct:transformsXsltXPathSecureValDisabled")
-                    .to("xmlsecurity:sign://transformsXsltXPathSecureValDisabled?keyAccessor=#accessor&transformMethods=#transformsXsltXPath",
-                        "xmlsecurity:verify://transformsXsltXPathSecureValDisabled?keySelector=#selector&secureValidation=false")
-                    .to("mock:result");
+                        .to("xmlsecurity:sign://transformsXsltXPathSecureValDisabled?keyAccessor=#accessor&transformMethods=#transformsXsltXPath",
+                                "xmlsecurity:verify://transformsXsltXPathSecureValDisabled?keySelector=#selector&secureValidation=false")
+                        .to("mock:result");
                 // END SNIPPET: transforms XSLT,XPath - secure Validation disabled
             }
         }, new RouteBuilder() {
             public void configure() throws Exception {
                 // START SNIPPET: cryptocontextprops
-                onException(XmlSignatureException.class).handled(false).to(
-                    "mock:exception");
+                onException(XmlSignatureException.class).handled(false).to("mock:exception");
                 from("direct:cryptocontextprops")
-                    .to("xmlsecurity:verify://cryptocontextprops?keySelector=#selectorKeyValue&cryptoContextProperties=#cryptoContextProperties")
-                    .to("mock:result");
+                        .to("xmlsecurity:verify://cryptocontextprops?keySelector=#selectorKeyValue&cryptoContextProperties=#cryptoContextProperties")
+                        .to("mock:result");
                 // END SNIPPET: cryptocontextprops
             }
         }, new RouteBuilder() {
             public void configure() throws Exception {
                 // START SNIPPET: URI dereferencer
                 from("direct:uridereferencer")
-                    .to("xmlsecurity:sign://uriderferencer?keyAccessor=#accessor&uriDereferencer=#uriDereferencer")
-                    .to("xmlsecurity:verify://uridereferencer?keySelector=#selector&uriDereferencer=#uriDereferencer")
-                    .to("mock:result");
+                        .to("xmlsecurity:sign://uriderferencer?keyAccessor=#accessor&uriDereferencer=#uriDereferencer")
+                        .to("xmlsecurity:verify://uridereferencer?keySelector=#selector&uriDereferencer=#uriDereferencer")
+                        .to("mock:result");
                 // END SNIPPET: URI dereferencer
             }
         }, new RouteBuilder() {
             public void configure() throws Exception {
                 // START SNIPPET: keyAccessorKeySelectorDefault
                 from("direct:keyAccessorKeySelectorDefault")
-                    .to("xmlsecurity:sign://keyAccessorKeySelectorDefault?keyAccessor=#keyAccessorDefault&addKeyInfoReference=true")
-                    .to("xmlsecurity:verify://keyAccessorKeySelectorDefault?keySelector=#keySelectorDefault")
-                    .to("mock:result");
+                        .to("xmlsecurity:sign://keyAccessorKeySelectorDefault?keyAccessor=#keyAccessorDefault&addKeyInfoReference=true")
+                        .to("xmlsecurity:verify://keyAccessorKeySelectorDefault?keySelector=#keySelectorDefault").to("mock:result");
                 // END SNIPPET: keyAccessorKeySelectorDefault
             }
         }, new RouteBuilder() {
@@ -248,64 +244,61 @@ public class XmlSignatureTest extends CamelTestSupport {
                 // START SNIPPET: xmlSignatureChecker
                 onException(XmlSignatureInvalidException.class).handled(false).to("mock:exception");
                 from("direct:xmlSignatureChecker")
-                    .to("xmlsecurity:verify://xmlSignatureChecker?keySelector=#selectorKeyValue&xmlSignatureChecker=#envelopingSignatureChecker")
-                    .to("mock:result");
+                        .to("xmlsecurity:verify://xmlSignatureChecker?keySelector=#selectorKeyValue&xmlSignatureChecker=#envelopingSignatureChecker")
+                        .to("mock:result");
                 // END SNIPPET: xmlSignatureChecker
             }
         }, new RouteBuilder() {
             public void configure() throws Exception { //
                 // START SNIPPET: properties
                 from("direct:props")
-                    .to("xmlsecurity:sign://properties?keyAccessor=#accessor&properties=#signatureProperties")
-                    .to("xmlsecurity:verify://properties?keySelector=#selector&xmlSignature2Message=#xmlSignature2MessageWithTimestampProperty")
-                    .to("mock:result");
+                        .to("xmlsecurity:sign://properties?keyAccessor=#accessor&properties=#signatureProperties")
+                        .to("xmlsecurity:verify://properties?keySelector=#selector&xmlSignature2Message=#xmlSignature2MessageWithTimestampProperty")
+                        .to("mock:result");
                 // END SNIPPET: properties
             }
         }, new RouteBuilder() {
             public void configure() throws Exception {
                 // START SNIPPET: verify output node search element name
-                onException(XmlSignatureException.class).handled(true).to(
-                    "mock:exception");
-                from("direct:outputnodesearchelementname")
-                    .to("xmlsecurity:verify://outputnodesearchelementname?keySelector=#selectorKeyValue"
-                        + "&outputNodeSearchType=ElementName&outputNodeSearch={http://test/test}root&removeSignatureElements=true")
-                    .to("mock:result");
+                onException(XmlSignatureException.class).handled(true).to("mock:exception");
+                from("direct:outputnodesearchelementname").to(
+                        "xmlsecurity:verify://outputnodesearchelementname?keySelector=#selectorKeyValue"
+                                + "&outputNodeSearchType=ElementName&outputNodeSearch={http://test/test}root&removeSignatureElements=true")
+                        .to("mock:result");
                 // END SNIPPET: verify output node search element name
             }
         }, new RouteBuilder() {
             public void configure() throws Exception {
                 // START SNIPPET: verify output node search xpath
-                onException(XmlSignatureException.class).handled(true).to(
-                    "mock:exception");
+                onException(XmlSignatureException.class).handled(true).to("mock:exception");
                 from("direct:outputnodesearchxpath")
-                    .to("xmlsecurity:verify://outputnodesearchxpath?keySelector=#selectorKeyValue&outputNodeSearchType=XPath&outputNodeSearch=#nodesearchxpath&removeSignatureElements=true")
-                    .to("mock:result");
+                        .to("xmlsecurity:verify://outputnodesearchxpath?keySelector=#selectorKeyValue&outputNodeSearchType=XPath&outputNodeSearch=#nodesearchxpath&removeSignatureElements=true")
+                        .to("mock:result");
                 // END SNIPPET: verify output node search xpath
             }
         }, new RouteBuilder() {
             public void configure() throws Exception {
                 // START SNIPPET: validationFailedHandler
                 from("direct:validationFailedHandler")
-                    .to("xmlsecurity:verify://validationFailedHandler?keySelector=#selectorKeyValue&validationFailedHandler=validationFailedHandlerIgnoreManifestFailures")
-                    .to("mock:result");
+                        .to("xmlsecurity:verify://validationFailedHandler?keySelector=#selectorKeyValue&validationFailedHandler=validationFailedHandlerIgnoreManifestFailures")
+                        .to("mock:result");
                 // END SNIPPET: validationFailedHandler
             }
         }, new RouteBuilder() {
             public void configure() throws Exception {
                 // START SNIPPET: further parameters
                 from("direct:furtherparams")
-                    .to("xmlsecurity:sign://furtherparams?keyAccessor=#accessor&prefixForXmlSignatureNamespace=digsig&disallowDoctypeDecl=false")
-                    .to("xmlsecurity:verify://bfurtherparams?keySelector=#selector&disallowDoctypeDecl=false")
-                    .to("mock:result");
+                        .to("xmlsecurity:sign://furtherparams?keyAccessor=#accessor&prefixForXmlSignatureNamespace=digsig&disallowDoctypeDecl=false")
+                        .to("xmlsecurity:verify://bfurtherparams?keySelector=#selector&disallowDoctypeDecl=false").to("mock:result");
                 // END SNIPPET: further parameters
             }
         }, new RouteBuilder() {
             public void configure() throws Exception {
                 // START SNIPPET: signer invalid keyexception
                 onException(XmlSignatureInvalidKeyException.class).handled(true).to("mock:exception");
-                from("direct:signexceptioninvalidkey")
-                    .to("xmlsecurity:sign://signexceptioninvalidkey?signatureAlgorithm=http://www.w3.org/2001/04/xmldsig-more#rsa-sha512")
-                    .to("mock:result");
+                from("direct:signexceptioninvalidkey").to(
+                        "xmlsecurity:sign://signexceptioninvalidkey?signatureAlgorithm=http://www.w3.org/2001/04/xmldsig-more#rsa-sha512")
+                        .to("mock:result");
                 // END SNIPPET: signer invalid keyexception
             }
         }, new RouteBuilder() {
@@ -313,48 +306,55 @@ public class XmlSignatureTest extends CamelTestSupport {
                 // START SNIPPET: signer exceptions
                 onException(XmlSignatureException.class).handled(true).to("mock:exception");
                 from("direct:signexceptions")
-                    .to("xmlsecurity:sign://signexceptions?keyAccessor=#accessor&signatureAlgorithm=http://www.w3.org/2001/04/xmldsig-more#rsa-sha512")
-                    .to("mock:result");
+                        .to("xmlsecurity:sign://signexceptions?keyAccessor=#accessor&signatureAlgorithm=http://www.w3.org/2001/04/xmldsig-more#rsa-sha512")
+                        .to("mock:result");
                 // END SNIPPET: signer exceptions
             }
         }, new RouteBuilder() {
             public void configure() throws Exception {
                 // START SNIPPET: NoSuchAlgorithmException
-                onException(XmlSignatureException.class).handled(true).to(
-                    "mock:exception");
+                onException(XmlSignatureException.class).handled(true).to("mock:exception");
                 from("direct:noSuchAlgorithmException")
-                    .to("xmlsecurity:sign://noSuchAlgorithmException?keyAccessor=#accessor&signatureAlgorithm=wrongalgorithm&digestAlgorithm=http://www.w3.org/2001/04/xmlenc#sha512")
-                    .to("mock:result");
+                        .to("xmlsecurity:sign://noSuchAlgorithmException?keyAccessor=#accessor&signatureAlgorithm=wrongalgorithm&digestAlgorithm=http://www.w3.org/2001/04/xmlenc#sha512")
+                        .to("mock:result");
                 // END SNIPPET: NoSuchAlgorithmException
             }
         }, new RouteBuilder() {
             public void configure() throws Exception {
                 // START SNIPPET: verifier exceptions
-                onException(XmlSignatureException.class).handled(false).to(
-                    "mock:exception");
-                from("direct:verifyexceptions")
-                    .to("xmlsecurity:verify://verifyexceptions?keySelector=#selector")
-                    .to("mock:result");
+                onException(XmlSignatureException.class).handled(false).to("mock:exception");
+                from("direct:verifyexceptions").to("xmlsecurity:verify://verifyexceptions?keySelector=#selector").to("mock:result");
                 // END SNIPPET: verifier exceptions
             }
         }, new RouteBuilder() {
             public void configure() throws Exception {
                 // START SNIPPET: verifier InvalidKeyException
                 onException(XmlSignatureException.class).handled(false).to("mock:exception");
-                from("direct:verifyInvalidKeyException")
-                    .to("xmlsecurity:verify://verifyInvalidKeyException?keySelector=#selector")
-                    .to("mock:result");
+                from("direct:verifyInvalidKeyException").to("xmlsecurity:verify://verifyInvalidKeyException?keySelector=#selector").to(
+                        "mock:result");
                 // END SNIPPET: verifier exceptions
             }
         }, new RouteBuilder() {
             public void configure() throws Exception {
                 // START SNIPPET: verifier InvalidHashException
                 onException(XmlSignatureException.class).handled(false).to("mock:exception");
-                from("direct:invalidhash")
-                    .to("xmlsecurity:verify://invalidhash?keySelector=#selectorKeyValue&baseUri=#baseUri&secureValidation=false")
-                    .to("mock:result");
+                from("direct:invalidhash").to(
+                        "xmlsecurity:verify://invalidhash?keySelector=#selectorKeyValue&baseUri=#baseUri&secureValidation=false").to(
+                        "mock:result");
                 // END SNIPPET: verifier InvalidHashException
             }
+        }, new RouteBuilder() {
+            public void configure() throws Exception {
+                // START SNIPPET: detached XML signature
+                onException(Exception.class).handled(false).to("mock:exception");
+                from("direct:detached")
+                        .to("xmlsecurity:sign://detached?keyAccessor=#keyAccessorDefault&xpathsToIdAttributes=#xpathsToIdAttributes&"//
+                        + "schemaResourceUri=org/apache/camel/component/xmlsecurity/Test.xsd&clearHeaders=false")
+                        .to("mock:result")
+                        .to("xmlsecurity:verify://detached?keySelector=#keySelectorDefault&schemaResourceUri=org/apache/camel/component/xmlsecurity/Test.xsd")
+                        .to("mock:verified");
+                // END SNIPPET: detached XML signature
+            }
         }
 
         };
@@ -376,32 +376,26 @@ public class XmlSignatureTest extends CamelTestSupport {
     }
 
     @Test
-    public void testEnvelopingSignatureWithPlainTextSetByHeaders()
-        throws Exception {
+    public void testEnvelopingSignatureWithPlainTextSetByHeaders() throws Exception {
         String text = "plain test text";
         setupMock(text);
         Map<String, Object> headers = new TreeMap<String, Object>();
-        headers.put(XmlSignatureConstants.HEADER_MESSAGE_IS_PLAIN_TEXT,
-                    Boolean.TRUE);
+        headers.put(XmlSignatureConstants.HEADER_MESSAGE_IS_PLAIN_TEXT, Boolean.TRUE);
         headers.put(XmlSignatureConstants.HEADER_PLAIN_TEXT_ENCODING, "UTF-8");
         sendBody("direct:enveloping", text, headers);
         assertMockEndpointsSatisfied();
     }
 
     @Test
-    public void testExceptionSignatureForPlainTextWithWrongEncoding()
-        throws Exception {
+    public void testExceptionSignatureForPlainTextWithWrongEncoding() throws Exception {
         String text = "plain test text";
         MockEndpoint mock = setupExceptionMock();
         Map<String, Object> headers = new TreeMap<String, Object>();
-        headers.put(XmlSignatureConstants.HEADER_MESSAGE_IS_PLAIN_TEXT,
-                    Boolean.TRUE);
-        headers.put(XmlSignatureConstants.HEADER_PLAIN_TEXT_ENCODING,
-            "wrongEncoding");
+        headers.put(XmlSignatureConstants.HEADER_MESSAGE_IS_PLAIN_TEXT, Boolean.TRUE);
+        headers.put(XmlSignatureConstants.HEADER_PLAIN_TEXT_ENCODING, "wrongEncoding");
         sendBody("direct:enveloping", text, headers);
         assertMockEndpointsSatisfied();
-        checkThrownException(mock, XmlSignatureException.class,
-                             UnsupportedEncodingException.class);
+        checkThrownException(mock, XmlSignatureException.class, UnsupportedEncodingException.class);
     }
 
     @Test
@@ -412,8 +406,7 @@ public class XmlSignatureTest extends CamelTestSupport {
     }
 
     @Test
-    public void testExceptionEnvelopedSignatureWithWrongParent()
-        throws Exception {
+    public void testExceptionEnvelopedSignatureWithWrongParent() throws Exception {
         // payload root element renamed to a -> parent name in route definition
         // does not fit
         String payload = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><a xmlns=\"http://test/test\"><test>Test Message</test></a>";
@@ -425,14 +418,12 @@ public class XmlSignatureTest extends CamelTestSupport {
     }
 
     @Test
-    public void testExceptionEnvelopedSignatureWithPlainTextPayload()
-        throws Exception {
+    public void testExceptionEnvelopedSignatureWithPlainTextPayload() throws Exception {
         // payload root element renamed to a -> parent name in route definition
         // does not fit
         String payload = "plain text Message";
         Map<String, Object> headers = new HashMap<String, Object>(1);
-        headers.put(XmlSignatureConstants.HEADER_MESSAGE_IS_PLAIN_TEXT,
-                    Boolean.TRUE);
+        headers.put(XmlSignatureConstants.HEADER_MESSAGE_IS_PLAIN_TEXT, Boolean.TRUE);
         MockEndpoint mock = setupExceptionMock();
         sendBody("direct:enveloped", payload, headers);
         assertMockEndpointsSatisfied();
@@ -448,8 +439,7 @@ public class XmlSignatureTest extends CamelTestSupport {
         String payloadOut = "<root xmlns=\"http://test/test\"><test>Test Message</test></root>";
         setupMock(payloadOut);
         Map<String, Object> headers = new TreeMap<String, Object>();
-        headers.put(XmlSignatureConstants.HEADER_OMIT_XML_DECLARATION,
-                    Boolean.TRUE);
+        headers.put(XmlSignatureConstants.HEADER_OMIT_XML_DECLARATION, Boolean.TRUE);
         InputStream payload = XmlSignatureTest.class
             .getResourceAsStream("/org/apache/camel/component/xmlsecurity/ExampleEnvelopedXmlSig.xml");
         assertNotNull("Cannot load payload", payload);
@@ -465,8 +455,7 @@ public class XmlSignatureTest extends CamelTestSupport {
     }
 
     @Test
-    public void testSetCanonicalizationMethodInRouteDefinition()
-        throws Exception {
+    public void testSetCanonicalizationMethodInRouteDefinition() throws Exception {
         setupMock();
         sendBody("direct:canonicalization", payload);
         assertMockEndpointsSatisfied();
@@ -481,8 +470,7 @@ public class XmlSignatureTest extends CamelTestSupport {
     }
 
     @Test
-    public void testSetTransformMethodXpath2InRouteDefinition()
-        throws Exception {
+    public void testSetTransformMethodXpath2InRouteDefinition() throws Exception {
         // example from http://www.w3.org/TR/2002/REC-xmldsig-filter2-20021108/
         String payload = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
             + "<Document xmlns=\"http://test/test\">                             "
@@ -511,8 +499,7 @@ public class XmlSignatureTest extends CamelTestSupport {
 
     // Secure Validation is enabled and so this should fail
     @Test
-    public void testSetTransformMethodXsltXpathInRouteDefinition()
-        throws Exception {
+    public void testSetTransformMethodXsltXpathInRouteDefinition() throws Exception {
         // byte[] encoded = Base64.encode("Test Message".getBytes("UTF-8"));
         // String contentBase64 = new String(encoded, "UTF-8");
         // String payload =
@@ -522,15 +509,14 @@ public class XmlSignatureTest extends CamelTestSupport {
         assertMockEndpointsSatisfied();
         checkThrownException(mock, XmlSignatureException.class, null);
     }
-    
+
     @Test
-    public void testSetTransformMethodXsltXpathInRouteDefinitionSecValDisabled()
-        throws Exception {
+    public void testSetTransformMethodXsltXpathInRouteDefinitionSecValDisabled() throws Exception {
         setupMock();
         sendBody("direct:transformsXsltXPathSecureValDisabled", payload);
         assertMockEndpointsSatisfied();
     }
-    
+
     @Test
     public void testProperties() throws Exception {
         setupMock();
@@ -549,13 +535,10 @@ public class XmlSignatureTest extends CamelTestSupport {
     }
 
     @Test
-    public void testVerifyExceptionOutputNodeSearchElementNameInvalidFormat1()
-        throws Exception {
-        XmlVerifierEndpoint endpoint = context
-            .getEndpoint(
-                         "xmlsecurity:verify://outputnodesearchelementname?keySelector=#selectorKeyValue"
-                         + "&outputNodeSearchType=ElementName&outputNodeSearch={http://test/test}root&removeSignatureElements=true",
-                         XmlVerifierEndpoint.class);
+    public void testVerifyExceptionOutputNodeSearchElementNameInvalidFormat1() throws Exception {
+        XmlVerifierEndpoint endpoint = context.getEndpoint("xmlsecurity:verify://outputnodesearchelementname?keySelector=#selectorKeyValue"
+                + "&outputNodeSearchType=ElementName&outputNodeSearch={http://test/test}root&removeSignatureElements=true",
+                XmlVerifierEndpoint.class);
         endpoint.setOutputNodeSearch("{wrongformat"); // closing '}' missing
         MockEndpoint mock = setupExceptionMock();
         InputStream payload = XmlSignatureTest.class
@@ -567,11 +550,11 @@ public class XmlSignatureTest extends CamelTestSupport {
     }
 
     @Test
-    public void testVerifyExceptionOutputNodeSearchElementNameInvalidFormat2()
-        throws Exception {
-        context.getEndpoint("xmlsecurity:verify://outputnodesearchelementname?keySelector=#selectorKeyValue"
-                            + "&outputNodeSearchType=ElementName&outputNodeSearch={http://test/test}root&removeSignatureElements=true",
-                            XmlVerifierEndpoint.class).setOutputNodeSearch("{wrongformat}"); 
+    public void testVerifyExceptionOutputNodeSearchElementNameInvalidFormat2() throws Exception {
+        context.getEndpoint(
+                "xmlsecurity:verify://outputnodesearchelementname?keySelector=#selectorKeyValue"
+                        + "&outputNodeSearchType=ElementName&outputNodeSearch={http://test/test}root&removeSignatureElements=true",
+                XmlVerifierEndpoint.class).setOutputNodeSearch("{wrongformat}");
         // local name missing
         MockEndpoint mock = setupExceptionMock();
         InputStream payload = XmlSignatureTest.class
@@ -583,8 +566,7 @@ public class XmlSignatureTest extends CamelTestSupport {
     }
 
     @Test
-    public void testExceptionVerifyOutputNodeSearchWrongElementName()
-        throws Exception {
+    public void testExceptionVerifyOutputNodeSearchWrongElementName() throws Exception {
         MockEndpoint mock = setupExceptionMock();
         InputStream payload = XmlSignatureTest.class
             .getResourceAsStream("/org/apache/camel/component/xmlsecurity/ExampleEnvelopingDigSig.xml");
@@ -595,8 +577,7 @@ public class XmlSignatureTest extends CamelTestSupport {
     }
 
     @Test
-    public void testExceptionVerifyOutputNodeSearchElementNameMoreThanOneOutputElement()
-        throws Exception {
+    public void testExceptionVerifyOutputNodeSearchElementNameMoreThanOneOutputElement() throws Exception {
         MockEndpoint mock = setupExceptionMock();
         InputStream payload = XmlSignatureTest.class
             .getResourceAsStream("/org/apache/camel/component/xmlsecurity/ExampleEnvelopingDigSigWithSeveralElementsWithNameRoot.xml");
@@ -617,11 +598,10 @@ public class XmlSignatureTest extends CamelTestSupport {
     }
 
     @Test
-    public void testExceptionVerifyOutputNodeSearchXPathWithNoResultNode()
-        throws Exception {
+    public void testExceptionVerifyOutputNodeSearchXPathWithNoResultNode() throws Exception {
         MockEndpoint mock = setupExceptionMock();
         InputStream payload = XmlSignatureTest.class
-            .getResourceAsStream("/org/apache/camel/component/xmlsecurity/ExampleEnvelopingDigSig.xml");
+                .getResourceAsStream("/org/apache/camel/component/xmlsecurity/ExampleEnvelopingDigSig.xml");
         assertNotNull("Cannot load payload", payload);
         sendBody("direct:outputnodesearchxpath", payload);
         assertMockEndpointsSatisfied();
@@ -629,11 +609,10 @@ public class XmlSignatureTest extends CamelTestSupport {
     }
 
     @Test
-    public void testExceptionVerifyOutputNodeSearchXPathMoreThanOneOutputElement()
-        throws Exception {
+    public void testExceptionVerifyOutputNodeSearchXPathMoreThanOneOutputElement() throws Exception {
         MockEndpoint mock = setupExceptionMock();
         InputStream payload = XmlSignatureTest.class
-            .getResourceAsStream("/org/apache/camel/component/xmlsecurity/ExampleEnvelopingDigSigWithSeveralElementsWithNameRoot.xml");
+                .getResourceAsStream("/org/apache/camel/component/xmlsecurity/ExampleEnvelopingDigSigWithSeveralElementsWithNameRoot.xml");
         assertNotNull("Cannot load payload", payload);
         sendBody("direct:outputnodesearchxpath", payload);
         assertMockEndpointsSatisfied();
@@ -645,8 +624,9 @@ public class XmlSignatureTest extends CamelTestSupport {
         MockEndpoint mock = setupExceptionMock();
         // wrong key type
         setUpKeys("DSA", 512);
-        context.getEndpoint("xmlsecurity:sign://signexceptioninvalidkey?signatureAlgorithm=http://www.w3.org/2001/04/xmldsig-more#rsa-sha512",
-                            XmlSignerEndpoint.class).setKeyAccessor(getKeyAccessor(keyPair.getPrivate()));
+        context.getEndpoint(
+                "xmlsecurity:sign://signexceptioninvalidkey?signatureAlgorithm=http://www.w3.org/2001/04/xmldsig-more#rsa-sha512",
+                XmlSignerEndpoint.class).setKeyAccessor(getKeyAccessor(keyPair.getPrivate()));
         sendBody("direct:signexceptioninvalidkey", payload);
         assertMockEndpointsSatisfied();
         checkThrownException(mock, XmlSignatureInvalidKeyException.class, null);
@@ -677,21 +657,9 @@ public class XmlSignatureTest extends CamelTestSupport {
     }
 
     @Test
-    public void testVerifyFormatExceptionNoXmlWithoutSignatureElement()
-        throws Exception {
+    public void testVerifyFormatExceptionNoXmlWithoutSignatureElement() throws Exception {
         MockEndpoint mock = setupExceptionMock();
-        sendBody("direct:verifyexceptions",
-            "<?xml version=\"1.0\" encoding=\"UTF-8\"?><NoSignature></NoSignature>");
-        assertMockEndpointsSatisfied();
-        checkThrownException(mock, XmlSignatureFormatException.class, null);
-    }
-
-    @Test
-    public void testVerifyFormatExceptionMoreThanOneSignatureElement()
-        throws Exception {
-        MockEndpoint mock = setupExceptionMock();
-        sendBody("direct:verifyexceptions",
-            "<?xml version=\"1.0\" encoding=\"UTF-8\"?><root><Signature xmlns=\"http://www.w3.org/2000/09/xmldsig#\"/><Signature xmlns=\"http://www.w3.org/2000/09/xmldsig#\"/></root>");
+        sendBody("direct:verifyexceptions", "<?xml version=\"1.0\" encoding=\"UTF-8\"?><NoSignature></NoSignature>");
         assertMockEndpointsSatisfied();
         checkThrownException(mock, XmlSignatureFormatException.class, null);
     }
@@ -699,8 +667,7 @@ public class XmlSignatureTest extends CamelTestSupport {
     @Test
     public void testVerifyInvalidContentHashException() throws Exception {
         MockEndpoint mock = setupExceptionMock();
-        InputStream payload = XmlSignatureTest.class
-            .getResourceAsStream("/org/apache/camel/component/xmlsecurity/ExampleDetached.xml");
+        InputStream payload = XmlSignatureTest.class.getResourceAsStream("/org/apache/camel/component/xmlsecurity/ExampleDetached.xml");
         assertNotNull("Cannot load payload", payload);
         sendBody("direct:invalidhash", payload);
         assertMockEndpointsSatisfied();
@@ -708,11 +675,10 @@ public class XmlSignatureTest extends CamelTestSupport {
     }
 
     @Test
-    public void testVerifyMantifestInvalidContentHashException()
-        throws Exception {
+    public void testVerifyMantifestInvalidContentHashException() throws Exception {
         MockEndpoint mock = setupExceptionMock();
         InputStream payload = XmlSignatureTest.class
-            .getResourceAsStream("/org/apache/camel/component/xmlsecurity/ManifestTest_TamperedContent.xml");
+                .getResourceAsStream("/org/apache/camel/component/xmlsecurity/ManifestTest_TamperedContent.xml");
         assertNotNull("Cannot load payload", payload);
         sendBody("direct:invalidhash", payload);
         assertMockEndpointsSatisfied();
@@ -727,7 +693,7 @@ public class XmlSignatureTest extends CamelTestSupport {
         // by the crypto context properties
         setupMock("some text tampered");
         InputStream payload = XmlSignatureTest.class
-            .getResourceAsStream("/org/apache/camel/component/xmlsecurity/ManifestTest_TamperedContent.xml");
+                .getResourceAsStream("/org/apache/camel/component/xmlsecurity/ManifestTest_TamperedContent.xml");
         assertNotNull("Cannot load payload", payload);
         sendBody("direct:cryptocontextprops", payload);
         assertMockEndpointsSatisfied();
@@ -737,11 +703,11 @@ public class XmlSignatureTest extends CamelTestSupport {
     public void testVerifySignatureInvalidValueException() throws Exception {
         MockEndpoint mock = setupExceptionMock();
         setUpKeys("DSA", 512);
-        context.getEndpoint("xmlsecurity:verify://verifyexceptions?keySelector=#selector",
-                            XmlVerifierEndpoint.class).setKeySelector(KeySelector.singletonKeySelector(keyPair.getPublic()));
+        context.getEndpoint("xmlsecurity:verify://verifyexceptions?keySelector=#selector", XmlVerifierEndpoint.class).setKeySelector(
+                KeySelector.singletonKeySelector(keyPair.getPublic()));
         // payload needs DSA key
         InputStream payload = XmlSignatureTest.class
-            .getResourceAsStream("/org/apache/camel/component/xmlsecurity/ExampleEnvelopingDigSig.xml");
+                .getResourceAsStream("/org/apache/camel/component/xmlsecurity/ExampleEnvelopingDigSig.xml");
         assertNotNull("Cannot load payload", payload);
         sendBody("direct:verifyexceptions", payload);
         assertMockEndpointsSatisfied();
@@ -752,7 +718,7 @@ public class XmlSignatureTest extends CamelTestSupport {
     public void testVerifyInvalidKeyException() throws Exception {
         MockEndpoint mock = setupExceptionMock();
         InputStream payload = XmlSignatureTest.class
-            .getResourceAsStream("/org/apache/camel/component/xmlsecurity/ExampleEnvelopingDigSig.xml");
+                .getResourceAsStream("/org/apache/camel/component/xmlsecurity/ExampleEnvelopingDigSig.xml");
         assertNotNull("Cannot load payload", payload);
         sendBody("direct:verifyInvalidKeyException", payload);
         assertMockEndpointsSatisfied();
@@ -770,7 +736,7 @@ public class XmlSignatureTest extends CamelTestSupport {
     public void testVerifyXmlSignatureChecker() throws Exception {
         MockEndpoint mock = setupExceptionMock();
         InputStream payload = XmlSignatureTest.class
-            .getResourceAsStream("/org/apache/camel/component/xmlsecurity/ExampleEnvelopedXmlSig.xml");
+                .getResourceAsStream("/org/apache/camel/component/xmlsecurity/ExampleEnvelopedXmlSig.xml");
         assertNotNull("Cannot load payload", payload);
         sendBody("direct:xmlSignatureChecker", payload);
         assertMockEndpointsSatisfied();
@@ -781,7 +747,7 @@ public class XmlSignatureTest extends CamelTestSupport {
     public void testVerifyValidationFailedHandler() throws Exception {
         setupMock("some text tampered");
         InputStream payload = XmlSignatureTest.class
-            .getResourceAsStream("/org/apache/camel/component/xmlsecurity/ManifestTest_TamperedContent.xml");
+                .getResourceAsStream("/org/apache/camel/component/xmlsecurity/ManifestTest_TamperedContent.xml");
         assertNotNull("Cannot load payload", payload);
         sendBody("direct:validationFailedHandler", payload);
         assertMockEndpointsSatisfied();
@@ -790,42 +756,303 @@ public class XmlSignatureTest extends CamelTestSupport {
     @Test
     public void testFurtherParameters() throws Exception {
         setupMock(payload);
-        String payloadWithDTDoctype = "<?xml version=\'1.0\'?>"
-            + "<!DOCTYPE Signature SYSTEM "
-            + "\"src/test/resources/org/apache/camel/component/xmlsecurity/xmldsig-core-schema.dtd\" [ <!ENTITY dsig "
-            + "\"http://www.w3.org/2000/09/xmldsig#\"> ]>"
-            + "<root xmlns=\"http://test/test\"><test>Test Message</test></root>";
+        String payloadWithDTDoctype = "<?xml version=\'1.0\'?>" + "<!DOCTYPE Signature SYSTEM "
+                + "\"src/test/resources/org/apache/camel/component/xmlsecurity/xmldsig-core-schema.dtd\" [ <!ENTITY dsig "
+                + "\"http://www.w3.org/2000/09/xmldsig#\"> ]>" + "<root xmlns=\"http://test/test\"><test>Test Message</test></root>";
 
         sendBody("direct:furtherparams", payloadWithDTDoctype);
         assertMockEndpointsSatisfied();
     }
 
-    private void checkThrownException(MockEndpoint mock,
-                                      Class<? extends XmlSignatureException> cl,
-                                      Class<? extends Exception> expectedCauseClass) throws Exception {
-        Exception e = (Exception) mock.getExchanges().get(0)
-            .getProperty(Exchange.EXCEPTION_CAUGHT);
+    @Test
+    public void testReferenceUriWithIdAttributeInTheEnvelopedCase() throws Exception {
+
+        XmlSignerEndpoint endpoint = getDetachedSignerEndpoint();
+        endpoint.setParentLocalName("root");
+        endpoint.setParentNamespace("http://test");
+        endpoint.setXpathsToIdAttributes(null);
+
+        String detachedPayload = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + //
+                "<ns:root xmlns:ns=\"http://test\"><a ID=\"myID\"><b>bValue</b></a></ns:root>";
+        MockEndpoint mock = getMockEndpoint("mock:result");
+        mock.expectedMessageCount(1);
+        sendBody("direct:detached", detachedPayload,
+                Collections.singletonMap(XmlSignatureConstants.HEADER_CONTENT_REFERENCE_URI, (Object) "#myID"));
+        assertMockEndpointsSatisfied();
+        String expectedPartContent = "<ds:Reference URI=\"#myID\">";
+        checkBodyContains(mock, expectedPartContent);
+    }
+
+    @Test
+    public void testDetachedSignature() throws Exception {
+        String detachedPayload = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + //
+                "<ns:root xmlns:ns=\"http://test\"><a ID=\"myID\"><b>bValue</b></a></ns:root>";
+        MockEndpoint mock = getMockEndpoint("mock:result");
+        mock.expectedMessageCount(1);
+        MockEndpoint mockVerified = getMockEndpoint("mock:verified");
+        mockVerified.expectedBodiesReceived(detachedPayload);
+        sendBody("direct:detached", detachedPayload);
+        assertMockEndpointsSatisfied();
+        Map<String, String> namespaceMap = new TreeMap<String, String>();
+        namespaceMap.put("ns", "http://test");
+        namespaceMap.put("ds", XMLSignature.XMLNS);
+        checkXpath(mock, "ns:root/ds:Signature", namespaceMap);
+    }
+
+    @Test
+    public void testDetachedSignatureComplexSchema() throws Exception {
+
+        String xpath1exp = "/ns:root/test/ns1:B/C/@ID";
+        String xpath2exp = "/ns:root/test/@ID";
+        testDetached2Xpaths(xpath1exp, xpath2exp);
+    }
+
+    /**
+     * Checks that the processor sorts the xpath expressions in such a way that
+     * elements with deeper hierarchy level are signed first.
+     * 
+     */
+    @Test
+    public void testDetachedSignatureWrongXPathOrder() throws Exception {
+
+        String xpath2exp = "/ns:root/test/ns1:B/C/@ID";
+        String xpath1exp = "/ns:root/test/@ID";
+        testDetached2Xpaths(xpath1exp, xpath2exp);
+    }
+
+    void testDetached2Xpaths(String xpath1exp, String xpath2exp) throws InterruptedException, XPathExpressionException, SAXException,
+            IOException, ParserConfigurationException {
+        String detachedPayload = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + //
+                "<ns:root xmlns:ns=\"http://test\"><test ID=\"myID\"><b>bValue</b><ts:B xmlns:ts=\"http://testB\"><C ID=\"cID\"><D>dvalue</D></C></ts:B></test></ns:root>";
+        MockEndpoint mock = getMockEndpoint("mock:result");
+        mock.expectedMessageCount(1);
+        MockEndpoint mockVerified = getMockEndpoint("mock:verified");
+        mockVerified.expectedBodiesReceived(detachedPayload);
+        Map<String, Object> headers = new TreeMap<String, Object>();
+        headers.put(XmlSignatureConstants.HEADER_SCHEMA_RESOURCE_URI, (Object) "org/apache/camel/component/xmlsecurity/TestComplex.xsd");
+        Map<String, String> namespaceMap = new TreeMap<String, String>();
+        namespaceMap.put("ns", "http://test");
+        namespaceMap.put("ns1", "http://testB");
+        XPathFilterParameterSpec xpath1 = XmlSignatureHelper.getXpathFilter(xpath1exp, namespaceMap);
+        XPathFilterParameterSpec xpath2 = XmlSignatureHelper.getXpathFilter(xpath2exp, namespaceMap);
+
+        List<XPathFilterParameterSpec> xpaths = new ArrayList<XPathFilterParameterSpec>();
+        xpaths.add(xpath1);
+        xpaths.add(xpath2);
+        headers.put(XmlSignatureConstants.HEADER_XPATHS_TO_ID_ATTRIBUTES, (Object) xpaths);
+        sendBody("direct:detached", detachedPayload, headers);
+        assertMockEndpointsSatisfied();
+        Map<String, String> namespaceMap2 = new TreeMap<String, String>();
+        namespaceMap2.put("ns", "http://test");
+        namespaceMap2.put("ds", XMLSignature.XMLNS);
+        namespaceMap2.put("nsB", "http://testB");
+        checkXpath(mock, "ns:root/test/nsB:B/ds:Signature", namespaceMap2);
+        checkXpath(mock, "ns:root/ds:Signature", namespaceMap2);
+    }
+
+    @Test
+    public void testExceptionEnvelopedAndDetached() throws Exception {
+        String detachedPayload = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + //
+                "<ns:root xmlns:ns=\"http://test\"><a ID=\"myID\"><b>bValue</b></a></ns:root>";
+        XmlSignerEndpoint endpoint = getDetachedSignerEndpoint();
+        String parentLocalName = "parent";
+        endpoint.setParentLocalName(parentLocalName);
+        MockEndpoint mock = setupExceptionMock();
+        mock.expectedMessageCount(1);
+        sendBody("direct:detached", detachedPayload);
+        assertMockEndpointsSatisfied();
+        checkThrownException(
+                mock,
+                XmlSignatureException.class,
+                "The configuration of the XML signer component is wrong. The parent local name "
+                        + parentLocalName
+                        + " for an enveloped signature and the XPATHs to ID attributes for a detached signature are specified. You must not specify both parameters.",
+                null);
+    }
+
+    @Test
+    public void testExceptionSchemaValidation() throws Exception {
+        String detachedPayload = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + //
+                "<ns:root xmlns:ns=\"http://test\"><a ID=\"myID\"><error>bValue</error></a></ns:root>";
+        MockEndpoint mock = setupExceptionMock();
+        mock.expectedMessageCount(1);
+        sendBody("direct:detached", detachedPayload);
+        assertMockEndpointsSatisfied();
+        checkThrownException(mock, SchemaValidationException.class, null);
+    }
+
+    @Test
+    public void testEceptionDetachedNoXmlSchema() throws Exception {
+        String detachedPayload = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + //
+                "<ns:root xmlns:ns=\"http://test\"><a ID=\"myID\"><b>bValue</b></a></ns:root>";
+        XmlSignerEndpoint endpoint = getDetachedSignerEndpoint();
+        endpoint.setSchemaResourceUri(null);
+        MockEndpoint mock = setupExceptionMock();
+        mock.expectedMessageCount(1);
+        sendBody("direct:detached", detachedPayload);
+        assertMockEndpointsSatisfied();
+        checkThrownException(mock, XmlSignatureException.class,
+                "The configruation of the XML Signature component is wrong: No XML schema specified in the detached case", null);
+    }
+
+    @Test
+    public void testExceptionDetachedXpathInvalid() throws Exception {
+        String wrongXPath = "n1:p/a"; // namespace prefix is not defined
+        MockEndpoint mock = testXpath(wrongXPath);
+        checkThrownException(mock, XmlSignatureException.class, "The configured xpath expression " + wrongXPath + " is invalid.",
+                XPathExpressionException.class);
+    }
+
+    @Test
+    public void testExceptionDetachedXPathNoIdAttribute() throws Exception {
+        String value = "not id";
+        String detachedPayload = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + //
+                "<ns:root xmlns:ns=\"http://test\"><a ID=\"myID\" stringAttr=\"" + value + "\"><b>bValue</b></a></ns:root>";
+        String xPath = "a/@stringAttr";
+
+        MockEndpoint mock = testXpath(xPath, detachedPayload);
+        checkThrownException(mock, XmlSignatureException.class,
+                "Wrong configured xpath expression for ID attributes: The evaluation of the xpath expression " + xPath
+                        + " resulted in an attribute which is not of type ID. The attribute value is " + value + ".", null);
+    }
+
+    @Test
+    public void testExceptionDetachedXpathNoAttribute() throws Exception {
+        String xPath = "a"; // Element a
+        MockEndpoint mock = testXpath(xPath);
+        checkThrownException(mock, XmlSignatureException.class,
+                "Wrong configured xpath expression for ID attributes: The evaluation of the xpath expression " + xPath
+                        + " returned a node which was not of type Attribute.", null);
+    }
+
+    @Test
+    public void testExceptionDetachedXPathNoResult() throws Exception {
+        String xPath = "a/@stringAttr"; // for this xpath there is no result
+        MockEndpoint mock = testXpath(xPath);
+        checkThrownException(
+                mock,
+                XmlSignatureException.class,
+                "No element to sign found in the detached case. No node found for the configured xpath expressions "
+                        + xPath
+                        + ". Either the configuration of the XML signature component is wrong or the incoming message has not the correct structure.",
+                null);
+    }
+
+    private MockEndpoint testXpath(String xPath) throws InterruptedException {
+        String detachedPayload = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + //
+                "<ns:root xmlns:ns=\"http://test\"><a ID=\"myID\"><b>bValue</b></a></ns:root>";
+        return testXpath(xPath, detachedPayload);
+    }
+
+    private MockEndpoint testXpath(String xPath, String detachedPayload) throws InterruptedException {
+        MockEndpoint mock = setupExceptionMock();
+        mock.expectedMessageCount(1);
+        List<XPathFilterParameterSpec> list = Collections.singletonList(XmlSignatureHelper.getXpathFilter(xPath, null));
+        sendBody("direct:detached", detachedPayload,
+                Collections.singletonMap(XmlSignatureConstants.HEADER_XPATHS_TO_ID_ATTRIBUTES, (Object) list));
+        assertMockEndpointsSatisfied();
+        return mock;
+    }
+
+    @Test
+    public void testExceptionDetachedNoParent() throws Exception {
+        String detachedPayload = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + //
+                "<ns:root ID=\"rootId\" xmlns:ns=\"http://test\"><a ID=\"myID\"><b>bValue</b></a></ns:root>";
+        String xPath = "//@ID";
+        String localName = "root";
+        String namespaceURI = "http://test";
+        String referenceUri = "#rootId";
+        MockEndpoint mock = testXpath(xPath, detachedPayload);
+        checkThrownException(mock, XmlSignatureException.class,
+                "Either the configuration of the XML Signature component is wrong or the incoming document has an invalid structure: The element "
+                        + localName + "{" + namespaceURI + "} which is referenced by the reference URI " + referenceUri
+                        + " has no parent element. The element must have a parent element in the configured detached case.", null);
+    }
+
+    XmlSignerEndpoint getDetachedSignerEndpoint() {
+        XmlSignerEndpoint endpoint = (XmlSignerEndpoint) context()
+                .getEndpoint(
+                        "xmlsecurity:sign://detached?keyAccessor=#keyAccessorDefault&xpathsToIdAttributes=#xpathsToIdAttributes&"//
+                        + "schemaResourceUri=org/apache/camel/component/xmlsecurity/Test.xsd&clearHeaders=false");
+        return endpoint;
+    }
+
+    private void checkBodyContains(MockEndpoint mock, String expectedPartContent) {
+        Message message = getMessage(mock);
+        String body = message.getBody(String.class);
+        assertNotNull(body);
+        assertTrue("The message body " + body + " does not contain the expected string " + expectedPartContent,
+                body.contains(expectedPartContent));
+    }
+
+    private void checkXpath(MockEndpoint mock, String xpathString, final Map<String, String> prefix2Namespace)
+        throws XPathExpressionException, SAXException, IOException, ParserConfigurationException {
+        Message mess = getMessage(mock);
+        InputStream body = mess.getBody(InputStream.class);
+        assertNotNull(body);
+        XPathFactory xpathFactory = XPathFactory.newInstance();
+        XPath xpath = xpathFactory.newXPath();
+        NamespaceContext nc = new NamespaceContext() {
+
+            @SuppressWarnings("rawtypes")
+            @Override
+            public Iterator getPrefixes(String namespaceURI) {
+                return null;
+            }
+
+            @Override
+            public String getPrefix(String namespaceURI) {
+                return null;
+            }
+
+            @Override
+            public String getNamespaceURI(String prefix) {
+                return prefix2Namespace.get(prefix);
+            }
+        };
+        xpath.setNamespaceContext(nc);
+        XPathExpression expr = xpath.compile(xpathString);
+        Object result = expr.evaluate(XmlSignatureHelper.newDocumentBuilder(true).parse(body), XPathConstants.NODE);
+        assertNotNull("The xpath " + xpathString + " returned a null value", result);
+    }
+
+    private Message getMessage(MockEndpoint mock) {
+        List<Exchange> exs = mock.getExchanges();
+        assertNotNull(exs);
+        assertEquals(1, exs.size());
+        Exchange ex = exs.get(0);
+        Message mess = ex.getIn();
+        assertNotNull(mess);
+        return mess;
+    }
+
+    private void checkThrownException(MockEndpoint mock, Class<? extends Exception> cl, Class<? extends Exception> expectedCauseClass)
+        throws Exception {
+        checkThrownException(mock, cl, null, expectedCauseClass);
+    }
+
+    private void checkThrownException(MockEndpoint mock, Class<? extends Exception> cl, String expectedMessage,
+            Class<? extends Exception> expectedCauseClass) throws Exception {
+        Exception e = (Exception) mock.getExchanges().get(0).getProperty(Exchange.EXCEPTION_CAUGHT);
         assertNotNull("Expected excpetion " + cl.getName() + " missing", e);
         if (e.getClass() != cl) {
             String stackTrace = getStrackTrace(e);
-            fail("Exception  " + cl.getName() + " excpected, but was "
-                + e.getClass().getName() + ": " + stackTrace);
+            fail("Exception  " + cl.getName() + " excpected, but was " + e.getClass().getName() + ": " + stackTrace);
+        }
+        if (expectedMessage != null) {
+            assertEquals(expectedMessage, e.getMessage());
         }
         if (expectedCauseClass != null) {
             Throwable cause = e.getCause();
-            assertNotNull(
-                          "Expected cause exception" + expectedCauseClass.getName()
-                          + " missing", cause);
+            assertNotNull("Expected cause exception" + expectedCauseClass.getName() + " missing", cause);
             if (expectedCauseClass != cause.getClass()) {
-                fail("Cause exception " + expectedCauseClass.getName()
-                     + " expected, but was " + cause.getClass().getName()
-                     + ": " + getStrackTrace(e));
+                fail("Cause exception " + expectedCauseClass.getName() + " expected, but was " + cause.getClass().getName() + ": "
+                        + getStrackTrace(e));
             }
         }
     }
 
-    private String getStrackTrace(Exception e)
-        throws UnsupportedEncodingException {
+    private String getStrackTrace(Exception e) throws UnsupportedEncodingException {
         ByteArrayOutputStream os = new ByteArrayOutputStream();
         PrintWriter w = new PrintWriter(os);
         e.printStackTrace(w);
@@ -853,18 +1080,16 @@ public class XmlSignatureTest extends CamelTestSupport {
     }
 
     public Exchange doTestSignatureRoute(RouteBuilder builder) throws Exception {
-        return doSignatureRouteTest(builder, null, Collections.<String, Object>emptyMap());
+        return doSignatureRouteTest(builder, null, Collections.<String, Object> emptyMap());
     }
 
-    public Exchange doSignatureRouteTest(RouteBuilder builder, Exchange e,
-                                         Map<String, Object> headers) throws Exception {
+    public Exchange doSignatureRouteTest(RouteBuilder builder, Exchange e, Map<String, Object> headers) throws Exception {
         CamelContext context = new DefaultCamelContext();
         try {
             context.addRoutes(builder);
             context.start();
 
-            MockEndpoint mock = context.getEndpoint("mock:result",
-                                                    MockEndpoint.class);
+            MockEndpoint mock = context.getEndpoint("mock:result", MockEndpoint.class);
             mock.setExpectedMessageCount(1);
 
             ProducerTemplate template = context.createProducerTemplate();
@@ -915,8 +1140,7 @@ public class XmlSignatureTest extends CamelTestSupport {
     }
 
     public PrivateKey getKeyFromKeystore() throws Exception {
-        return (PrivateKey) loadKeystore().getKey("bob",
-                                                  "letmein".toCharArray());
+        return (PrivateKey) loadKeystore().getKey("bob", "letmein".toCharArray());
     }
 
     private AlgorithmMethod getCanonicalizationMethod() {
@@ -928,18 +1152,14 @@ public class XmlSignatureTest extends CamelTestSupport {
     private List<AlgorithmMethod> getTransformsXPath2() {
 
         List<XPathAndFilter> list = new ArrayList<XPathAndFilter>(3);
-        XPathAndFilter xpath1 = new XPathAndFilter("//n0:ToBeSigned",
-                                                   XPathType.Filter.INTERSECT.toString());
+        XPathAndFilter xpath1 = new XPathAndFilter("//n0:ToBeSigned", XPathType.Filter.INTERSECT.toString());
         list.add(xpath1);
-        XPathAndFilter xpath2 = new XPathAndFilter("//n0:NotToBeSigned",
-                                                   XPathType.Filter.SUBTRACT.toString());
+        XPathAndFilter xpath2 = new XPathAndFilter("//n0:NotToBeSigned", XPathType.Filter.SUBTRACT.toString());
         list.add(xpath2);
-        XPathAndFilter xpath3 = new XPathAndFilter("//n0:ReallyToBeSigned",
-                                                   XPathType.Filter.UNION.toString());
+        XPathAndFilter xpath3 = new XPathAndFilter("//n0:ReallyToBeSigned", XPathType.Filter.UNION.toString());
         list.add(xpath3);
         List<AlgorithmMethod> result = new ArrayList<AlgorithmMethod>(2);
-        result.add(XmlSignatureHelper
-                   .getCanonicalizationMethod(CanonicalizationMethod.INCLUSIVE));
+        result.add(XmlSignatureHelper.getCanonicalizationMethod(CanonicalizationMethod.INCLUSIVE));
         result.add(XmlSignatureHelper.getXPath2Transform(list, getNamespaceMap()));
         return result;
     }
@@ -952,19 +1172,15 @@ public class XmlSignatureTest extends CamelTestSupport {
 
     private List<AlgorithmMethod> getTransformsXsltXpath() {
         try {
-            AlgorithmMethod transformXslt = XmlSignatureHelper
-                .getXslTransform("/org/apache/camel/component/xmlsecurity/xslt_test.xsl");
+            AlgorithmMethod transformXslt = XmlSignatureHelper.getXslTransform("/org/apache/camel/component/xmlsecurity/xslt_test.xsl");
             Map<String, String> namespaceMap = new HashMap<String, String>(1);
             namespaceMap.put("n0", "https://org.apache/camel/xmlsecurity/test");
-            AlgorithmMethod transformXpath = XmlSignatureHelper
-                .getXPathTransform("//n0:XMLSecurity/n0:Content",
-                                   namespaceMap);
+            AlgorithmMethod transformXpath = XmlSignatureHelper.getXPathTransform("//n0:XMLSecurity/n0:Content", namespaceMap);
             // I removed base 64 transform because the JDK implementation does
             // not correctly support this transformation
             // AlgorithmMethod transformBase64 = helper.getBase64Transform();
             List<AlgorithmMethod> result = new ArrayList<AlgorithmMethod>(3);
-            result.add(XmlSignatureHelper
-                       .getCanonicalizationMethod(CanonicalizationMethod.INCLUSIVE));
+            result.add(XmlSignatureHelper.getCanonicalizationMethod(CanonicalizationMethod.INCLUSIVE));
             result.add(transformXslt);
             result.add(transformXpath);
             // result.add(transformBase64);
@@ -983,8 +1199,7 @@ public class XmlSignatureTest extends CamelTestSupport {
             }
 
             @Override
-            public KeyInfo getKeyInfo(Message mess, Node messageBody,
-                                      KeyInfoFactory keyInfoFactory) throws Exception {
+            public KeyInfo getKeyInfo(Message mess, Node messageBody, KeyInfoFactory keyInfoFactory) throws Exception {
                 return null;
             }
         };
@@ -992,8 +1207,7 @@ public class XmlSignatureTest extends CamelTestSupport {
     }
 
     public static String getBaseUri() {
-        String uri = "file:/" + System.getProperty("user.dir")
-            + "/src/test/resources/org/apache/camel/component/xmlsecurity/";
+        String uri = "file:/" + System.getProperty("user.dir") + "/src/test/resources/org/apache/camel/component/xmlsecurity/";
         return uri.replace('\\', '/');
     }
 
@@ -1007,9 +1221,8 @@ public class XmlSignatureTest extends CamelTestSupport {
      * then the public key will be ignored.
      */
     static class KeyValueKeySelector extends KeySelector {
-        public KeySelectorResult select(KeyInfo keyInfo,
-                                        KeySelector.Purpose purpose, AlgorithmMethod method,
-                                        XMLCryptoContext context) throws KeySelectorException {
+        public KeySelectorResult select(KeyInfo keyInfo, KeySelector.Purpose purpose, AlgorithmMethod method, XMLCryptoContext context)
+            throws KeySelectorException {
             if (keyInfo == null) {
                 throw new KeySelectorException("Null KeyInfo object!");
             }
@@ -1037,8 +1250,8 @@ public class XmlSignatureTest extends CamelTestSupport {
         }
 
         static boolean algEquals(String algURI, String algName) {
-            return (algName.equalsIgnoreCase("DSA") && algURI.equalsIgnoreCase(SignatureMethod.DSA_SHA1)) 
-                || (algName.equalsIgnoreCase("RSA") && algURI.equalsIgnoreCase(SignatureMethod.RSA_SHA1));
+            return (algName.equalsIgnoreCase("DSA") && algURI.equalsIgnoreCase(SignatureMethod.DSA_SHA1))
+                    || (algName.equalsIgnoreCase("RSA") && algURI.equalsIgnoreCase(SignatureMethod.RSA_SHA1));
         }
     }
 
@@ -1055,8 +1268,7 @@ public class XmlSignatureTest extends CamelTestSupport {
     }
 
     public static Map<String, ? extends Object> getCrytoContextProperties() {
-        return Collections.singletonMap("org.jcp.xml.dsig.validateManifests",
-                                        Boolean.FALSE);
+        return Collections.singletonMap("org.jcp.xml.dsig.validateManifests", Boolean.FALSE);
     }
 
     public static KeyAccessor getDefaultKeyAccessor() throws Exception {
@@ -1092,8 +1304,7 @@ public class XmlSignatureTest extends CamelTestSupport {
     }
 
     public static XPathFilterParameterSpec getNodeSerachXPath() {
-        Map<String, String> prefix2Namespace = Collections.singletonMap("pre",
-            "http://test/test");
+        Map<String, String> prefix2Namespace = Collections.singletonMap("pre", "http://test/test");
         return XmlSignatureHelper.getXpathFilter("//pre:root", prefix2Namespace);
     }
 

http://git-wip-us.apache.org/repos/asf/camel/blob/12241987/components/camel-xmlsecurity/src/test/resources/log4j.properties
----------------------------------------------------------------------
diff --git a/components/camel-xmlsecurity/src/test/resources/log4j.properties b/components/camel-xmlsecurity/src/test/resources/log4j.properties
index 12589cb..8a07d01 100755
--- a/components/camel-xmlsecurity/src/test/resources/log4j.properties
+++ b/components/camel-xmlsecurity/src/test/resources/log4j.properties
@@ -21,6 +21,7 @@
 log4j.rootLogger=INFO, file
 
 #log4j.logger.org.apache.camel.dataformat.xmlsecurity=DEBUG
+#log4j.logger.org.apache.camel.component.xmlsecurity=DEBUG
 
 # CONSOLE appender not used by default
 log4j.appender.console=org.apache.log4j.ConsoleAppender


Mime
View raw message