You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@santuario.apache.org by co...@apache.org on 2012/01/10 17:36:37 UTC

svn commit: r1229629 - in /santuario/xml-security-java/trunk: ./ src/main/java/org/apache/xml/security/signature/ src/main/java/org/apache/xml/security/signature/reference/ src/test/java/org/apache/xml/security/test/interop/ src/test/java/org/apache/xm...

Author: coheigea
Date: Tue Jan 10 16:36:36 2012
New Revision: 1229629

URL: http://svn.apache.org/viewvc?rev=1229629&view=rev
Log:
[SANTUARIO-192] - Add the ability to access the dereferenced Elements after signature validation in the non-JSR-105 API

Added:
    santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/signature/reference/
    santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/signature/reference/ReferenceData.java
    santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/signature/reference/ReferenceNodeSetData.java
    santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/signature/reference/ReferenceOctetStreamData.java
    santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/signature/reference/ReferenceSubTreeData.java
    santuario/xml-security-java/trunk/src/test/java/org/apache/xml/security/test/signature/SignatureReferenceTest.java
Modified:
    santuario/xml-security-java/trunk/CHANGELOG.txt
    santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/signature/Reference.java
    santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/signature/XMLSignatureInput.java
    santuario/xml-security-java/trunk/src/test/java/org/apache/xml/security/test/interop/InteropTestBase.java

Modified: santuario/xml-security-java/trunk/CHANGELOG.txt
URL: http://svn.apache.org/viewvc/santuario/xml-security-java/trunk/CHANGELOG.txt?rev=1229629&r1=1229628&r2=1229629&view=diff
==============================================================================
--- santuario/xml-security-java/trunk/CHANGELOG.txt (original)
+++ santuario/xml-security-java/trunk/CHANGELOG.txt Tue Jan 10 16:36:36 2012
@@ -1,6 +1,7 @@
 Changelog for "Apache xml-security" <http://santuario.apache.org/>
 
 New in v1.5.0-SNAPSHOT
+    Fixed SANTUARIO-292: Add the ability to access the dereferenced Elements after signature validation in the non-JSR-105 API.
     Fixed SANTUARIO-290: Add a secure validation switch for signature processing
     Fixed SANTUARIO-255: Port JSR 105 code to JDK 1.5.
     Fixed SANTUARIO-288: Add support for GCM algorithms via a third-party Crypto provider.

Modified: santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/signature/Reference.java
URL: http://svn.apache.org/viewvc/santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/signature/Reference.java?rev=1229629&r1=1229628&r2=1229629&view=diff
==============================================================================
--- santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/signature/Reference.java (original)
+++ santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/signature/Reference.java Tue Jan 10 16:36:36 2012
@@ -23,6 +23,7 @@ import java.io.OutputStream;
 import java.security.AccessController;
 import java.security.PrivilegedAction;
 import java.util.HashSet;
+import java.util.Iterator;
 import java.util.Set;
 
 import org.apache.xml.security.algorithms.MessageDigestAlgorithm;
@@ -30,6 +31,10 @@ import org.apache.xml.security.c14n.Cano
 import org.apache.xml.security.c14n.InvalidCanonicalizerException;
 import org.apache.xml.security.exceptions.Base64DecodingException;
 import org.apache.xml.security.exceptions.XMLSecurityException;
+import org.apache.xml.security.signature.reference.ReferenceData;
+import org.apache.xml.security.signature.reference.ReferenceNodeSetData;
+import org.apache.xml.security.signature.reference.ReferenceOctetStreamData;
+import org.apache.xml.security.signature.reference.ReferenceSubTreeData;
 import org.apache.xml.security.transforms.InvalidTransformException;
 import org.apache.xml.security.transforms.Transform;
 import org.apache.xml.security.transforms.TransformationException;
@@ -104,9 +109,6 @@ public class Reference extends Signature
     /** Field MANIFEST_URI */
     public static final String MANIFEST_URI = Constants.SignatureSpecNS + Constants._TAG_MANIFEST;
     
