1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.struts2.jasper.xmlparser;
19
20 import com.opensymphony.xwork2.util.logging.LoggerFactory;
21 import org.apache.struts2.jasper.Constants;
22 import org.apache.struts2.jasper.JasperException;
23 import org.apache.struts2.jasper.compiler.Localizer;
24 import org.w3c.dom.*;
25 import org.xml.sax.*;
26
27 import javax.xml.parsers.DocumentBuilder;
28 import javax.xml.parsers.DocumentBuilderFactory;
29 import javax.xml.parsers.ParserConfigurationException;
30 import java.io.IOException;
31 import java.io.InputStream;
32
33
34 /***
35 * XML parsing utilities for processing web application deployment
36 * descriptor and tag library descriptor files. FIXME - make these
37 * use a separate class loader for the parser to be used.
38 *
39 * @author Craig R. McClanahan
40 * @version $Revision: 609409 $ $Date: 2008-01-06 14:31:23 -0700 (Sun, 06 Jan 2008) $
41 */
42
43 public class ParserUtils {
44
45 /***
46 * An error handler for use when parsing XML documents.
47 */
48 static ErrorHandler errorHandler = new MyErrorHandler();
49
50 /***
51 * An entity resolver for use when parsing XML documents.
52 */
53 static EntityResolver entityResolver = new MyEntityResolver();
54
55
56 public static boolean validating = false;
57
58
59
60
61 /***
62 * Parse the specified XML document, and return a <code>TreeNode</code>
63 * that corresponds to the root node of the document tree.
64 *
65 * @param uri URI of the XML document being parsed
66 * @param is Input source containing the deployment descriptor
67 * @throws JasperException if an input/output error occurs
68 * @throws JasperException if a parsing error occurs
69 */
70 public TreeNode parseXMLDocument(String uri, InputSource is)
71 throws JasperException {
72
73 Document document = null;
74
75
76 try {
77 DocumentBuilderFactory factory =
78 DocumentBuilderFactory.newInstance();
79 factory.setNamespaceAware(true);
80 factory.setValidating(validating);
81 DocumentBuilder builder = factory.newDocumentBuilder();
82 builder.setEntityResolver(entityResolver);
83 builder.setErrorHandler(errorHandler);
84 document = builder.parse(is);
85 } catch (ParserConfigurationException ex) {
86 throw new JasperException
87 (Localizer.getMessage("jsp.error.parse.xml", uri), ex);
88 } catch (SAXParseException ex) {
89 throw new JasperException
90 (Localizer.getMessage("jsp.error.parse.xml.line",
91 uri,
92 Integer.toString(ex.getLineNumber()),
93 Integer.toString(ex.getColumnNumber())),
94 ex);
95 } catch (SAXException sx) {
96 throw new JasperException
97 (Localizer.getMessage("jsp.error.parse.xml", uri), sx);
98 } catch (IOException io) {
99 throw new JasperException
100 (Localizer.getMessage("jsp.error.parse.xml", uri), io);
101 }
102
103
104 return (convert(null, document.getDocumentElement()));
105 }
106
107
108 /***
109 * Parse the specified XML document, and return a <code>TreeNode</code>
110 * that corresponds to the root node of the document tree.
111 *
112 * @param uri URI of the XML document being parsed
113 * @param is Input stream containing the deployment descriptor
114 * @throws JasperException if an input/output error occurs
115 * @throws JasperException if a parsing error occurs
116 */
117 public TreeNode parseXMLDocument(String uri, InputStream is)
118 throws JasperException {
119
120 return (parseXMLDocument(uri, new InputSource(is)));
121 }
122
123
124
125
126
127 /***
128 * Create and return a TreeNode that corresponds to the specified Node,
129 * including processing all of the attributes and children nodes.
130 *
131 * @param parent The parent TreeNode (if any) for the new TreeNode
132 * @param node The XML document Node to be converted
133 */
134 protected TreeNode convert(TreeNode parent, Node node) {
135
136
137 TreeNode treeNode = new TreeNode(node.getNodeName(), parent);
138
139
140 NamedNodeMap attributes = node.getAttributes();
141 if (attributes != null) {
142 int n = attributes.getLength();
143 for (int i = 0; i < n; i++) {
144 Node attribute = attributes.item(i);
145 treeNode.addAttribute(attribute.getNodeName(),
146 attribute.getNodeValue());
147 }
148 }
149
150
151 NodeList children = node.getChildNodes();
152 if (children != null) {
153 int n = children.getLength();
154 for (int i = 0; i < n; i++) {
155 Node child = children.item(i);
156 if (child instanceof Comment)
157 continue;
158 if (child instanceof Text) {
159 String body = ((Text) child).getData();
160 if (body != null) {
161 body = body.trim();
162 if (body.length() > 0)
163 treeNode.setBody(body);
164 }
165 } else {
166 TreeNode treeChild = convert(treeNode, child);
167 }
168 }
169 }
170
171
172 return (treeNode);
173 }
174 }
175
176
177
178
179 class MyEntityResolver implements EntityResolver {
180
181 public InputSource resolveEntity(String publicId, String systemId)
182 throws SAXException {
183 for (int i = 0; i < Constants.CACHED_DTD_PUBLIC_IDS.length; i++) {
184 String cachedDtdPublicId = Constants.CACHED_DTD_PUBLIC_IDS[i];
185 if (cachedDtdPublicId.equals(publicId)) {
186 String resourcePath = Constants.CACHED_DTD_RESOURCE_PATHS[i];
187 InputStream input = this.getClass().getResourceAsStream(
188 resourcePath);
189 if (input == null) {
190 throw new SAXException(Localizer.getMessage(
191 "jsp.error.internal.filenotfound", resourcePath));
192 }
193 InputSource isrc = new InputSource(input);
194 return isrc;
195 }
196 }
197 com.opensymphony.xwork2.util.logging.Logger log = LoggerFactory.getLogger(MyEntityResolver.class);
198 if (log.isDebugEnabled())
199 log.debug("Resolve entity failed" + publicId + " " + systemId);
200 log.error(Localizer.getMessage("jsp.error.parse.xml.invalidPublicId",
201 publicId));
202 return null;
203 }
204 }
205
206 class MyErrorHandler implements ErrorHandler {
207
208 public void warning(SAXParseException ex) throws SAXException {
209 com.opensymphony.xwork2.util.logging.Logger log = LoggerFactory.getLogger(MyErrorHandler.class);
210 if (log.isDebugEnabled())
211 log.debug("ParserUtils: warning ", ex);
212
213 }
214
215 public void error(SAXParseException ex) throws SAXException {
216 throw ex;
217 }
218
219 public void fatalError(SAXParseException ex) throws SAXException {
220 throw ex;
221 }
222 }