View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.myfaces.commons.resourcehandler.webapp.config.impl;
20  
21  import java.io.IOException;
22  import java.io.InputStream;
23  import java.net.URL;
24  import java.net.URLConnection;
25  import java.util.ArrayList;
26  import java.util.List;
27  
28  import javax.faces.FacesException;
29  import javax.faces.context.ExternalContext;
30  import javax.faces.context.FacesContext;
31  import javax.xml.parsers.ParserConfigurationException;
32  import javax.xml.parsers.SAXParser;
33  import javax.xml.parsers.SAXParserFactory;
34  
35  import org.apache.myfaces.commons.resourcehandler.webapp.config.WebRegistration;
36  import org.apache.myfaces.commons.resourcehandler.webapp.config.element.impl.FilterRegistrationImpl;
37  import org.apache.myfaces.commons.resourcehandler.webapp.config.element.impl.ServletRegistrationImpl;
38  import org.xml.sax.Attributes;
39  import org.xml.sax.InputSource;
40  import org.xml.sax.Locator;
41  import org.xml.sax.SAXException;
42  import org.xml.sax.SAXParseException;
43  import org.xml.sax.XMLReader;
44  import org.xml.sax.helpers.DefaultHandler;
45  
46  /**
47   * XML-parser for /WEB-INF/web.xml
48   *
49   * @author Leonardo Uribe
50   */
51  public class WebXmlConfigParser
52  {
53      private static final String WEB_XML_PATH = "/WEB-INF/web.xml";
54      
55      public static WebRegistration getWebRegistrationFromParsedWebXml(FacesContext facesContext)
56      {
57          try
58          {
59              URL url = facesContext.getExternalContext().getResource(WEB_XML_PATH);
60              if (url != null)
61              {
62                  WebRegistration mrc = parseFile(facesContext, url);
63                  return mrc;
64              }
65              else
66              {
67                  return null;
68              }
69          }
70          catch (IOException e) {
71              throw new FacesException("Cannot parse /WEB-INF/web.xml file ");
72          }
73      }
74      
75      private static WebRegistration parseFile(FacesContext facesContext, URL configFileUrl) throws IOException
76      {
77          InputStream is = null;
78          URLConnection conn = null;
79          try
80          {
81              ExternalContext externalContext = FacesContext.getCurrentInstance().getExternalContext();
82              boolean schemaValidating = false;
83  
84              // parse file
85              WebConfigHandler handler = new WebConfigHandler(configFileUrl);
86              SAXParser parser = createSAXParser(handler, externalContext, schemaValidating);
87              conn = configFileUrl.openConnection();
88              conn.setUseCaches(false);
89              is = conn.getInputStream();
90              parser.parse(is, handler);
91              return handler.getWebConfigProvider();
92          }
93          catch (SAXException e)
94          {
95              IOException ioe = new IOException("Error parsing [" + configFileUrl + "]: ");
96              ioe.initCause(e);
97              throw ioe;
98          }
99          catch (ParserConfigurationException e)
100         {
101             IOException ioe = new IOException("Error parsing [" + configFileUrl + "]: ");
102             ioe.initCause(e);
103             throw ioe;
104         }
105         finally
106         {
107             if (is != null)
108                 is.close();
109         }
110     }
111 
112     private static final SAXParser createSAXParser(WebConfigHandler handler, ExternalContext externalContext, boolean schemaValidating) throws SAXException,
113     ParserConfigurationException
114     {
115         SAXParserFactory factory = SAXParserFactory.newInstance();
116         
117         //Just parse it and do not validate, because it is not necessary.
118         factory.setNamespaceAware(true);
119         factory.setFeature("http://xml.org/sax/features/validation", false);
120         factory.setValidating(false);
121         
122         SAXParser parser = factory.newSAXParser();
123         XMLReader reader = parser.getXMLReader();
124         reader.setErrorHandler(handler);
125         reader.setEntityResolver(handler);
126         return parser;
127     }
128     
129     private static class WebConfigHandler extends DefaultHandler
130     {
131         private final URL source;
132 
133         private final StringBuffer buffer;
134         
135         private Locator locator;
136         
137         private WebRegistrationImpl config;
138         
139         private String servletName;
140         
141         private String servletClassName;
142         
143         private List<String> urlPatterns;
144         
145         private String filterName;
146         
147         private String filterClassName;
148         
149         private List<String> servletNameMappings;
150         
151         public WebConfigHandler(URL source)
152         {
153             this.source = source;
154             this.buffer = new StringBuffer(64);
155             this.config = null;
156         }
157         
158         public WebRegistration getWebConfigProvider()
159         {
160             return this.config;
161         }
162 
163         public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException
164         {
165             this.buffer.setLength(0);
166             if ("web-app".equals(qName))
167             {
168                 this.config = new WebRegistrationImpl();
169                 this.urlPatterns = new ArrayList<String>();
170                 this.servletNameMappings = new ArrayList<String>();
171             }
172             else if ("servlet".equals(qName))
173             {
174                 this.servletName = null;
175                 this.servletClassName = null;
176             }
177             else if ("servlet-mapping".equals(qName))
178             {
179                 this.servletName = null;
180                 this.urlPatterns.clear();
181             }
182             else if ("filter".equals(qName))
183             {
184                 this.filterName = null;
185                 this.filterClassName = null;
186             }
187             else if ("filter-mapping".equals(qName))
188             {
189                 this.filterName = null;
190                 this.urlPatterns.clear();
191                 this.servletNameMappings.clear();
192             }
193         }
194         
195         public void endElement(String uri, String localName, String qName) throws SAXException
196         {
197             try
198             {
199                 if (this.config == null)
200                 {
201                     return;
202                 }
203                 
204                 if ("servlet".equals(localName))
205                 {
206                     ServletRegistrationImpl sr = (ServletRegistrationImpl) this.config.getServletRegistration(this.servletName);
207                     if (sr == null)
208                     {
209                         sr = new ServletRegistrationImpl(this.servletName, this.servletClassName);
210                     }
211                     else
212                     {
213                         sr.setClassName(this.servletClassName);
214                     }
215                     this.config.getServletRegistrations().put(this.servletName, sr);
216                 }
217                 else if ("servlet-name".equals(localName))
218                 {
219                     servletName = captureBuffer();
220                 }
221                 else if ("servlet-class".equals(localName))
222                 {
223                     servletClassName = captureBuffer();
224                 }
225                 else if ("filter".equals(localName))
226                 {
227                     FilterRegistrationImpl sr = (FilterRegistrationImpl) this.config.getFilterRegistration(this.filterName);
228                     if (sr == null)
229                     {
230                         sr = new FilterRegistrationImpl(this.filterName, this.filterClassName);
231                     }
232                     else
233                     {
234                         sr.setClassName(this.filterClassName);
235                     }
236                     this.config.getFilterRegistrations().put(this.filterName, sr);
237                 }
238                 else if ("filter-name".equals(localName))
239                 {
240                     filterName = captureBuffer();
241                 }
242                 else if ("filter-class".equals(localName))
243                 {
244                     filterClassName = captureBuffer();
245                 }
246                 else if ("servlet-mapping".equals(localName))
247                 {
248                     ServletRegistrationImpl sr = (ServletRegistrationImpl) this.config.getServletRegistration(this.servletName);
249                     if (sr == null)
250                     {
251                         sr = new ServletRegistrationImpl(this.servletName);
252                         this.config.getServletRegistrations().put(this.servletName, sr);
253                     }
254                     for (String url: urlPatterns)
255                     {
256                         sr.addMapping(url);
257                     }
258                 }
259                 else if ("filter-mapping".equals(localName))
260                 {
261                     FilterRegistrationImpl sr = (FilterRegistrationImpl) this.config.getFilterRegistration(this.filterName);
262                     if (sr == null)
263                     {
264                         sr = new FilterRegistrationImpl(this.filterName);
265                         this.config.getFilterRegistrations().put(this.filterName, sr);
266                     }
267                     for (String url: urlPatterns)
268                     {
269                         sr.addUrlNameMapping(url);
270                     }
271                     for (String name : servletNameMappings)
272                     {
273                         sr.addServletNameMapping(name);
274                     }
275                     urlPatterns.clear();
276                     servletNameMappings.clear();
277                 }
278                 else if ("url-pattern".equals(localName))
279                 {
280                     urlPatterns.add(captureBuffer());
281                 }
282             }
283             catch (Exception e)
284             {
285                 SAXException saxe = new SAXException("Error Handling [" + this.source + "@"
286                         + this.locator.getLineNumber() + "," + this.locator.getColumnNumber() + "] <" + qName + ">");
287                 saxe.initCause(e);
288                 throw saxe;
289             }
290         }
291 
292         public void characters(char[] ch, int start, int length) throws SAXException
293         {
294             this.buffer.append(ch, start, length);
295         }
296         
297         private String captureBuffer() throws Exception
298         {
299             String s = this.buffer.toString().trim();
300             if (s.length() == 0)
301             {
302                 throw new Exception("Value Cannot be Empty");
303             }
304             this.buffer.setLength(0);
305             return s;
306         }        
307         
308         public InputSource resolveEntity(String publicId, String systemId) throws SAXException
309         {
310             return null;
311         }
312 
313         public void error(SAXParseException e) throws SAXException
314         {
315             SAXException saxe = new SAXException("Error Handling [" + this.source + "@" + e.getLineNumber() + ","
316                     + e.getColumnNumber() + "]");
317             saxe.initCause(e);
318             throw saxe;
319         }
320 
321         public void setDocumentLocator(Locator locator)
322         {
323             this.locator = locator;
324         }
325 
326         public void fatalError(SAXParseException e) throws SAXException
327         {
328             throw e;
329         }
330 
331         public void warning(SAXParseException e) throws SAXException
332         {
333             throw e;
334         }
335     }
336 
337 }