001: /*
002: * Copyright 1999,2004 The Apache Software Foundation.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016:
017: package org.araneaframework.http.support;
018:
019: import java.io.IOException;
020: import java.io.InputStream;
021: import javax.xml.parsers.DocumentBuilder;
022: import javax.xml.parsers.DocumentBuilderFactory;
023: import javax.xml.parsers.ParserConfigurationException;
024: import org.apache.commons.logging.Log;
025: import org.apache.commons.logging.LogFactory;
026: import org.araneaframework.core.AraneaRuntimeException;
027: import org.w3c.dom.Comment;
028: import org.w3c.dom.Document;
029: import org.w3c.dom.NamedNodeMap;
030: import org.w3c.dom.Node;
031: import org.w3c.dom.NodeList;
032: import org.w3c.dom.Text;
033: import org.xml.sax.EntityResolver;
034: import org.xml.sax.ErrorHandler;
035: import org.xml.sax.InputSource;
036: import org.xml.sax.SAXException;
037: import org.xml.sax.SAXParseException;
038:
039: /**
040: * XML parsing utilities for processing web application deployment
041: * descriptor and tag library descriptor files. FIXME - make these
042: * use a separate class loader for the parser to be used.
043: *
044: * @author Craig R. McClanahan
045: * @version $Revision$ $Date$
046: */
047:
048: public class ParserUtils {
049:
050: /**
051: * An error handler for use when parsing XML documents.
052: */
053: static ErrorHandler errorHandler = new MyErrorHandler();
054:
055: /**
056: * An entity resolver for use when parsing XML documents.
057: */
058: static EntityResolver entityResolver = CachingEntityResolver
059: .getInstance();
060:
061: // Turn off for JSP 2.0 until switch over to using xschema.
062: public static boolean validating = false;
063:
064: // --------------------------------------------------------- Public Methods
065:
066: /**
067: * Parse the specified XML document, and return a <code>TreeNode</code>
068: * that corresponds to the root node of the document tree.
069: *
070: * @param uri URI of the XML document being parsed
071: * @param is Input source containing the deployment descriptor
072: *
073: * @exception AraneaRuntimeException if an input/output error occurs
074: * @exception AraneaRuntimeException if a parsing error occurs
075: */
076: public TreeNode parseXMLDocument(String uri, InputSource is)
077: throws AraneaRuntimeException {
078:
079: Document document = null;
080:
081: // Perform an XML parse of this document, via JAXP
082: try {
083: DocumentBuilderFactory factory = DocumentBuilderFactory
084: .newInstance();
085: factory.setNamespaceAware(true);
086: factory.setValidating(validating);
087: DocumentBuilder builder = factory.newDocumentBuilder();
088: builder.setEntityResolver(entityResolver);
089: builder.setErrorHandler(errorHandler);
090: document = builder.parse(is);
091: } catch (ParserConfigurationException ex) {
092: throw new AraneaRuntimeException("jsp.error.parse.xml", ex);
093: } catch (SAXParseException ex) {
094: throw new AraneaRuntimeException(
095: "jsp.error.parse.xml.line", ex);
096: } catch (SAXException sx) {
097: throw new AraneaRuntimeException("jsp.error.parse.xml", sx);
098: } catch (IOException io) {
099: throw new AraneaRuntimeException("jsp.error.parse.xml", io);
100: }
101:
102: // Convert the resulting document to a graph of TreeNodes
103: return (convert(null, document.getDocumentElement()));
104: }
105:
106: /**
107: * Parse the specified XML document, and return a <code>TreeNode</code>
108: * that corresponds to the root node of the document tree.
109: *
110: * @param uri URI of the XML document being parsed
111: * @param is Input stream containing the deployment descriptor
112: *
113: * @exception AraneaRuntimeException if an input/output error occurs
114: * @exception AraneaRuntimeException if a parsing error occurs
115: */
116: public TreeNode parseXMLDocument(String uri, InputStream is)
117: throws AraneaRuntimeException {
118:
119: return (parseXMLDocument(uri, new InputSource(is)));
120: }
121:
122: // ------------------------------------------------------ Protected Methods
123:
124: /**
125: * Create and return a TreeNode that corresponds to the specified Node,
126: * including processing all of the attributes and children nodes.
127: *
128: * @param parent The parent TreeNode (if any) for the new TreeNode
129: * @param node The XML document Node to be converted
130: */
131: protected TreeNode convert(TreeNode parent, Node node) {
132:
133: // Construct a new TreeNode for this node
134: TreeNode treeNode = new TreeNode(node.getNodeName(), parent);
135:
136: // Convert all attributes of this node
137: NamedNodeMap attributes = node.getAttributes();
138: if (attributes != null) {
139: int n = attributes.getLength();
140: for (int i = 0; i < n; i++) {
141: Node attribute = attributes.item(i);
142: treeNode.addAttribute(attribute.getNodeName(),
143: attribute.getNodeValue());
144: }
145: }
146:
147: // Create and attach all children of this node
148: NodeList children = node.getChildNodes();
149: if (children != null) {
150: int n = children.getLength();
151: for (int i = 0; i < n; i++) {
152: Node child = children.item(i);
153: if (child instanceof Comment)
154: continue;
155: if (child instanceof Text) {
156: String body = ((Text) child).getData();
157: if (body != null) {
158: body = body.trim();
159: if (body.length() > 0)
160: treeNode.setBody(body);
161: }
162: } else {
163: TreeNode treeChild = convert(treeNode, child);
164: }
165: }
166: }
167:
168: // Return the completed TreeNode graph
169: return (treeNode);
170: }
171: }
172:
173: // ------------------------------------------------------------ Private Classes
174:
175: class MyErrorHandler implements ErrorHandler {
176:
177: // Logger
178: private static final Log log = LogFactory
179: .getLog(MyErrorHandler.class);
180:
181: public void warning(SAXParseException ex) throws SAXException {
182: if (log.isDebugEnabled())
183: log.debug("ParserUtils: warning ", ex);
184: // We ignore warnings
185: }
186:
187: public void error(SAXParseException ex) throws SAXException {
188: throw ex;
189: }
190:
191: public void fatalError(SAXParseException ex) throws SAXException {
192: throw ex;
193: }
194: }
|