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