blob: f48a5d276b96772ffe26e71f5c61f8b2886035e1 [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 2005 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: ApacheCanonicalizer.java,v 1.17 2005/09/19 18:20:04 mullan Exp $
27 */
28package org.jcp.xml.dsig.internal.dom;
29
30import java.io.ByteArrayInputStream;
31import java.io.ByteArrayOutputStream;
32import java.io.IOException;
33import java.io.OutputStream;
34import java.security.spec.AlgorithmParameterSpec;
35import java.security.InvalidAlgorithmParameterException;
36import java.util.Set;
37import java.util.logging.Logger;
38import java.util.logging.Level;
39import javax.xml.crypto.*;
40import javax.xml.crypto.dom.DOMCryptoContext;
41import javax.xml.crypto.dsig.TransformException;
42import javax.xml.crypto.dsig.TransformService;
43import javax.xml.crypto.dsig.XMLSignatureException;
44import javax.xml.crypto.dsig.spec.C14NMethodParameterSpec;
45
46import com.sun.org.apache.xml.internal.security.c14n.Canonicalizer;
47import com.sun.org.apache.xml.internal.security.c14n.InvalidCanonicalizerException;
48import com.sun.org.apache.xml.internal.security.signature.XMLSignatureInput;
49import com.sun.org.apache.xml.internal.security.transforms.Transform;
50import org.w3c.dom.Document;
51import org.w3c.dom.Element;
52import org.w3c.dom.NodeList;
53
54public abstract class ApacheCanonicalizer extends TransformService {
55
56 private static Logger log = Logger.getLogger("org.jcp.xml.dsig.internal.dom");
57 protected Canonicalizer apacheCanonicalizer;
58 private Transform apacheTransform;
59 protected String inclusiveNamespaces;
60 protected C14NMethodParameterSpec params;
61 protected Document ownerDoc;
62 protected Element transformElem;
63
64 public final AlgorithmParameterSpec getParameterSpec() {
65 return params;
66 }
67
68 public void init(XMLStructure parent, XMLCryptoContext context)
69 throws InvalidAlgorithmParameterException {
70 if (context != null && !(context instanceof DOMCryptoContext)) {
71 throw new ClassCastException
72 ("context must be of type DOMCryptoContext");
73 }
74 transformElem = (Element)
75 ((javax.xml.crypto.dom.DOMStructure) parent).getNode();
76 ownerDoc = DOMUtils.getOwnerDocument(transformElem);
77 }
78
79 public void marshalParams(XMLStructure parent, XMLCryptoContext context)
80 throws MarshalException {
81 if (context != null && !(context instanceof DOMCryptoContext)) {
82 throw new ClassCastException
83 ("context must be of type DOMCryptoContext");
84 }
85 transformElem = (Element)
86 ((javax.xml.crypto.dom.DOMStructure) parent).getNode();
87 ownerDoc = DOMUtils.getOwnerDocument(transformElem);
88 }
89
90 public Data canonicalize(Data data, XMLCryptoContext xc)
91 throws TransformException {
92 return canonicalize(data, xc, null);
93 }
94
95 public Data canonicalize(Data data, XMLCryptoContext xc, OutputStream os)
96 throws TransformException {
97
98 if (apacheCanonicalizer == null) {
99 try {
100 apacheCanonicalizer = Canonicalizer.getInstance(getAlgorithm());
101 if (log.isLoggable(Level.FINE)) {
102 log.log(Level.FINE, "Created canonicalizer for algorithm: "
103 + getAlgorithm());
104 }
105 } catch (InvalidCanonicalizerException ice) {
106 throw new TransformException
107 ("Couldn't find Canonicalizer for: " + getAlgorithm() +
108 ": " + ice.getMessage(), ice);
109 }
110 }
111
112 if (os != null) {
113 apacheCanonicalizer.setWriter(os);
114 } else {
115 apacheCanonicalizer.setWriter(new ByteArrayOutputStream());
116 }
117
118 try {
119 Set nodeSet = null;
120 if (data instanceof ApacheData) {
121 XMLSignatureInput in =
122 ((ApacheData) data).getXMLSignatureInput();
123 if (in.isElement()) {
124 if (inclusiveNamespaces != null) {
125 return new OctetStreamData(new ByteArrayInputStream
126 (apacheCanonicalizer.canonicalizeSubtree
127 (in.getSubNode(), inclusiveNamespaces)));
128 } else {
129 return new OctetStreamData(new ByteArrayInputStream
130 (apacheCanonicalizer.canonicalizeSubtree
131 (in.getSubNode())));
132 }
133 } else if (in.isNodeSet()) {
134 nodeSet = in.getNodeSet();
135 } else {
136 return new OctetStreamData(new ByteArrayInputStream(
137 apacheCanonicalizer.canonicalize(
138 Utils.readBytesFromStream(in.getOctetStream()))));
139 }
140 } else if (data instanceof DOMSubTreeData) {
141 DOMSubTreeData subTree = (DOMSubTreeData) data;
142 if (inclusiveNamespaces != null) {
143 return new OctetStreamData(new ByteArrayInputStream
144 (apacheCanonicalizer.canonicalizeSubtree
145 (subTree.getRoot(), inclusiveNamespaces)));
146 } else {
147 return new OctetStreamData(new ByteArrayInputStream
148 (apacheCanonicalizer.canonicalizeSubtree
149 (subTree.getRoot())));
150 }
151 } else if (data instanceof NodeSetData) {
152 NodeSetData nsd = (NodeSetData) data;
153 // convert Iterator to Set
154 nodeSet = Utils.toNodeSet(nsd.iterator());
155 if (log.isLoggable(Level.FINE)) {
156 log.log(Level.FINE, "Canonicalizing " + nodeSet.size()
157 + " nodes");
158 }
159 } else {
160 return new OctetStreamData(new ByteArrayInputStream(
161 apacheCanonicalizer.canonicalize(
162 Utils.readBytesFromStream(
163 ((OctetStreamData)data).getOctetStream()))));
164 }
165 if (inclusiveNamespaces != null) {
166 return new OctetStreamData(new ByteArrayInputStream(
167 apacheCanonicalizer.canonicalizeXPathNodeSet
168 (nodeSet, inclusiveNamespaces)));
169 } else {
170 return new OctetStreamData(new ByteArrayInputStream(
171 apacheCanonicalizer.canonicalizeXPathNodeSet(nodeSet)));
172 }
173 } catch (Exception e) {
174 throw new TransformException(e);
175 }
176 }
177
178 public Data transform(Data data, XMLCryptoContext xc, OutputStream os)
179 throws TransformException {
180 if (data == null) {
181 throw new NullPointerException("data must not be null");
182 }
183 if (os == null) {
184 throw new NullPointerException("output stream must not be null");
185 }
186
187 if (ownerDoc == null) {
188 throw new TransformException("transform must be marshalled");
189 }
190
191 if (apacheTransform == null) {
192 try {
193 apacheTransform = Transform.getInstance
194 (ownerDoc, getAlgorithm(), transformElem.getChildNodes());
195 apacheTransform.setElement(transformElem, xc.getBaseURI());
196 if (log.isLoggable(Level.FINE)) {
197 log.log(Level.FINE, "Created transform for algorithm: "
198 + getAlgorithm());
199 }
200 } catch (Exception ex) {
201 throw new TransformException
202 ("Couldn't find Transform for: " + getAlgorithm(), ex);
203 }
204 }
205
206 XMLSignatureInput in;
207 if (data instanceof ApacheData) {
208 if (log.isLoggable(Level.FINE)) {
209 log.log(Level.FINE, "ApacheData = true");
210 }
211 in = ((ApacheData) data).getXMLSignatureInput();
212 } else if (data instanceof NodeSetData) {
213 if (log.isLoggable(Level.FINE)) {
214 log.log(Level.FINE, "isNodeSet() = true");
215 }
216 if (data instanceof DOMSubTreeData) {
217 DOMSubTreeData subTree = (DOMSubTreeData) data;
218 in = new XMLSignatureInput(subTree.getRoot());
219 in.setExcludeComments(subTree.excludeComments());
220 } else {
221 Set nodeSet =
222 Utils.toNodeSet(((NodeSetData) data).iterator());
223 in = new XMLSignatureInput(nodeSet);
224 }
225 } else {
226 if (log.isLoggable(Level.FINE)) {
227 log.log(Level.FINE, "isNodeSet() = false");
228 }
229 try {
230 in = new XMLSignatureInput
231 (((OctetStreamData)data).getOctetStream());
232 } catch (Exception ex) {
233 throw new TransformException(ex);
234 }
235 }
236
237 try {
238 if (os != null) {
239 in = apacheTransform.performTransform(in, os);
240 if (!in.isNodeSet() && !in.isElement()) {
241 return null;
242 }
243 } else {
244 in = apacheTransform.performTransform(in);
245 }
246 if (in.isOctetStream()) {
247 return new ApacheOctetStreamData(in);
248 } else {
249 return new ApacheNodeSetData(in);
250 }
251 } catch (Exception ex) {
252 throw new TransformException(ex);
253 }
254 }
255
256 public final boolean isFeatureSupported(String feature) {
257 if (feature == null) {
258 throw new NullPointerException();
259 } else {
260 return false;
261 }
262 }
263}