1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.myfaces.shared.webapp.webxml;
20
21 import java.io.IOException;
22 import java.io.InputStream;
23 import java.net.URL;
24 import java.util.logging.Level;
25 import java.util.logging.Logger;
26
27 import javax.faces.FacesException;
28 import javax.faces.context.ExternalContext;
29 import javax.xml.parsers.DocumentBuilder;
30 import javax.xml.parsers.DocumentBuilderFactory;
31
32 import org.apache.myfaces.shared.util.ClassUtils;
33 import org.apache.myfaces.shared.util.xml.MyFacesErrorHandler;
34 import org.apache.myfaces.shared.util.xml.XmlUtils;
35 import org.w3c.dom.Document;
36 import org.w3c.dom.Element;
37 import org.w3c.dom.Node;
38 import org.w3c.dom.NodeList;
39 import org.xml.sax.EntityResolver;
40 import org.xml.sax.InputSource;
41
42 public class WebXmlParser
43 {
44
45 private static final Logger log = Logger.getLogger(WebXmlParser.class.getName());
46
47
48
49
50
51
52
53
54 private static final String WEB_XML_PATH = "/WEB-INF/web.xml";
55
56 private static final String WEB_APP_2_2_J2EE_SYSTEM_ID = "http://java.sun.com/j2ee/dtds/web-app_2_2.dtd";
57 private static final String WEB_APP_2_2_SYSTEM_ID = "http://java.sun.com/dtd/web-app_2_2.dtd";
58 private static final String WEB_APP_2_2_RESOURCE = "javax/servlet/resources/web-app_2_2.dtd";
59
60 private static final String WEB_APP_2_3_SYSTEM_ID = "http://java.sun.com/dtd/web-app_2_3.dtd";
61 private static final String WEB_APP_2_3_RESOURCE = "javax/servlet/resources/web-app_2_3.dtd";
62
63 private ExternalContext _context;
64 private org.apache.myfaces.shared.webapp.webxml.WebXml _webXml;
65
66 public WebXmlParser(ExternalContext context)
67 {
68 _context = context;
69 }
70
71 public WebXml parse()
72 {
73 _webXml = new WebXml();
74
75 try
76 {
77 DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
78 dbf.setIgnoringElementContentWhitespace(true);
79 dbf.setIgnoringComments(true);
80 dbf.setNamespaceAware(true);
81 dbf.setValidating(false);
82
83
84 DocumentBuilder db = dbf.newDocumentBuilder();
85 db.setEntityResolver(new _EntityResolver());
86 db.setErrorHandler(new MyFacesErrorHandler(log));
87
88 InputSource is = createContextInputSource(null, WEB_XML_PATH);
89
90 if(is==null)
91 {
92 URL url = _context.getResource(WEB_XML_PATH);
93 log.fine("No web-xml found at : "+(url==null?" null ":url.toString()));
94 return _webXml;
95 }
96
97 Document document = db.parse(is);
98
99 Element webAppElem = document.getDocumentElement();
100 if (webAppElem == null ||
101 !webAppElem.getNodeName().equals("web-app"))
102 {
103 throw new FacesException("No valid web-app root element found!");
104 }
105
106 readWebApp(webAppElem);
107
108 return _webXml;
109 }
110 catch (Exception e)
111 {
112 log.log(Level.SEVERE, "Unable to parse web.xml", e);
113 throw new FacesException(e);
114 }
115 }
116
117 public static long getWebXmlLastModified(ExternalContext context)
118 {
119 try
120 {
121 URL url = context.getResource(WEB_XML_PATH);
122 if (url != null)
123 {
124 return url.openConnection().getLastModified();
125 }
126 }
127 catch (IOException e)
128 {
129 log.log(Level.SEVERE, "Could not find web.xml in path " + WEB_XML_PATH);
130 }
131 return 0L;
132 }
133
134
135 private InputSource createContextInputSource(String publicId, String systemId)
136 {
137 InputStream inStream = _context.getResourceAsStream(systemId);
138 if (inStream == null)
139 {
140
141 return null;
142 }
143 InputSource is = new InputSource(inStream);
144 is.setPublicId(publicId);
145 is.setSystemId(systemId);
146
147
148
149 return is;
150 }
151
152 private InputSource createClassloaderInputSource(String publicId, String systemId)
153 {
154 InputStream inStream = ClassUtils.getResourceAsStream(systemId);
155 if (inStream == null)
156 {
157
158 return null;
159 }
160 InputSource is = new InputSource(inStream);
161 is.setPublicId(publicId);
162 is.setSystemId(systemId);
163
164
165
166
167 return is;
168 }
169
170 private class _EntityResolver implements EntityResolver
171 {
172 public InputSource resolveEntity(String publicId, String systemId) throws IOException
173 {
174 if (systemId == null)
175 {
176 throw new UnsupportedOperationException("systemId must not be null");
177 }
178
179 if (systemId.equals(WebXmlParser.WEB_APP_2_2_SYSTEM_ID) ||
180 systemId.equals(WebXmlParser.WEB_APP_2_2_J2EE_SYSTEM_ID))
181 {
182
183 return createClassloaderInputSource(publicId, WebXmlParser.WEB_APP_2_2_RESOURCE);
184 }
185 else if (systemId.equals(WebXmlParser.WEB_APP_2_3_SYSTEM_ID))
186 {
187
188 return createClassloaderInputSource(publicId, WebXmlParser.WEB_APP_2_3_RESOURCE);
189 }
190 else
191 {
192
193 return createContextInputSource(publicId, systemId);
194 }
195 }
196
197 }
198
199
200 private void readWebApp(Element webAppElem)
201 {
202 NodeList nodeList = webAppElem.getChildNodes();
203 for (int i = 0, len = nodeList.getLength(); i < len; i++)
204 {
205 Node n = nodeList.item(i);
206 if (n.getNodeType() == Node.ELEMENT_NODE)
207 {
208 if (n.getNodeName().equals("servlet"))
209 {
210 readServlet((Element)n);
211 }
212 if (n.getNodeName().equals("servlet-mapping"))
213 {
214 readServletMapping((Element)n);
215 }
216 if (n.getNodeName().equals("filter"))
217 {
218 readFilter((Element)n);
219 }
220 if (n.getNodeName().equals("filter-mapping"))
221 {
222 readFilterMapping((Element)n);
223 }
224 if (n.getNodeName().equals("error-page"))
225 {
226 _webXml.setErrorPagePresent(true);
227 }
228 }
229 else
230 {
231 if (log.isLoggable(Level.FINE))
232 {
233 log.fine("Ignored node '" + n.getNodeName() + "' of type " + n.getNodeType());
234 }
235 }
236 }
237 }
238
239 private void readServlet(Element servletElem)
240 {
241 String servletName = null;
242 String servletClass = null;
243 NodeList nodeList = servletElem.getChildNodes();
244 for (int i = 0, len = nodeList.getLength(); i < len; i++)
245 {
246 Node n = nodeList.item(i);
247 if (n.getNodeType() == Node.ELEMENT_NODE)
248 {
249 if (n.getNodeName().equals("servlet-name"))
250 {
251 servletName = XmlUtils.getElementText((Element)n);
252 }
253 else if (n.getNodeName().equals("servlet-class"))
254 {
255 servletClass = org.apache.myfaces.shared.util.xml.XmlUtils.getElementText((Element)n).trim();
256 }
257 else if (n.getNodeName().equals("description") || n.getNodeName().equals("load-on-startup")
258 || n.getNodeName().equals("init-param"))
259 {
260
261 }
262 else
263 {
264 if (log.isLoggable(Level.FINE))
265 {
266 log.fine("Ignored element '" + n.getNodeName() + "' as child of '" +
267 servletElem.getNodeName() + "'.");
268 }
269 }
270 }
271 else
272 {
273 if (log.isLoggable(Level.FINE))
274 {
275 log.fine("Ignored node '" + n.getNodeName() + "' of type " + n.getNodeType());
276 }
277 }
278 }
279 _webXml.addServlet(servletName, servletClass);
280 }
281
282
283 private void readServletMapping(Element servletMappingElem)
284 {
285 String servletName = null;
286 String urlPattern = null;
287 NodeList nodeList = servletMappingElem.getChildNodes();
288 for (int i = 0, len = nodeList.getLength(); i < len; i++)
289 {
290 Node n = nodeList.item(i);
291 if (n.getNodeType() == Node.ELEMENT_NODE)
292 {
293 if (n.getNodeName().equals("servlet-name"))
294 {
295 servletName = org.apache.myfaces.shared.util.xml.XmlUtils.getElementText((Element)n);
296 }
297 else if (n.getNodeName().equals("url-pattern"))
298 {
299 urlPattern = org.apache.myfaces.shared.util.xml.XmlUtils.getElementText((Element)n).trim();
300 }
301 else
302 {
303 if (log.isLoggable(Level.FINE))
304 {
305 log.fine("Ignored element '" + n.getNodeName() + "' as child of '" +
306 servletMappingElem.getNodeName() + "'.");
307 }
308 }
309 }
310 else
311 {
312 if (log.isLoggable(Level.FINE))
313 {
314 log.fine("Ignored node '" + n.getNodeName() + "' of type " + n.getNodeType());
315 }
316 }
317 }
318 urlPattern = urlPattern.trim();
319 _webXml.addServletMapping(servletName, urlPattern);
320 }
321
322 private void readFilter(Element filterElem)
323 {
324 String filterName = null;
325 String filterClass = null;
326 NodeList nodeList = filterElem.getChildNodes();
327 for (int i = 0, len = nodeList.getLength(); i < len; i++)
328 {
329 Node n = nodeList.item(i);
330 if (n.getNodeType() == Node.ELEMENT_NODE)
331 {
332 if (n.getNodeName().equals("filter-name"))
333 {
334 filterName = XmlUtils.getElementText((Element)n).trim();
335 }
336 else if (n.getNodeName().equals("filter-class"))
337 {
338 filterClass = org.apache.myfaces.shared.util.xml.XmlUtils.getElementText((Element)n).trim();
339 }
340 else if (n.getNodeName().equals("description") || n.getNodeName().equals("init-param"))
341 {
342
343 }
344 else
345 {
346 if (log.isLoggable(Level.FINE))
347 {
348 log.fine("Ignored element '" + n.getNodeName() + "' as child of '" +
349 filterElem.getNodeName() + "'.");
350 }
351 }
352 }
353 else
354 {
355 if (log.isLoggable(Level.FINE))
356 {
357 log.fine("Ignored node '" + n.getNodeName() + "' of type " + n.getNodeType());
358 }
359 }
360 }
361 _webXml.addFilter(filterName, filterClass);
362 }
363
364
365 private void readFilterMapping(Element filterMappingElem)
366 {
367 String filterName = null;
368 String urlPattern = null;
369 NodeList nodeList = filterMappingElem.getChildNodes();
370 for (int i = 0, len = nodeList.getLength(); i < len; i++)
371 {
372 Node n = nodeList.item(i);
373 if (n.getNodeType() == Node.ELEMENT_NODE)
374 {
375 if (n.getNodeName().equals("filter-name"))
376 {
377 filterName = org.apache.myfaces.shared.util.xml.XmlUtils.getElementText((Element)n).trim();
378 }
379 else if (n.getNodeName().equals("url-pattern"))
380 {
381 urlPattern = org.apache.myfaces.shared.util.xml.XmlUtils.getElementText((Element)n).trim();
382 }
383 else if (n.getNodeName().equals("servlet-name"))
384 {
385
386 }
387 else
388 {
389 if (log.isLoggable(Level.FINE))
390 {
391 log.fine("Ignored element '" + n.getNodeName() + "' as child of '" +
392 filterMappingElem.getNodeName() + "'.");
393 }
394 }
395 }
396 else
397 {
398 if (log.isLoggable(Level.FINE))
399 {
400 log.fine("Ignored node '" + n.getNodeName() + "' of type " + n.getNodeType());
401 }
402 }
403 }
404 _webXml.addFilterMapping(filterName, urlPattern);
405 }
406 }