001 /*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements. See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License. You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017 package org.apache.servicemix.soap.util;
018
019 import java.io.IOException;
020 import java.io.InputStream;
021
022 import javax.xml.XMLConstants;
023 import javax.xml.namespace.QName;
024 import javax.xml.parsers.DocumentBuilderFactory;
025 import javax.xml.parsers.ParserConfigurationException;
026 import javax.xml.transform.Source;
027 import javax.xml.transform.Transformer;
028 import javax.xml.transform.TransformerConfigurationException;
029 import javax.xml.transform.TransformerException;
030 import javax.xml.transform.TransformerFactory;
031 import javax.xml.transform.dom.DOMResult;
032
033 import org.apache.servicemix.soap.api.Fault;
034 import org.w3c.dom.Document;
035 import org.w3c.dom.Element;
036 import org.w3c.dom.Node;
037 import org.w3c.dom.NodeList;
038 import org.xml.sax.SAXException;
039
040 /**
041 * DOM related utilities.
042 *
043 * @author <a href="mailto:gnodet [at] gmail.com">Guillaume Nodet</a>
044 */
045 public class DomUtil {
046
047 private static DocumentBuilderFactory documentBuilderFactory;
048 private static TransformerFactory transformerFactory;
049
050 public static Document createDocument() {
051 try {
052 return getDocumentBuilderFactory().newDocumentBuilder().newDocument();
053 } catch (ParserConfigurationException e) {
054 throw new Fault(e);
055 }
056 }
057
058 public static Document parse(InputStream is) {
059 try {
060 return getDocumentBuilderFactory().newDocumentBuilder().parse(is);
061 } catch (SAXException e) {
062 throw new Fault(e);
063 } catch (IOException e) {
064 throw new Fault(e);
065 } catch (ParserConfigurationException e) {
066 throw new Fault(e);
067 }
068 }
069
070 public static Document parse(Source source) {
071 try {
072 Document doc = createDocument();
073 DOMResult result = new DOMResult(doc);
074 Transformer transformer = getTransformerFactory().newTransformer();
075 transformer.transform(source, result);
076 return doc;
077 } catch (TransformerConfigurationException e) {
078 throw new Fault(e);
079 } catch (TransformerException e) {
080 throw new Fault(e);
081 }
082 }
083
084 public static DocumentBuilderFactory getDocumentBuilderFactory() {
085 if (documentBuilderFactory == null) {
086 DocumentBuilderFactory f = DocumentBuilderFactory.newInstance();
087 f.setNamespaceAware(true);
088 documentBuilderFactory = f;
089 }
090 return documentBuilderFactory;
091 }
092
093 public static TransformerFactory getTransformerFactory() {
094 if (transformerFactory == null) {
095 transformerFactory = TransformerFactory.newInstance();
096 }
097 return transformerFactory;
098 }
099
100 /**
101 * Get the first child element
102 * @param parent
103 * @return
104 */
105 public static Element getFirstChildElement(Node parent) {
106 NodeList childs = parent.getChildNodes();
107 for (int i = 0; i < childs.getLength(); i++) {
108 Node child = childs.item(i);
109 if (child instanceof Element) {
110 return (Element) child;
111 }
112 }
113 return null;
114 }
115
116 /**
117 * Returns the text of the element
118 */
119 public static String getElementText(Element element) {
120 StringBuffer buffer = new StringBuffer();
121 NodeList nodeList = element.getChildNodes();
122 for (int i = 0, size = nodeList.getLength(); i < size; i++) {
123 Node node = nodeList.item(i);
124 if (node.getNodeType() == Node.TEXT_NODE || node.getNodeType() == Node.CDATA_SECTION_NODE) {
125 buffer.append(node.getNodeValue());
126 }
127 }
128 return buffer.toString();
129 }
130
131 /**
132 * Get the next sibling element
133 * @param el
134 * @return
135 */
136 public static Element getNextSiblingElement(Element el) {
137 for (Node n = el.getNextSibling(); n != null; n = n.getNextSibling()) {
138 if (n instanceof Element) {
139 return (Element) n;
140 }
141 }
142 return null;
143 }
144
145 public static Element createElement(Node parent, QName name) {
146 Document doc = parent instanceof Document ? (Document) parent : parent.getOwnerDocument();
147 Element element;
148 if (name.getPrefix() != null && name.getPrefix().length() > 0) {
149 element = doc.createElementNS(name.getNamespaceURI(), name.getPrefix() + ":" + name.getLocalPart());
150 String attr = recursiveGetAttributeValue(parent, XMLConstants.XMLNS_ATTRIBUTE + ":" + name.getPrefix());
151 if (attr == null || !attr.equals(name.getNamespaceURI())) {
152 element.setAttribute(XMLConstants.XMLNS_ATTRIBUTE + ":" + name.getPrefix(),
153 name.getNamespaceURI());
154 }
155 } else if (name.getNamespaceURI() != null && name.getNamespaceURI().length() > 0) {
156 element = doc.createElementNS(name.getNamespaceURI(), name.getLocalPart());
157 String attr = recursiveGetAttributeValue(parent, XMLConstants.XMLNS_ATTRIBUTE);
158 if (attr == null || !attr.equals(name.getNamespaceURI())) {
159 element.setAttribute(XMLConstants.XMLNS_ATTRIBUTE,
160 name.getNamespaceURI());
161 }
162 } else {
163 element = doc.createElementNS(null, name.getLocalPart());
164 String attr = recursiveGetAttributeValue(parent, XMLConstants.XMLNS_ATTRIBUTE);
165 if (attr == null || attr.length() > 0) {
166 element.setAttribute(XMLConstants.XMLNS_ATTRIBUTE,
167 "");
168 }
169 }
170 parent.appendChild(element);
171 return element;
172 }
173
174 /**
175 * Creates a QName instance from the given namespace context for the given qualifiedName
176 *
177 * @param element the element to use as the namespace context
178 * @param qualifiedName the fully qualified name
179 * @return the QName which matches the qualifiedName
180 */
181 public static QName createQName(Element element, String qualifiedName) {
182 int index = qualifiedName.indexOf(':');
183 if (index >= 0) {
184 String prefix = qualifiedName.substring(0, index);
185 String localName = qualifiedName.substring(index + 1);
186 String uri = recursiveGetAttributeValue(element, XMLConstants.XMLNS_ATTRIBUTE + ":" + prefix);
187 return new QName(uri, localName, prefix);
188 }
189 else {
190 String uri = recursiveGetAttributeValue(element, XMLConstants.XMLNS_ATTRIBUTE);
191 if (uri != null) {
192 return new QName(uri, qualifiedName);
193 }
194 return new QName(qualifiedName);
195 }
196 }
197
198 /**
199 * Recursive method to find a given attribute value
200 */
201 public static String recursiveGetAttributeValue(Node parent, String attributeName) {
202 if (parent instanceof Element) {
203 Element element = (Element) parent;
204 String answer = element.getAttribute(attributeName);
205 if (answer == null || answer.length() == 0) {
206 Node parentNode = element.getParentNode();
207 if (parentNode instanceof Element) {
208 return recursiveGetAttributeValue((Element) parentNode, attributeName);
209 }
210 }
211 return answer;
212 } else {
213 return null;
214 }
215 }
216
217 protected static String getUniquePrefix(Element element) {
218 int n = 1;
219 while (true) {
220 String nsPrefix = "ns" + n;
221 if (recursiveGetAttributeValue(element, XMLConstants.XMLNS_ATTRIBUTE + ":" + nsPrefix) == null) {
222 return nsPrefix;
223 }
224 n++;
225 }
226 }
227
228 public static QName getQName(Element el) {
229 if (el == null) {
230 return null;
231 } else if (el.getPrefix() != null) {
232 return new QName(el.getNamespaceURI(), el.getLocalName(), el.getPrefix());
233 } else {
234 return new QName(el.getNamespaceURI(), el.getLocalName());
235 }
236 }
237
238 }