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