src/share/jaxws_classes/com/sun/xml/internal/ws/util/DOMUtil.java

changeset 286
f50545b5e2f1
child 368
0989ad8c0860
equal deleted inserted replaced
284:88b85470e72c 286:f50545b5e2f1
1 /*
2 * Copyright (c) 1997, 2010, Oracle and/or its affiliates. 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. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package com.sun.xml.internal.ws.util;
27
28 import org.w3c.dom.Document;
29 import org.w3c.dom.NamedNodeMap;
30 import org.w3c.dom.Node;
31 import org.w3c.dom.NodeList;
32 import org.w3c.dom.Element;
33 import org.xml.sax.SAXException;
34
35 import javax.xml.parsers.DocumentBuilder;
36 import javax.xml.parsers.DocumentBuilderFactory;
37 import javax.xml.parsers.FactoryConfigurationError;
38 import javax.xml.parsers.ParserConfigurationException;
39 import javax.xml.stream.XMLStreamException;
40 import javax.xml.stream.XMLStreamWriter;
41 import javax.xml.XMLConstants;
42 import javax.xml.namespace.NamespaceContext;
43 import java.io.IOException;
44 import java.io.InputStream;
45 import java.util.Iterator;
46 import java.util.List;
47 import java.util.ArrayList;
48
49 import com.sun.istack.internal.NotNull;
50 import com.sun.istack.internal.Nullable;
51
52 /**
53 * @author: JAXWS Development Team
54 */
55 public class DOMUtil {
56
57 private static DocumentBuilder db;
58
59 /**
60 * Creates a new DOM document.
61 */
62 public static Document createDom() {
63 synchronized (DOMUtil.class) {
64 if (db == null) {
65 try {
66 DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
67 dbf.setNamespaceAware(true);
68 db = dbf.newDocumentBuilder();
69 } catch (ParserConfigurationException e) {
70 throw new FactoryConfigurationError(e);
71 }
72 }
73 return db.newDocument();
74 }
75 }
76
77 public static Node createDOMNode(InputStream inputStream) {
78
79 DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
80 dbf.setNamespaceAware(true);
81 dbf.setValidating(false);
82 try {
83 DocumentBuilder builder = dbf.newDocumentBuilder();
84 try {
85 return builder.parse(inputStream);
86 } catch (SAXException e) {
87 e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
88 } catch (IOException e) {
89 e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
90 }
91 } catch (ParserConfigurationException pce) {
92 IllegalArgumentException iae = new IllegalArgumentException(pce.getMessage());
93 iae.initCause(pce);
94 throw iae;
95 }
96 return null;
97 }
98
99 /**
100 * Traverses a DOM node and writes out on a streaming writer.
101 *
102 * @param node
103 * @param writer
104 */
105 public static void serializeNode(Element node, XMLStreamWriter writer) throws XMLStreamException {
106 writeTagWithAttributes(node, writer);
107
108 if (node.hasChildNodes()) {
109 NodeList children = node.getChildNodes();
110 for (int i = 0; i < children.getLength(); i++) {
111 Node child = children.item(i);
112 switch (child.getNodeType()) {
113 case Node.PROCESSING_INSTRUCTION_NODE:
114 writer.writeProcessingInstruction(child.getNodeValue());
115 case Node.DOCUMENT_TYPE_NODE:
116 break;
117 case Node.CDATA_SECTION_NODE:
118 writer.writeCData(child.getNodeValue());
119 break;
120 case Node.COMMENT_NODE:
121 writer.writeComment(child.getNodeValue());
122 break;
123 case Node.TEXT_NODE:
124 writer.writeCharacters(child.getNodeValue());
125 break;
126 case Node.ELEMENT_NODE:
127 serializeNode((Element) child, writer);
128 break;
129 }
130 }
131 }
132 writer.writeEndElement();
133 }
134
135 public static void writeTagWithAttributes(Element node, XMLStreamWriter writer) throws XMLStreamException {
136 String nodePrefix = fixNull(node.getPrefix());
137 String nodeNS = fixNull(node.getNamespaceURI());
138 //fix to work with DOM level 1 nodes.
139 String nodeLocalName = node.getLocalName()== null?node.getNodeName():node.getLocalName();
140
141 // See if nodePrefix:nodeNS is declared in writer's NamespaceContext before writing start element
142 // Writing start element puts nodeNS in NamespaceContext even though namespace declaration not written
143 boolean prefixDecl = isPrefixDeclared(writer, nodeNS, nodePrefix);
144 writer.writeStartElement(nodePrefix, nodeLocalName, nodeNS);
145
146 if (node.hasAttributes()) {
147 NamedNodeMap attrs = node.getAttributes();
148 int numOfAttributes = attrs.getLength();
149 // write namespace declarations first.
150 // if we interleave this with attribue writing,
151 // Zephyr will try to fix it and we end up getting inconsistent namespace bindings.
152 for (int i = 0; i < numOfAttributes; i++) {
153 Node attr = attrs.item(i);
154 String nsUri = fixNull(attr.getNamespaceURI());
155 if (nsUri.equals(XMLConstants.XMLNS_ATTRIBUTE_NS_URI)) {
156 // handle default ns declarations
157 String local = attr.getLocalName().equals(XMLConstants.XMLNS_ATTRIBUTE) ? "" : attr.getLocalName();
158 if (local.equals(nodePrefix) && attr.getNodeValue().equals(nodeNS)) {
159 prefixDecl = true;
160 }
161 if (local.equals("")) {
162 writer.writeDefaultNamespace(attr.getNodeValue());
163 } else {
164 // this is a namespace declaration, not an attribute
165 writer.setPrefix(attr.getLocalName(), attr.getNodeValue());
166 writer.writeNamespace(attr.getLocalName(), attr.getNodeValue());
167 }
168 }
169 }
170 }
171 // node's namespace is not declared as attribute, but declared on ancestor
172 if (!prefixDecl) {
173 writer.writeNamespace(nodePrefix, nodeNS);
174 }
175
176 // Write all other attributes which are not namespace decl.
177 if (node.hasAttributes()) {
178 NamedNodeMap attrs = node.getAttributes();
179 int numOfAttributes = attrs.getLength();
180
181 for (int i = 0; i < numOfAttributes; i++) {
182 Node attr = attrs.item(i);
183 String attrPrefix = fixNull(attr.getPrefix());
184 String attrNS = fixNull(attr.getNamespaceURI());
185 if (!attrNS.equals(XMLConstants.XMLNS_ATTRIBUTE_NS_URI)) {
186 String localName = attr.getLocalName();
187 if (localName == null) {
188 // TODO: this is really a bug in the caller for not creating proper DOM tree.
189 // will remove this workaround after plugfest
190 localName = attr.getNodeName();
191 }
192 boolean attrPrefixDecl = isPrefixDeclared(writer, attrNS, attrPrefix);
193 if (!attrPrefix.equals("") && !attrPrefixDecl) {
194 // attr has namespace but namespace decl is there in ancestor node
195 // So write the namespace decl before writing the attr
196 writer.setPrefix(attr.getLocalName(), attr.getNodeValue());
197 writer.writeNamespace(attrPrefix, attrNS);
198 }
199 writer.writeAttribute(attrPrefix, attrNS, localName, attr.getNodeValue());
200 }
201 }
202 }
203 }
204
205 private static boolean isPrefixDeclared(XMLStreamWriter writer, String nsUri, String prefix) {
206 boolean prefixDecl = false;
207 NamespaceContext nscontext = writer.getNamespaceContext();
208 Iterator prefixItr = nscontext.getPrefixes(nsUri);
209 while (prefixItr.hasNext()) {
210 if (prefix.equals(prefixItr.next())) {
211 prefixDecl = true;
212 break;
213 }
214 }
215 return prefixDecl;
216 }
217
218 /**
219 * Gets the first child of the given name, or null.
220 */
221 public static Element getFirstChild(Element e, String nsUri, String local) {
222 for (Node n = e.getFirstChild(); n != null; n = n.getNextSibling()) {
223 if (n.getNodeType() == Node.ELEMENT_NODE) {
224 Element c = (Element) n;
225 if (c.getLocalName().equals(local) && c.getNamespaceURI().equals(nsUri))
226 return c;
227 }
228 }
229 return null;
230 }
231
232 private static
233 @NotNull
234 String fixNull(@Nullable String s) {
235 if (s == null) return "";
236 else return s;
237 }
238
239 /**
240 * Gets the first element child.
241 */
242 public static
243 @Nullable
244 Element getFirstElementChild(Node parent) {
245 for (Node n = parent.getFirstChild(); n != null; n = n.getNextSibling()) {
246 if (n.getNodeType() == Node.ELEMENT_NODE) {
247 return (Element) n;
248 }
249 }
250 return null;
251 }
252
253 public static @NotNull
254 List<Element> getChildElements(Node parent){
255 List<Element> elements = new ArrayList<Element>();
256 for (Node n = parent.getFirstChild(); n != null; n = n.getNextSibling()) {
257 if (n.getNodeType() == Node.ELEMENT_NODE) {
258 elements.add((Element)n);
259 }
260 }
261 return elements;
262 }
263 }

mercurial