-    /** Field CacheSignedNodes */
-    public static final boolean CacheSignedNodes = false;
-    
     /**
      * The maximum number of transforms per reference, if secure validation is enabled.
      */
@@ -138,6 +140,8 @@ public class Reference extends Signature
     private Element digestMethodElem;
 
     private Element digestValueElement;
+    
+    private ReferenceData referenceData;
 
     /**
      * Constructor Reference
@@ -472,6 +476,7 @@ public class Reference extends Signature
     public XMLSignatureInput getContentsAfterTransformation()
         throws XMLSignatureException {
         XMLSignatureInput input = this.getContentsBeforeTransformation();
+        cacheDereferencedElement(input);
 
         return this.getContentsAfterTransformation(input, null);
     }
@@ -487,6 +492,7 @@ public class Reference extends Signature
         throws XMLSignatureException {
         try {
             XMLSignatureInput input = this.getContentsBeforeTransformation();
+            cacheDereferencedElement(input);
             XMLSignatureInput output = input;
             Transforms transforms = this.getTransforms();
 
@@ -585,6 +591,14 @@ public class Reference extends Signature
     public XMLSignatureInput getTransformsOutput() {
         return this.transformsOutput;
     }
+    
+    /**
+     * Get the ReferenceData that corresponds to the cached representation of the dereferenced
+     * object before transformation.
+     */
+    public ReferenceData getReferenceData() {
+        return referenceData;
+    }
 
     /**
      * This method returns the {@link XMLSignatureInput} which is referenced by the
@@ -599,23 +613,44 @@ public class Reference extends Signature
         throws XMLSignatureException {
         try {
             XMLSignatureInput input = this.getContentsBeforeTransformation();
+            cacheDereferencedElement(input);
+            
             XMLSignatureInput output = this.getContentsAfterTransformation(input, os);
-
-            /* at this stage, this._transformsInput and this.transformsOutput
-             * contain a huge amount of nodes. When we do not cache these nodes
-             * but only preserve the octets, the memory footprint is dramatically
-             * reduced.
-             */
-            if (!Reference.CacheSignedNodes) {
-                this.transformsOutput = output;//new XMLSignatureInput(output.getBytes());
-
-                //this.transformsOutput.setSourceURI(output.getSourceURI());
-            }
+            this.transformsOutput = output;
             return output;
         } catch (XMLSecurityException ex) {
             throw new ReferenceNotInitializedException("empty", ex);
         }
     }
