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); + } + } + } } }