I observed that there were some TODO items in XMLCipher.java. Some of them were related to martialing of KeyInfo and ReferenceList. I have prepared (please find attached) a patch for these. The KeyInfo martialing I thought was already achieved (KeyInfo.getElement()), and for ReferenceList I did the following --
1) Converted ReferenceList class into an interface.
2) Added implementation for it (containing a toElement() method) inside the private Factory class.
This change results in a uniformity across the implementation. ReferenceList is now being handled like other encryption elements. Please let me know if there are any issues with this patch.
Regards, Vishal
/* * Copyright 2003-2004 The Apache Software Foundation. * * Licensed 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.encryption;
import java.util.Iterator;
import org.w3c.dom.Element;
/**
* A wrapper for a pointer from a key value of an <code>EncryptedKey</code> to
* items encrypted by that key value (<code>EncryptedData</code> or
* <code>EncryptedKey</code> elements).
* <p>
* It is defined as follows:
* <xmp>
* <complexType name='ReferenceType'>
* <sequence>
* <any namespace='##other' minOccurs='0' maxOccurs='unbounded'/>
* </sequence>
* <attribute name='URI' type='anyURI' use='required'/>
* </complexType>
* </xmp>
*
* @author Axl Mattheus
* @see ReferenceList
*/
public interface Reference {
/**
* Returns a <code>URI</code> that points to an <code>Element</code> that
* were encrypted using the key defined in the enclosing
* <code>EncryptedKey</code> element.
*
* @return an Uniform Resource Identifier that qualifies an
* <code>EncryptedType</code>.
*/
String getURI();
/**
* Sets a <code>URI</code> that points to an <code>Element</code> that
* were encrypted using the key defined in the enclosing
* <code>EncryptedKey</code> element.
*
* @param uri the Uniform Resource Identifier that qualifies an
* <code>EncryptedType</code>.
*/
void setURI(String uri);
/**
* Returns an <code>Iterator</code> over all the child elements contained in
* this <code>Reference</code> that will aid the recipient in retrieving the
* <code>EncryptedKey</code> and/or <code>EncryptedData</code> elements.
* These could include information such as XPath transforms, decompression
* transforms, or information on how to retrieve the elements from a
* document storage facility.
*
* @return child elements.
*/
Iterator getElementRetrievalInformation();
/**
* Adds retrieval information.
*
* @param node.
*/
void addElementRetrievalInformation(Element info);
/**
* Removes the specified retrieval information.
*
* @param node.
*/
void removeElementRetrievalInformation(Element info);
}
--- XMLCipher.java.orig 2004-02-19 18:57:48.000000000 +0530
+++ XMLCipher.java 2004-02-19 21:38:33.000000000 +0530
@@ -1728,7 +1728,7 @@
* Create a new ReferenceList object
*/
public ReferenceList createReferenceList(int type) {
- return (new ReferenceList(type));
+ return (_factory.newReferenceList(type));
}
/**
@@ -2080,7 +2080,7 @@
*
*/
ReferenceList newReferenceList(int type) {
- return (new ReferenceList(type));
+ return (new ReferenceListImpl(type));
}
/**
@@ -2131,24 +2131,34 @@
// Figure out how to make this pesky line work..
// <any namespace="##other" minOccurs="0" maxOccurs="unbounded"/>
- // TODO: ///////////////////////////////////////////////////////////
- // Implement properly, implement a KeyInfo marshaler.
+ // TODO: Work out how to handle relative URI
+
Element originatorKeyInfoElement =
(Element) element.getElementsByTagNameNS(
EncryptionConstants.EncryptionSpecNS,
EncryptionConstants._TAG_ORIGINATORKEYINFO).item(0);
if (null != originatorKeyInfoElement) {
- result.setOriginatorKeyInfo(null);
+ try {
+ result.setOriginatorKeyInfo(
+ new KeyInfo(originatorKeyInfoElement, null));
+ } catch (XMLSecurityException xse) {
+ throw new XMLEncryptionException("empty", xse);
+ }
}
- // TODO: ///////////////////////////////////////////////////////////
- // Implement properly, implement a KeyInfo marshaler.
+ // TODO: Work out how to handle relative URI
+
Element recipientKeyInfoElement =
(Element) element.getElementsByTagNameNS(
EncryptionConstants.EncryptionSpecNS,
EncryptionConstants._TAG_RECIPIENTKEYINFO).item(0);
if (null != recipientKeyInfoElement) {
- result.setRecipientKeyInfo(null);
+ try {
+ result.setRecipientKeyInfo(
+ new KeyInfo(recipientKeyInfoElement, null));
+ } catch (XMLSecurityException xse) {
+ throw new XMLEncryptionException("empty", xse);
+ }
}
return (result);
@@ -2585,7 +2595,7 @@
// complain
}
- ReferenceList result = newReferenceList(type);
+ ReferenceList result = new ReferenceListImpl(type);
NodeList list = null;
switch (type) {
case ReferenceList.DATA_REFERENCE:
@@ -2599,7 +2609,7 @@
((Element) list.item(0)).getNodeValue()).toString();
} catch (URI.MalformedURIException mfue) {
}
- result.add(ReferenceList.newDataReference(uri));
+ result.add(result.newDataReference(uri));
}
case ReferenceList.KEY_REFERENCE:
list = element.getElementsByTagNameNS(
@@ -2612,7 +2622,7 @@
((Element) list.item(0)).getNodeValue()).toString();
} catch (URI.MalformedURIException mfue) {
}
- result.add(ReferenceList.newKeyReference(uri));
+ result.add(result.newKeyReference(uri));
}
}
@@ -2690,9 +2700,7 @@
}
Element toElement(ReferenceList referenceList) {
- // NOTE: ///////////////////////////////////////////////////////////
- // TODO: Complete
- return (null);
+ return ((ReferenceListImpl) referenceList).toElement();
}
/**
@@ -2814,10 +2822,10 @@
}
}
if (null != originatorKeyInfo) {
- // TODO: complete
+ result.appendChild(originatorKeyInfo.getElement());
}
if (null != recipientKeyInfo) {
- // TODO: complete
+ result.appendChild(recipientKeyInfo.getElement());
}
return (result);
@@ -3205,7 +3213,7 @@
super.getEncryptionMethod()).toElement());
}
if (null != super.getKeyInfo()) {
- // TODO: complete
+ result.appendChild(super.getKeyInfo().getElement());
}
result.appendChild(
((CipherDataImpl) super.getCipherData()).toElement());
@@ -3214,7 +3222,8 @@
super.getEncryptionProperties()).toElement());
}
if (referenceList != null && !referenceList.isEmpty()) {
- // TODO: complete
+ result.appendChild(((ReferenceListImpl)
+ getReferenceList()).toElement());
}
if (null != carriedName) {
result.appendChild(
@@ -3612,5 +3621,151 @@
}
}
+
+ //<element name='ReferenceList'>
+ // <complexType>
+ // <choice minOccurs='1' maxOccurs='unbounded'>
+ // <element name='DataReference' type='xenc:ReferenceType'/>
+ // <element name='KeyReference' type='xenc:ReferenceType'/>
+ // </choice>
+ // </complexType>
+ //</element>
+ private class ReferenceListImpl implements ReferenceList {
+ private Class sentry;
+ private List references;
+
+ public ReferenceListImpl(int type) {
+ if (type == ReferenceList.DATA_REFERENCE) {
+ sentry = DataReference.class;
+ } else if (type == ReferenceList.KEY_REFERENCE) {
+ sentry = KeyReference.class;
+ } else {
+ throw new IllegalArgumentException();
+ }
+ references = new LinkedList();
+ }
+
+ public void add(Reference reference) {
+ if (!reference.getClass().equals(sentry)) {
+ throw new IllegalArgumentException();
+ } else {
+ references.add(reference);
+ }
+ }
+
+ public void remove(Reference reference) {
+ if (!reference.getClass().equals(sentry)) {
+ throw new IllegalArgumentException();
+ } else {
+ references.remove(reference);
+ }
+ }
+
+ public int size() {
+ return (references.size());
+ }
+
+ public boolean isEmpty() {
+ return (references.isEmpty());
+ }
+
+ public Iterator getReferences() {
+ return (references.iterator());
+ }
+
+ Element toElement() {
+ Element result = ElementProxy.createElementForFamily(
+ _contextDocument,
+ EncryptionConstants.EncryptionSpecNS,
+ EncryptionConstants._TAG_REFERENCELIST);
+ Iterator eachReference = references.iterator();
+ while (eachReference.hasNext()) {
+ Reference reference = (Reference) eachReference.next();
+ result.appendChild(
+ ((ReferenceImpl) reference).toElement());
+ }
+ return (result);
+ }
+
+ public Reference newDataReference(String uri) {
+ return (new DataReference(uri));
+ }
+
+ public Reference newKeyReference(String uri) {
+ return (new KeyReference(uri));
+ }
+
+ /**
+ * <code>ReferenceImpl</code> is an implementation of
+ * <code>Reference</code>.
+ *
+ * @see Reference.
+ */
+ private abstract class ReferenceImpl implements Reference {
+ private String uri;
+ private List referenceInformation;
+
+ ReferenceImpl(String _uri) {
+ this.uri = _uri;
+ referenceInformation = new LinkedList();
+ }
+
+ public String getURI() {
+ return (uri);
+ }
+
+ public Iterator getElementRetrievalInformation() {
+ return (referenceInformation.iterator());
+ }
+
+ public void setURI(String _uri) {
+ this.uri = _uri;
+ }
+
+ public void removeElementRetrievalInformation(Element node) {
+ referenceInformation.remove(node);
+ }
+
+ public void addElementRetrievalInformation(Element node) {
+ referenceInformation.add(node);
+ }
+
+ public abstract Element toElement();
+
+ Element toElement(String tagName) {
+ Element result = ElementProxy.createElementForFamily(
+ _contextDocument,
+ EncryptionConstants.EncryptionSpecNS,
+ tagName);
+ result.setAttribute(EncryptionConstants._ATT_URI, uri);
+
+ // TODO: Need to martial referenceInformation
+ // Figure out how to make this work..
+ // <any namespace="##other" minOccurs="0" maxOccurs="unbounded"/>
+
+ return (result);
+ }
+ }
+
+ private class DataReference extends ReferenceImpl {
+ DataReference(String uri) {
+ super(uri);
+ }
+
+ public Element toElement() {
+ return toElement(EncryptionConstants._TAG_DATAREFERENCE);
+ }
+ }
+
+ private class KeyReference extends ReferenceImpl {
+ KeyReference(String uri) {
+ super (uri);
+ }
+
+ public Element toElement() {
+ return toElement(EncryptionConstants._TAG_KEYREFERENCE);
+ }
+ }
+ }
}
}
