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