1. /*
  2. * ====================================================================
  3. *
  4. * The Apache Software License, Version 1.1
  5. *
  6. * Copyright (c) 1999 The Apache Software Foundation. All rights
  7. * reserved.
  8. *
  9. * Redistribution and use in source and binary forms, with or without
  10. * modification, are permitted provided that the following conditions
  11. * are met:
  12. *
  13. * 1. Redistributions of source code must retain the above copyright
  14. * notice, this list of conditions and the following disclaimer.
  15. *
  16. * 2. Redistributions in binary form must reproduce the above copyright
  17. * notice, this list of conditions and the following disclaimer in
  18. * the documentation and/or other materials provided with the
  19. * distribution.
  20. *
  21. * 3. The end-user documentation included with the redistribution, if
  22. * any, must include the following acknowlegement:
  23. * "This product includes software developed by the
  24. * Apache Software Foundation (http://www.apache.org/)."
  25. * Alternately, this acknowlegement may appear in the software itself,
  26. * if and wherever such third-party acknowlegements normally appear.
  27. *
  28. * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
  29. * Foundation" must not be used to endorse or promote products derived
  30. * from this software without prior written permission. For written
  31. * permission, please contact apache@apache.org.
  32. *
  33. * 5. Products derived from this software may not be called "Apache"
  34. * nor may "Apache" appear in their names without prior written
  35. * permission of the Apache Group.
  36. *
  37. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
  38. * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  39. * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  40. * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
  41. * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  42. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  43. * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
  44. * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  45. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  46. * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
  47. * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  48. * SUCH DAMAGE.
  49. * ====================================================================
  50. *
  51. * This software consists of voluntary contributions made by many
  52. * individuals on behalf of the Apache Software Foundation. For more
  53. * information on the Apache Software Foundation, please see
  54. * <http://www.apache.org/>.
  55. *
  56. * [Additional notices, if required by prior licensing conditions]
  57. *
  58. */
  59. package org.apache.commons.modeler.util;
  60. import java.io.IOException;
  61. import java.io.InputStream;
  62. import java.io.OutputStream;
  63. import java.io.StringReader;
  64. import javax.xml.parsers.DocumentBuilder;
  65. import javax.xml.parsers.DocumentBuilderFactory;
  66. import javax.xml.parsers.ParserConfigurationException;
  67. import javax.xml.transform.OutputKeys;
  68. import javax.xml.transform.Transformer;
  69. import javax.xml.transform.TransformerException;
  70. import javax.xml.transform.TransformerFactory;
  71. import javax.xml.transform.dom.DOMSource;
  72. import javax.xml.transform.stream.StreamResult;
  73. import org.w3c.dom.Document;
  74. import org.w3c.dom.NamedNodeMap;
  75. import org.w3c.dom.Node;
  76. import org.xml.sax.EntityResolver;
  77. import org.xml.sax.InputSource;
  78. import org.xml.sax.SAXException;
  79. /**
  80. * Few simple utils to read DOM
  81. *
  82. * @author Costin Manolache
  83. */
  84. public class DomUtil {
  85. private static org.apache.commons.logging.Log log=
  86. org.apache.commons.logging.LogFactory.getLog( DomUtil.class );
  87. // -------------------- DOM utils --------------------
  88. /** Get the trimed text content of a node or null if there is no text
  89. */
  90. public static String getContent(Node n ) {
  91. if( n==null ) return null;
  92. Node n1=DomUtil.getChild(n, Node.TEXT_NODE);
  93. if( n1==null ) return null;
  94. String s1=n1.getNodeValue();
  95. return s1.trim();
  96. }
  97. /** Get the first element child.
  98. * @param parent lookup direct childs
  99. * @param name name of the element. If null return the first element.
  100. */
  101. public static Node getChild( Node parent, String name ) {
  102. if( parent==null ) return null;
  103. Node first=parent.getFirstChild();
  104. if( first==null ) return null;
  105. for (Node node = first; node != null;
  106. node = node.getNextSibling()) {
  107. //System.out.println("getNode: " + name + " " + node.getNodeName());
  108. if( node.getNodeType()!=Node.ELEMENT_NODE)
  109. continue;
  110. if( name != null &&
  111. name.equals( node.getNodeName() ) ) {
  112. return node;
  113. }
  114. if( name == null ) {
  115. return node;
  116. }
  117. }
  118. return null;
  119. }
  120. public static String getAttribute(Node element, String attName ) {
  121. NamedNodeMap attrs=element.getAttributes();
  122. if( attrs==null ) return null;
  123. Node attN=attrs.getNamedItem(attName);
  124. if( attN==null ) return null;
  125. return attN.getNodeValue();
  126. }
  127. public static void setAttribute(Node node, String attName, String val) {
  128. NamedNodeMap attributes=node.getAttributes();
  129. Node attNode=node.getOwnerDocument().createAttribute(attName);
  130. attNode.setNodeValue( val );
  131. attributes.setNamedItem(attNode);
  132. }
  133. public static void removeAttribute( Node node, String attName ) {
  134. NamedNodeMap attributes=node.getAttributes();
  135. attributes.removeNamedItem(attName);
  136. }
  137. /** Set or replace the text value
  138. */
  139. public static void setText(Node node, String val) {
  140. Node chld=DomUtil.getChild(node, Node.TEXT_NODE);
  141. if( chld == null ) {
  142. Node textN=node.getOwnerDocument().createTextNode(val);
  143. node.appendChild(textN);
  144. return;
  145. }
  146. // change the value
  147. chld.setNodeValue(val);
  148. }
  149. /** Find the first direct child with a given attribute.
  150. * @param parent
  151. * @param elemName name of the element, or null for any
  152. * @param attName attribute we're looking for
  153. * @param attVal attribute value or null if we just want any
  154. */
  155. public static Node findChildWithAtt(Node parent, String elemName,
  156. String attName, String attVal) {
  157. Node child=DomUtil.getChild(parent, Node.ELEMENT_NODE);
  158. if( attVal== null ) {
  159. while( child!= null &&
  160. ( elemName==null || elemName.equals( child.getNodeName())) &&
  161. DomUtil.getAttribute(child, attName) != null ) {
  162. child=getNext(child, elemName, Node.ELEMENT_NODE );
  163. }
  164. } else {
  165. while( child!= null &&
  166. ( elemName==null || elemName.equals( child.getNodeName())) &&
  167. ! attVal.equals( DomUtil.getAttribute(child, attName)) ) {
  168. child=getNext(child, elemName, Node.ELEMENT_NODE );
  169. }
  170. }
  171. return child;
  172. }
  173. /** Get the first child's content ( ie it's included TEXT node ).
  174. */
  175. public static String getChildContent( Node parent, String name ) {
  176. Node first=parent.getFirstChild();
  177. if( first==null ) return null;
  178. for (Node node = first; node != null;
  179. node = node.getNextSibling()) {
  180. //System.out.println("getNode: " + name + " " + node.getNodeName());
  181. if( name.equals( node.getNodeName() ) ) {
  182. return getContent( node );
  183. }
  184. }
  185. return null;
  186. }
  187. /** Get the first direct child with a given type
  188. */
  189. public static Node getChild( Node parent, int type ) {
  190. Node n=parent.getFirstChild();
  191. while( n!=null && type != n.getNodeType() ) {
  192. n=n.getNextSibling();
  193. }
  194. if( n==null ) return null;
  195. return n;
  196. }
  197. /** Get the next sibling with the same name and type
  198. */
  199. public static Node getNext( Node current ) {
  200. String name=current.getNodeName();
  201. int type=current.getNodeType();
  202. return getNext( current, name, type);
  203. }
  204. /** Return the next sibling with a given name and type
  205. */
  206. public static Node getNext( Node current, String name, int type) {
  207. Node first=current.getNextSibling();
  208. if( first==null ) return null;
  209. for (Node node = first; node != null;
  210. node = node.getNextSibling()) {
  211. if( type >= 0 && node.getNodeType() != type ) continue;
  212. //System.out.println("getNode: " + name + " " + node.getNodeName());
  213. if( name==null )
  214. return node;
  215. if( name.equals( node.getNodeName() ) ) {
  216. return node;
  217. }
  218. }
  219. return null;
  220. }
  221. public static class NullResolver implements EntityResolver {
  222. public InputSource resolveEntity (String publicId,
  223. String systemId)
  224. throws SAXException, IOException
  225. {
  226. if( log.isTraceEnabled())
  227. log.trace("ResolveEntity: " + publicId + " " + systemId);
  228. return new InputSource(new StringReader(""));
  229. }
  230. }
  231. public static void setAttributes( Object o, Node parent)
  232. {
  233. NamedNodeMap attrs=parent.getAttributes();
  234. if( attrs==null ) return;
  235. for (int i=0; i<attrs.getLength(); i++ ) {
  236. Node n=attrs.item(i);
  237. String name=n.getNodeName();
  238. String value=n.getNodeValue();
  239. if( log.isTraceEnabled() )
  240. log.trace("Attribute " + parent.getNodeName() + " " +
  241. name + "=" + value);
  242. try {
  243. IntrospectionUtils.setProperty(o, name, value);
  244. } catch( Exception ex ) {
  245. ex.printStackTrace();
  246. }
  247. }
  248. }
  249. /** Read XML as DOM.
  250. */
  251. public static Document readXml(InputStream is)
  252. throws SAXException, IOException, ParserConfigurationException
  253. {
  254. DocumentBuilderFactory dbf =
  255. DocumentBuilderFactory.newInstance();
  256. dbf.setValidating(false);
  257. dbf.setIgnoringComments(false);
  258. dbf.setIgnoringElementContentWhitespace(true);
  259. //dbf.setCoalescing(true);
  260. //dbf.setExpandEntityReferences(true);
  261. DocumentBuilder db = null;
  262. db = dbf.newDocumentBuilder();
  263. db.setEntityResolver( new NullResolver() );
  264. // db.setErrorHandler( new MyErrorHandler());
  265. Document doc = db.parse(is);
  266. return doc;
  267. }
  268. public static void writeXml( Node n, OutputStream os )
  269. throws TransformerException
  270. {
  271. TransformerFactory tf=TransformerFactory.newInstance();
  272. //identity
  273. Transformer t=tf.newTransformer();
  274. t.setOutputProperty(OutputKeys.INDENT, "yes");
  275. t.transform(new DOMSource( n ), new StreamResult( os ));
  276. }
  277. }