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