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