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.List; |
|
26 |
|
27 import javax.xml.XMLConstants; |
|
28 import javax.xml.crypto.MarshalException; |
|
29 import javax.xml.crypto.XMLCryptoContext; |
|
30 import javax.xml.crypto.XMLStructure; |
|
31 import javax.xml.crypto.dom.DOMStructure; |
|
32 |
|
33 import org.w3c.dom.Attr; |
|
34 import org.w3c.dom.Comment; |
|
35 import org.w3c.dom.Document; |
|
36 import org.w3c.dom.Element; |
|
37 import org.w3c.dom.Node; |
|
38 import org.w3c.dom.Text; |
|
39 |
|
40 /** |
|
41 * Manifestation of XmlWriter interface designed to write to a tree. |
|
42 */ |
|
43 public class XmlWriterToTree implements XmlWriter { |
|
44 |
|
45 private Document factory; |
|
46 |
|
47 private Element createdElement; |
|
48 |
|
49 private Node nextSibling; |
|
50 |
|
51 private Node currentNode; |
|
52 |
|
53 private List<XmlWriter.ToMarshal<? extends XMLStructure>> m_marshallers; |
|
54 |
|
55 public XmlWriterToTree(List<XmlWriter.ToMarshal<? extends XMLStructure>> marshallers, Node parent) { |
|
56 m_marshallers = marshallers; |
|
57 factory = parent instanceof Document ? (Document)parent : parent.getOwnerDocument(); |
|
58 currentNode = parent; |
|
59 } |
|
60 |
|
61 /** |
|
62 * Reset to a new parent so that the writer can be re-used. |
|
63 * @param newParent |
|
64 */ |
|
65 public void resetToNewParent(Node newParent) { |
|
66 currentNode = newParent; |
|
67 createdElement = null; |
|
68 } |
|
69 |
|
70 /** |
|
71 * Get the root element created with this writer. |
|
72 * @return the root element created with this writer. |
|
73 */ |
|
74 public Element getCreatedElement() { |
|
75 return createdElement; |
|
76 } |
|
77 |
|
78 /** |
|
79 * In cases where the serialization is supposed to precede a specific |
|
80 * element, we add an extra parameter to capture that. Only affects the |
|
81 * first element insertion (obviously?). |
|
82 * |
|
83 * @param marshallers |
|
84 * @param parent |
|
85 * @param nextSibling The first element created will be created *before* this element. |
|
86 */ |
|
87 public XmlWriterToTree(List<XmlWriter.ToMarshal<? extends XMLStructure>> marshallers, Node parent, Node nextSibling) { |
|
88 this(marshallers, parent); |
|
89 this.nextSibling = nextSibling; |
|
90 } |
|
91 |
|
92 @Override |
|
93 public void writeStartElement(String prefix, String localName, String namespaceURI) { |
|
94 if ("".equals(namespaceURI)) { |
|
95 // Map global namespace from StAX to DOM |
|
96 namespaceURI = null; |
|
97 } |
|
98 |
|
99 Element newElem = factory.createElementNS(namespaceURI, DOMUtils.getQNameString(prefix, localName)); |
|
100 if (nextSibling != null) { |
|
101 newElem = (Element)nextSibling.getParentNode().insertBefore(newElem, nextSibling); |
|
102 } |
|
103 else { |
|
104 newElem = (Element)currentNode.appendChild(newElem); |
|
105 } |
|
106 nextSibling = null; |
|
107 currentNode = newElem; |
|
108 |
|
109 if (createdElement == null) { |
|
110 createdElement = newElem; |
|
111 } |
|
112 } |
|
113 |
|
114 @Override |
|
115 public void writeEndElement() { |
|
116 currentNode = currentNode.getParentNode(); |
|
117 } |
|
118 |
|
119 |
|
120 @Override |
|
121 public void writeTextElement(String prefix, String localName, String namespaceURI, String value) { |
|
122 writeStartElement(prefix, localName, namespaceURI); |
|
123 writeCharacters(value); |
|
124 writeEndElement(); |
|
125 } |
|
126 |
|
127 @Override |
|
128 public void writeNamespace(String prefix, String namespaceURI) { |
|
129 if ("".equals(prefix) || prefix == null) { |
|
130 writeAttribute(null, XMLConstants.XMLNS_ATTRIBUTE_NS_URI, "xmlns", namespaceURI); |
|
131 } |
|
132 else { |
|
133 writeAttribute("xmlns", XMLConstants.XMLNS_ATTRIBUTE_NS_URI, prefix, namespaceURI); |
|
134 } |
|
135 } |
|
136 |
|
137 @Override |
|
138 public void writeCharacters(String text) { |
|
139 Text textNode = factory.createTextNode(text); |
|
140 currentNode.appendChild(textNode); |
|
141 } |
|
142 |
|
143 |
|
144 @Override |
|
145 public void writeComment(String text) { |
|
146 Comment commentNode = factory.createComment(text); |
|
147 currentNode.appendChild(commentNode); |
|
148 } |
|
149 |
|
150 @Override |
|
151 public Attr writeAttribute(String prefix, String namespaceURI, String localName, String value) { |
|
152 |
|
153 Attr result = null; |
|
154 if (value != null) { |
|
155 if ("".equals(namespaceURI)) { |
|
156 // Map global namespace from StAX to DOM |
|
157 namespaceURI = null; |
|
158 } |
|
159 |
|
160 result = factory.createAttributeNS(namespaceURI, DOMUtils.getQNameString(prefix, localName)); |
|
161 result.setTextContent(value); |
|
162 if (! (currentNode instanceof Element)) { |
|
163 throw new IllegalStateException( |
|
164 "Attempting to add an attribute to something other than an element node. Node is " |
|
165 + currentNode.toString()); |
|
166 } |
|
167 ( (Element)currentNode).setAttributeNodeNS(result); |
|
168 } |
|
169 return result; |
|
170 } |
|
171 |
|
172 @Override |
|
173 public void writeIdAttribute(String prefix, String namespaceURI, String localName, String value) { |
|
174 if (value == null) { |
|
175 return; |
|
176 } |
|
177 Attr newAttr = writeAttribute(prefix, namespaceURI, localName, value); |
|
178 ( (Element)currentNode).setIdAttributeNode(newAttr, true); |
|
179 } |
|
180 |
|
181 |
|
182 @Override |
|
183 public String getCurrentLocalName() { |
|
184 return currentNode.getLocalName(); |
|
185 } |
|
186 |
|
187 @Override |
|
188 public XMLStructure getCurrentNodeAsStructure() { |
|
189 return new DOMStructure(currentNode); |
|
190 } |
|
191 |
|
192 @Override |
|
193 public void marshalStructure(XMLStructure toMarshal, String dsPrefix, XMLCryptoContext context) throws MarshalException { |
|
194 |
|
195 // look for the first isInstance match, and marshal to that. |
|
196 for (int idx = 0 ; idx < m_marshallers.size() ; idx++) { |
|
197 @SuppressWarnings("unchecked") |
|
198 XmlWriter.ToMarshal<XMLStructure> marshaller = (ToMarshal<XMLStructure>) m_marshallers.get(idx); |
|
199 if (marshaller.clazzToMatch.isInstance(toMarshal)) { |
|
200 marshaller.marshalObject(this, toMarshal, dsPrefix, context); |
|
201 return; |
|
202 } |
|
203 } |
|
204 throw new IllegalArgumentException("Unable to marshal unexpected object of class " + toMarshal.getClass().toString()); |
|
205 } |
|
206 |
|
207 |
|
208 } |
|