+    
+    /**
+     * Store the dereferenced Element(s) so that it/they can be retrieved later.
+     */
+    private void cacheDereferencedElement(XMLSignatureInput input) {
+        if (input.isNodeSet()) {
+            try {
+                final Set<Node> s = input.getNodeSet();
+                referenceData = new ReferenceNodeSetData() {
+                    public Iterator<Node> iterator() { return s.iterator(); }
+                };
+            } catch (Exception e) {
+                // log a warning
+                log.warn("cannot cache dereferenced data: " + e);
+            }
+        } else if (input.isElement()) {
+            referenceData = new ReferenceSubTreeData
+                (input.getSubNode(), input.isExcludeComments());
+        } else if (input.isOctetStream() || input.isByteArray()) {
+            try {
+                referenceData = new ReferenceOctetStreamData
+                    (input.getOctetStream(), input.getSourceURI(),
+                        input.getMIMEType());
+            } catch (IOException ioe) {
+                // log a warning
+                log.warn("cannot cache dereferenced data: " + ioe);
+            }
+        }
+    }
 
     /**
      * Method getTransforms

Modified: santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/signature/XMLSignatureInput.java
URL: http://svn.apache.org/viewvc/santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/signature/XMLSignatureInput.java?rev=1229629&r1=1229628&r2=1229629&view=diff
==============================================================================
--- santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/signature/XMLSignatureInput.java (original)
+++ santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/signature/XMLSignatureInput.java Tue Jan 10 16:36:36 2012
@@ -292,7 +292,7 @@ public class XMLSignatureInput {
     /**
      * Determines if the object has been set up with an Element
      *
-     * @return true if the object has been set up with a Node set
+     * @return true if the object has been set up with an Element
      */
     public boolean isElement() {
         return (inputOctetStreamProxy == null && subNode != null

Added: santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/signature/reference/ReferenceData.java
URL: http://svn.apache.org/viewvc/santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/signature/reference/ReferenceData.java?rev=1229629&view=auto
==============================================================================
--- santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/signature/reference/ReferenceData.java (added)
+++ santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/signature/reference/ReferenceData.java Tue Jan 10 16:36:36 2012
@@ -0,0 +1,30 @@
+/**
+ * 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.
+ */
+/*
+ * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ */
+/*
+ * $Id$
+ */
+package org.apache.xml.security.signature.reference;
+
+/**
+ * An abstract representation of the result of dereferencing a ds:Reference URI.
+ */
+public interface ReferenceData { }

Added: santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/signature/reference/ReferenceNodeSetData.java
URL: http://svn.apache.org/viewvc/santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/signature/reference/ReferenceNodeSetData.java?rev=1229629&view=auto
==============================================================================
--- santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/signature/reference/ReferenceNodeSetData.java (added)
+++ santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/signature/reference/ReferenceNodeSetData.java Tue Jan 10 16:36:36 2012
@@ -0,0 +1,49 @@
+/**
+ * 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.
+ */
+/*
+ * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ */
+/*
+ * $Id$
+ */
+package org.apache.xml.security.signature.reference;
+
+import java.util.Iterator;
+
+import org.w3c.dom.Node;
+
+/**
+ * An abstract representation of a <code>ReferenceData</code> type containing a node-set.
+ */
+public interface ReferenceNodeSetData extends ReferenceData {
+
+    /**
+     * Returns a read-only iterator over the nodes contained in this 
+     * <code>NodeSetData</code> in 
+     * <a href="http://www.w3.org/TR/1999/REC-xpath-19991116#dt-document-order">
+     * document order</a>. Attempts to modify the returned iterator
+     * via the <code>remove</code> method throw 
+     * <code>UnsupportedOperationException</code>.
+     *
+     * @return an <code>Iterator</code> over the nodes in this 
+     *    <code>NodeSetData</code> in document order
+     */
+    Iterator<Node> iterator();
+    
+}

Added: santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/signature/reference/ReferenceOctetStreamData.java
URL: http://svn.apache.org/viewvc/santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/signature/reference/ReferenceOctetStreamData.java?rev=1229629&view=auto
==============================================================================
--- santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/signature/reference/ReferenceOctetStreamData.java (added)
+++ santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/signature/reference/ReferenceOctetStreamData.java Tue Jan 10 16:36:36 2012
@@ -0,0 +1,101 @@
+/**
+ * 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.
+ */
+/*
+ * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ */
+/*
+ * $Id$
+ */
+package org.apache.xml.security.signature.reference;
+
+import java.io.InputStream;
+
+/**
+ * A representation of a <code>ReferenceData</code> type containing an OctetStream.
+ */
+public class ReferenceOctetStreamData implements ReferenceData {
+    private InputStream octetStream;
+    private String uri;
+    private String mimeType;
+
+    /**
+     * Creates a new <code>ReferenceOctetStreamData</code>.
+     *
+     * @param octetStream the input stream containing the octets
+     * @throws NullPointerException if <code>octetStream</code> is 
+     *    <code>null</code>
+     */
+    public ReferenceOctetStreamData(InputStream octetStream) {
+        if (octetStream == null) {
+            throw new NullPointerException("octetStream is null");
+        }
+        this.octetStream = octetStream;
+    }
+
+    /**
+     * Creates a new <code>ReferenceOctetStreamData</code>.
+     *
+     * @param octetStream the input stream containing the octets
+     * @param uri the URI String identifying the data object (may be 
+     *    <code>null</code>) 
+     * @param mimeType the MIME type associated with the data object (may be 
+     *    <code>null</code>) 
+     * @throws NullPointerException if <code>octetStream</code> is 
+     *    <code>null</code>
+     */
+    public ReferenceOctetStreamData(InputStream octetStream, String uri, 
+        String mimeType) {
+        if (octetStream == null) {
+            throw new NullPointerException("octetStream is null");
+        }
+        this.octetStream = octetStream;
+        this.uri = uri;
+        this.mimeType = mimeType;
+    }
+
+    /**
+     * Returns the input stream of this <code>ReferenceOctetStreamData</code>.
+     *
+     * @return the input stream of this <code>ReferenceOctetStreamData</code>.
+     */
+    public InputStream getOctetStream() {
+        return octetStream;
+    }
+
+    /**
+     * Returns the URI String identifying the data object represented by this
+     * <code>ReferenceOctetStreamData</code>.
+     *
+     * @return the URI String or <code>null</code> if not applicable
+     */
+    public String getURI() {
+        return uri;
+    }
+
+    /**
+     * Returns the MIME type associated with the data object represented by this
+     * <code>ReferenceOctetStreamData</code>.
+     *
+     * @return the MIME type or <code>null</code> if not applicable
+     */
+    public String getMimeType() {
+        return mimeType;
+    }
+    
+}

Added: santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/signature/reference/ReferenceSubTreeData.java
URL: http://svn.apache.org/viewvc/santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/signature/reference/ReferenceSubTreeData.java?rev=1229629&view=auto
==============================================================================
--- santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/signature/reference/ReferenceSubTreeData.java (added)
+++ santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/signature/reference/ReferenceSubTreeData.java Tue Jan 10 16:36:36 2012
@@ -0,0 +1,168 @@
+/**
+ * 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.
+ */
+/*
+ * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ */
+/*
+ * $Id$
+ */
+package org.apache.xml.security.signature.reference;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.ListIterator;
+import java.util.NoSuchElementException;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+
+/**
+ * A representation of a <code>ReferenceNodeSetData</code> type containing a node-set.
+ * This is a subtype of NodeSetData that represents a dereferenced
+ * same-document URI as the root of a subdocument. The main reason is
+ * for efficiency and performance, as some transforms can operate
+ * directly on the subdocument and there is no need to convert it
+ * first to an XPath node-set.
+ */
+public class ReferenceSubTreeData implements ReferenceNodeSetData {
+
+    private boolean excludeComments;
+    private Node root;
+
+    public ReferenceSubTreeData(Node root, boolean excludeComments) {
+        this.root = root;
+        this.excludeComments = excludeComments;
+    }
+
+    public Iterator<Node> iterator() {
+        return new DelayedNodeIterator(root, excludeComments);
+    }
+
+    public Node getRoot() {
+        return root;
+    }
+
+    public boolean excludeComments() {
+        return excludeComments;
+    }
+
+    /**
+     * This is an Iterator that contains a backing node-set that is
+     * not populated until the caller first attempts to advance the iterator.
+     */
+    static class DelayedNodeIterator implements Iterator<Node> {
+        private Node root;
+        private List<Node> nodeSet;
+        private ListIterator<Node> li;
+        private boolean withComments;
+
+        DelayedNodeIterator(Node root, boolean excludeComments) {
+            this.root = root;
+            this.withComments = !excludeComments;
+        }
+
+        public boolean hasNext() {
+            if (nodeSet == null) {
+                nodeSet = dereferenceSameDocumentURI(root);
+                li = nodeSet.listIterator();
+            }
+            return li.hasNext();
+        }
+
+        public Node next() {
+            if (nodeSet == null) {
+                nodeSet = dereferenceSameDocumentURI(root);
+                li = nodeSet.listIterator();
+            }
+            if (li.hasNext()) {
+                return li.next();
+            } else {
+                throw new NoSuchElementException();
+            }
+        }
+
+        public void remove() {
+            throw new UnsupportedOperationException();
+        }
+
+        /**
+         * Dereferences a same-document URI fragment.
+         *
+         * @param node the node (document or element) referenced by the
+         *	 URI fragment. If null, returns an empty set.
+         * @return a set of nodes (minus any comment nodes)
+         */
+        private List<Node> dereferenceSameDocumentURI(Node node) {
+            List<Node> nodeSet = new ArrayList<Node>();
+            if (node != null) {
+                nodeSetMinusCommentNodes(node, nodeSet, null);
+            }
+            return nodeSet;
+        }
+
+        /**
+         * Recursively traverses the subtree, and returns an XPath-equivalent
+         * node-set of all nodes traversed, excluding any comment nodes,
+         * if specified.
+         *
+         * @param node the node to traverse
+         * @param nodeSet the set of nodes traversed so far
+         * @param the previous sibling node
+         */
+        @SuppressWarnings("fallthrough")
+        private void nodeSetMinusCommentNodes(Node node, List<Node> nodeSet,
+                                              Node prevSibling)
+        {
+            switch (node.getNodeType()) {
+                case Node.ELEMENT_NODE :
+                    NamedNodeMap attrs = node.getAttributes();
+                    if (attrs != null) {
+                        for (int i = 0, len = attrs.getLength(); i < len; i++) {
+                            nodeSet.add(attrs.item(i));
+                        }
+                    }
+                    nodeSet.add(node);
+                case Node.DOCUMENT_NODE :
+                    Node pSibling = null;
+                    for (Node child = node.getFirstChild(); child != null;
+                        child = child.getNextSibling()) {
+                        nodeSetMinusCommentNodes(child, nodeSet, pSibling);
+                        pSibling = child;
+                    }
+                    break;
+                case Node.TEXT_NODE :
+                case Node.CDATA_SECTION_NODE:
+                    // emulate XPath which only returns the first node in
+                    // contiguous text/cdata nodes
+                    if (prevSibling != null &&
+                        (prevSibling.getNodeType() == Node.TEXT_NODE ||
+                         prevSibling.getNodeType() == Node.CDATA_SECTION_NODE)) {
+                        return;
+                    }
+                case Node.PROCESSING_INSTRUCTION_NODE :
+                    nodeSet.add(node);
+                    break;
+                case Node.COMMENT_NODE:
+                    if (withComments) { 
+                        nodeSet.add(node);
+                    }
+            }
+        }
+    }
+}

Modified: santuario/xml-security-java/trunk/src/test/java/org/apache/xml/security/test/interop/InteropTestBase.java
URL: http://svn.apache.org/viewvc/santuario/xml-security-java/trunk/src/test/java/org/apache/xml/security/test/interop/InteropTestBase.java?rev=1229629&r1=1229628&r2=1229629&view=diff
==============================================================================
--- santuario/xml-security-java/trunk/src/test/java/org/apache/xml/security/test/interop/InteropTestBase.java (original)
+++ santuario/xml-security-java/trunk/src/test/java/org/apache/xml/security/test/interop/InteropTestBase.java Tue Jan 10 16:36:36 2012
@@ -21,16 +21,23 @@ package org.apache.xml.security.test.int
 import java.io.File;
 import java.security.PublicKey;
 import java.security.cert.X509Certificate;
+import java.util.Iterator;
 
 import javax.xml.xpath.XPath;
 import javax.xml.xpath.XPathConstants;
 import javax.xml.xpath.XPathFactory;
 
 import org.apache.xml.security.keys.KeyInfo;
+import org.apache.xml.security.signature.Reference;
+import org.apache.xml.security.signature.SignedInfo;
 import org.apache.xml.security.signature.XMLSignature;
+import org.apache.xml.security.signature.reference.ReferenceData;
+import org.apache.xml.security.signature.reference.ReferenceNodeSetData;
+import org.apache.xml.security.signature.reference.ReferenceOctetStreamData;
 import org.apache.xml.security.test.DSNamespaceContext;
 import org.apache.xml.security.utils.resolver.ResourceResolverSpi;
 import org.w3c.dom.Element;
+import org.w3c.dom.Node;
 
 public class InteropTestBase extends org.junit.Assert {
 
@@ -133,6 +140,7 @@ public class InteropTestBase extends org
                     "Did not find a public key, so I can't check the signature");
                 }
             }
