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.webapp;
20  
21  import java.util.List;
22  import java.util.Locale;
23  
24  import javax.el.ExpressionFactory;
25  import javax.faces.component.UIViewRoot;
26  import javax.faces.context.ExternalContext;
27  import javax.faces.context.FacesContext;
28  import javax.servlet.ServletContext;
29  
30  import org.apache.commons.logging.Log;
31  import org.apache.commons.logging.LogFactory;
32  import org.apache.myfaces.application.ApplicationImpl;
33  import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFWebConfigParam;
34  import org.apache.myfaces.config.FacesConfigValidator;
35  import org.apache.myfaces.config.FacesConfigurator;
36  import org.apache.myfaces.config.RuntimeConfig;
37  import org.apache.myfaces.context.ReleaseableExternalContext;
38  import org.apache.myfaces.context.servlet.ServletExternalContextImpl;
39  import org.apache.myfaces.context.servlet.StartupFacesContextImpl;
40  import org.apache.myfaces.context.servlet.StartupServletExternalContextImpl;
41  import org.apache.myfaces.shared_impl.util.StateUtils;
42  import org.apache.myfaces.shared_impl.webapp.webxml.WebXml;
43  
44  /**
45   * Performs common initialization tasks.
46   *
47   */
48  public abstract class AbstractFacesInitializer implements FacesInitializer
49  {
50      /**
51       * The logger instance for this class.
52       */
53      private static final Log log = LogFactory.getLog(AbstractFacesInitializer.class);
54      
55      /**
56       * This parameter specifies the ExpressionFactory implementation to use.
57       */
58      @JSFWebConfigParam(since="1.2.7")
59      protected static final String EXPRESSION_FACTORY = "org.apache.myfaces.EXPRESSION_FACTORY";
60  
61      /**
62       * Performs all necessary initialization tasks like configuring this JSF
63       * application.
64       */
65      public void initFaces(ServletContext servletContext)
66      {
67          try {
68              if (log.isTraceEnabled()) {
69                  log.trace("Initializing MyFaces");
70              }
71  
72              // Some parts of the following configuration tasks have been implemented 
73              // by using an ExternalContext. However, that's no problem as long as no 
74              // one tries to call methods depending on either the ServletRequest or 
75              // the ServletResponse.
76              ExternalContext externalContext = FacesContext.getCurrentInstance().getExternalContext();
77                  //new ServletExternalContextImpl(servletContext, null, null);
78  
79              // Parse and validate the web.xml configuration file
80              WebXml webXml = WebXml.getWebXml(externalContext);
81              if (webXml == null) {
82                  if (log.isWarnEnabled()) {
83                      log.warn("Couldn't find the web.xml configuration file. "
84                              + "Abort initializing MyFaces.");
85                  }
86  
87                  return;
88              } else if (webXml.getFacesServletMappings().isEmpty()) {
89                  if (log.isWarnEnabled()) {
90                      log.warn("No mappings of FacesServlet found. Abort initializing MyFaces.");
91                  }
92  
93                  return;
94              }
95              
96              initContainerIntegration(servletContext, externalContext);
97  
98              String useEncryption = servletContext.getInitParameter(StateUtils.USE_ENCRYPTION);
99              if (!"false".equals(useEncryption)) { // the default value is true
100                 StateUtils.initSecret(servletContext);
101             }
102 
103             if (log.isInfoEnabled()) {
104                 log.info("ServletContext '" + servletContext.getRealPath("/") + "' initialized.");
105             }
106         } catch (Exception ex) {
107             log.error("An error occured while initializing MyFaces: "
108                     + ex.getMessage(), ex);
109         }
110     }
111 
112     /**
113      * Cleans up all remaining resources (well, theoretically).
114      * 
115      */
116     public void destroyFaces(ServletContext servletContext)
117     {
118         // TODO is it possible to make a real cleanup?
119     }
120 
121     /**
122      * Configures this JSF application. It's required that every
123      * FacesInitializer (i.e. every subclass) calls this method during
124      * initialization.
125      * 
126      * @param servletContext
127      *            the current ServletContext
128      * @param externalContext
129      *            the current ExternalContext
130      * @param expressionFactory
131      *            the ExpressionFactory to use
132      * 
133      * @return the current runtime configuration
134      */
135     protected RuntimeConfig buildConfiguration(ServletContext servletContext,
136             ExternalContext externalContext, ExpressionFactory expressionFactory)
137     {
138         RuntimeConfig runtimeConfig = RuntimeConfig.getCurrentInstance(externalContext);
139         runtimeConfig.setExpressionFactory(expressionFactory);
140         
141         //ApplicationImpl.setInitializingRuntimeConfig(runtimeConfig);
142         
143         // And configure everything
144         new FacesConfigurator(externalContext).configure();
145         
146         validateFacesConfig(servletContext, externalContext);
147         
148         return runtimeConfig;
149     }
150     
151     protected void validateFacesConfig(ServletContext servletContext, ExternalContext externalContext)
152     {
153         String validate = servletContext.getInitParameter(FacesConfigValidator.VALIDATE_CONTEXT_PARAM);
154         if ("true".equals(validate) && log.isWarnEnabled()) { // the default value is false
155             List<String> warnings = FacesConfigValidator.validate(
156                     externalContext, servletContext.getRealPath("/"));
157             
158             for (String warning : warnings) {
159                 log.warn(warning);
160             }
161         }
162     }
163     
164     /**
165      * Try to load user-definied ExpressionFactory. Returns <code>null</code>,
166      * if no custom ExpressionFactory was specified. 
167      * 
168      * @param externalContext the current ExternalContext
169      * 
170      * @return User-specified ExpressionFactory, or 
171      *          <code>null</code>, if no no custom implementation was specified
172      * 
173      */
174     protected static ExpressionFactory getUserDefinedExpressionFactory(ExternalContext externalContext)
175     {
176         String expressionFactoryClassName = externalContext.getInitParameter(EXPRESSION_FACTORY);
177         if (expressionFactoryClassName != null
178                 && expressionFactoryClassName.trim().length() > 0) {
179             if (log.isDebugEnabled()) {
180                 log.debug("Attempting to load the ExpressionFactory implementation " 
181                         + "you've specified: '" + expressionFactoryClassName + "'.");
182             }
183             
184             return loadExpressionFactory(expressionFactoryClassName);
185         }
186         
187         return null;
188     }
189     
190     /**
191      * Loads and instantiates the given ExpressionFactory implementation.
192      * 
193      * @param expressionFactoryClassName
194      *            the class name of the ExpressionFactory implementation
195      * 
196      * @return the newly created ExpressionFactory implementation, or
197      *         <code>null</code>, if an error occurred
198      */
199     protected static ExpressionFactory loadExpressionFactory(String expressionFactoryClassName) 
200     {
201        try {
202            Class<?> expressionFactoryClass = Class.forName(expressionFactoryClassName);
203            return (ExpressionFactory) expressionFactoryClass.newInstance();
204        } catch (Exception ex) {
205            if (log.isDebugEnabled()) {
206                log.debug("An error occured while instantiating a new ExpressionFactory. " 
207                    + "Attempted to load class '" + expressionFactoryClassName + "'.", ex);
208            }
209        }
210        
211        return null;
212     }
213     
214     public FacesContext initStartupFacesContext(ServletContext servletContext)
215     {
216         // We cannot use FacesContextFactory, because it is necessary to initialize 
217         // before Application and RenderKit factories, so we should use different object. 
218         return _createFacesContext(servletContext, true);
219     }
220         
221     public void destroyStartupFacesContext(FacesContext facesContext)
222     {
223         _releaseFacesContext(facesContext);
224     }
225     
226     public FacesContext initShutdownFacesContext(ServletContext servletContext)
227     {
228         return _createFacesContext(servletContext, false);
229     }
230         
231     public void destroyShutdownFacesContext(FacesContext facesContext)
232     {
233         _releaseFacesContext(facesContext);
234     }
235     
236     private FacesContext _createFacesContext(ServletContext servletContext, boolean startup)
237     {
238         ExternalContext externalContext = new StartupServletExternalContextImpl(servletContext, startup);
239         FacesContext facesContext = new StartupFacesContextImpl(externalContext, 
240                 (ReleaseableExternalContext) externalContext, startup);
241         
242         // If getViewRoot() is called during application startup or shutdown, 
243         // it should return a new UIViewRoot with its locale set to Locale.getDefault().
244         UIViewRoot startupViewRoot = new UIViewRoot();
245         startupViewRoot.setLocale(Locale.getDefault());
246         facesContext.setViewRoot(startupViewRoot);
247         
248         return facesContext;
249     }
250     
251     private void _releaseFacesContext(FacesContext facesContext)
252     {        
253         // make sure that the facesContext gets released.
254         // This is important in an OSGi environment 
255         if (facesContext != null)
256         {
257             facesContext.release();
258         }        
259     }
260     
261     /**
262      * Performs initialization tasks depending on the current environment.
263      * 
264      * @param servletContext
265      *            the current ServletContext
266      * @param externalContext
267      *            the current ExternalContext
268      */
269     protected abstract void initContainerIntegration(
270             ServletContext servletContext, ExternalContext externalContext);
271 
272 }