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 com.icesoft.jasper.xmlparser;
018:
019: import com.icesoft.jasper.JasperException;
020: import com.icesoft.jasper.compiler.Localizer;
021: import org.apache.commons.logging.Log;
022: import org.apache.commons.logging.LogFactory;
023: import org.w3c.dom.Comment;
024: import org.w3c.dom.Document;
025: import org.w3c.dom.NamedNodeMap;
026: import org.w3c.dom.Node;
027: import org.w3c.dom.NodeList;
028: import org.w3c.dom.Text;
029: import org.xml.sax.EntityResolver;
030: import org.xml.sax.ErrorHandler;
031: import org.xml.sax.SAXException;
032: import org.xml.sax.SAXParseException;
033:
034: import javax.xml.parsers.DocumentBuilder;
035: import javax.xml.parsers.DocumentBuilderFactory;
036: import javax.xml.parsers.ParserConfigurationException;
037: import java.io.IOException;
038: import java.io.InputStream;
039:
040: /**
041: * XML parsing utilities for processing web application deployment descriptor
042: * and tag library descriptor files. FIXME - make these use a separate class
043: * loader for the parser to be used.
044: *
045: * @author Craig R. McClanahan
046: * @version $Revision: 1.10 $ $Date: 2004/03/17 19:23:05 $
047: */
048:
049: public class ParserUtils {
050:
051: // Logger
052: static Log log = LogFactory.getLog(ParserUtils.class);
053:
054: /**
055: * An error handler for use when parsing XML documents.
056: */
057: static ErrorHandler errorHandler = new MyErrorHandler();
058:
059: /**
060: * An entity resolver for use when parsing XML documents.
061: */
062: public static EntityResolver entityResolver = new CachedEntityResolver();
063:
064: // Turn off for JSP 2.0 until switch over to using xschema.
065: public static boolean validating = false;
066:
067: // --------------------------------------------------------- Public Methods
068:
069: /**
070: * Parse the specified XML document, and return a <code>TreeNode</code> that
071: * corresponds to the root node of the document tree.
072: *
073: * @param uri URI of the XML document being parsed
074: * @param is Input stream containing the deployment descriptor
075: * @throws JasperException if an input/output error occurs
076: * @throws JasperException if a parsing error occurs
077: */
078: public TreeNode parseXMLDocument(String uri, InputStream is)
079: throws JasperException {
080:
081: Document document = null;
082:
083: // Perform an XML parse of this document, via JAXP
084: try {
085: DocumentBuilderFactory factory = DocumentBuilderFactory
086: .newInstance();
087: factory.setNamespaceAware(true);
088: factory.setValidating(validating);
089: DocumentBuilder builder = factory.newDocumentBuilder();
090: builder.setEntityResolver(entityResolver);
091: builder.setErrorHandler(errorHandler);
092: document = builder.parse(is);
093: } catch (ParserConfigurationException ex) {
094: throw new JasperException(Localizer.getMessage(
095: "jsp.error.parse.xml", uri), ex);
096: } catch (SAXParseException ex) {
097: throw new JasperException(Localizer.getMessage(
098: "jsp.error.parse.xml.line", uri, Integer
099: .toString(ex.getLineNumber()), Integer
100: .toString(ex.getColumnNumber())), ex);
101: } catch (SAXException sx) {
102: throw new JasperException(Localizer.getMessage(
103: "jsp.error.parse.xml", uri), sx);
104: } catch (IOException io) {
105: throw new JasperException(Localizer.getMessage(
106: "jsp.error.parse.xml", uri), io);
107: }
108:
109: // Convert the resulting document to a graph of TreeNodes
110: return (convert(null, document.getDocumentElement()));
111: }
112:
113: // ------------------------------------------------------ Protected Methods
114:
115: /**
116: * Create and return a TreeNode that corresponds to the specified Node,
117: * including processing all of the attributes and children nodes.
118: *
119: * @param parent The parent TreeNode (if any) for the new TreeNode
120: * @param node The XML document Node to be converted
121: */
122: protected TreeNode convert(TreeNode parent, Node node) {
123:
124: // Construct a new TreeNode for this node
125: TreeNode treeNode = new TreeNode(node.getNodeName(), parent);
126:
127: // Convert all attributes of this node
128: NamedNodeMap attributes = node.getAttributes();
129: if (attributes != null) {
130: int n = attributes.getLength();
131: for (int i = 0; i < n; i++) {
132: Node attribute = attributes.item(i);
133: treeNode.addAttribute(attribute.getNodeName(),
134: attribute.getNodeValue());
135: }
136: }
137:
138: // Create and attach all children of this node
139: NodeList children = node.getChildNodes();
140: if (children != null) {
141: int n = children.getLength();
142: for (int i = 0; i < n; i++) {
143: Node child = children.item(i);
144: if (child instanceof Comment)
145: continue;
146: if (child instanceof Text) {
147: String body = ((Text) child).getData();
148: if (body != null) {
149: body = body.trim();
150: if (body.length() > 0)
151: treeNode.setBody(body);
152: }
153: } else {
154: TreeNode treeChild = convert(treeNode, child);
155: }
156: }
157: }
158:
159: // Return the completed TreeNode graph
160: return (treeNode);
161: }
162: }
163:
164: // ------------------------------------------------------------ Private Classes
165:
166: /*
167: class MyEntityResolver implements EntityResolver {
168: public InputSource resolveEntity(String publicId, String systemId)
169: throws SAXException
170: {
171: for (int i=0; i<Constants.CACHED_DTD_PUBLIC_IDS.length; i++) {
172: String cachedDtdPublicId = Constants.CACHED_DTD_PUBLIC_IDS[i];
173: if (cachedDtdPublicId.equals(publicId)) {
174: String resourcePath = Constants.CACHED_DTD_RESOURCE_PATHS[i];
175: InputStream input =
176: this.getClass().getResourceAsStream(resourcePath);
177: if (input == null) {
178: throw new SAXException(
179: Localizer.getMessage("jsp.error.internal.filenotfound",
180: resourcePath));
181: }
182: InputSource isrc = new InputSource(input);
183: return isrc;
184: }
185: }
186: System.out.println("Resolve entity failed" + publicId + " "
187: + systemId );
188: ParserUtils.log.error(Localizer.getMessage("jsp.error.parse.xml.invalidPublicId",
189: publicId));
190: return null;
191: }
192: }
193: */
194:
195: class MyErrorHandler implements ErrorHandler {
196: public void warning(SAXParseException ex) throws SAXException {
197: System.out.println("ParserUtils: warning " + ex);
198: // We ignore warnings
199: }
200:
201: public void error(SAXParseException ex) throws SAXException {
202: throw ex;
203: }
204:
205: public void fatalError(SAXParseException ex) throws SAXException {
206: throw ex;
207: }
208: }
|