+            checkReferences(signature);
         } else {
             throw new RuntimeException("Did not find a KeyInfo");
         }
@@ -148,10 +156,38 @@ public class InteropTestBase extends org
                     log.debug("Reference " + i + " was not OK");
                 }
             }
+            checkReferences(signature);
             //throw new RuntimeException("Falle:"+sb.toString());
         }
 
         return result;
     }
     
+    private void checkReferences(XMLSignature xmlSignature) throws Exception {
+        SignedInfo signedInfo = xmlSignature.getSignedInfo();
+        assertTrue(signedInfo.getLength() > 0);
+        for (int i = 0; i < signedInfo.getLength(); i++) {
+            Reference reference = signedInfo.item(i);
+            assertNotNull(reference);
+            ReferenceData referenceData = reference.getReferenceData();
+            assertNotNull(referenceData);
+            
+            if (referenceData instanceof ReferenceNodeSetData) {
+                Iterator<Node> iter = ((ReferenceNodeSetData)referenceData).iterator();
+                assertTrue(iter.hasNext());
+                boolean found = false;
+                while (iter.hasNext()) {
+                    Node n = (Node)iter.next();
+                    if (n instanceof Element) {
+                        found = true;
+                        break;
+                    }
+                }
+                assertTrue(found);
+            } else if (referenceData instanceof ReferenceOctetStreamData) {
+                assertNotNull(((ReferenceOctetStreamData)referenceData).getOctetStream());
+            }
+        }
+    }
+    
 }

