View Javadoc

1   /*
2    * JaspertReports JSF Plugin Copyright (C) 2011 A. Alonso Dominguez
3    *
4    * This library is free software; you can redistribute it and/or modify it
5    * under the terms of the GNU Lesser General Public License as published by
6    * the Free Software Foundation; either version 2.1 of the License, or (at
7    * your option) any later version. This library is distributed in the hope
8    * that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
9    * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
10   *
11   * See the GNU Lesser General Public License for more details. You should have
12   * received a copy of the GNU Lesser General Public License along with this
13   * library; if not, write to the Free Software Foundation, Inc., 59 Temple
14   * Place, Suite 330, Boston, MA 02111-1307 USA A.
15   *
16   * Alonso Dominguez
17   * alonsoft@users.sf.net
18   */
19  package net.sf.jasperreports.jsf.config;
20  
21  import java.io.InputStream;
22  import java.util.ArrayList;
23  import java.util.Collection;
24  import java.util.Collections;
25  import java.util.List;
26  import java.util.logging.Level;
27  import java.util.logging.Logger;
28  import javax.faces.context.ExternalContext;
29  
30  import javax.faces.webapp.FacesServlet;
31  import javax.servlet.ServletContext;
32  import net.sf.jasperreports.jsf.Constants;
33  
34  import net.sf.jasperreports.jsf.util.Util;
35  
36  import org.w3c.dom.Document;
37  import org.w3c.dom.Element;
38  
39  /**
40   * Webapp singleton instance used to hold the plugin's relevant
41   * information about current webapp faces' configuration.
42   *
43   * @author A. Alonso Dominguez
44   */
45  public final class Configuration {
46  
47      /** Singleton instance key. */
48      protected static final String INSTANCE_KEY =
49              Configuration.class.getPackage().getName();
50  
51      /** The logger instance. */
52      private static final Logger logger = Logger.getLogger(
53              Configuration.class.getPackage().getName(),
54              Constants.LOG_MESSAGES_BUNDLE);
55  
56      /** Faces' servlet class name. */
57      private static final String FACES_SERVLET_CLASS =
58              FacesServlet.class.getName();
59  
60      /** <tt>url-pattern</tt> tag. */
61      private static final String TAG_URL_PATTERN = "url-pattern";
62      /** <tt>servlet</tt> tag. */
63      private static final String TAG_SERVLET = "servlet";
64      /** <tt>servlet-class</tt> tag. */
65      private static final String TAG_SERVLET_CLASS = "servlet-class";
66      /** <tt>servlet-mapping</tt> tag. */
67      private static final String TAG_SERVLET_MAPPING = "servlet-mapping";
68      /** <tt>servlet-name</tt> tag. */
69      private static final String TAG_SERVLET_NAME = "servlet-name";
70      /** Web application config file. */
71      private static final String WEB_XML = "/WEB-INF/web.xml";
72  
73      /**
74       * Obtains the singleton configuration instance.
75       * <p>
76       * If there is not any configuration instance preloaded, the
77       * application configuration files will be parsed and loaded
78       * into the application scope map.
79       *
80       * @param context current faces' external context
81       * @return the singleton instance
82       * @throws ConfigurationException if application is not properly configured.
83       */
84      public static Configuration getInstance(final ExternalContext context)
85              throws ConfigurationException {
86          if (context == null) {
87              throw new IllegalArgumentException("context");
88          }
89  
90          Configuration instance = (Configuration) context
91                  .getApplicationMap().get(INSTANCE_KEY);
92          if (instance == null) {
93              instance = new Configuration(context);
94              context.getApplicationMap().put(INSTANCE_KEY,
95                      instance);
96          }
97          return instance;
98      }
99  
100     /** Faces' servlet mappings. */
101     private final List<String> facesMappings = new ArrayList<String>();
102     /** Faces' default mapping. */
103     private String defaultMapping;
104 
105     /**
106      * Constructor from a servlet context.
107      *
108      * @param context a servlet context.
109      * @throws ConfigurationException if application is not properly configured.
110      */
111     protected Configuration(final ServletContext context)
112     throws ConfigurationException {
113         final InputStream is = context.getResourceAsStream(WEB_XML);
114         loadMappings(is);
115     }
116 
117     /**
118      * Constructor from a faces' external context.
119      *
120      * @param context a faces' external context.
121      * @throws ConfigurationException if application is not properly configured.
122      */
123     protected Configuration(final ExternalContext context)
124             throws ConfigurationException {
125         final InputStream is = context
126                 .getResourceAsStream(WEB_XML);
127         loadMappings(is);
128     }
129 
130     /**
131      * Obtains the default faces' mapping.
132      *
133      * @return a faces' mapping.
134      */
135     public String getDefaultMapping() {
136         return defaultMapping;
137     }
138 
139     /**
140      * Obtains the collection of faces' servlet mappings.
141      *
142      * @return the faces' mappings.
143      */
144     public Collection<String> getFacesMappings() {
145         return Collections.unmodifiableList(facesMappings);
146     }
147 
148     /**
149      * Parses the <tt>web.xml</tt> file from a stream.
150      *
151      * @param stream the stream which holds the <tt>web.xml</tt> file.
152      * @throws ConfigurationException if application is not properly configured.
153      */
154     private void loadMappings(final InputStream stream)
155     throws ConfigurationException {
156         Document webXml;
157         try {
158             webXml = XmlHelper.loadDocument(stream);
159         } catch (final Exception e) {
160             throw new ConfigurationException(e);
161         }
162 
163         loadMappings(webXml);
164     }
165 
166     /**
167      * Parses the <tt>web.xml</tt> file.
168      *
169      * @param webXml the <tt>web.xml</tt> document.
170      * @throws ConfigurationException if application is not properly configured
171      */
172     private void loadMappings(final Document webXml)
173     throws ConfigurationException {
174         final List<Element> servletList = XmlHelper.getChildElements(webXml
175                 .getDocumentElement(), TAG_SERVLET);
176         for (final Element servlet : servletList) {
177             final String servletName = XmlHelper.getChildText(servlet,
178                     TAG_SERVLET_NAME);
179             final String servletClass = XmlHelper.getChildText(servlet,
180                     TAG_SERVLET_CLASS);
181             if (!FACES_SERVLET_CLASS.equals(servletClass)) {
182                 continue;
183             }
184 
185             if (logger.isLoggable(Level.CONFIG)) {
186                 logger.log(Level.CONFIG, "JRJSF_0024", servletName);
187             }
188 
189             final List<Element> servletMappingList = XmlHelper.getChildElements(
190                     webXml.getDocumentElement(),
191                     TAG_SERVLET_MAPPING);
192             for (final Element servletMapping : servletMappingList) {
193                 final String mappingName = XmlHelper.getChildText(
194                         servletMapping, TAG_SERVLET_NAME);
195                 if (!servletName.equals(mappingName)) {
196                     continue;
197                 }
198 
199                 final String urlPattern = XmlHelper.getChildText(
200                         servletMapping, TAG_URL_PATTERN);
201                 if ("/*".equals(urlPattern)) {
202                     throw new IllegalFacesMappingException(urlPattern);
203                 }
204 
205                 final String mapping = stripMapping(urlPattern);
206                 if (defaultMapping == null) {
207                     defaultMapping = mapping;
208                     if (logger.isLoggable(Level.CONFIG)) {
209                         logger.log(Level.CONFIG, "JRJSF_0026", new Object[]{
210                             servletName, mapping
211                         });
212                     }
213                 } else if (logger.isLoggable(Level.CONFIG)) {
214                     logger.log(Level.CONFIG, "JRJSF_0025", new Object[]{
215                         servletName, mapping
216                     });
217                 }
218                 facesMappings.add(mapping);
219             }
220         }
221 
222         if (defaultMapping == null) {
223             throw new FacesServletNotFoundException();
224         }
225     }
226 
227     /**
228      * Extract's the base URI mapping of the specified pattern.
229      *
230      * @param urlPattern the faces' servlet url pattern.
231      * @return the faces' servlet uri mapping.
232      */
233     private String stripMapping(final String urlPattern) {
234         String mapping;
235         if (Util.isPrefixMapped(urlPattern)) {
236             mapping = urlPattern.substring(0, urlPattern.lastIndexOf("/"));
237         } else {
238             mapping = urlPattern.substring(urlPattern.indexOf("."));
239         }
240         return mapping;
241     }
242 
243 }