1 /* |
|
2 * reserved comment block |
|
3 * DO NOT REMOVE OR ALTER! |
|
4 */ |
|
5 /** |
|
6 * Licensed to the Apache Software Foundation (ASF) under one |
|
7 * or more contributor license agreements. See the NOTICE file |
|
8 * distributed with this work for additional information |
|
9 * regarding copyright ownership. The ASF licenses this file |
|
10 * to you under the Apache License, Version 2.0 (the |
|
11 * "License"); you may not use this file except in compliance |
|
12 * with the License. You may obtain a copy of the License at |
|
13 * |
|
14 * http://www.apache.org/licenses/LICENSE-2.0 |
|
15 * |
|
16 * Unless required by applicable law or agreed to in writing, |
|
17 * software distributed under the License is distributed on an |
|
18 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
|
19 * KIND, either express or implied. See the License for the |
|
20 * specific language governing permissions and limitations |
|
21 * under the License. |
|
22 */ |
|
23 package org.jcp.xml.dsig.internal.dom; |
|
24 |
|
25 import java.util.ArrayList; |
|
26 import java.util.Base64; |
|
27 import java.util.List; |
|
28 |
|
29 import javax.xml.XMLConstants; |
|
30 import javax.xml.crypto.MarshalException; |
|
31 import javax.xml.crypto.XMLCryptoContext; |
|
32 import javax.xml.crypto.XMLStructure; |
|
33 import javax.xml.crypto.dsig.DigestMethod; |
|
34 import javax.xml.crypto.dsig.Manifest; |
|
35 import javax.xml.crypto.dsig.SignatureProperties; |
|
36 import javax.xml.crypto.dsig.SignatureProperty; |
|
37 import javax.xml.crypto.dsig.XMLSignature; |
|
38 import javax.xml.crypto.dsig.keyinfo.KeyInfo; |
|
39 import javax.xml.crypto.dsig.keyinfo.KeyName; |
|
40 import javax.xml.crypto.dsig.keyinfo.KeyValue; |
|
41 import javax.xml.crypto.dsig.keyinfo.PGPData; |
|
42 import javax.xml.crypto.dsig.keyinfo.X509Data; |
|
43 import javax.xml.crypto.dsig.keyinfo.X509IssuerSerial; |
|
44 |
|
45 import org.w3c.dom.Attr; |
|
46 import org.w3c.dom.NamedNodeMap; |
|
47 import org.w3c.dom.Node; |
|
48 |
|
49 /** |
|
50 * Defines the individual marshallers for each of the different javax.xml.crypto structures. |
|
51 */ |
|
52 class Marshaller { |
|
53 |
|
54 private Marshaller() { |
|
55 // complete |
|
56 } |
|
57 |
|
58 public static List<XmlWriter.ToMarshal<? extends XMLStructure>> getMarshallers() { |
|
59 return MARSHALLERS; |
|
60 } |
|
61 |
|
62 /** |
|
63 * Marshals a {@link KeyName}. |
|
64 * |
|
65 * @param xwriter |
|
66 * @param keyName |
|
67 * @param dsPrefix |
|
68 */ |
|
69 public static void marshalKeyName(XmlWriter xwriter, KeyName keyName, String dsPrefix) { |
|
70 xwriter.writeTextElement(dsPrefix, "KeyName", XMLSignature.XMLNS, keyName.getName()); |
|
71 } |
|
72 |
|
73 /** |
|
74 * Marshals a {@link PGPData} |
|
75 * |
|
76 * @param xwriter |
|
77 * @param pgpData |
|
78 * @param dsPrefix |
|
79 * @param context |
|
80 * @throws MarshalException |
|
81 */ |
|
82 public static void marshalPGPData(XmlWriter xwriter, PGPData pgpData, String dsPrefix, XMLCryptoContext context) |
|
83 throws MarshalException { |
|
84 xwriter.writeStartElement(dsPrefix, "PGPData", XMLSignature.XMLNS); |
|
85 |
|
86 // create and append PGPKeyID element |
|
87 byte[] keyId = pgpData.getKeyId(); |
|
88 if (keyId != null) { |
|
89 xwriter.writeTextElement(dsPrefix, "PGPKeyID", XMLSignature.XMLNS, |
|
90 Base64.getMimeEncoder().encodeToString(keyId)); |
|
91 } |
|
92 |
|
93 // create and append PGPKeyPacket element |
|
94 byte[] keyPacket = pgpData.getKeyPacket(); |
|
95 if (keyPacket != null) { |
|
96 xwriter.writeTextElement(dsPrefix, "XMLSignature.XMLNS", XMLSignature.XMLNS, |
|
97 Base64.getMimeEncoder().encodeToString(keyPacket)); |
|
98 } |
|
99 |
|
100 // create and append any elements |
|
101 @SuppressWarnings("unchecked") |
|
102 List<XMLStructure> externalElements = pgpData.getExternalElements(); |
|
103 for (XMLStructure externalItem : externalElements) { |
|
104 xwriter.marshalStructure(externalItem, dsPrefix, context); |
|
105 } |
|
106 |
|
107 xwriter.writeEndElement(); // "PGPData" |
|
108 } |
|
109 |
|
110 /** |
|
111 * Marshals an {@link X509IssuerSerial} |
|
112 * |
|
113 * @param xwriter |
|
114 * @param issuerSerial |
|
115 * @param dsPrefix |
|
116 */ |
|
117 public static void marshalX509IssuerSerial(XmlWriter xwriter, X509IssuerSerial issuerSerial, String dsPrefix) { |
|
118 xwriter.writeStartElement(dsPrefix, "X509IssuerSerial", XMLSignature.XMLNS); |
|
119 xwriter.writeTextElement(dsPrefix, "X509IssuerName", XMLSignature.XMLNS, |
|
120 issuerSerial.getIssuerName()); |
|
121 |
|
122 xwriter.writeTextElement(dsPrefix, "X509SerialNumber", XMLSignature.XMLNS, |
|
123 issuerSerial.getSerialNumber().toString()); |
|
124 |
|
125 xwriter.writeEndElement(); // "X509IssuerSerial" |
|
126 } |
|
127 |
|
128 private static XmlWriter.ToMarshal<KeyName> Marshal_KeyName = new XmlWriter.ToMarshal<KeyName>(KeyName.class) { |
|
129 @Override |
|
130 public void marshalObject(XmlWriter xwriter, KeyName toMarshal, String dsPrefix, |
|
131 XMLCryptoContext context) throws MarshalException { |
|
132 Marshaller.marshalKeyName(xwriter, toMarshal, dsPrefix); |
|
133 } |
|
134 }; |
|
135 |
|
136 private static XmlWriter.ToMarshal<KeyInfo> Marshal_KeyInfo = new XmlWriter.ToMarshal<KeyInfo>(KeyInfo.class) { |
|
137 @Override |
|
138 public void marshalObject(XmlWriter xwriter, KeyInfo toMarshal, String dsPrefix, |
|
139 XMLCryptoContext context) throws MarshalException { |
|
140 DOMKeyInfo.marshal(xwriter, toMarshal, dsPrefix, context); |
|
141 } |
|
142 }; |
|
143 |
|
144 private static XmlWriter.ToMarshal<KeyValue> Marshal_KeyValue = new XmlWriter.ToMarshal<KeyValue>(KeyValue.class) { |
|
145 @Override |
|
146 public void marshalObject(XmlWriter xwriter, KeyValue toMarshal, String dsPrefix, |
|
147 XMLCryptoContext context) throws MarshalException { |
|
148 // Since DOMKeyValue allows for deserializing unrecognized keys, and that |
|
149 // capability isn't available via the KeyValue interface, this must continue |
|
150 // to cast to DOMKeyValue. |
|
151 DOMKeyValue<?> dkv = (DOMKeyValue<?>) toMarshal; |
|
152 dkv.marshal( xwriter, dsPrefix, context); |
|
153 } |
|
154 }; |
|
155 |
|
156 private static XmlWriter.ToMarshal<X509IssuerSerial> Marshal_X509IssuerSerial = |
|
157 new XmlWriter.ToMarshal<X509IssuerSerial>(X509IssuerSerial.class) { |
|
158 @Override |
|
159 public void marshalObject(XmlWriter xwriter, X509IssuerSerial toMarshal, String dsPrefix, |
|
160 XMLCryptoContext context) throws MarshalException { |
|
161 Marshaller.marshalX509IssuerSerial( xwriter, toMarshal, dsPrefix); |
|
162 } |
|
163 }; |
|
164 |
|
165 private static XmlWriter.ToMarshal<X509Data> Marshal_X509Data = |
|
166 new XmlWriter.ToMarshal<X509Data>(X509Data.class) { |
|
167 @Override |
|
168 public void marshalObject(XmlWriter xwriter, X509Data toMarshal, String dsPrefix, |
|
169 XMLCryptoContext context) throws MarshalException { |
|
170 DOMX509Data.marshal( xwriter, toMarshal, dsPrefix, context); |
|
171 } |
|
172 }; |
|
173 |
|
174 private static XmlWriter.ToMarshal<DigestMethod> Marshal_DigestMethod = |
|
175 new XmlWriter.ToMarshal<DigestMethod>(DigestMethod.class) { |
|
176 @Override |
|
177 public void marshalObject(XmlWriter xwriter, DigestMethod toMarshal, String dsPrefix, |
|
178 XMLCryptoContext context) throws MarshalException { |
|
179 DOMDigestMethod.marshal( xwriter, toMarshal, dsPrefix); |
|
180 } |
|
181 }; |
|
182 |
|
183 private static XmlWriter.ToMarshal<PGPData> Marshal_PGPData = |
|
184 new XmlWriter.ToMarshal<PGPData>(PGPData.class) { |
|
185 @Override |
|
186 public void marshalObject(XmlWriter xwriter, PGPData toMarshal, String dsPrefix, |
|
187 XMLCryptoContext context) throws MarshalException { |
|
188 Marshaller.marshalPGPData( xwriter, toMarshal, dsPrefix, context); |
|
189 } |
|
190 }; |
|
191 |
|
192 private static XmlWriter.ToMarshal<SignatureProperty> Marshal_SignatureProperty = |
|
193 new XmlWriter.ToMarshal<SignatureProperty>(SignatureProperty.class) { |
|
194 @Override |
|
195 public void marshalObject(XmlWriter xwriter, SignatureProperty toMarshal, String dsPrefix, |
|
196 XMLCryptoContext context) throws MarshalException { |
|
197 DOMSignatureProperty.marshal(xwriter, toMarshal, dsPrefix, context); |
|
198 } |
|
199 }; |
|
200 |
|
201 private static XmlWriter.ToMarshal<SignatureProperties> Marshal_SignatureProperties = |
|
202 new XmlWriter.ToMarshal<SignatureProperties>(SignatureProperties.class) { |
|
203 @Override |
|
204 public void marshalObject(XmlWriter xwriter, SignatureProperties toMarshal, String dsPrefix, |
|
205 XMLCryptoContext context) throws MarshalException { |
|
206 DOMSignatureProperties.marshal(xwriter, toMarshal, dsPrefix, context); |
|
207 } |
|
208 }; |
|
209 |
|
210 private static XmlWriter.ToMarshal<DOMSignatureMethod> Marshal_DOMSignatureMethod = |
|
211 new XmlWriter.ToMarshal<DOMSignatureMethod>(DOMSignatureMethod.class) { |
|
212 @Override |
|
213 public void marshalObject(XmlWriter xwriter, DOMSignatureMethod toMarshal, String dsPrefix, |
|
214 XMLCryptoContext context) throws MarshalException { |
|
215 toMarshal.marshal(xwriter, dsPrefix); |
|
216 } |
|
217 }; |
|
218 |
|
219 private static XmlWriter.ToMarshal<DOMTransform> Marshal_DOMTransform = |
|
220 new XmlWriter.ToMarshal<DOMTransform>(DOMTransform.class) { |
|
221 @Override |
|
222 public void marshalObject(XmlWriter xwriter, DOMTransform toMarshal, String dsPrefix, |
|
223 XMLCryptoContext context) throws MarshalException { |
|
224 toMarshal.marshal(xwriter, dsPrefix, context); |
|
225 } |
|
226 }; |
|
227 |
|
228 private static XmlWriter.ToMarshal<Manifest> Marshal_Manifest = |
|
229 new XmlWriter.ToMarshal<Manifest>(Manifest.class) { |
|
230 @Override |
|
231 public void marshalObject(XmlWriter xwriter, Manifest toMarshal, String dsPrefix, |
|
232 XMLCryptoContext context) throws MarshalException { |
|
233 DOMManifest.marshal(xwriter, toMarshal, dsPrefix, context); |
|
234 } |
|
235 }; |
|
236 |
|
237 private static XmlWriter.ToMarshal<DOMStructure> Marshal_DOMStructure = |
|
238 new XmlWriter.ToMarshal<DOMStructure>(DOMStructure.class) { |
|
239 @Override |
|
240 public void marshalObject(XmlWriter xwriter, DOMStructure toMarshal, String dsPrefix, |
|
241 XMLCryptoContext context) throws MarshalException { |
|
242 toMarshal.marshal(xwriter, dsPrefix, context); |
|
243 } |
|
244 }; |
|
245 |
|
246 private static XmlWriter.ToMarshal<javax.xml.crypto.dom.DOMStructure> Marshal_JavaXDOMStructure = |
|
247 new XmlWriter.ToMarshal<javax.xml.crypto.dom.DOMStructure>(javax.xml.crypto.dom.DOMStructure.class) { |
|
248 @Override |
|
249 public void marshalObject(XmlWriter xwriter, javax.xml.crypto.dom.DOMStructure toMarshal, String dsPrefix, |
|
250 XMLCryptoContext context) throws MarshalException { |
|
251 marshalGenericNode(xwriter, toMarshal); |
|
252 } |
|
253 }; |
|
254 |
|
255 private static final List<XmlWriter.ToMarshal<? extends XMLStructure>> MARSHALLERS = |
|
256 new ArrayList<XmlWriter.ToMarshal<? extends XMLStructure>>(); |
|
257 |
|
258 static { |
|
259 MARSHALLERS.add(Marshal_KeyName); |
|
260 MARSHALLERS.add(Marshal_KeyInfo); |
|
261 MARSHALLERS.add(Marshal_KeyValue); |
|
262 MARSHALLERS.add(Marshal_X509IssuerSerial); |
|
263 MARSHALLERS.add(Marshal_X509Data); |
|
264 MARSHALLERS.add(Marshal_DigestMethod); |
|
265 MARSHALLERS.add(Marshal_PGPData); |
|
266 MARSHALLERS.add(Marshal_SignatureProperty); |
|
267 MARSHALLERS.add(Marshal_SignatureProperties); |
|
268 MARSHALLERS.add(Marshal_DOMSignatureMethod); |
|
269 MARSHALLERS.add(Marshal_DOMTransform); |
|
270 MARSHALLERS.add(Marshal_Manifest); |
|
271 MARSHALLERS.add(Marshal_DOMStructure); |
|
272 MARSHALLERS.add(Marshal_JavaXDOMStructure); |
|
273 } |
|
274 |
|
275 private static void marshalGenericNode(XmlWriter xwriter, javax.xml.crypto.dom.DOMStructure xmlStruct) { |
|
276 Node node = xmlStruct.getNode(); |
|
277 |
|
278 // if it is a namespace, make a copy. |
|
279 if (DOMUtils.isNamespace(node)) { |
|
280 xwriter.writeNamespace(node.getLocalName(), node.getTextContent()); |
|
281 } |
|
282 else if (Node.ATTRIBUTE_NODE == node.getNodeType() ) { |
|
283 sendAttributeToWriter(xwriter, (Attr) node); |
|
284 } |
|
285 else { |
|
286 marshalGenericNode(xwriter, node); |
|
287 } |
|
288 } |
|
289 |
|
290 private static void marshalGenericNode(XmlWriter xwriter, Node node) { |
|
291 |
|
292 short nodeType = node.getNodeType(); |
|
293 if (DOMUtils.isNamespace(node)) { |
|
294 xwriter.writeNamespace(node.getLocalName(), node.getTextContent()); |
|
295 } |
|
296 else if (nodeType == Node.ATTRIBUTE_NODE) { |
|
297 // if it is an attribute, make a copy. |
|
298 sendAttributeToWriter(xwriter, (Attr) node); |
|
299 } |
|
300 else { |
|
301 switch (nodeType) { |
|
302 case Node.ELEMENT_NODE: |
|
303 xwriter.writeStartElement(node.getPrefix(), node.getLocalName(), node.getNamespaceURI()); |
|
304 |
|
305 // emit all the namespaces and attributes. |
|
306 NamedNodeMap nnm = node.getAttributes(); |
|
307 for (int idx = 0 ; idx < nnm.getLength() ; idx++) { |
|
308 Attr attr = (Attr) nnm.item(idx); |
|
309 // is this a namespace node? |
|
310 if (XMLConstants.XMLNS_ATTRIBUTE_NS_URI.equals(node.getNamespaceURI())) { |
|
311 xwriter.writeNamespace(attr.getLocalName(), attr.getValue()); |
|
312 } |
|
313 else { |
|
314 // nope - standard attribute. |
|
315 sendAttributeToWriter(xwriter, attr); |
|
316 } |
|
317 } |
|
318 // now loop through all the children. |
|
319 for (Node child = node.getFirstChild() ; child != null ; child = child.getNextSibling()) { |
|
320 marshalGenericNode(xwriter, child); |
|
321 } |
|
322 xwriter.writeEndElement(); |
|
323 break; |
|
324 case Node.COMMENT_NODE: |
|
325 xwriter.writeComment(node.getTextContent()); |
|
326 break; |
|
327 case Node.TEXT_NODE: |
|
328 xwriter.writeCharacters(node.getTextContent()); |
|
329 break; |
|
330 default: |
|
331 // unhandled - don't care to deal with processing instructions. |
|
332 break; |
|
333 } |
|
334 } |
|
335 } |
|
336 |
|
337 private static void sendAttributeToWriter(XmlWriter xwriter, Attr attr) { |
|
338 if (attr.isId()) { |
|
339 xwriter.writeIdAttribute(attr.getPrefix(), attr.getNamespaceURI(), |
|
340 attr.getLocalName(), attr.getTextContent()); |
|
341 } |
|
342 else { |
|
343 if (attr.getNamespaceURI() == null && attr.getLocalName() == null) { |
|
344 // Level 1 DOM attribute |
|
345 xwriter.writeAttribute(null, null, attr.getName(), attr.getTextContent()); |
|
346 } else { |
|
347 xwriter.writeAttribute(attr.getPrefix(), attr.getNamespaceURI(), attr.getLocalName(), |
|
348 attr.getTextContent()); |
|
349 } |
|
350 } |
|
351 } |
|
352 |
|
353 } |
|