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