1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/share/jaxws_classes/com/sun/xml/internal/ws/util/DOMUtil.java Tue Mar 06 16:09:35 2012 -0800 1.3 @@ -0,0 +1,263 @@ 1.4 +/* 1.5 + * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. 1.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 1.7 + * 1.8 + * This code is free software; you can redistribute it and/or modify it 1.9 + * under the terms of the GNU General Public License version 2 only, as 1.10 + * published by the Free Software Foundation. Oracle designates this 1.11 + * particular file as subject to the "Classpath" exception as provided 1.12 + * by Oracle in the LICENSE file that accompanied this code. 1.13 + * 1.14 + * This code is distributed in the hope that it will be useful, but WITHOUT 1.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1.17 + * version 2 for more details (a copy is included in the LICENSE file that 1.18 + * accompanied this code). 1.19 + * 1.20 + * You should have received a copy of the GNU General Public License version 1.21 + * 2 along with this work; if not, write to the Free Software Foundation, 1.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 1.23 + * 1.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 1.25 + * or visit www.oracle.com if you need additional information or have any 1.26 + * questions. 1.27 + */ 1.28 + 1.29 +package com.sun.xml.internal.ws.util; 1.30 + 1.31 +import org.w3c.dom.Document; 1.32 +import org.w3c.dom.NamedNodeMap; 1.33 +import org.w3c.dom.Node; 1.34 +import org.w3c.dom.NodeList; 1.35 +import org.w3c.dom.Element; 1.36 +import org.xml.sax.SAXException; 1.37 + 1.38 +import javax.xml.parsers.DocumentBuilder; 1.39 +import javax.xml.parsers.DocumentBuilderFactory; 1.40 +import javax.xml.parsers.FactoryConfigurationError; 1.41 +import javax.xml.parsers.ParserConfigurationException; 1.42 +import javax.xml.stream.XMLStreamException; 1.43 +import javax.xml.stream.XMLStreamWriter; 1.44 +import javax.xml.XMLConstants; 1.45 +import javax.xml.namespace.NamespaceContext; 1.46 +import java.io.IOException; 1.47 +import java.io.InputStream; 1.48 +import java.util.Iterator; 1.49 +import java.util.List; 1.50 +import java.util.ArrayList; 1.51 + 1.52 +import com.sun.istack.internal.NotNull; 1.53 +import com.sun.istack.internal.Nullable; 1.54 + 1.55 +/** 1.56 + * @author: JAXWS Development Team 1.57 + */ 1.58 +public class DOMUtil { 1.59 + 1.60 + private static DocumentBuilder db; 1.61 + 1.62 + /** 1.63 + * Creates a new DOM document. 1.64 + */ 1.65 + public static Document createDom() { 1.66 + synchronized (DOMUtil.class) { 1.67 + if (db == null) { 1.68 + try { 1.69 + DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); 1.70 + dbf.setNamespaceAware(true); 1.71 + db = dbf.newDocumentBuilder(); 1.72 + } catch (ParserConfigurationException e) { 1.73 + throw new FactoryConfigurationError(e); 1.74 + } 1.75 + } 1.76 + return db.newDocument(); 1.77 + } 1.78 + } 1.79 + 1.80 + public static Node createDOMNode(InputStream inputStream) { 1.81 + 1.82 + DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); 1.83 + dbf.setNamespaceAware(true); 1.84 + dbf.setValidating(false); 1.85 + try { 1.86 + DocumentBuilder builder = dbf.newDocumentBuilder(); 1.87 + try { 1.88 + return builder.parse(inputStream); 1.89 + } catch (SAXException e) { 1.90 + e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. 1.91 + } catch (IOException e) { 1.92 + e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. 1.93 + } 1.94 + } catch (ParserConfigurationException pce) { 1.95 + IllegalArgumentException iae = new IllegalArgumentException(pce.getMessage()); 1.96 + iae.initCause(pce); 1.97 + throw iae; 1.98 + } 1.99 + return null; 1.100 + } 1.101 + 1.102 + /** 1.103 + * Traverses a DOM node and writes out on a streaming writer. 1.104 + * 1.105 + * @param node 1.106 + * @param writer 1.107 + */ 1.108 + public static void serializeNode(Element node, XMLStreamWriter writer) throws XMLStreamException { 1.109 + writeTagWithAttributes(node, writer); 1.110 + 1.111 + if (node.hasChildNodes()) { 1.112 + NodeList children = node.getChildNodes(); 1.113 + for (int i = 0; i < children.getLength(); i++) { 1.114 + Node child = children.item(i); 1.115 + switch (child.getNodeType()) { 1.116 + case Node.PROCESSING_INSTRUCTION_NODE: 1.117 + writer.writeProcessingInstruction(child.getNodeValue()); 1.118 + case Node.DOCUMENT_TYPE_NODE: 1.119 + break; 1.120 + case Node.CDATA_SECTION_NODE: 1.121 + writer.writeCData(child.getNodeValue()); 1.122 + break; 1.123 + case Node.COMMENT_NODE: 1.124 + writer.writeComment(child.getNodeValue()); 1.125 + break; 1.126 + case Node.TEXT_NODE: 1.127 + writer.writeCharacters(child.getNodeValue()); 1.128 + break; 1.129 + case Node.ELEMENT_NODE: 1.130 + serializeNode((Element) child, writer); 1.131 + break; 1.132 + } 1.133 + } 1.134 + } 1.135 + writer.writeEndElement(); 1.136 + } 1.137 + 1.138 + public static void writeTagWithAttributes(Element node, XMLStreamWriter writer) throws XMLStreamException { 1.139 + String nodePrefix = fixNull(node.getPrefix()); 1.140 + String nodeNS = fixNull(node.getNamespaceURI()); 1.141 + //fix to work with DOM level 1 nodes. 1.142 + String nodeLocalName = node.getLocalName()== null?node.getNodeName():node.getLocalName(); 1.143 + 1.144 + // See if nodePrefix:nodeNS is declared in writer's NamespaceContext before writing start element 1.145 + // Writing start element puts nodeNS in NamespaceContext even though namespace declaration not written 1.146 + boolean prefixDecl = isPrefixDeclared(writer, nodeNS, nodePrefix); 1.147 + writer.writeStartElement(nodePrefix, nodeLocalName, nodeNS); 1.148 + 1.149 + if (node.hasAttributes()) { 1.150 + NamedNodeMap attrs = node.getAttributes(); 1.151 + int numOfAttributes = attrs.getLength(); 1.152 + // write namespace declarations first. 1.153 + // if we interleave this with attribue writing, 1.154 + // Zephyr will try to fix it and we end up getting inconsistent namespace bindings. 1.155 + for (int i = 0; i < numOfAttributes; i++) { 1.156 + Node attr = attrs.item(i); 1.157 + String nsUri = fixNull(attr.getNamespaceURI()); 1.158 + if (nsUri.equals(XMLConstants.XMLNS_ATTRIBUTE_NS_URI)) { 1.159 + // handle default ns declarations 1.160 + String local = attr.getLocalName().equals(XMLConstants.XMLNS_ATTRIBUTE) ? "" : attr.getLocalName(); 1.161 + if (local.equals(nodePrefix) && attr.getNodeValue().equals(nodeNS)) { 1.162 + prefixDecl = true; 1.163 + } 1.164 + if (local.equals("")) { 1.165 + writer.writeDefaultNamespace(attr.getNodeValue()); 1.166 + } else { 1.167 + // this is a namespace declaration, not an attribute 1.168 + writer.setPrefix(attr.getLocalName(), attr.getNodeValue()); 1.169 + writer.writeNamespace(attr.getLocalName(), attr.getNodeValue()); 1.170 + } 1.171 + } 1.172 + } 1.173 + } 1.174 + // node's namespace is not declared as attribute, but declared on ancestor 1.175 + if (!prefixDecl) { 1.176 + writer.writeNamespace(nodePrefix, nodeNS); 1.177 + } 1.178 + 1.179 + // Write all other attributes which are not namespace decl. 1.180 + if (node.hasAttributes()) { 1.181 + NamedNodeMap attrs = node.getAttributes(); 1.182 + int numOfAttributes = attrs.getLength(); 1.183 + 1.184 + for (int i = 0; i < numOfAttributes; i++) { 1.185 + Node attr = attrs.item(i); 1.186 + String attrPrefix = fixNull(attr.getPrefix()); 1.187 + String attrNS = fixNull(attr.getNamespaceURI()); 1.188 + if (!attrNS.equals(XMLConstants.XMLNS_ATTRIBUTE_NS_URI)) { 1.189 + String localName = attr.getLocalName(); 1.190 + if (localName == null) { 1.191 + // TODO: this is really a bug in the caller for not creating proper DOM tree. 1.192 + // will remove this workaround after plugfest 1.193 + localName = attr.getNodeName(); 1.194 + } 1.195 + boolean attrPrefixDecl = isPrefixDeclared(writer, attrNS, attrPrefix); 1.196 + if (!attrPrefix.equals("") && !attrPrefixDecl) { 1.197 + // attr has namespace but namespace decl is there in ancestor node 1.198 + // So write the namespace decl before writing the attr 1.199 + writer.setPrefix(attr.getLocalName(), attr.getNodeValue()); 1.200 + writer.writeNamespace(attrPrefix, attrNS); 1.201 + } 1.202 + writer.writeAttribute(attrPrefix, attrNS, localName, attr.getNodeValue()); 1.203 + } 1.204 + } 1.205 + } 1.206 + } 1.207 + 1.208 + private static boolean isPrefixDeclared(XMLStreamWriter writer, String nsUri, String prefix) { 1.209 + boolean prefixDecl = false; 1.210 + NamespaceContext nscontext = writer.getNamespaceContext(); 1.211 + Iterator prefixItr = nscontext.getPrefixes(nsUri); 1.212 + while (prefixItr.hasNext()) { 1.213 + if (prefix.equals(prefixItr.next())) { 1.214 + prefixDecl = true; 1.215 + break; 1.216 + } 1.217 + } 1.218 + return prefixDecl; 1.219 + } 1.220 + 1.221 + /** 1.222 + * Gets the first child of the given name, or null. 1.223 + */ 1.224 + public static Element getFirstChild(Element e, String nsUri, String local) { 1.225 + for (Node n = e.getFirstChild(); n != null; n = n.getNextSibling()) { 1.226 + if (n.getNodeType() == Node.ELEMENT_NODE) { 1.227 + Element c = (Element) n; 1.228 + if (c.getLocalName().equals(local) && c.getNamespaceURI().equals(nsUri)) 1.229 + return c; 1.230 + } 1.231 + } 1.232 + return null; 1.233 + } 1.234 + 1.235 + private static 1.236 + @NotNull 1.237 + String fixNull(@Nullable String s) { 1.238 + if (s == null) return ""; 1.239 + else return s; 1.240 + } 1.241 + 1.242 + /** 1.243 + * Gets the first element child. 1.244 + */ 1.245 + public static 1.246 + @Nullable 1.247 + Element getFirstElementChild(Node parent) { 1.248 + for (Node n = parent.getFirstChild(); n != null; n = n.getNextSibling()) { 1.249 + if (n.getNodeType() == Node.ELEMENT_NODE) { 1.250 + return (Element) n; 1.251 + } 1.252 + } 1.253 + return null; 1.254 + } 1.255 + 1.256 + public static @NotNull 1.257 + List<Element> getChildElements(Node parent){ 1.258 + List<Element> elements = new ArrayList<Element>(); 1.259 + for (Node n = parent.getFirstChild(); n != null; n = n.getNextSibling()) { 1.260 + if (n.getNodeType() == Node.ELEMENT_NODE) { 1.261 + elements.add((Element)n); 1.262 + } 1.263 + } 1.264 + return elements; 1.265 + } 1.266 +}