001: /*
002: * Copyright 2004 The Apache Software Foundation.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016: package org.apache.myfaces.shared_impl.webapp.webxml;
017:
018: import java.io.IOException;
019: import java.io.InputStream;
020: import java.net.URL;
021:
022: import javax.faces.FacesException;
023: import javax.faces.context.ExternalContext;
024: import javax.xml.parsers.DocumentBuilder;
025: import javax.xml.parsers.DocumentBuilderFactory;
026:
027: import org.apache.commons.logging.Log;
028: import org.apache.commons.logging.LogFactory;
029: import org.apache.myfaces.shared_impl.util.xml.MyFacesErrorHandler;
030: import org.apache.myfaces.shared_impl.util.xml.XmlUtils;
031: import org.w3c.dom.Document;
032: import org.w3c.dom.Element;
033: import org.w3c.dom.Node;
034: import org.w3c.dom.NodeList;
035: import org.xml.sax.EntityResolver;
036: import org.xml.sax.InputSource;
037:
038: /**
039: * @author Manfred Geiler (latest modification by $Author: dennisbyrne $)
040: * @version $Revision: 522834 $ $Date: 2007-03-27 11:26:40 +0200 (Di, 27 Mrz 2007) $
041: */
042: public class WebXmlParser {
043: private static final Log log = LogFactory
044: .getLog(WebXmlParser.class);
045:
046: /*
047: private static final String JAXP_SCHEMA_LANGUAGE =
048: "http://java.sun.com/xml/jaxp/properties/schemaLanguage";
049: private static final String W3C_XML_SCHEMA =
050: "http://www.w3.org/2001/XMLSchema";
051: */
052:
053: private static final String WEB_XML_PATH = "/WEB-INF/web.xml";
054:
055: private static final String WEB_APP_2_2_J2EE_SYSTEM_ID = "http://java.sun.com/j2ee/dtds/web-app_2_2.dtd";
056: private static final String WEB_APP_2_2_SYSTEM_ID = "http://java.sun.com/dtd/web-app_2_2.dtd";
057: private static final String WEB_APP_2_2_RESOURCE = "javax/servlet/resources/web-app_2_2.dtd";
058:
059: private static final String WEB_APP_2_3_SYSTEM_ID = "http://java.sun.com/dtd/web-app_2_3.dtd";
060: private static final String WEB_APP_2_3_RESOURCE = "javax/servlet/resources/web-app_2_3.dtd";
061:
062: private ExternalContext _context;
063: private org.apache.myfaces.shared_impl.webapp.webxml.WebXml _webXml;
064:
065: public WebXmlParser(ExternalContext context) {
066: _context = context;
067: }
068:
069: public WebXml parse() {
070: _webXml = new WebXml();
071:
072: try {
073: DocumentBuilderFactory dbf = DocumentBuilderFactory
074: .newInstance();
075: dbf.setIgnoringElementContentWhitespace(true);
076: dbf.setIgnoringComments(true);
077: dbf.setNamespaceAware(true);
078: dbf.setValidating(false);
079: // dbf.setAttribute(JAXP_SCHEMA_LANGUAGE, W3C_XML_SCHEMA);
080:
081: DocumentBuilder db = dbf.newDocumentBuilder();
082: db.setEntityResolver(new _EntityResolver());
083: db.setErrorHandler(new MyFacesErrorHandler(log));
084:
085: InputSource is = createContextInputSource(null,
086: WEB_XML_PATH);
087:
088: if (is == null) {
089: URL url = _context.getResource(WEB_XML_PATH);
090: log.debug("No web-xml found at : "
091: + (url == null ? " null " : url.toString()));
092: return _webXml;
093: }
094:
095: Document document = db.parse(is);
096:
097: Element webAppElem = document.getDocumentElement();
098: if (webAppElem == null
099: || !webAppElem.getNodeName().equals("web-app")) {
100: throw new FacesException(
101: "No valid web-app root element found!");
102: }
103:
104: readWebApp(webAppElem);
105:
106: return _webXml;
107: } catch (Exception e) {
108: log.fatal("Unable to parse web.xml", e);
109: throw new FacesException(e);
110: }
111: }
112:
113: private InputSource createContextInputSource(String publicId,
114: String systemId) {
115: InputStream inStream = _context.getResourceAsStream(systemId);
116: if (inStream == null) {
117: // there is no such entity
118: return null;
119: }
120: InputSource is = new InputSource(inStream);
121: is.setPublicId(publicId);
122: is.setSystemId(systemId);
123: //the next line was removed - encoding should be determined automatically out of the inputStream
124: //DEFAULT_ENCODING was ISO-8859-1
125: //is.setEncoding(DEFAULT_ENCODING);
126: return is;
127: }
128:
129: private InputSource createClassloaderInputSource(String publicId,
130: String systemId) {
131: InputStream inStream = Thread.currentThread()
132: .getContextClassLoader().getResourceAsStream(systemId);
133: if (inStream == null) {
134: // there is no such entity
135: return null;
136: }
137: InputSource is = new InputSource(inStream);
138: is.setPublicId(publicId);
139: is.setSystemId(systemId);
140: //the next line was removed - encoding should be determined automatically out of the inputStream
141: //encoding should be determined automatically out of the inputStream
142: //DEFAULT_ENCODING was ISO-8859-1
143: //is.setEncoding(DEFAULT_ENCODING);
144: return is;
145: }
146:
147: private class _EntityResolver implements EntityResolver {
148: public InputSource resolveEntity(String publicId,
149: String systemId) throws IOException {
150: if (systemId == null) {
151: throw new UnsupportedOperationException(
152: "systemId must not be null");
153: }
154:
155: if (systemId.equals(WebXmlParser.WEB_APP_2_2_SYSTEM_ID)
156: || systemId
157: .equals(WebXmlParser.WEB_APP_2_2_J2EE_SYSTEM_ID)) {
158: //Load DTD from servlet.jar
159: return createClassloaderInputSource(publicId,
160: WebXmlParser.WEB_APP_2_2_RESOURCE);
161: } else if (systemId
162: .equals(WebXmlParser.WEB_APP_2_3_SYSTEM_ID)) {
163: //Load DTD from servlet.jar
164: return createClassloaderInputSource(publicId,
165: WebXmlParser.WEB_APP_2_3_RESOURCE);
166: } else {
167: //Load additional entities from web context
168: return createContextInputSource(publicId, systemId);
169: }
170: }
171:
172: }
173:
174: private void readWebApp(Element webAppElem) {
175: NodeList nodeList = webAppElem.getChildNodes();
176: for (int i = 0, len = nodeList.getLength(); i < len; i++) {
177: Node n = nodeList.item(i);
178: if (n.getNodeType() == Node.ELEMENT_NODE) {
179: if (n.getNodeName().equals("servlet")) {
180: readServlet((Element) n);
181: }
182: if (n.getNodeName().equals("servlet-mapping")) {
183: readServletMapping((Element) n);
184: }
185: if (n.getNodeName().equals("filter")) {
186: readFilter((Element) n);
187: }
188: if (n.getNodeName().equals("filter-mapping")) {
189: readFilterMapping((Element) n);
190: }
191: } else {
192: if (log.isDebugEnabled())
193: log.debug("Ignored node '" + n.getNodeName()
194: + "' of type " + n.getNodeType());
195: }
196: }
197: }
198:
199: private void readServlet(Element servletElem) {
200: String servletName = null;
201: String servletClass = null;
202: NodeList nodeList = servletElem.getChildNodes();
203: for (int i = 0, len = nodeList.getLength(); i < len; i++) {
204: Node n = nodeList.item(i);
205: if (n.getNodeType() == Node.ELEMENT_NODE) {
206: if (n.getNodeName().equals("servlet-name")) {
207: servletName = XmlUtils.getElementText((Element) n);
208: } else if (n.getNodeName().equals("servlet-class")) {
209: servletClass = org.apache.myfaces.shared_impl.util.xml.XmlUtils
210: .getElementText((Element) n).trim();
211: } else if (n.getNodeName().equals("description")
212: || n.getNodeName().equals("load-on-startup")
213: || n.getNodeName().equals("init-param")) {
214: //ignore
215: } else {
216: if (log.isDebugEnabled())
217: log.debug("Ignored element '" + n.getNodeName()
218: + "' as child of '"
219: + servletElem.getNodeName() + "'.");
220: }
221: } else {
222: if (log.isDebugEnabled())
223: log.debug("Ignored node '" + n.getNodeName()
224: + "' of type " + n.getNodeType());
225: }
226: }
227: _webXml.addServlet(servletName, servletClass);
228: }
229:
230: private void readServletMapping(Element servletMappingElem) {
231: String servletName = null;
232: String urlPattern = null;
233: NodeList nodeList = servletMappingElem.getChildNodes();
234: for (int i = 0, len = nodeList.getLength(); i < len; i++) {
235: Node n = nodeList.item(i);
236: if (n.getNodeType() == Node.ELEMENT_NODE) {
237: if (n.getNodeName().equals("servlet-name")) {
238: servletName = org.apache.myfaces.shared_impl.util.xml.XmlUtils
239: .getElementText((Element) n);
240: } else if (n.getNodeName().equals("url-pattern")) {
241: urlPattern = org.apache.myfaces.shared_impl.util.xml.XmlUtils
242: .getElementText((Element) n).trim();
243: } else {
244: if (log.isDebugEnabled())
245: log.debug("Ignored element '" + n.getNodeName()
246: + "' as child of '"
247: + servletMappingElem.getNodeName()
248: + "'.");
249: }
250: } else {
251: if (log.isDebugEnabled())
252: log.debug("Ignored node '" + n.getNodeName()
253: + "' of type " + n.getNodeType());
254: }
255: }
256: urlPattern = urlPattern.trim();
257: _webXml.addServletMapping(servletName, urlPattern);
258: }
259:
260: private void readFilter(Element filterElem) {
261: String filterName = null;
262: String filterClass = null;
263: NodeList nodeList = filterElem.getChildNodes();
264: for (int i = 0, len = nodeList.getLength(); i < len; i++) {
265: Node n = nodeList.item(i);
266: if (n.getNodeType() == Node.ELEMENT_NODE) {
267: if (n.getNodeName().equals("filter-name")) {
268: filterName = XmlUtils.getElementText((Element) n)
269: .trim();
270: } else if (n.getNodeName().equals("filter-class")) {
271: filterClass = org.apache.myfaces.shared_impl.util.xml.XmlUtils
272: .getElementText((Element) n).trim();
273: } else if (n.getNodeName().equals("description")
274: || n.getNodeName().equals("init-param")) {
275: //ignore
276: } else {
277: if (log.isDebugEnabled())
278: log.debug("Ignored element '" + n.getNodeName()
279: + "' as child of '"
280: + filterElem.getNodeName() + "'.");
281: }
282: } else {
283: if (log.isDebugEnabled())
284: log.debug("Ignored node '" + n.getNodeName()
285: + "' of type " + n.getNodeType());
286: }
287: }
288: _webXml.addFilter(filterName, filterClass);
289: }
290:
291: private void readFilterMapping(Element filterMappingElem) {
292: String filterName = null;
293: String urlPattern = null;
294: NodeList nodeList = filterMappingElem.getChildNodes();
295: for (int i = 0, len = nodeList.getLength(); i < len; i++) {
296: Node n = nodeList.item(i);
297: if (n.getNodeType() == Node.ELEMENT_NODE) {
298: if (n.getNodeName().equals("filter-name")) {
299: filterName = org.apache.myfaces.shared_impl.util.xml.XmlUtils
300: .getElementText((Element) n).trim();
301: } else if (n.getNodeName().equals("url-pattern")) {
302: urlPattern = org.apache.myfaces.shared_impl.util.xml.XmlUtils
303: .getElementText((Element) n).trim();
304: } else if (n.getNodeName().equals("servlet-name")) {
305: // we are not interested in servlet-name based mapping - for now
306: } else {
307: if (log.isDebugEnabled())
308: log.debug("Ignored element '" + n.getNodeName()
309: + "' as child of '"
310: + filterMappingElem.getNodeName()
311: + "'.");
312: }
313: } else {
314: if (log.isDebugEnabled())
315: log.debug("Ignored node '" + n.getNodeName()
316: + "' of type " + n.getNodeType());
317: }
318: }
319: _webXml.addFilterMapping(filterName, urlPattern);
320: }
321: }
|