Coverage Report - org.apache.myfaces.webapp.AbstractFacesInitializer
 
Classes in this File Line Coverage Branch Coverage Complexity
AbstractFacesInitializer
0%
0/210
0%
0/100
4.5
 
 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 org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFWebConfigParam;
 22  
 import org.apache.myfaces.config.FacesConfigValidator;
 23  
 import org.apache.myfaces.config.FacesConfigurator;
 24  
 import org.apache.myfaces.config.ManagedBeanBuilder;
 25  
 import org.apache.myfaces.config.RuntimeConfig;
 26  
 import org.apache.myfaces.config.element.ManagedBean;
 27  
 import org.apache.myfaces.context.ReleaseableExternalContext;
 28  
 import org.apache.myfaces.context.servlet.StartupFacesContextImpl;
 29  
 import org.apache.myfaces.context.servlet.StartupServletExternalContextImpl;
 30  
 import org.apache.myfaces.shared.util.StateUtils;
 31  
 import org.apache.myfaces.shared.util.WebConfigParamUtils;
 32  
 import org.apache.myfaces.cdi.dependent.BeanEntry;
 33  
 import org.apache.myfaces.spi.InjectionProvider;
 34  
 import org.apache.myfaces.spi.InjectionProviderException;
 35  
 import org.apache.myfaces.spi.InjectionProviderFactory;
 36  
 import org.apache.myfaces.spi.ViewScopeProvider;
 37  
 import org.apache.myfaces.spi.ViewScopeProviderFactory;
 38  
 import org.apache.myfaces.spi.WebConfigProvider;
 39  
 import org.apache.myfaces.spi.WebConfigProviderFactory;
 40  
 import org.apache.myfaces.util.ExternalSpecifications;
 41  
 import org.apache.myfaces.view.facelets.tag.MetaRulesetImpl;
 42  
 
 43  
 import javax.el.ExpressionFactory;
 44  
 import javax.faces.application.Application;
 45  
 import javax.faces.application.ProjectStage;
 46  
 import javax.faces.component.UIViewRoot;
 47  
 import javax.faces.context.ExceptionHandler;
 48  
 import javax.faces.context.ExternalContext;
 49  
 import javax.faces.context.FacesContext;
 50  
 import javax.faces.event.PostConstructApplicationEvent;
 51  
 import javax.faces.event.PreDestroyApplicationEvent;
 52  
 import javax.faces.event.SystemEvent;
 53  
 import javax.servlet.ServletContext;
 54  
 import java.lang.reflect.InvocationTargetException;
 55  
 import java.lang.reflect.Method;
 56  
 import java.util.ArrayList;
 57  
 import java.util.List;
 58  
 import java.util.Locale;
 59  
 import java.util.Map;
 60  
 import java.util.logging.Level;
 61  
 import java.util.logging.Logger;
 62  
 import org.apache.myfaces.shared.context.ExceptionHandlerImpl;
 63  
 import org.apache.myfaces.shared.util.ClassUtils;
 64  
 import org.apache.myfaces.spi.ServiceProviderFinder;
 65  
 import org.apache.myfaces.spi.ServiceProviderFinderFactory;
 66  
 import org.apache.myfaces.view.facelets.ViewPoolProcessor;
 67  
 
 68  
 /**
 69  
  * Performs common initialization tasks.
 70  
  */
 71  0
 public abstract class AbstractFacesInitializer implements FacesInitializer
 72  
 {
 73  
     /**
 74  
      * The logger instance for this class.
 75  
      */
 76  
     //private static final Log log = LogFactory.getLog(AbstractFacesInitializer.class);
 77  0
     private static final Logger log = Logger.getLogger(AbstractFacesInitializer.class.getName());
 78  
     
 79  
     /**
 80  
      * If the servlet mapping for the FacesServlet is added dynamically, Boolean.TRUE 
 81  
      * is stored under this key in the ServletContext.
 82  
      * ATTENTION: this constant is duplicate in MyFacesContainerInitializer.
 83  
      */
 84  
     private static final String FACES_SERVLET_ADDED_ATTRIBUTE = "org.apache.myfaces.DYNAMICALLY_ADDED_FACES_SERVLET";
 85  
 
 86  
     /**
 87  
      * If the servlet mapping for the FacesServlet is found on the ServletContext, Boolean.TRUE 
 88  
      * is stored under this key in the ServletContext.
 89  
      * ATTENTION: this constant is duplicate in MyFacesContainerInitializer.
 90  
      */
 91  
     private static final String FACES_SERVLET_FOUND = "org.apache.myfaces.FACES_SERVLET_FOUND"; 
 92  
 
 93  
     /**
 94  
      * This parameter specifies the ExpressionFactory implementation to use.
 95  
      */
 96  
     @JSFWebConfigParam(since="1.2.7", group="EL")
 97  
     protected static final String EXPRESSION_FACTORY = "org.apache.myfaces.EXPRESSION_FACTORY";
 98  
     
 99  
     /**
 100  
      * If this param is set to true, the check for faces servlet mapping is not done 
 101  
      */
 102  
     @JSFWebConfigParam(since="2.0.3", defaultValue="false")
 103  
     protected static final String INITIALIZE_ALWAYS_STANDALONE = "org.apache.myfaces.INITIALIZE_ALWAYS_STANDALONE";
 104  
     
 105  
     /**
 106  
      * Indicate if log all web config params should be done before initialize the webapp. 
 107  
      * <p>
 108  
      * If is set in "auto" mode, web config params are only logged on "Development" and "Production" project stages.
 109  
      * </p> 
 110  
      */
 111  
     @JSFWebConfigParam(expectedValues="true, auto, false", defaultValue="auto")
 112  
     public static final String INIT_PARAM_LOG_WEB_CONTEXT_PARAMS = "org.apache.myfaces.LOG_WEB_CONTEXT_PARAMS";
 113  
     public static final String INIT_PARAM_LOG_WEB_CONTEXT_PARAMS_DEFAULT ="auto";
 114  
     
 115  
     public static final String CDI_BEAN_MANAGER_INSTANCE = "oam.cdi.BEAN_MANAGER_INSTANCE";
 116  
     
 117  
     private static final String CDI_SERVLET_CONTEXT_BEAN_MANAGER_ATTRIBUTE = 
 118  
         "javax.enterprise.inject.spi.BeanManager";
 119  
 
 120  
     private static final String INJECTED_BEAN_STORAGE_KEY = "org.apache.myfaces.spi.BEAN_ENTRY_STORAGE";
 121  
 
 122  
     /**
 123  
      * Performs all necessary initialization tasks like configuring this JSF
 124  
      * application.
 125  
      */
 126  
     public void initFaces(ServletContext servletContext)
 127  
     {
 128  
         try
 129  
         {
 130  0
             if (log.isLoggable(Level.FINEST))
 131  
             {
 132  0
                 log.finest("Initializing MyFaces");
 133  
             }
 134  
 
 135  
             // Some parts of the following configuration tasks have been implemented 
 136  
             // by using an ExternalContext. However, that's no problem as long as no 
 137  
             // one tries to call methods depending on either the ServletRequest or 
 138  
             // the ServletResponse.
 139  
             // JSF 2.0: FacesInitializer now has some new methods to
 140  
             // use proper startup FacesContext and ExternalContext instances.
 141  0
             FacesContext facesContext = FacesContext.getCurrentInstance();
 142  0
             ExternalContext externalContext = facesContext.getExternalContext();
 143  
 
 144  
             // Setup ServiceProviderFinder
 145  0
             ServiceProviderFinder spf = ServiceProviderFinderFactory.getServiceProviderFinder(
 146  
                 externalContext);
 147  0
             Map<String, List<String>> spfConfig = spf.calculateKnownServiceProviderMapInfo(
 148  
                 externalContext, ServiceProviderFinder.KNOWN_SERVICES);
 149  0
             if (spfConfig != null)
 150  
             {
 151  0
                 spf.initKnownServiceProviderMapInfo(externalContext, spfConfig);
 152  
             }
 153  
             
 154  
             // Parse and validate the web.xml configuration file
 155  
             
 156  0
             if (!WebConfigParamUtils.getBooleanInitParameter(externalContext, INITIALIZE_ALWAYS_STANDALONE, false))
 157  
             {
 158  0
                 WebConfigProvider webConfigProvider = WebConfigProviderFactory.getWebConfigProviderFactory(
 159  
                         facesContext.getExternalContext()).getWebConfigProvider(facesContext.getExternalContext());
 160  
 
 161  0
                 if (webConfigProvider.getFacesServletMappings(facesContext.getExternalContext()).isEmpty())
 162  
                 {
 163  
                     // check to see if the FacesServlet was found by MyFacesContainerInitializer
 164  0
                     Boolean mappingAdded = (Boolean) servletContext.getAttribute(FACES_SERVLET_FOUND);
 165  
 
 166  0
                     if (mappingAdded == null || !mappingAdded)
 167  
                     {
 168  
                         // check if the FacesServlet has been added dynamically
 169  
                         // in a Servlet 3.0 environment by MyFacesContainerInitializer
 170  0
                         mappingAdded = (Boolean) servletContext.getAttribute(FACES_SERVLET_ADDED_ATTRIBUTE);
 171  
 
 172  0
                         if (mappingAdded == null || !mappingAdded)
 173  
                         {
 174  0
                             if (log.isLoggable(Level.WARNING))
 175  
                             {
 176  0
                                 log.warning("No mappings of FacesServlet found. Abort initializing MyFaces.");
 177  
                             }
 178  0
                             return;
 179  
                         }
 180  
                     }
 181  
                 }
 182  
             }
 183  
 
 184  0
             initCDIIntegration(servletContext, externalContext);
 185  
             
 186  0
             initContainerIntegration(servletContext, externalContext);
 187  
             
 188  0
             ViewScopeProviderFactory factory = ViewScopeProviderFactory.getViewScopeHandlerFactory(
 189  
                 externalContext);
 190  
             
 191  0
             ViewScopeProvider viewScopeHandler = factory.getViewScopeHandler(
 192  
                 externalContext);
 193  
             
 194  0
             ManagedBeanDestroyerListener listener = (ManagedBeanDestroyerListener)
 195  
                 externalContext.getApplicationMap().get(
 196  
                     ManagedBeanDestroyerListener.APPLICATION_MAP_KEY);
 197  
             
 198  0
             listener.setViewScopeHandler(viewScopeHandler);
 199  
 
 200  0
             String useEncryption = servletContext.getInitParameter(StateUtils.USE_ENCRYPTION);
 201  0
             if (!"false".equals(useEncryption)) // the default value is true
 202  
             {
 203  0
                 StateUtils.initSecret(servletContext);
 204  
             }
 205  
 
 206  
             // initialize eager managed beans
 207  0
             _createEagerBeans(facesContext);
 208  
 
 209  0
             _dispatchApplicationEvent(servletContext, PostConstructApplicationEvent.class);
 210  
 
 211  0
             if ( (facesContext.isProjectStage(ProjectStage.Development) || 
 212  
                   facesContext.isProjectStage(ProjectStage.Production)) &&
 213  
                  log.isLoggable(Level.INFO))
 214  
             {
 215  0
                 log.info("ServletContext initialized.");
 216  
             }
 217  
 
 218  0
             WebConfigParamsLogger.logWebContextParams(facesContext);
 219  
             
 220  
             //Force output EL message
 221  0
             ExternalSpecifications.isUnifiedELAvailable();
 222  0
             ExternalSpecifications.isBeanValidationAvailable();
 223  
             
 224  
             //Start ViewPoolProcessor if necessary
 225  0
             ViewPoolProcessor.initialize(facesContext);
 226  
 
 227  
             // print out a very prominent log message if the project stage is != Production
 228  0
             if (!facesContext.isProjectStage(ProjectStage.Production) &&
 229  
                 !facesContext.isProjectStage(ProjectStage.UnitTest))
 230  
             {
 231  0
                 ProjectStage projectStage = facesContext.getApplication().getProjectStage();
 232  0
                 StringBuilder message = new StringBuilder("\n\n");
 233  0
                 message.append("*******************************************************************\n");
 234  0
                 message.append("*** WARNING: Apache MyFaces-2 is running in ");
 235  0
                 message.append(projectStage.name().toUpperCase());        
 236  0
                 message.append(" mode.");
 237  0
                 int length = projectStage.name().length();
 238  0
                 for (int i = 0; i < 11 - length; i++)
 239  
                 {
 240  0
                     message.append(" ");
 241  
                 }
 242  0
                 message.append("   ***\n");
 243  0
                 message.append("***                                         ");
 244  0
                 for (int i = 0; i < length; i++)
 245  
                 {
 246  0
                     message.append("^");
 247  
                 }
 248  0
                 for (int i = 0; i < 20 - length; i++)
 249  
                 {
 250  0
                     message.append(" ");
 251  
                 }
 252  0
                 message.append("***\n");
 253  0
                 message.append("*** Do NOT deploy to your live server(s) without changing this. ***\n");
 254  0
                 message.append("*** See Application#getProjectStage() for more information.     ***\n");
 255  0
                 message.append("*******************************************************************\n");
 256  0
                 log.log(Level.WARNING, message.toString());
 257  
             }
 258  
 
 259  
         }
 260  0
         catch (Exception ex)
 261  
         {
 262  0
             log.log(Level.SEVERE, "An error occured while initializing MyFaces: "
 263  
                       + ex.getMessage(), ex);
 264  0
         }
 265  0
     }
 266  
     
 267  
     /**
 268  
      * Checks for application scoped managed-beans with eager=true,
 269  
      * creates them and stores them in the application map.
 270  
      * @param facesContext
 271  
      */
 272  
     private void _createEagerBeans(FacesContext facesContext)
 273  
     {
 274  0
         ExternalContext externalContext = facesContext.getExternalContext();
 275  0
         RuntimeConfig runtimeConfig = RuntimeConfig.getCurrentInstance(externalContext);
 276  0
         List<ManagedBean> eagerBeans = new ArrayList<ManagedBean>();
 277  
         
 278  
         // check all registered managed-beans
 279  0
         for (ManagedBean bean : runtimeConfig.getManagedBeans().values())
 280  
         {
 281  0
             String eager = bean.getEager();
 282  0
             if (eager != null && "true".equals(eager))
 283  
             {
 284  
                 // eager beans are only allowed for application scope
 285  0
                 if (ManagedBeanBuilder.APPLICATION.equals(bean.getManagedBeanScope()))
 286  
                 {
 287  
                     // add to eager beans
 288  0
                     eagerBeans.add(bean);
 289  
                 }
 290  
                 else
 291  
                 {
 292  
                     // log warning and continue (the bean will be lazy loaded)
 293  0
                     log.log(Level.WARNING, "The managed-bean with name "
 294  
                             + bean.getManagedBeanName()
 295  
                             + " must be application scoped to support eager=true.");
 296  
                 }
 297  
             }
 298  0
         }
 299  
         
 300  
         // check if there are any eager beans
 301  0
         if (!eagerBeans.isEmpty())
 302  
         {
 303  0
             ManagedBeanBuilder managedBeanBuilder = new ManagedBeanBuilder();
 304  0
             Map<String, Object> applicationMap = externalContext.getApplicationMap();
 305  
             
 306  0
             for (ManagedBean bean : eagerBeans)
 307  
             {
 308  
                 // check application scope for bean instance
 309  0
                 if (applicationMap.containsKey(bean.getManagedBeanName()))
 310  
                 {
 311  
                     // do not build bean, because it already exists
 312  
                     // (e.g. @ManagedProperty from previous managed bean already created it)
 313  0
                     continue;
 314  
                 }
 315  
 
 316  
                 // create instance
 317  0
                 Object beanInstance = managedBeanBuilder.buildManagedBean(facesContext, bean);
 318  
                 
 319  
                 // put in application scope
 320  0
                 applicationMap.put(bean.getManagedBeanName(), beanInstance);
 321  0
             }
 322  
         }
 323  0
     }
 324  
 
 325  
     /**
 326  
      * Eventually we can use our plugin infrastructure for this as well
 327  
      * it would be a cleaner interception point than the base class
 328  
      * but for now this position is valid as well
 329  
      * <p/>
 330  
      * Note we add it for now here because the application factory object
 331  
      * leaves no possibility to have a destroy interceptor
 332  
      * and applications are per web application singletons
 333  
      * Note if this does not work out
 334  
      * move the event handler into the application factory
 335  
      *
 336  
      * @param servletContext the servlet context to be passed down
 337  
      * @param eventClass     the class to be passed down into the dispatching
 338  
      *                       code
 339  
      */
 340  
     private void _dispatchApplicationEvent(ServletContext servletContext, Class<? extends SystemEvent> eventClass)
 341  
     {
 342  0
         FacesContext facesContext = FacesContext.getCurrentInstance();
 343  0
         Application application = facesContext.getApplication();
 344  0
         application.publishEvent(facesContext, eventClass, Application.class, application);
 345  0
     }
 346  
     
 347  
     /**
 348  
      * Cleans up all remaining resources (well, theoretically).
 349  
      */
 350  
     public void destroyFaces(ServletContext servletContext)
 351  
     {
 352  
 
 353  0
         FacesContext facesContext = FacesContext.getCurrentInstance();
 354  
 
 355  0
         if (!WebConfigParamUtils.getBooleanInitParameter(facesContext.getExternalContext(),
 356  
                                                          INITIALIZE_ALWAYS_STANDALONE, false))
 357  
         {
 358  
             //We need to check if the current application was initialized by myfaces
 359  0
             WebConfigProvider webConfigProvider = WebConfigProviderFactory.getWebConfigProviderFactory(
 360  
                     facesContext.getExternalContext()).getWebConfigProvider(facesContext.getExternalContext());
 361  
 
 362  0
             if (webConfigProvider.getFacesServletMappings(facesContext.getExternalContext()).isEmpty())
 363  
             {
 364  
                 // check to see if the FacesServlet was found by MyFacesContainerInitializer
 365  0
                 Boolean mappingAdded = (Boolean) servletContext.getAttribute(FACES_SERVLET_FOUND);
 366  
 
 367  0
                 if (mappingAdded == null || !mappingAdded)
 368  
                 {
 369  
                     // check if the FacesServlet has been added dynamically
 370  
                     // in a Servlet 3.0 environment by MyFacesContainerInitializer
 371  0
                     mappingAdded = (Boolean) servletContext.getAttribute(FACES_SERVLET_ADDED_ATTRIBUTE);
 372  
 
 373  0
                     if (mappingAdded == null || !mappingAdded)
 374  
                     {
 375  0
                         if (log.isLoggable(Level.WARNING))
 376  
                         {
 377  0
                             log.warning("No mappings of FacesServlet found. Abort destroy MyFaces.");
 378  
                         }
 379  0
                         return;
 380  
                     }
 381  
                 }
 382  
             }
 383  
         }
 384  
 
 385  0
         _dispatchApplicationEvent(servletContext, PreDestroyApplicationEvent.class);
 386  
 
 387  0
         _callPreDestroyOnInjectedJSFArtifacts(facesContext);
 388  
         
 389  
         // clear the cache of MetaRulesetImpl in order to prevent a memory leak
 390  0
         MetaRulesetImpl.clearMetadataTargetCache();
 391  
         
 392  
         // clear UIViewParameter default renderer map
 393  
         try
 394  
         {
 395  0
             Class<?> c = Class.forName("javax.faces.component.UIViewParameter");
 396  0
             Method m = c.getDeclaredMethod("releaseRenderer");
 397  0
             m.setAccessible(true);
 398  0
             m.invoke(null);
 399  
         }
 400  0
         catch(ClassNotFoundException e)
 401  
         {
 402  0
             log.log(Level.SEVERE, e.getMessage(), e);
 403  
         }
 404  0
         catch(NoSuchMethodException e)
 405  
         {
 406  0
             log.log(Level.SEVERE, e.getMessage(), e);
 407  
         }
 408  0
         catch(IllegalAccessException e)
 409  
         {
 410  0
             log.log(Level.SEVERE, e.getMessage(), e);
 411  
         }
 412  0
         catch(InvocationTargetException e)
 413  
         {
 414  0
             log.log(Level.SEVERE, e.getMessage(), e);
 415  0
         }
 416  
 
 417  
         // TODO is it possible to make a real cleanup?
 418  0
     }
 419  
 
 420  
     /**
 421  
      * Configures this JSF application. It's required that every
 422  
      * FacesInitializer (i.e. every subclass) calls this method during
 423  
      * initialization.
 424  
      *
 425  
      * @param servletContext    the current ServletContext
 426  
      * @param externalContext   the current ExternalContext
 427  
      * @param expressionFactory the ExpressionFactory to use
 428  
      * @return the current runtime configuration
 429  
      */
 430  
     protected RuntimeConfig buildConfiguration(ServletContext servletContext,
 431  
                                                ExternalContext externalContext, ExpressionFactory expressionFactory)
 432  
     {
 433  0
         RuntimeConfig runtimeConfig = RuntimeConfig.getCurrentInstance(externalContext);
 434  0
         runtimeConfig.setExpressionFactory(expressionFactory);
 435  
 
 436  
         // And configure everything
 437  0
         new FacesConfigurator(externalContext).configure();
 438  
 
 439  0
         validateFacesConfig(servletContext, externalContext);
 440  
 
 441  0
         return runtimeConfig;
 442  
     }
 443  
 
 444  
     protected void validateFacesConfig(ServletContext servletContext, ExternalContext externalContext)
 445  
     {
 446  0
         String validate = servletContext.getInitParameter(FacesConfigValidator.VALIDATE_CONTEXT_PARAM);
 447  0
         if ("true".equals(validate) && log.isLoggable(Level.WARNING))
 448  
         { // the default value is false
 449  0
             List<String> warnings = FacesConfigValidator.validate(
 450  
                     externalContext);
 451  
 
 452  0
             for (String warning : warnings)
 453  
             {
 454  0
                 log.warning(warning);
 455  0
             }
 456  
         }
 457  0
     }
 458  
 
 459  
     /**
 460  
      * Try to load user-definied ExpressionFactory. Returns <code>null</code>,
 461  
      * if no custom ExpressionFactory was specified.
 462  
      *
 463  
      * @param externalContext the current ExternalContext
 464  
      * @return User-specified ExpressionFactory, or
 465  
      *         <code>null</code>, if no no custom implementation was specified
 466  
      */
 467  
     protected static ExpressionFactory getUserDefinedExpressionFactory(ExternalContext externalContext)
 468  
     {
 469  0
         String expressionFactoryClassName
 470  
                 = WebConfigParamUtils.getStringInitParameter(externalContext, EXPRESSION_FACTORY);
 471  0
         if (expressionFactoryClassName != null
 472  
                 && expressionFactoryClassName.trim().length() > 0)
 473  
         {
 474  0
             if (log.isLoggable(Level.FINE))
 475  
             {
 476  0
                 log.fine("Attempting to load the ExpressionFactory implementation "
 477  
                         + "you've specified: '" + expressionFactoryClassName + "'.");
 478  
             }
 479  
 
 480  0
             return loadExpressionFactory(expressionFactoryClassName);
 481  
         }
 482  
 
 483  0
         return null;
 484  
     }
 485  
 
 486  
     /**
 487  
      * Loads and instantiates the given ExpressionFactory implementation.
 488  
      *
 489  
      * @param expressionFactoryClassName the class name of the ExpressionFactory implementation
 490  
      * @return the newly created ExpressionFactory implementation, or
 491  
      *         <code>null</code>, if an error occurred
 492  
      */
 493  
     protected static ExpressionFactory loadExpressionFactory(String expressionFactoryClassName)
 494  
     {
 495  
         try
 496  
         {
 497  0
             ClassLoader cl = ClassUtils.getContextClassLoader();
 498  0
             if (cl == null)
 499  
             {
 500  0
                 cl = AbstractFacesInitializer.class.getClassLoader();
 501  
             }
 502  
 
 503  0
             Class<?> expressionFactoryClass = cl.loadClass(expressionFactoryClassName);
 504  0
             return (ExpressionFactory) expressionFactoryClass.newInstance();
 505  
         }
 506  0
         catch (Exception ex)
 507  
         {
 508  0
             if (log.isLoggable(Level.FINE))
 509  
             {
 510  0
                 log.log(Level.FINE, "An error occured while instantiating a new ExpressionFactory. "
 511  
                         + "Attempted to load class '" + expressionFactoryClassName + "'.", ex);
 512  
             }
 513  
         }
 514  
 
 515  0
         return null;
 516  
     }
 517  
 
 518  
     public FacesContext initStartupFacesContext(ServletContext servletContext)
 519  
     {
 520  
         // We cannot use FacesContextFactory, because it is necessary to initialize 
 521  
         // before Application and RenderKit factories, so we should use different object. 
 522  0
         return _createFacesContext(servletContext, true);
 523  
     }
 524  
         
 525  
     public void destroyStartupFacesContext(FacesContext facesContext)
 526  
     {
 527  0
         _releaseFacesContext(facesContext);
 528  0
     }
 529  
     
 530  
     public FacesContext initShutdownFacesContext(ServletContext servletContext)
 531  
     {
 532  0
         return _createFacesContext(servletContext, false);
 533  
     }
 534  
         
 535  
     public void destroyShutdownFacesContext(FacesContext facesContext)
 536  
     {
 537  0
         _releaseFacesContext(facesContext);
 538  0
     }
 539  
     
 540  
     private FacesContext _createFacesContext(ServletContext servletContext, boolean startup)
 541  
     {
 542  0
         ExternalContext externalContext = new StartupServletExternalContextImpl(servletContext, startup);
 543  0
         ExceptionHandler exceptionHandler = new ExceptionHandlerImpl();
 544  0
         FacesContext facesContext = new StartupFacesContextImpl(externalContext, 
 545  
                 (ReleaseableExternalContext) externalContext, exceptionHandler, startup);
 546  
         
 547  
         // If getViewRoot() is called during application startup or shutdown, 
 548  
         // it should return a new UIViewRoot with its locale set to Locale.getDefault().
 549  0
         UIViewRoot startupViewRoot = new UIViewRoot();
 550  0
         startupViewRoot.setLocale(Locale.getDefault());
 551  0
         facesContext.setViewRoot(startupViewRoot);
 552  
         
 553  0
         return facesContext;
 554  
     }
 555  
     
 556  
     private void _releaseFacesContext(FacesContext facesContext)
 557  
     {        
 558  
         // make sure that the facesContext gets released.
 559  
         // This is important in an OSGi environment 
 560  0
         if (facesContext != null)
 561  
         {
 562  0
             facesContext.release();
 563  
         }        
 564  0
     }
 565  
     
 566  
     /**
 567  
      * Performs initialization tasks depending on the current environment.
 568  
      *
 569  
      * @param servletContext  the current ServletContext
 570  
      * @param externalContext the current ExternalContext
 571  
      */
 572  
     protected abstract void initContainerIntegration(
 573  
             ServletContext servletContext, ExternalContext externalContext);
 574  
 
 575  
     /**
 576  
      * The intention of this method is provide a point where CDI integration is done.
 577  
      * Faces Flow and javax.faces.view.ViewScope requires CDI in order to work, so
 578  
      * this method should set a BeanManager instance on application map under
 579  
      * the key "oam.cdi.BEAN_MANAGER_INSTANCE". The default implementation look on
 580  
      * ServletContext first and then use JNDI.
 581  
      * 
 582  
      * @param servletContext
 583  
      * @param externalContext 
 584  
      */
 585  
     protected void initCDIIntegration(
 586  
             ServletContext servletContext, ExternalContext externalContext)
 587  
     {
 588  
         // Lookup bean manager and put it into an application scope attribute to 
 589  
         // access it later. Remember the trick here is do not call any CDI api 
 590  
         // directly, so if no CDI api is on the classpath no exception will be thrown.
 591  
         
 592  
         // Try with servlet context
 593  0
         Object beanManager = servletContext.getAttribute(
 594  
             CDI_SERVLET_CONTEXT_BEAN_MANAGER_ATTRIBUTE);
 595  0
         if (beanManager == null)
 596  
         {
 597  0
             beanManager = lookupBeanManagerFromCDI();
 598  
         }
 599  0
         if (beanManager == null)
 600  
         {
 601  0
             beanManager = lookupBeanManagerFromJndi();
 602  
         }
 603  0
         if (beanManager != null)
 604  
         {
 605  0
             externalContext.getApplicationMap().put(CDI_BEAN_MANAGER_INSTANCE,
 606  
                 beanManager);
 607  
         }
 608  0
     }
 609  
 
 610  
     /**
 611  
      * This method tries to use the CDI-1.1 CDI.current() method to lookup the CDI BeanManager.
 612  
      * We do all this via reflection to not blow up if CDI-1.1 is not on the classpath.
 613  
      * @return the BeanManager or {@code null} if either not in a CDI-1.1 environment
 614  
      *         or the BeanManager doesn't exist yet.
 615  
      */
 616  
     private Object lookupBeanManagerFromCDI()
 617  
     {
 618  
         try
 619  
         {
 620  0
             Class cdiClass = null;
 621  0
             Method cdiCurrentMethod = null;
 622  0
             Method cdiGetBeanManagerMethod = null;
 623  0
             cdiClass = simpleClassForNameNoException("javax.enterprise.inject.spi.CDI");
 624  0
             if (cdiClass != null)
 625  
             {
 626  0
                 cdiCurrentMethod = cdiClass.getMethod("current");
 627  
 
 628  0
                 Object cdiInstance = cdiCurrentMethod.invoke(null);
 629  
 
 630  0
                 cdiGetBeanManagerMethod = cdiClass.getMethod("getBeanManager");
 631  0
                 return cdiGetBeanManagerMethod.invoke(cdiInstance);
 632  
             }
 633  
         }
 634  0
         catch (Exception e)
 635  
         {
 636  
             // ignore
 637  0
         }
 638  0
         return null;
 639  
     }
 640  
     
 641  
     private static Class simpleClassForNameNoException(String type)
 642  
     {
 643  
         try
 644  
         {
 645  0
             return ClassUtils.classForName(type);
 646  
         }
 647  0
         catch (ClassNotFoundException e)
 648  
         {
 649  
             //log.log(Level.SEVERE, "Class " + type + " not found", e);
 650  
             //Ignore
 651  0
             return null;
 652  
         }
 653  
     }
 654  
 
 655  
     /**
 656  
      * Try to lookup the CDI BeanManager from JNDI.
 657  
      * We do all this via reflection to not blow up if CDI is not available.
 658  
      */
 659  
     private Object lookupBeanManagerFromJndi()
 660  
     {
 661  0
         Object beanManager = null;
 662  
         // Use reflection to avoid restricted API in GAE
 663  0
         Class icclazz = null;
 664  0
         Method lookupMethod = null;
 665  
         try
 666  
         {
 667  0
             icclazz = ClassUtils.simpleClassForName("javax.naming.InitialContext");
 668  0
             if (icclazz != null)
 669  
             {
 670  0
                 lookupMethod = icclazz.getMethod("doLookup", String.class);
 671  
             }
 672  
         }
 673  0
         catch (Throwable t)
 674  
         {
 675  
             //
 676  0
         }
 677  0
         if (lookupMethod != null)
 678  
         {
 679  
             // Try with JNDI
 680  
             try
 681  
             {
 682  
                 // in an application server
 683  
                 //beanManager = InitialContext.doLookup("java:comp/BeanManager");
 684  0
                 beanManager = lookupMethod.invoke(icclazz, "java:comp/BeanManager");
 685  
             }
 686  0
             catch (Exception e)
 687  
             {
 688  
                 // silently ignore
 689  
             }
 690  0
             catch (NoClassDefFoundError e)
 691  
             {
 692  
                 //On Google App Engine, javax.naming.Context is a restricted class.
 693  
                 //In that case, NoClassDefFoundError is thrown. stageName needs to be configured
 694  
                 //below by context parameter.
 695  0
             }
 696  
 
 697  0
             if (beanManager == null)
 698  
             {
 699  
                 try
 700  
                 {
 701  
                     // in a servlet container
 702  
                     //beanManager = InitialContext.doLookup("java:comp/env/BeanManager");
 703  0
                     beanManager = lookupMethod.invoke(icclazz, "java:comp/env/BeanManager");
 704  
                 }
 705  0
                 catch (Exception e)
 706  
                 {
 707  
                     // silently ignore
 708  
                 }
 709  0
                 catch (NoClassDefFoundError e)
 710  
                 {
 711  
                     //On Google App Engine, javax.naming.Context is a restricted class.
 712  
                     //In that case, NoClassDefFoundError is thrown. stageName needs to be configured
 713  
                     //below by context parameter.
 714  0
                 }
 715  
             }
 716  
         }
 717  
 
 718  0
         return beanManager;
 719  
     }
 720  
 
 721  
     public void _callPreDestroyOnInjectedJSFArtifacts(FacesContext facesContext)
 722  
     {
 723  0
         InjectionProvider injectionProvider = InjectionProviderFactory.getInjectionProviderFactory(
 724  
             facesContext.getExternalContext()).getInjectionProvider(facesContext.getExternalContext());
 725  0
         List<BeanEntry> injectedBeanStorage =
 726  
                 (List<BeanEntry>)facesContext.getExternalContext().getApplicationMap().get(INJECTED_BEAN_STORAGE_KEY);
 727  
 
 728  0
         if (injectedBeanStorage != null)
 729  
         {
 730  0
             for (BeanEntry entry : injectedBeanStorage)
 731  
             {
 732  
                 try
 733  
                 {
 734  0
                     injectionProvider.preDestroy(entry.getInstance(), entry.getCreationMetaData());
 735  
                 }
 736  0
                 catch (InjectionProviderException ex)
 737  
                 {
 738  0
                     log.log(Level.INFO, "Exception on PreDestroy", ex);
 739  0
                 }
 740  0
             }
 741  0
             injectedBeanStorage.clear();
 742  
         }
 743  0
     }
 744  
 }