| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| package org.apache.tomcat.util; |
| |
| import java.io.IOException; |
| import java.io.InputStream; |
| import java.io.OutputStream; |
| import java.io.StringReader; |
| |
| import javax.xml.parsers.DocumentBuilder; |
| import javax.xml.parsers.DocumentBuilderFactory; |
| import javax.xml.parsers.ParserConfigurationException; |
| import javax.xml.transform.OutputKeys; |
| import javax.xml.transform.Transformer; |
| import javax.xml.transform.TransformerException; |
| import javax.xml.transform.TransformerFactory; |
| import javax.xml.transform.dom.DOMSource; |
| import javax.xml.transform.stream.StreamResult; |
| |
| import org.w3c.dom.Document; |
| import org.w3c.dom.NamedNodeMap; |
| import org.w3c.dom.Node; |
| import org.xml.sax.EntityResolver; |
| import org.xml.sax.InputSource; |
| import org.xml.sax.SAXException; |
| |
| |
| /** |
| * Few simple utils to read DOM |
| * |
| * @author Costin Manolache |
| */ |
| public class DomUtil { |
| private static final org.apache.juli.logging.Log log= |
| org.apache.juli.logging.LogFactory.getLog( DomUtil.class ); |
| |
| // -------------------- DOM utils -------------------- |
| |
| /** Get the trimmed text content of a node or null if there is no text |
| */ |
| public static String getContent(Node n ) { |
| if( n==null ) return null; |
| Node n1=DomUtil.getChild(n, Node.TEXT_NODE); |
| |
| if( n1==null ) return null; |
| |
| String s1=n1.getNodeValue(); |
| return s1.trim(); |
| } |
| |
| /** Get the first element child. |
| * @param parent lookup direct children |
| * @param name name of the element. If null return the first element. |
| */ |
| public static Node getChild( Node parent, String name ) { |
| if( parent==null ) return null; |
| Node first=parent.getFirstChild(); |
| if( first==null ) return null; |
| |
| for (Node node = first; node != null; |
| node = node.getNextSibling()) { |
| //System.out.println("getNode: " + name + " " + node.getNodeName()); |
| if( node.getNodeType()!=Node.ELEMENT_NODE) |
| continue; |
| if( name != null && |
| name.equals( node.getNodeName() ) ) { |
| return node; |
| } |
| if( name == null ) { |
| return node; |
| } |
| } |
| return null; |
| } |
| |
| public static String getAttribute(Node element, String attName ) { |
| NamedNodeMap attrs=element.getAttributes(); |
| if( attrs==null ) return null; |
| Node attN=attrs.getNamedItem(attName); |
| if( attN==null ) return null; |
| return attN.getNodeValue(); |
| } |
| |
| public static void setAttribute(Node node, String attName, String val) { |
| NamedNodeMap attributes=node.getAttributes(); |
| Node attNode=node.getOwnerDocument().createAttribute(attName); |
| attNode.setNodeValue( val ); |
| attributes.setNamedItem(attNode); |
| } |
| |
| public static void removeAttribute( Node node, String attName ) { |
| NamedNodeMap attributes=node.getAttributes(); |
| attributes.removeNamedItem(attName); |
| } |
| |
| |
| /** Set or replace the text value |
| */ |
| public static void setText(Node node, String val) { |
| Node chld=DomUtil.getChild(node, Node.TEXT_NODE); |
| if( chld == null ) { |
| Node textN=node.getOwnerDocument().createTextNode(val); |
| node.appendChild(textN); |
| return; |
| } |
| // change the value |
| chld.setNodeValue(val); |
| } |
| |
| /** Find the first direct child with a given attribute. |
| * @param parent |
| * @param elemName name of the element, or null for any |
| * @param attName attribute we're looking for |
| * @param attVal attribute value or null if we just want any |
| */ |
| public static Node findChildWithAtt(Node parent, String elemName, |
| String attName, String attVal) { |
| |
| Node child=DomUtil.getChild(parent, Node.ELEMENT_NODE); |
| if( attVal== null ) { |
| while( child!= null && |
| ( elemName==null || elemName.equals( child.getNodeName())) && |
| DomUtil.getAttribute(child, attName) != null ) { |
| child=getNext(child, elemName, Node.ELEMENT_NODE ); |
| } |
| } else { |
| while( child!= null && |
| ( elemName==null || elemName.equals( child.getNodeName())) && |
| ! attVal.equals( DomUtil.getAttribute(child, attName)) ) { |
| child=getNext(child, elemName, Node.ELEMENT_NODE ); |
| } |
| } |
| return child; |
| } |
| |
| |
| /** Get the first child's content ( ie it's included TEXT node ). |
| */ |
| public static String getChildContent( Node parent, String name ) { |
| Node first=parent.getFirstChild(); |
| if( first==null ) return null; |
| for (Node node = first; node != null; |
| node = node.getNextSibling()) { |
| //System.out.println("getNode: " + name + " " + node.getNodeName()); |
| if( name.equals( node.getNodeName() ) ) { |
| return getContent( node ); |
| } |
| } |
| return null; |
| } |
| |
| /** Get the first direct child with a given type |
| */ |
| public static Node getChild( Node parent, int type ) { |
| Node n=parent.getFirstChild(); |
| while( n!=null && type != n.getNodeType() ) { |
| n=n.getNextSibling(); |
| } |
| if( n==null ) return null; |
| return n; |
| } |
| |
| /** Get the next sibling with the same name and type |
| */ |
| public static Node getNext( Node current ) { |
| String name=current.getNodeName(); |
| int type=current.getNodeType(); |
| return getNext( current, name, type); |
| } |
| |
| /** Return the next sibling with a given name and type |
| */ |
| public static Node getNext( Node current, String name, int type) { |
| Node first=current.getNextSibling(); |
| if( first==null ) return null; |
| |
| for (Node node = first; node != null; |
| node = node.getNextSibling()) { |
| |
| if( type >= 0 && node.getNodeType() != type ) continue; |
| //System.out.println("getNode: " + name + " " + node.getNodeName()); |
| if( name==null ) |
| return node; |
| if( name.equals( node.getNodeName() ) ) { |
| return node; |
| } |
| } |
| return null; |
| } |
| |
| public static class NullResolver implements EntityResolver { |
| public InputSource resolveEntity (String publicId, |
| String systemId) |
| throws SAXException, IOException |
| { |
| if( log.isTraceEnabled()) |
| log.trace("ResolveEntity: " + publicId + " " + systemId); |
| return new InputSource(new StringReader("")); |
| } |
| } |
| |
| public static void setAttributes( Object o, Node parent) |
| { |
| NamedNodeMap attrs=parent.getAttributes(); |
| if( attrs==null ) return; |
| |
| for (int i=0; i<attrs.getLength(); i++ ) { |
| Node n=attrs.item(i); |
| String name=n.getNodeName(); |
| String value=n.getNodeValue(); |
| |
| if( log.isTraceEnabled() ) |
| log.trace("Attribute " + parent.getNodeName() + " " + |
| name + "=" + value); |
| try { |
| IntrospectionUtils.setProperty(o, name, value); |
| } catch( Exception ex ) { |
| ex.printStackTrace(); |
| } |
| } |
| } |
| |
| /** Read XML as DOM. |
| */ |
| public static Document readXml(InputStream is) |
| throws SAXException, IOException, ParserConfigurationException |
| { |
| DocumentBuilderFactory dbf = |
| DocumentBuilderFactory.newInstance(); |
| |
| dbf.setValidating(false); |
| dbf.setIgnoringComments(false); |
| dbf.setIgnoringElementContentWhitespace(true); |
| //dbf.setCoalescing(true); |
| //dbf.setExpandEntityReferences(true); |
| |
| DocumentBuilder db = null; |
| db = dbf.newDocumentBuilder(); |
| db.setEntityResolver( new NullResolver() ); |
| |
| // db.setErrorHandler( new MyErrorHandler()); |
| |
| Document doc = db.parse(is); |
| return doc; |
| } |
| |
| public static void writeXml( Node n, OutputStream os ) |
| throws TransformerException |
| { |
| TransformerFactory tf=TransformerFactory.newInstance(); |
| //identity |
| Transformer t=tf.newTransformer(); |
| t.setOutputProperty(OutputKeys.INDENT, "yes"); |
| t.transform(new DOMSource( n ), new StreamResult( os )); |
| } |
| } |