blob: eb7cb6cad0103150cfa2382588a2ffc6da1f556b [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * reserved comment block
3 * DO NOT REMOVE OR ALTER!
4 */
5/*
6 * Copyright 1999-2004 The Apache Software Foundation.
7 *
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 * http://www.apache.org/licenses/LICENSE-2.0
13 *
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 *
20 */
21package com.sun.org.apache.xml.internal.security.c14n;
22
23
24
25import java.io.ByteArrayInputStream;
26import java.io.OutputStream;
27import java.util.HashMap;
28import java.util.Map;
29import java.util.Set;
30
31import javax.xml.parsers.DocumentBuilder;
32import javax.xml.parsers.DocumentBuilderFactory;
33
34import com.sun.org.apache.xml.internal.security.exceptions.AlgorithmAlreadyRegisteredException;
35import org.w3c.dom.Document;
36import org.w3c.dom.Node;
37import org.w3c.dom.NodeList;
38import org.xml.sax.InputSource;
39
40
41/**
42 *
43 *
44 * @author Christian Geuer-Pollmann
45 */
46public class Canonicalizer {
47
48 //J-
49 /** The output encoding of canonicalized data */
50 public static final String ENCODING = "UTF8";
51
52
53 /**
54 * XPath Expresion for selecting every node and continuos comments joined in only one node
55 */
56 public static final String XPATH_C14N_WITH_COMMENTS_SINGLE_NODE = "(.//. | .//@* | .//namespace::*)";
57
58
59 /**
60 * The URL defined in XML-SEC Rec for inclusive c14n <b>without</b> comments.
61 */
62 public static final String ALGO_ID_C14N_OMIT_COMMENTS = "http://www.w3.org/TR/2001/REC-xml-c14n-20010315";
63 /**
64 * The URL defined in XML-SEC Rec for inclusive c14n <b>with</b> comments.
65 */
66 public static final String ALGO_ID_C14N_WITH_COMMENTS = ALGO_ID_C14N_OMIT_COMMENTS + "#WithComments";
67 /**
68 * The URL defined in XML-SEC Rec for exclusive c14n <b>without</b> comments.
69 */
70 public static final String ALGO_ID_C14N_EXCL_OMIT_COMMENTS = "http://www.w3.org/2001/10/xml-exc-c14n#";
71 /**
72 * The URL defined in XML-SEC Rec for exclusive c14n <b>with</b> comments.
73 */
74 public static final String ALGO_ID_C14N_EXCL_WITH_COMMENTS = ALGO_ID_C14N_EXCL_OMIT_COMMENTS + "WithComments";
75
76 static boolean _alreadyInitialized = false;
77 static Map _canonicalizerHash = null;
78
79 protected CanonicalizerSpi canonicalizerSpi = null;
80 //J+
81
82 /**
83 * Method init
84 *
85 */
86 public static void init() {
87
88 if (!Canonicalizer._alreadyInitialized) {
89 Canonicalizer._canonicalizerHash = new HashMap(10);
90 Canonicalizer._alreadyInitialized = true;
91 }
92 }
93
94 /**
95 * Constructor Canonicalizer
96 *
97 * @param algorithmURI
98 * @throws InvalidCanonicalizerException
99 */
100 private Canonicalizer(String algorithmURI)
101 throws InvalidCanonicalizerException {
102
103 try {
104 Class implementingClass = getImplementingClass(algorithmURI);
105
106 this.canonicalizerSpi =
107 (CanonicalizerSpi) implementingClass.newInstance();
108 this.canonicalizerSpi.reset=true;
109 } catch (Exception e) {
110 Object exArgs[] = { algorithmURI };
111
112 throw new InvalidCanonicalizerException(
113 "signature.Canonicalizer.UnknownCanonicalizer", exArgs);
114 }
115 }
116
117 /**
118 * Method getInstance
119 *
120 * @param algorithmURI
121 * @return a Conicicalizer instance ready for the job
122 * @throws InvalidCanonicalizerException
123 */
124 public static final Canonicalizer getInstance(String algorithmURI)
125 throws InvalidCanonicalizerException {
126
127 Canonicalizer c14nizer = new Canonicalizer(algorithmURI);
128
129 return c14nizer;
130 }
131
132 /**
133 * Method register
134 *
135 * @param algorithmURI
136 * @param implementingClass
137 * @throws AlgorithmAlreadyRegisteredException
138 */
139 public static void register(String algorithmURI, String implementingClass)
140 throws AlgorithmAlreadyRegisteredException {
141
142 // check whether URI is already registered
143 Class registeredClass = getImplementingClass(algorithmURI);
144
145 if (registeredClass != null) {
146 Object exArgs[] = { algorithmURI, registeredClass };
147
148 throw new AlgorithmAlreadyRegisteredException(
149 "algorithm.alreadyRegistered", exArgs);
150 }
151
152 try {
153 _canonicalizerHash.put(algorithmURI, Class.forName(implementingClass));
154 } catch (ClassNotFoundException e) {
155 throw new RuntimeException("c14n class not found");
156 }
157 }
158
159 /**
160 * Method getURI
161 *
162 * @return the URI defined for this c14n instance.
163 */
164 public final String getURI() {
165 return this.canonicalizerSpi.engineGetURI();
166 }
167
168 /**
169 * Method getIncludeComments
170 *
171 * @return true if the c14n respect the comments.
172 */
173 public boolean getIncludeComments() {
174 return this.canonicalizerSpi.engineGetIncludeComments();
175 }
176
177 /**
178 * This method tries to canonicalize the given bytes. It's possible to even
179 * canonicalize non-wellformed sequences if they are well-formed after being
180 * wrapped with a <CODE>&gt;a&lt;...&gt;/a&lt;</CODE>.
181 *
182 * @param inputBytes
183 * @return the result of the conicalization.
184 * @throws CanonicalizationException
185 * @throws java.io.IOException
186 * @throws javax.xml.parsers.ParserConfigurationException
187 * @throws org.xml.sax.SAXException
188 */
189 public byte[] canonicalize(byte[] inputBytes)
190 throws javax.xml.parsers.ParserConfigurationException,
191 java.io.IOException, org.xml.sax.SAXException,
192 CanonicalizationException {
193
194 ByteArrayInputStream bais = new ByteArrayInputStream(inputBytes);
195 InputSource in = new InputSource(bais);
196 DocumentBuilderFactory dfactory = DocumentBuilderFactory.newInstance();
197
198 dfactory.setNamespaceAware(true);
199
200 // needs to validate for ID attribute nomalization
201 dfactory.setValidating(true);
202
203 DocumentBuilder db = dfactory.newDocumentBuilder();
204
205 /*
206 * for some of the test vectors from the specification,
207 * there has to be a validatin parser for ID attributes, default
208 * attribute values, NMTOKENS, etc.
209 * Unfortunaltely, the test vectors do use different DTDs or
210 * even no DTD. So Xerces 1.3.1 fires many warnings about using
211 * ErrorHandlers.
212 *
213 * Text from the spec:
214 *
215 * The input octet stream MUST contain a well-formed XML document,
216 * but the input need not be validated. However, the attribute
217 * value normalization and entity reference resolution MUST be
218 * performed in accordance with the behaviors of a validating
219 * XML processor. As well, nodes for default attributes (declared
220 * in the ATTLIST with an AttValue but not specified) are created
221 * in each element. Thus, the declarations in the document type
222 * declaration are used to help create the canonical form, even
223 * though the document type declaration is not retained in the
224 * canonical form.
225 *
226 */
227 db.setErrorHandler(new com.sun.org.apache.xml.internal.security.utils
228 .IgnoreAllErrorHandler());
229
230 Document document = db.parse(in);
231 byte result[] = this.canonicalizeSubtree(document);
232
233 return result;
234 }
235
236 /**
237 * Canonicalizes the subtree rooted by <CODE>node</CODE>.
238 *
239 * @param node The node to canicalize
240 * @return the result of the c14n.
241 *
242 * @throws CanonicalizationException
243 */
244 public byte[] canonicalizeSubtree(Node node)
245 throws CanonicalizationException {
246 return this.canonicalizerSpi.engineCanonicalizeSubTree(node);
247 }
248
249 /**
250 * Canonicalizes the subtree rooted by <CODE>node</CODE>.
251 *
252 * @param node
253 * @param inclusiveNamespaces
254 * @return the result of the c14n.
255 * @throws CanonicalizationException
256 */
257 public byte[] canonicalizeSubtree(Node node, String inclusiveNamespaces)
258 throws CanonicalizationException {
259 return this.canonicalizerSpi.engineCanonicalizeSubTree(node,
260 inclusiveNamespaces);
261 }
262
263 /**
264 * Canonicalizes an XPath node set. The <CODE>xpathNodeSet</CODE> is treated
265 * as a list of XPath nodes, not as a list of subtrees.
266 *
267 * @param xpathNodeSet
268 * @return the result of the c14n.
269 * @throws CanonicalizationException
270 */
271 public byte[] canonicalizeXPathNodeSet(NodeList xpathNodeSet)
272 throws CanonicalizationException {
273 return this.canonicalizerSpi.engineCanonicalizeXPathNodeSet(xpathNodeSet);
274 }
275
276 /**
277 * Canonicalizes an XPath node set. The <CODE>xpathNodeSet</CODE> is treated
278 * as a list of XPath nodes, not as a list of subtrees.
279 *
280 * @param xpathNodeSet
281 * @param inclusiveNamespaces
282 * @return the result of the c14n.
283 * @throws CanonicalizationException
284 */
285 public byte[] canonicalizeXPathNodeSet(
286 NodeList xpathNodeSet, String inclusiveNamespaces)
287 throws CanonicalizationException {
288 return this.canonicalizerSpi.engineCanonicalizeXPathNodeSet(xpathNodeSet,
289 inclusiveNamespaces);
290 }
291
292 /**
293 * Canonicalizes an XPath node set.
294 *
295 * @param xpathNodeSet
296 * @return the result of the c14n.
297 * @throws CanonicalizationException
298 */
299 public byte[] canonicalizeXPathNodeSet(Set xpathNodeSet)
300 throws CanonicalizationException {
301 return this.canonicalizerSpi.engineCanonicalizeXPathNodeSet(xpathNodeSet);
302 }
303
304 /**
305 * Canonicalizes an XPath node set.
306 *
307 * @param xpathNodeSet
308 * @param inclusiveNamespaces
309 * @return the result of the c14n.
310 * @throws CanonicalizationException
311 */
312 public byte[] canonicalizeXPathNodeSet(
313 Set xpathNodeSet, String inclusiveNamespaces)
314 throws CanonicalizationException {
315 return this.canonicalizerSpi.engineCanonicalizeXPathNodeSet(xpathNodeSet,
316 inclusiveNamespaces);
317 }
318
319 /**
320 * Sets the writter where the cannocalization ends. ByteArrayOutputStream if
321 * none is setted.
322 * @param os
323 */
324 public void setWriter(OutputStream os) {
325 this.canonicalizerSpi.setWriter(os);
326 }
327
328 /**
329 * Returns the name of the implementing {@link CanonicalizerSpi} class
330 *
331 * @return the name of the implementing {@link CanonicalizerSpi} class
332 */
333 public String getImplementingCanonicalizerClass() {
334 return this.canonicalizerSpi.getClass().getName();
335 }
336
337 /**
338 * Method getImplementingClass
339 *
340 * @param URI
341 * @return the name of the class that implements the give URI
342 */
343 private static Class getImplementingClass(String URI) {
344 return (Class) _canonicalizerHash.get(URI);
345 }
346
347 /**
348 * Set the canonicalizator behaviour to not reset.
349 *
350 */
351 public void notReset() {
352 this.canonicalizerSpi.reset=false;
353 }
354}