Added: santuario/xml-security-java/trunk/src/test/java/org/apache/xml/security/test/signature/SignatureReferenceTest.java
URL: http://svn.apache.org/viewvc/santuario/xml-security-java/trunk/src/test/java/org/apache/xml/security/test/signature/SignatureReferenceTest.java?rev=1229629&view=auto
==============================================================================
--- santuario/xml-security-java/trunk/src/test/java/org/apache/xml/security/test/signature/SignatureReferenceTest.java (added)
+++ santuario/xml-security-java/trunk/src/test/java/org/apache/xml/security/test/signature/SignatureReferenceTest.java Tue Jan 10 16:36:36 2012
@@ -0,0 +1,159 @@
+/**
+ * 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.apache.xml.security.test.signature;
+
+import java.io.FileInputStream;
+import java.io.InputStream;
+import java.security.KeyStore;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.util.Enumeration;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+import org.apache.xml.security.Init;
+import org.apache.xml.security.signature.Reference;
+import org.apache.xml.security.signature.SignedInfo;
+import org.apache.xml.security.signature.XMLSignature;
+import org.apache.xml.security.signature.reference.ReferenceData;
+import org.apache.xml.security.signature.reference.ReferenceNodeSetData;
+import org.apache.xml.security.transforms.Transforms;
+import org.apache.xml.security.utils.Constants;
+import org.apache.xml.security.utils.ElementProxy;
+import org.apache.xml.security.utils.resolver.implementations.ResolverXPointer;
+
+/**
+ * Test a Signature and Validation, and check that we have access to the Element(s) that was
+ * validated.
+ */
+public class SignatureReferenceTest extends org.junit.Assert {
+    public final static String DS_NS = "http://www.w3.org/2000/09/xmldsig#";
+
+    private static final String BASEDIR = 
+        System.getProperty("basedir") == null ? "./": System.getProperty("basedir");
+    public final static String KEYSTORE_DIRECTORY = BASEDIR + "/src/test/resources/";
+    public final static String KEYSTORE_PASSWORD_STRING = "changeit";
+    public final static char[] KEYSTORE_PASSWORD = KEYSTORE_PASSWORD_STRING.toCharArray();
+
+    public SignatureReferenceTest() throws Exception {
+        Init.init();
+        ElementProxy.setDefaultPrefix(Constants.SignatureSpecNS, "ds");
+    }
+
+    @org.junit.Test
+    public void testSigningVerifyingReference() throws Throwable {
+        Document doc = getOriginalDocument();
+        XMLSignature signature = signDocument(doc);
+
+        PublicKey pubKey = getPublicKey();
+        assertTrue(signature.checkSignatureValue(pubKey));
+        
+        // Check the reference(s)
+        SignedInfo signedInfo = signature.getSignedInfo();
+        assertTrue(signedInfo.getLength() == 1);
+        Reference reference = signedInfo.item(0);
+        ReferenceData referenceData = reference.getReferenceData();
+        assertNotNull(referenceData);
+        assertTrue(referenceData instanceof ReferenceNodeSetData);
+        
+        // Test the cached Element
+        Element referenceElement = 
+            (Element)((ReferenceNodeSetData)referenceData).iterator().next();
+        assertNotNull(referenceElement);
+        assertTrue("root".equals(referenceElement.getLocalName()));
+        
+        Element originalElement =
+            (Element) doc.getElementsByTagNameNS("http://ns.example.org/", "root").item(0);
+        assertNotNull(originalElement);
+        assertEquals(referenceElement, originalElement);
+    }
+
+    /**
+     * Loads the 'localhost' keystore from the test keystore.
+     * 
+     * @return test keystore.
+     * @throws Exception
+     */
+    private KeyStore getKeyStore() throws Exception {
+        KeyStore ks = KeyStore.getInstance("JKS");
+        InputStream ksis = new FileInputStream(KEYSTORE_DIRECTORY + "test.jks");
+        ks.load(ksis, KEYSTORE_PASSWORD);
+        ksis.close();
+        return ks;
+    }
+
+    private PublicKey getPublicKey() throws Exception {
+        KeyStore keyStore = getKeyStore();
+        Enumeration<String> aliases = keyStore.aliases();
+        while (aliases.hasMoreElements()) {
+            String alias = aliases.nextElement();
+            if (keyStore.isKeyEntry(alias)) {
+                return keyStore.getCertificate(alias).getPublicKey();
+            }
+        }
+        return null;
+    }
+
+    private PrivateKey getPrivateKey() throws Exception {
+        KeyStore keyStore = getKeyStore();
+        Enumeration<String> aliases = keyStore.aliases();
+        while (aliases.hasMoreElements()) {
+            String alias = aliases.nextElement();
+            if (keyStore.isKeyEntry(alias)) {
+                return (PrivateKey) keyStore.getKey(alias, KEYSTORE_PASSWORD);
+            }
+        }
+        return null;
+    }
+
+    private Document getOriginalDocument() throws Throwable {
+        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+        dbf.setNamespaceAware(true);
+        DocumentBuilder db = dbf.newDocumentBuilder();
+        Document doc = db.newDocument();
+
+        Element rootElement = doc.createElementNS("http://ns.example.org/", "root");
+        rootElement.appendChild(doc.createTextNode("Hello World!"));
+        doc.appendChild(rootElement);
+
+        return doc;
+    }
+
+    private XMLSignature signDocument(Document doc) throws Throwable {
+        XMLSignature sig = new XMLSignature(doc, "", XMLSignature.ALGO_ID_SIGNATURE_DSA);
+        Element root = doc.getDocumentElement();
+        root.appendChild(sig.getElement());
+
+        sig.getSignedInfo().addResourceResolver(new ResolverXPointer());
+
+        Transforms transforms = new Transforms(doc);
+        transforms.addTransform(Transforms.TRANSFORM_ENVELOPED_SIGNATURE);
+        transforms.addTransform(Transforms.TRANSFORM_C14N_WITH_COMMENTS);
+        sig.addDocument("", transforms, Constants.ALGO_ID_DIGEST_SHA1);
+
+        sig.addKeyInfo(getPublicKey());
+        sig.sign(getPrivateKey());
+
+        return sig;
+    }
+}