blob: d246198ef1de32b311186924d6ba43ab1c3913b8 [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 2005-2006 Sun Microsystems, Inc. All Rights Reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25/*
26 * $Id: DOMKeyInfo.java,v 1.19 2005/05/12 19:28:30 mullan Exp $
27 */
28package org.jcp.xml.dsig.internal.dom;
29
30import javax.xml.crypto.*;
31import javax.xml.crypto.dsig.*;
32import javax.xml.crypto.dsig.dom.DOMSignContext;
33import javax.xml.crypto.dsig.keyinfo.KeyInfo;
34import javax.xml.crypto.dom.*;
35
36import java.util.*;
37import org.w3c.dom.Document;
38import org.w3c.dom.Element;
39import org.w3c.dom.Node;
40import org.w3c.dom.NodeList;
41
42/**
43 * DOM-based implementation of KeyInfo.
44 *
45 * @author Sean Mullan
46 */
47public final class DOMKeyInfo extends DOMStructure implements KeyInfo {
48
49 private final String id;
50 private final List keyInfoTypes;
51
52 /**
53 * Creates a <code>DOMKeyInfo</code>.
54 *
55 * @param content a list of one or more {@link XMLStructure}s representing
56 * key information types. The list is defensively copied to protect
57 * against subsequent modification.
58 * @param id an ID attribute
59 * @throws NullPointerException if <code>content</code> is <code>null</code>
60 * @throws IllegalArgumentException if <code>content</code> is empty
61 * @throws ClassCastException if <code>content</code> contains any entries
62 * that are not of type {@link XMLStructure}
63 */
64 public DOMKeyInfo(List content, String id) {
65 if (content == null) {
66 throw new NullPointerException("content cannot be null");
67 }
68 List typesCopy = new ArrayList(content);
69 if (typesCopy.isEmpty()) {
70 throw new IllegalArgumentException("content cannot be empty");
71 }
72 for (int i = 0, size = typesCopy.size(); i < size; i++) {
73 if (!(typesCopy.get(i) instanceof XMLStructure)) {
74 throw new ClassCastException
75 ("content["+i+"] is not a valid KeyInfo type");
76 }
77 }
78 this.keyInfoTypes = Collections.unmodifiableList(typesCopy);
79 this.id = id;
80 }
81
82 /**
83 * Creates a <code>DOMKeyInfo</code> from XML.
84 *
85 * @param input XML input
86 */
87 public DOMKeyInfo(Element kiElem, XMLCryptoContext context)
88 throws MarshalException {
89 // get Id attribute, if specified
90 id = DOMUtils.getAttributeValue(kiElem, "Id");
91
92 // get all children nodes
93 NodeList nl = kiElem.getChildNodes();
94 int length = nl.getLength();
95 if (length < 1) {
96 throw new MarshalException
97 ("KeyInfo must contain at least one type");
98 }
99 List content = new ArrayList(length);
100 for (int i = 0; i < length; i++) {
101 Node child = nl.item(i);
102 // ignore all non-Element nodes
103 if (child.getNodeType() != Node.ELEMENT_NODE) {
104 continue;
105 }
106 Element childElem = (Element) child;
107 String localName = childElem.getLocalName();
108 if (localName.equals("X509Data")) {
109 content.add(new DOMX509Data(childElem));
110 } else if (localName.equals("KeyName")) {
111 content.add(new DOMKeyName(childElem));
112 } else if (localName.equals("KeyValue")) {
113 content.add(new DOMKeyValue(childElem));
114 } else if (localName.equals("RetrievalMethod")) {
115 content.add(new DOMRetrievalMethod(childElem, context));
116 } else { //may be MgmtData, SPKIData or element from other namespace
117 content.add(new javax.xml.crypto.dom.DOMStructure((childElem)));
118 }
119 }
120 keyInfoTypes = Collections.unmodifiableList(content);
121 }
122
123 public String getId() {
124 return id;
125 }
126
127 public List getContent() {
128 return keyInfoTypes;
129 }
130
131 public void marshal(XMLStructure parent, XMLCryptoContext context)
132 throws MarshalException {
133 if (parent == null) {
134 throw new NullPointerException("parent is null");
135 }
136
137 Node pNode = ((javax.xml.crypto.dom.DOMStructure) parent).getNode();
138 String dsPrefix = DOMUtils.getSignaturePrefix(context);
139 Element kiElem = DOMUtils.createElement
140 (DOMUtils.getOwnerDocument(pNode), "KeyInfo",
141 XMLSignature.XMLNS, dsPrefix);
142 if (dsPrefix == null) {
143 kiElem.setAttributeNS
144 ("http://www.w3.org/2000/xmlns/", "xmlns", XMLSignature.XMLNS);
145 } else {
146 kiElem.setAttributeNS
147 ("http://www.w3.org/2000/xmlns/", "xmlns:" + dsPrefix,
148 XMLSignature.XMLNS);
149 }
150 marshal(pNode, kiElem, null, dsPrefix, (DOMCryptoContext) context);
151 }
152
153 public void marshal(Node parent, String dsPrefix,
154 DOMCryptoContext context) throws MarshalException {
155 marshal(parent, null, dsPrefix, context);
156 }
157
158 public void marshal(Node parent, Node nextSibling, String dsPrefix,
159 DOMCryptoContext context) throws MarshalException {
160 Document ownerDoc = DOMUtils.getOwnerDocument(parent);
161
162 Element kiElem = DOMUtils.createElement
163 (ownerDoc, "KeyInfo", XMLSignature.XMLNS, dsPrefix);
164 marshal(parent, kiElem, nextSibling, dsPrefix, context);
165 }
166
167 private void marshal(Node parent, Element kiElem, Node nextSibling,
168 String dsPrefix, DOMCryptoContext context) throws MarshalException {
169 // create and append KeyInfoType elements
170 for (int i = 0, size = keyInfoTypes.size(); i < size; i++) {
171 XMLStructure kiType = (XMLStructure) keyInfoTypes.get(i);
172 if (kiType instanceof DOMStructure) {
173 ((DOMStructure) kiType).marshal(kiElem, dsPrefix, context);
174 } else {
175 DOMUtils.appendChild(kiElem,
176 ((javax.xml.crypto.dom.DOMStructure) kiType).getNode());
177 }
178 }
179
180 // append id attribute
181 DOMUtils.setAttributeID(kiElem, "Id", id);
182
183 parent.insertBefore(kiElem, nextSibling);
184 }
185
186 public boolean equals(Object o) {
187 if (this == o) {
188 return true;
189 }
190
191 if (!(o instanceof KeyInfo)) {
192 return false;
193 }
194 KeyInfo oki = (KeyInfo) o;
195
196 boolean idsEqual = (id == null ? oki.getId() == null :
197 id.equals(oki.getId()));
198
199 return (keyInfoTypes.equals(oki.getContent()) && idsEqual);
200 }
201}