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.tomcat.util;
018:
019: import java.io.IOException;
020: import java.io.InputStream;
021: import java.io.OutputStream;
022: import java.io.StringReader;
023:
024: import javax.xml.parsers.DocumentBuilder;
025: import javax.xml.parsers.DocumentBuilderFactory;
026: import javax.xml.parsers.ParserConfigurationException;
027: import javax.xml.transform.OutputKeys;
028: import javax.xml.transform.Transformer;
029: import javax.xml.transform.TransformerException;
030: import javax.xml.transform.TransformerFactory;
031: import javax.xml.transform.dom.DOMSource;
032: import javax.xml.transform.stream.StreamResult;
033:
034: import org.w3c.dom.Document;
035: import org.w3c.dom.NamedNodeMap;
036: import org.w3c.dom.Node;
037: import org.xml.sax.EntityResolver;
038: import org.xml.sax.InputSource;
039: import org.xml.sax.SAXException;
040:
041: /**
042: * Few simple utils to read DOM
043: *
044: * @author Costin Manolache
045: */
046: public class DomUtil {
047: private static org.apache.juli.logging.Log log = org.apache.juli.logging.LogFactory
048: .getLog(DomUtil.class);
049:
050: // -------------------- DOM utils --------------------
051:
052: /** Get the trimed text content of a node or null if there is no text
053: */
054: public static String getContent(Node n) {
055: if (n == null)
056: return null;
057: Node n1 = DomUtil.getChild(n, Node.TEXT_NODE);
058:
059: if (n1 == null)
060: return null;
061:
062: String s1 = n1.getNodeValue();
063: return s1.trim();
064: }
065:
066: /** Get the first element child.
067: * @param parent lookup direct childs
068: * @param name name of the element. If null return the first element.
069: */
070: public static Node getChild(Node parent, String name) {
071: if (parent == null)
072: return null;
073: Node first = parent.getFirstChild();
074: if (first == null)
075: return null;
076:
077: for (Node node = first; node != null; node = node
078: .getNextSibling()) {
079: //System.out.println("getNode: " + name + " " + node.getNodeName());
080: if (node.getNodeType() != Node.ELEMENT_NODE)
081: continue;
082: if (name != null && name.equals(node.getNodeName())) {
083: return node;
084: }
085: if (name == null) {
086: return node;
087: }
088: }
089: return null;
090: }
091:
092: public static String getAttribute(Node element, String attName) {
093: NamedNodeMap attrs = element.getAttributes();
094: if (attrs == null)
095: return null;
096: Node attN = attrs.getNamedItem(attName);
097: if (attN == null)
098: return null;
099: return attN.getNodeValue();
100: }
101:
102: public static void setAttribute(Node node, String attName,
103: String val) {
104: NamedNodeMap attributes = node.getAttributes();
105: Node attNode = node.getOwnerDocument().createAttribute(attName);
106: attNode.setNodeValue(val);
107: attributes.setNamedItem(attNode);
108: }
109:
110: public static void removeAttribute(Node node, String attName) {
111: NamedNodeMap attributes = node.getAttributes();
112: attributes.removeNamedItem(attName);
113: }
114:
115: /** Set or replace the text value
116: */
117: public static void setText(Node node, String val) {
118: Node chld = DomUtil.getChild(node, Node.TEXT_NODE);
119: if (chld == null) {
120: Node textN = node.getOwnerDocument().createTextNode(val);
121: node.appendChild(textN);
122: return;
123: }
124: // change the value
125: chld.setNodeValue(val);
126: }
127:
128: /** Find the first direct child with a given attribute.
129: * @param parent
130: * @param elemName name of the element, or null for any
131: * @param attName attribute we're looking for
132: * @param attVal attribute value or null if we just want any
133: */
134: public static Node findChildWithAtt(Node parent, String elemName,
135: String attName, String attVal) {
136:
137: Node child = DomUtil.getChild(parent, Node.ELEMENT_NODE);
138: if (attVal == null) {
139: while (child != null
140: && (elemName == null || elemName.equals(child
141: .getNodeName()))
142: && DomUtil.getAttribute(child, attName) != null) {
143: child = getNext(child, elemName, Node.ELEMENT_NODE);
144: }
145: } else {
146: while (child != null
147: && (elemName == null || elemName.equals(child
148: .getNodeName()))
149: && !attVal.equals(DomUtil.getAttribute(child,
150: attName))) {
151: child = getNext(child, elemName, Node.ELEMENT_NODE);
152: }
153: }
154: return child;
155: }
156:
157: /** Get the first child's content ( ie it's included TEXT node ).
158: */
159: public static String getChildContent(Node parent, String name) {
160: Node first = parent.getFirstChild();
161: if (first == null)
162: return null;
163: for (Node node = first; node != null; node = node
164: .getNextSibling()) {
165: //System.out.println("getNode: " + name + " " + node.getNodeName());
166: if (name.equals(node.getNodeName())) {
167: return getContent(node);
168: }
169: }
170: return null;
171: }
172:
173: /** Get the first direct child with a given type
174: */
175: public static Node getChild(Node parent, int type) {
176: Node n = parent.getFirstChild();
177: while (n != null && type != n.getNodeType()) {
178: n = n.getNextSibling();
179: }
180: if (n == null)
181: return null;
182: return n;
183: }
184:
185: /** Get the next sibling with the same name and type
186: */
187: public static Node getNext(Node current) {
188: String name = current.getNodeName();
189: int type = current.getNodeType();
190: return getNext(current, name, type);
191: }
192:
193: /** Return the next sibling with a given name and type
194: */
195: public static Node getNext(Node current, String name, int type) {
196: Node first = current.getNextSibling();
197: if (first == null)
198: return null;
199:
200: for (Node node = first; node != null; node = node
201: .getNextSibling()) {
202:
203: if (type >= 0 && node.getNodeType() != type)
204: continue;
205: //System.out.println("getNode: " + name + " " + node.getNodeName());
206: if (name == null)
207: return node;
208: if (name.equals(node.getNodeName())) {
209: return node;
210: }
211: }
212: return null;
213: }
214:
215: public static class NullResolver implements EntityResolver {
216: public InputSource resolveEntity(String publicId,
217: String systemId) throws SAXException, IOException {
218: if (log.isTraceEnabled())
219: log
220: .trace("ResolveEntity: " + publicId + " "
221: + systemId);
222: return new InputSource(new StringReader(""));
223: }
224: }
225:
226: public static void setAttributes(Object o, Node parent) {
227: NamedNodeMap attrs = parent.getAttributes();
228: if (attrs == null)
229: return;
230:
231: for (int i = 0; i < attrs.getLength(); i++) {
232: Node n = attrs.item(i);
233: String name = n.getNodeName();
234: String value = n.getNodeValue();
235:
236: if (log.isTraceEnabled())
237: log.trace("Attribute " + parent.getNodeName() + " "
238: + name + "=" + value);
239: try {
240: IntrospectionUtils.setProperty(o, name, value);
241: } catch (Exception ex) {
242: ex.printStackTrace();
243: }
244: }
245: }
246:
247: /** Read XML as DOM.
248: */
249: public static Document readXml(InputStream is) throws SAXException,
250: IOException, ParserConfigurationException {
251: DocumentBuilderFactory dbf = DocumentBuilderFactory
252: .newInstance();
253:
254: dbf.setValidating(false);
255: dbf.setIgnoringComments(false);
256: dbf.setIgnoringElementContentWhitespace(true);
257: //dbf.setCoalescing(true);
258: //dbf.setExpandEntityReferences(true);
259:
260: DocumentBuilder db = null;
261: db = dbf.newDocumentBuilder();
262: db.setEntityResolver(new NullResolver());
263:
264: // db.setErrorHandler( new MyErrorHandler());
265:
266: Document doc = db.parse(is);
267: return doc;
268: }
269:
270: public static void writeXml(Node n, OutputStream os)
271: throws TransformerException {
272: TransformerFactory tf = TransformerFactory.newInstance();
273: //identity
274: Transformer t = tf.newTransformer();
275: t.setOutputProperty(OutputKeys.INDENT, "yes");
276: t.transform(new DOMSource(n), new StreamResult(os));
277: }
278: }
|