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
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.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 URL url = context.getResource(WEB_XML_PATH);
125 if (url != null)
126 return url.openConnection().getLastModified();
127 } catch (IOException e) {
128 log.log(Level.SEVERE, "Could not find web.xml in path " + WEB_XML_PATH);
129 }
130 return 0L;
131 }
132
133
134 private InputSource createContextInputSource(String publicId, String systemId)
135 {
136 InputStream inStream = _context.getResourceAsStream(systemId);
137 if (inStream == null)
138 {
139
140 return null;
141 }
142 InputSource is = new InputSource(inStream);
143 is.setPublicId(publicId);
144 is.setSystemId(systemId);
145
146
147
148 return is;
149 }
150
151 private InputSource createClassloaderInputSource(String publicId, String systemId)
152 {
153 InputStream inStream = ClassUtils.getResourceAsStream(systemId);
154 if (inStream == null)
155 {
156
157 return null;
158 }
159 InputSource is = new InputSource(inStream);
160 is.setPublicId(publicId);
161 is.setSystemId(systemId);
162
163
164
165
166 return is;
167 }
168
169 private class _EntityResolver implements EntityResolver
170 {
171 public InputSource resolveEntity(String publicId, String systemId) throws IOException
172 {
173 if (systemId == null)
174 {
175 throw new UnsupportedOperationException("systemId must not be null");
176 }
177
178 if (systemId.equals(WebXmlParser.WEB_APP_2_2_SYSTEM_ID) ||
179 systemId.equals(WebXmlParser.WEB_APP_2_2_J2EE_SYSTEM_ID))
180 {
181
182 return createClassloaderInputSource(publicId, WebXmlParser.WEB_APP_2_2_RESOURCE);
183 }
184 else if (systemId.equals(WebXmlParser.WEB_APP_2_3_SYSTEM_ID))
185 {
186
187 return createClassloaderInputSource(publicId, WebXmlParser.WEB_APP_2_3_RESOURCE);
188 }
189 else
190 {
191
192 return createContextInputSource(publicId, systemId);
193 }
194 }
195
196 }
197
198
199 private void readWebApp(Element webAppElem)
200 {
201 NodeList nodeList = webAppElem.getChildNodes();
202 for (int i = 0, len = nodeList.getLength(); i < len; i++)
203 {
204 Node n = nodeList.item(i);
205 if (n.getNodeType() == Node.ELEMENT_NODE)
206 {
207 if (n.getNodeName().equals("servlet"))
208 {
209 readServlet((Element)n);
210 }
211 if (n.getNodeName().equals("servlet-mapping"))
212 {
213 readServletMapping((Element)n);
214 }
215 if (n.getNodeName().equals("filter"))
216 {
217 readFilter((Element)n);
218 }
219 if (n.getNodeName().equals("filter-mapping"))
220 {
221 readFilterMapping((Element)n);
222 }
223 if (n.getNodeName().equals("error-page"))
224 {
225 _webXml.setErrorPagePresent(true);
226 }
227 }
228 else
229 {
230 if (log.isLoggable(Level.FINE)) log.fine("Ignored node '" + n.getNodeName() + "' of type " + n.getNodeType());
231 }
232 }
233 }
234
235 private void readServlet(Element servletElem)
236 {
237 String servletName = null;
238 String servletClass = null;
239 NodeList nodeList = servletElem.getChildNodes();
240 for (int i = 0, len = nodeList.getLength(); i < len; i++)
241 {
242 Node n = nodeList.item(i);
243 if (n.getNodeType() == Node.ELEMENT_NODE)
244 {
245 if (n.getNodeName().equals("servlet-name"))
246 {
247 servletName = XmlUtils.getElementText((Element)n);
248 }
249 else if (n.getNodeName().equals("servlet-class"))
250 {
251 servletClass = org.apache.myfaces.shared.util.xml.XmlUtils.getElementText((Element)n).trim();
252 }
253 else if (n.getNodeName().equals("description") || n.getNodeName().equals("load-on-startup") || n.getNodeName().equals("init-param"))
254 {
255
256 }
257 else
258 {
259 if (log.isLoggable(Level.FINE)) log.fine("Ignored element '" + n.getNodeName() + "' as child of '" + servletElem.getNodeName() + "'.");
260 }
261 }
262 else
263 {
264 if (log.isLoggable(Level.FINE)) log.fine("Ignored node '" + n.getNodeName() + "' of type " + n.getNodeType());
265 }
266 }
267 _webXml.addServlet(servletName, servletClass);
268 }
269
270
271 private void readServletMapping(Element servletMappingElem)
272 {
273 String servletName = null;
274 String urlPattern = null;
275 NodeList nodeList = servletMappingElem.getChildNodes();
276 for (int i = 0, len = nodeList.getLength(); i < len; i++)
277 {
278 Node n = nodeList.item(i);
279 if (n.getNodeType() == Node.ELEMENT_NODE)
280 {
281 if (n.getNodeName().equals("servlet-name"))
282 {
283 servletName = org.apache.myfaces.shared.util.xml.XmlUtils.getElementText((Element)n);
284 }
285 else if (n.getNodeName().equals("url-pattern"))
286 {
287 urlPattern = org.apache.myfaces.shared.util.xml.XmlUtils.getElementText((Element)n).trim();
288 }
289 else
290 {
291 if (log.isLoggable(Level.FINE)) log.fine("Ignored element '" + n.getNodeName() + "' as child of '" + servletMappingElem.getNodeName() + "'.");
292 }
293 }
294 else
295 {
296 if (log.isLoggable(Level.FINE)) log.fine("Ignored node '" + n.getNodeName() + "' of type " + n.getNodeType());
297 }
298 }
299 urlPattern = urlPattern.trim();
300 _webXml.addServletMapping(servletName, urlPattern);
301 }
302
303 private void readFilter(Element filterElem)
304 {
305 String filterName = null;
306 String filterClass = null;
307 NodeList nodeList = filterElem.getChildNodes();
308 for (int i = 0, len = nodeList.getLength(); i < len; i++)
309 {
310 Node n = nodeList.item(i);
311 if (n.getNodeType() == Node.ELEMENT_NODE)
312 {
313 if (n.getNodeName().equals("filter-name"))
314 {
315 filterName = XmlUtils.getElementText((Element)n).trim();
316 }
317 else if (n.getNodeName().equals("filter-class"))
318 {
319 filterClass = org.apache.myfaces.shared.util.xml.XmlUtils.getElementText((Element)n).trim();
320 }
321 else if (n.getNodeName().equals("description") || n.getNodeName().equals("init-param"))
322 {
323
324 }
325 else
326 {
327 if (log.isLoggable(Level.FINE)) log.fine("Ignored element '" + n.getNodeName() + "' as child of '" + filterElem.getNodeName() + "'.");
328 }
329 }
330 else
331 {
332 if (log.isLoggable(Level.FINE)) log.fine("Ignored node '" + n.getNodeName() + "' of type " + n.getNodeType());
333 }
334 }
335 _webXml.addFilter(filterName, filterClass);
336 }
337
338
339 private void readFilterMapping(Element filterMappingElem)
340 {
341 String filterName = null;
342 String urlPattern = null;
343 NodeList nodeList = filterMappingElem.getChildNodes();
344 for (int i = 0, len = nodeList.getLength(); i < len; i++)
345 {
346 Node n = nodeList.item(i);
347 if (n.getNodeType() == Node.ELEMENT_NODE)
348 {
349 if (n.getNodeName().equals("filter-name"))
350 {
351 filterName = org.apache.myfaces.shared.util.xml.XmlUtils.getElementText((Element)n).trim();
352 }
353 else if (n.getNodeName().equals("url-pattern"))
354 {
355 urlPattern = org.apache.myfaces.shared.util.xml.XmlUtils.getElementText((Element)n).trim();
356 }
357 else if (n.getNodeName().equals("servlet-name"))
358 {
359
360 }
361 else
362 {
363 if (log.isLoggable(Level.FINE)) log.fine("Ignored element '" + n.getNodeName() + "' as child of '" + filterMappingElem.getNodeName() + "'.");
364 }
365 }
366 else
367 {
368 if (log.isLoggable(Level.FINE)) log.fine("Ignored node '" + n.getNodeName() + "' of type " + n.getNodeType());
369 }
370 }
371 _webXml.addFilterMapping(filterName, urlPattern);
372 }
373 }