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.config;
20  
21  import java.io.File;
22  import java.io.IOException;
23  import java.lang.reflect.Constructor;
24  import java.lang.reflect.InvocationTargetException;
25  import java.lang.reflect.Method;
26  import java.net.JarURLConnection;
27  import java.net.URL;
28  import java.net.URLConnection;
29  import java.util.ArrayList;
30  import java.util.Collection;
31  import java.util.Collections;
32  import java.util.Comparator;
33  import java.util.HashMap;
34  import java.util.Iterator;
35  import java.util.List;
36  import java.util.Locale;
37  import java.util.Map;
38  import java.util.Set;
39  import java.util.StringTokenizer;
40  import java.util.concurrent.CopyOnWriteArrayList;
41  import java.util.function.Predicate;
42  import java.util.logging.Level;
43  import java.util.logging.Logger;
44  
45  import javax.el.ELResolver;
46  import javax.faces.FacesException;
47  import javax.faces.FacesWrapper;
48  import javax.faces.FactoryFinder;
49  import javax.faces.application.Application;
50  import javax.faces.application.ApplicationFactory;
51  import javax.faces.application.ConfigurableNavigationHandler;
52  import javax.faces.application.NavigationHandler;
53  import javax.faces.application.ProjectStage;
54  import javax.faces.application.ResourceHandler;
55  import javax.faces.application.StateManager;
56  import javax.faces.application.ViewHandler;
57  import javax.faces.component.search.SearchExpressionHandler;
58  import javax.faces.component.search.SearchKeywordResolver;
59  import javax.faces.context.ExternalContext;
60  import javax.faces.context.FacesContext;
61  import javax.faces.el.PropertyResolver;
62  import javax.faces.el.VariableResolver;
63  import javax.faces.event.ActionListener;
64  import javax.faces.event.ComponentSystemEvent;
65  import javax.faces.event.PhaseListener;
66  import javax.faces.event.PostConstructApplicationEvent;
67  import javax.faces.event.PreDestroyCustomScopeEvent;
68  import javax.faces.event.PreDestroyViewMapEvent;
69  import javax.faces.event.SystemEvent;
70  import javax.faces.flow.FlowHandler;
71  import javax.faces.flow.FlowHandlerFactory;
72  import javax.faces.lifecycle.ClientWindow;
73  import javax.faces.lifecycle.Lifecycle;
74  import javax.faces.lifecycle.LifecycleFactory;
75  import javax.faces.render.RenderKit;
76  import javax.faces.render.RenderKitFactory;
77  import javax.faces.validator.BeanValidator;
78  import javax.faces.webapp.FacesServlet;
79  
80  import org.apache.myfaces.application.ApplicationFactoryImpl;
81  import org.apache.myfaces.application.BackwardsCompatibleNavigationHandlerWrapper;
82  import org.apache.myfaces.component.visit.VisitContextFactoryImpl;
83  import org.apache.myfaces.config.annotation.AnnotationConfigurator;
84  import org.apache.myfaces.config.annotation.LifecycleProvider;
85  import org.apache.myfaces.config.annotation.LifecycleProviderFactory;
86  import org.apache.myfaces.config.element.Behavior;
87  import org.apache.myfaces.config.element.ClientBehaviorRenderer;
88  import org.apache.myfaces.config.element.ComponentTagDeclaration;
89  import org.apache.myfaces.config.element.ContractMapping;
90  import org.apache.myfaces.config.element.FaceletsProcessing;
91  import org.apache.myfaces.config.element.FacesConfig;
92  import org.apache.myfaces.config.element.FacesConfigData;
93  import org.apache.myfaces.config.element.FacesFlowCall;
94  import org.apache.myfaces.config.element.FacesFlowDefinition;
95  import org.apache.myfaces.config.element.FacesFlowMethodCall;
96  import org.apache.myfaces.config.element.FacesFlowMethodParameter;
97  import org.apache.myfaces.config.element.FacesFlowParameter;
98  import org.apache.myfaces.config.element.FacesFlowReturn;
99  import org.apache.myfaces.config.element.FacesFlowSwitch;
100 import org.apache.myfaces.config.element.FacesFlowView;
101 import org.apache.myfaces.config.element.ManagedBean;
102 import org.apache.myfaces.config.element.NamedEvent;
103 import org.apache.myfaces.config.element.NavigationCase;
104 import org.apache.myfaces.config.element.NavigationRule;
105 import org.apache.myfaces.config.element.Renderer;
106 import org.apache.myfaces.config.element.ResourceBundle;
107 import org.apache.myfaces.config.element.SystemEventListener;
108 import org.apache.myfaces.config.impl.digester.DigesterFacesConfigDispenserImpl;
109 import org.apache.myfaces.config.impl.digester.DigesterFacesConfigUnmarshallerImpl;
110 import org.apache.myfaces.context.ExceptionHandlerFactoryImpl;
111 import org.apache.myfaces.context.ExternalContextFactoryImpl;
112 import org.apache.myfaces.context.FacesContextFactoryImpl;
113 import org.apache.myfaces.context.PartialViewContextFactoryImpl;
114 import org.apache.myfaces.context.servlet.ServletFlashFactoryImpl;
115 import org.apache.myfaces.el.DefaultPropertyResolver;
116 import org.apache.myfaces.el.VariableResolverImpl;
117 import org.apache.myfaces.el.unified.ResolverBuilderBase;
118 import org.apache.myfaces.lifecycle.ClientWindowFactoryImpl;
119 import org.apache.myfaces.flow.FlowCallNodeImpl;
120 import org.apache.myfaces.flow.FlowHandlerFactoryImpl;
121 import org.apache.myfaces.flow.FlowImpl;
122 import org.apache.myfaces.flow.MethodCallNodeImpl;
123 import org.apache.myfaces.flow.ParameterImpl;
124 import org.apache.myfaces.flow.ReturnNodeImpl;
125 import org.apache.myfaces.flow.SwitchCaseImpl;
126 import org.apache.myfaces.flow.SwitchNodeImpl;
127 import org.apache.myfaces.flow.ViewNodeImpl;
128 import org.apache.myfaces.flow.impl.AnnotatedFlowConfigurator;
129 import org.apache.myfaces.lifecycle.LifecycleFactoryImpl;
130 import org.apache.myfaces.renderkit.RenderKitFactoryImpl;
131 import org.apache.myfaces.renderkit.html.HtmlRenderKitImpl;
132 import org.apache.myfaces.shared.config.MyfacesConfig;
133 import org.apache.myfaces.shared.util.ClassUtils;
134 import org.apache.myfaces.shared.util.LocaleUtils;
135 import org.apache.myfaces.shared.util.StateUtils;
136 import org.apache.myfaces.shared.util.StringUtils;
137 import org.apache.myfaces.shared.util.WebConfigParamUtils;
138 import org.apache.myfaces.shared_impl.util.serial.DefaultSerialFactory;
139 import org.apache.myfaces.shared_impl.util.serial.SerialFactory;
140 import org.apache.myfaces.cdi.util.BeanEntry;
141 import org.apache.myfaces.component.search.SearchExpressionContextFactoryImpl;
142 import org.apache.myfaces.config.element.FaceletsTemplateMapping;
143 import org.apache.myfaces.config.element.ViewPoolMapping;
144 import org.apache.myfaces.config.element.facelets.FaceletTagLibrary;
145 import org.apache.myfaces.lifecycle.LifecycleImpl;
146 import org.apache.myfaces.renderkit.LazyRenderKit;
147 import org.apache.myfaces.spi.FacesConfigurationMerger;
148 import org.apache.myfaces.spi.FacesConfigurationMergerFactory;
149 import org.apache.myfaces.spi.InjectionProvider;
150 import org.apache.myfaces.spi.InjectionProviderException;
151 import org.apache.myfaces.spi.InjectionProviderFactory;
152 import org.apache.myfaces.spi.ResourceLibraryContractsProvider;
153 import org.apache.myfaces.spi.ResourceLibraryContractsProviderFactory;
154 import org.apache.myfaces.util.ContainerUtils;
155 import org.apache.myfaces.util.ExternalSpecifications;
156 import org.apache.myfaces.util.NavigationUtils;
157 import org.apache.myfaces.view.ViewDeclarationLanguageFactoryImpl;
158 import org.apache.myfaces.view.facelets.el.ELText;
159 import org.apache.myfaces.view.facelets.impl.FaceletCacheFactoryImpl;
160 import org.apache.myfaces.view.facelets.tag.jsf.TagHandlerDelegateFactoryImpl;
161 import org.apache.myfaces.view.facelets.tag.ui.DebugPhaseListener;
162 import org.apache.myfaces.webapp.ManagedBeanDestroyerListener;
163 
164 /**
165  * Configures everything for a given context. The FacesConfigurator is independent of the concrete implementations that
166  * lie behind FacesConfigUnmarshaller and FacesConfigDispenser.
167  *
168  * @author Manfred Geiler (latest modification by $Author$)
169  * @version $Revision$ $Date$
170  */
171 @SuppressWarnings("deprecation")
172 public class FacesConfigurator
173 {
174     private final Class<?>[] NO_PARAMETER_TYPES = new Class[]{};
175     private final Object[] NO_PARAMETERS = new Object[]{};
176 
177     private static final Logger log = Logger.getLogger(FacesConfigurator.class.getName());
178 
179     private static final String DEFAULT_RENDER_KIT_CLASS = HtmlRenderKitImpl.class.getName();
180     private static final String DEFAULT_APPLICATION_FACTORY = ApplicationFactoryImpl.class.getName();
181     private static final String DEFAULT_EXTERNAL_CONTEXT_FACTORY = ExternalContextFactoryImpl.class.getName();
182     private static final String DEFAULT_FACES_CONTEXT_FACTORY = FacesContextFactoryImpl.class.getName();
183     private static final String DEFAULT_LIFECYCLE_FACTORY = LifecycleFactoryImpl.class.getName();
184     private static final String DEFAULT_RENDER_KIT_FACTORY = RenderKitFactoryImpl.class.getName();
185     private static final String DEFAULT_PARTIAL_VIEW_CONTEXT_FACTORY = PartialViewContextFactoryImpl.class.getName();
186     private static final String DEFAULT_VISIT_CONTEXT_FACTORY = VisitContextFactoryImpl.class.getName();
187     private static final String DEFAULT_VIEW_DECLARATION_LANGUAGE_FACTORY
188             = ViewDeclarationLanguageFactoryImpl.class.getName();
189     private static final String DEFAULT_EXCEPTION_HANDLER_FACTORY = ExceptionHandlerFactoryImpl.class.getName();
190     private static final String DEFAULT_TAG_HANDLER_DELEGATE_FACTORY = TagHandlerDelegateFactoryImpl.class.getName();
191     private static final String DEFAULT_FACELET_CACHE_FACTORY = FaceletCacheFactoryImpl.class.getName();
192     private static final String DEFAULT_FLASH_FACTORY = ServletFlashFactoryImpl.class.getName();
193     private static final String DEFAULT_CLIENT_WINDOW_FACTORY = ClientWindowFactoryImpl.class.getName();
194     private static final String DEFAULT_FLOW_FACTORY = FlowHandlerFactoryImpl.class.getName();
195     private static final String DEFAULT_SEARCH_EXPRESSION_CONTEXT_FACTORY = 
196             SearchExpressionContextFactoryImpl.class.getName();
197     private static final String DEFAULT_FACES_CONFIG = "/WEB-INF/faces-config.xml";
198 
199     private static final String INJECTED_BEAN_STORAGE_KEY = "org.apache.myfaces.spi.BEAN_ENTRY_STORAGE";
200 
201     /**
202      * Set this attribute if the current configuration requires enable window mode
203      */
204     public static final String ENABLE_DEFAULT_WINDOW_MODE = 
205         "org.apache.myfaces.ENABLE_DEFAULT_WINDOW_MODE";
206     
207     private final static String PARAM_FACELETS_LIBRARIES_DEPRECATED = "facelets.LIBRARIES";
208     private final static String[] PARAMS_FACELETS_LIBRARIES = {ViewHandler.FACELETS_LIBRARIES_PARAM_NAME,
209         PARAM_FACELETS_LIBRARIES_DEPRECATED};
210 
211     private final ExternalContext _externalContext;
212     private FacesContext _facesContext;
213     private FacesConfigUnmarshaller<? extends FacesConfig> _unmarshaller;
214     private FacesConfigData _dispenser;
215     private AnnotationConfigurator _annotationConfigurator;
216 
217     private RuntimeConfig _runtimeConfig;
218     
219     private Application _application;
220     
221     private InjectionProvider _injectionProvider;
222 
223     private static long lastUpdate;
224 
225     public FacesConfigurator(ExternalContext externalContext)
226     {
227         if (externalContext == null)
228         {
229             throw new IllegalArgumentException("external context must not be null");
230         }
231         _externalContext = externalContext;
232 
233         // In dev mode a new Faces Configurator is created for every request so only
234         // create a new bean storage list if we don't already have one which will be
235         // the case first time through during init.
236         if (_externalContext.getApplicationMap().get(INJECTED_BEAN_STORAGE_KEY) == null) 
237         {
238             _externalContext.getApplicationMap().put(INJECTED_BEAN_STORAGE_KEY, new CopyOnWriteArrayList());
239         }
240     }
241 
242     /**
243      * @param unmarshaller
244      *            the unmarshaller to set
245      */
246     public void setUnmarshaller(FacesConfigUnmarshaller<? extends FacesConfig> unmarshaller)
247     {
248         _unmarshaller = unmarshaller;
249     }
250 
251     /**
252      * @return the unmarshaller
253      */
254     protected FacesConfigUnmarshaller<? extends FacesConfig> getUnmarshaller()
255     {
256         if (_unmarshaller == null)
257         {
258             _unmarshaller = new DigesterFacesConfigUnmarshallerImpl(_externalContext);
259         }
260 
261         return _unmarshaller;
262     }
263 
264     /**
265      * @param dispenser
266      *            the dispenser to set
267      */
268     public void setDispenser(FacesConfigData dispenser)
269     {
270         _dispenser = dispenser;
271     }
272 
273     /**
274      * @return the dispenser
275      */
276     protected FacesConfigData getDispenser()
277     {
278         if (_dispenser == null)
279         {
280             _dispenser = new DigesterFacesConfigDispenserImpl();
281         }
282 
283         return _dispenser;
284     }
285 
286     public void setAnnotationConfigurator(AnnotationConfigurator configurator)
287     {
288         _annotationConfigurator = configurator;
289     }
290 
291     protected AnnotationConfigurator getAnnotationConfigurator()
292     {
293         if (_annotationConfigurator == null)
294         {
295             _annotationConfigurator = new AnnotationConfigurator();
296         }
297         return _annotationConfigurator;
298     }
299 
300     private long getResourceLastModified(String resource)
301     {
302         try
303         {
304             URL url = _externalContext.getResource(resource);
305             if (url != null)
306             {
307                 return getResourceLastModified(url);
308             }
309         }
310         catch (IOException e)
311         {
312             log.log(Level.SEVERE, "Could not read resource " + resource, e);
313         }
314         return 0;
315     }
316 
317     //Taken from trinidad URLUtils
318     private long getResourceLastModified(URL url) throws IOException
319     {
320         if ("file".equals(url.getProtocol()))
321         {
322             String externalForm = url.toExternalForm();
323             // Remove the "file:"
324             File file = new File(externalForm.substring(5));
325 
326             return file.lastModified();
327         }
328         else
329         {
330             return getResourceLastModified(url.openConnection());
331         }
332     }
333 
334     //Taken from trinidad URLUtils
335     private long getResourceLastModified(URLConnection connection) throws IOException
336     {
337         long modified;
338         if (connection instanceof JarURLConnection)
339         {
340             // The following hack is required to work-around a JDK bug.
341             // getLastModified() on a JAR entry URL delegates to the actual JAR file
342             // rather than the JAR entry.
343             // This opens internally, and does not close, an input stream to the JAR
344             // file.
345             // In turn, you cannot close it by yourself, because it's internal.
346             // The work-around is to get the modification date of the JAR file
347             // manually,
348             // and then close that connection again.
349 
350             URL jarFileUrl = ((JarURLConnection) connection).getJarFileURL();
351             URLConnection jarFileConnection = jarFileUrl.openConnection();
352 
353             try
354             {
355                 modified = jarFileConnection.getLastModified();
356             }
357             finally
358             {
359                 try
360                 {
361                     jarFileConnection.getInputStream().close();
362                 }
363                 catch (Exception exception)
364                 {
365                     // Ignored
366                 }
367             }
368         }
369         else
370         {
371             modified = connection.getLastModified();
372         }
373 
374         return modified;
375     }
376 
377     private long getLastModifiedTime()
378     {
379         long lastModified = 0;
380         long resModified;
381 
382         resModified = getResourceLastModified(DEFAULT_FACES_CONFIG);
383         if (resModified > lastModified)
384         {
385             lastModified = resModified;
386         }
387 
388         // perf: method getConfigFilesList() creates a ArrayList    
389         List<String> configFilesList = getConfigFilesList();
390         for (int i = 0, size = configFilesList.size(); i < size; i++)
391         {
392             String systemId = configFilesList.get(i);
393             resModified = getResourceLastModified(systemId);
394             if (resModified > lastModified)
395             {
396                 lastModified = resModified;
397             }
398         }
399         
400         // get last modified from .taglib.xml
401         String faceletsFiles = WebConfigParamUtils.getStringInitParameter(_externalContext, 
402                 PARAMS_FACELETS_LIBRARIES);
403         if (faceletsFiles != null)
404         {
405             String[] faceletFilesList = StringUtils.trim(faceletsFiles.split(";"));
406             for (int i = 0, size = faceletFilesList.length; i < size; i++)
407             {
408                 String systemId = faceletFilesList[i];
409                 resModified = getResourceLastModified(systemId);
410                 if (resModified > lastModified)
411                 {
412                     lastModified = resModified;
413                 }
414             }
415         }
416         
417         // get last modified from -flow.xml
418         Set<String> directoryPaths = _externalContext.getResourcePaths("/");
419         if (directoryPaths != null)
420         {
421             List<String> contextSpecifiedList = configFilesList;
422             for (String dirPath : directoryPaths)
423             {
424                 if (dirPath.equals("/WEB-INF/"))
425                 {
426                     // Look on /WEB-INF/<flow-Name>/<flowName>-flow.xml
427                     Set<String> webDirectoryPaths = _externalContext.getResourcePaths(dirPath);
428                     for (String webDirPath : webDirectoryPaths)
429                     {
430                         if (webDirPath.endsWith("/") && 
431                             !webDirPath.equals("/WEB-INF/classes/"))
432                         {
433                             String flowName = webDirPath.substring(9, webDirPath.length() - 1);
434                             String filePath = webDirPath+flowName+"-flow.xml";
435                             if (!contextSpecifiedList.contains(filePath))
436                             {
437                                 resModified = getResourceLastModified(filePath);
438                                 if (resModified > lastModified)
439                                 {
440                                     lastModified = resModified;
441                                 }
442                             }
443                         }
444                     }
445                 }
446                 else if (!dirPath.startsWith("/META-INF") && dirPath.endsWith("/"))
447                 {
448                     // Look on /<flowName>/<flowName>-flow.xml
449                     String flowName = dirPath.substring(1, dirPath.length() - 1);
450                     String filePath = dirPath+flowName+"-flow.xml";
451                     if (!contextSpecifiedList.contains(filePath))
452                     {
453                         resModified = getResourceLastModified(filePath);
454                         if (resModified > lastModified)
455                         {
456                             lastModified = resModified;
457                         }
458                     }
459                 }                
460             }
461         }
462         
463         return lastModified;
464     }
465 
466     public void update()
467     {
468         //Google App Engine does not allow to get last modified time of a file; 
469         //and when an application is running on GAE there is no way to update faces config xml file.
470         //thus, no need to check if the config file is modified.
471         if (ContainerUtils.isRunningOnGoogleAppEngine(_externalContext))
472         {
473             return;
474         }
475         long refreshPeriod = (MyfacesConfig.getCurrentInstance(_externalContext).getConfigRefreshPeriod()) * 1000;
476 
477         if (refreshPeriod > 0)
478         {
479             long ttl = lastUpdate + refreshPeriod;
480             if ((System.currentTimeMillis() > ttl) && (getLastModifiedTime() > ttl))
481             {
482                 boolean purged = false;
483                 try
484                 {
485                     purged = purgeConfiguration();
486                 }
487                 catch (NoSuchMethodException e)
488                 {
489                     log.severe("Configuration objects do not support clean-up. Update aborted");
490 
491                     // We still want to update the timestamp to avoid running purge on every subsequent
492                     // request after this one.
493                     //
494                     lastUpdate = System.currentTimeMillis();
495 
496                     return;
497                 }
498                 catch (IllegalAccessException e)
499                 {
500                     log.severe("Error during configuration clean-up" + e.getMessage());
501                 }
502                 catch (InvocationTargetException e)
503                 {
504                     log.severe("Error during configuration clean-up" + e.getMessage());
505                 }
506                 if (purged)
507                 {
508                     configure();
509                     
510                     // JSF 2.0 Publish PostConstructApplicationEvent after all configuration resources
511                     // has been parsed and processed
512                     FacesContext facesContext = getFacesContext();
513                     Application application = facesContext.getApplication();
514 
515                     application.publishEvent(facesContext, PostConstructApplicationEvent.class,
516                             Application.class, application);
517                 }
518             }
519         }
520     }
521 
522     private boolean purgeConfiguration() throws NoSuchMethodException, IllegalAccessException, InvocationTargetException
523     {
524 
525         Method appFactoryPurgeMethod;
526         Method renderKitPurgeMethod;
527         Method lifecyclePurgeMethod;
528         Method facesContextPurgeMethod;
529 
530         // Check that we have access to all of the necessary purge methods before purging anything
531         //
532         ApplicationFactory applicationFactory
533                 = (ApplicationFactory) FactoryFinder.getFactory(FactoryFinder.APPLICATION_FACTORY);
534         //appFactoryPurgeMethod = applicationFactory.getClass().getMethod("purgeApplication", NO_PARAMETER_TYPES);
535         appFactoryPurgeMethod = getPurgeMethod(applicationFactory, "purgeApplication", NO_PARAMETER_TYPES);
536 
537         RenderKitFactory renderKitFactory
538                 = (RenderKitFactory) FactoryFinder.getFactory(FactoryFinder.RENDER_KIT_FACTORY);
539         //renderKitPurgeMethod = renderKitFactory.getClass().getMethod("purgeRenderKit", NO_PARAMETER_TYPES);
540         renderKitPurgeMethod = getPurgeMethod(renderKitFactory, "purgeRenderKit", NO_PARAMETER_TYPES);
541 
542         LifecycleFactory lifecycleFactory
543                 = (LifecycleFactory) FactoryFinder.getFactory(FactoryFinder.LIFECYCLE_FACTORY);
544         //lifecyclePurgeMethod = lifecycleFactory.getClass().getMethod("purgeLifecycle", NO_PARAMETER_TYPES);
545         lifecyclePurgeMethod = getPurgeMethod(lifecycleFactory, "purgeLifecycle", NO_PARAMETER_TYPES);
546 
547         FacesContext facesContext = getFacesContext();
548         facesContextPurgeMethod = getPurgeMethod(facesContext, "purgeFacesContext", NO_PARAMETER_TYPES);
549         
550         // If there was no exception so far, now we can purge
551         //
552         if (appFactoryPurgeMethod != null && renderKitPurgeMethod != null && lifecyclePurgeMethod != null && 
553             facesContextPurgeMethod != null)
554         {
555             appFactoryPurgeMethod.invoke(applicationFactory, NO_PARAMETERS);
556             renderKitPurgeMethod.invoke(renderKitFactory, NO_PARAMETERS);
557             RuntimeConfig.getCurrentInstance(_externalContext).purge();
558             lifecyclePurgeMethod.invoke(lifecycleFactory, NO_PARAMETERS);
559             facesContextPurgeMethod.invoke(facesContext, NO_PARAMETERS);
560 
561             // factories and serial factory need not be purged...
562 
563             // Remove first request processed so we can initialize it again
564             _externalContext.getApplicationMap().remove(LifecycleImpl.FIRST_REQUEST_PROCESSED_PARAM);
565             return true;
566         }
567         return false;
568     }
569     
570     private Method getPurgeMethod(Object instance, String methodName, Class<?>[] parameters)
571     {
572         while (instance != null)
573         {
574             Method purgeMethod = null;
575             try
576             {
577                 purgeMethod = instance.getClass().getMethod(methodName, parameters);
578             }
579             catch (NoSuchMethodException e)
580             {
581                 // No op, it is expected to found this case, so in that case
582                 // look for the parent to do the purge
583             }
584             if (purgeMethod != null)
585             {
586                 return purgeMethod;
587             }
588             if (instance instanceof FacesWrapper)
589             {
590                 instance = ((FacesWrapper)instance).getWrapped();
591             }
592         }
593         return null;
594     }
595 
596     public void configure() throws FacesException
597     {
598         // get FacesConfigurationMerger SPI implementation
599         FacesConfigurationMerger facesConfigurationMerger = FacesConfigurationMergerFactory
600                 .getFacesConfigurationMergerFactory(_externalContext).getFacesConfigurationMerger(_externalContext);
601 
602         // get all faces-config data, merge it and set it as Dispenser
603         setDispenser(facesConfigurationMerger.getFacesConfigData(_externalContext));
604 
605         configureFactories();
606         configureApplication();
607         configureRenderKits();
608 
609         //Now we can configure annotations
610         //getAnnotationConfigurator().configure(
611         //        ((ApplicationFactory) FactoryFinder.getFactory(
612         //                FactoryFinder.APPLICATION_FACTORY)).getApplication(),
613         //        getDispenser(), metadataComplete);
614 
615         configureRuntimeConfig();
616         configureLifecycle();
617         handleSerialFactory();
618         configureManagedBeanDestroyer();
619         configureFlowHandler();
620 
621         configureProtectedViews();
622         
623         // record the time of update
624         lastUpdate = System.currentTimeMillis();
625     }
626 
627     private List<String> getConfigFilesList()
628     {
629         String configFiles = _externalContext.getInitParameter(FacesServlet.CONFIG_FILES_ATTR);
630         List<String> configFilesList = new ArrayList<String>();
631         if (configFiles != null)
632         {
633             StringTokenizer st = new StringTokenizer(configFiles, ",", false);
634             while (st.hasMoreTokens())
635             {
636                 String systemId = st.nextToken().trim();
637 
638                 if (DEFAULT_FACES_CONFIG.equals(systemId))
639                 {
640                     if (log.isLoggable(Level.WARNING))
641                     {
642                         log.warning(DEFAULT_FACES_CONFIG + " has been specified in the "
643                                 + FacesServlet.CONFIG_FILES_ATTR
644                                 + " context parameter of "
645                                 + "the deployment descriptor. This will automatically be removed, "
646                                 + "if we wouldn't do this, it would be loaded twice.  See JSF spec 1.1, 10.3.2");
647                     }
648                 }
649                 else
650                 {
651                     configFilesList.add(systemId);
652                 }
653             }
654         }
655         return configFilesList;
656     }
657 
658     private void configureFactories()
659     {
660         FacesConfigData dispenser = getDispenser();
661         setFactories(FactoryFinder.APPLICATION_FACTORY, dispenser.getApplicationFactoryIterator(),
662                 DEFAULT_APPLICATION_FACTORY);
663         setFactories(FactoryFinder.EXCEPTION_HANDLER_FACTORY, dispenser.getExceptionHandlerFactoryIterator(),
664                 DEFAULT_EXCEPTION_HANDLER_FACTORY);
665         setFactories(FactoryFinder.EXTERNAL_CONTEXT_FACTORY, dispenser.getExternalContextFactoryIterator(),
666                 DEFAULT_EXTERNAL_CONTEXT_FACTORY);
667         setFactories(FactoryFinder.FACES_CONTEXT_FACTORY, dispenser.getFacesContextFactoryIterator(),
668                 DEFAULT_FACES_CONTEXT_FACTORY);
669         setFactories(FactoryFinder.LIFECYCLE_FACTORY, dispenser.getLifecycleFactoryIterator(),
670                 DEFAULT_LIFECYCLE_FACTORY);
671         setFactories(FactoryFinder.RENDER_KIT_FACTORY, dispenser.getRenderKitFactoryIterator(),
672                 DEFAULT_RENDER_KIT_FACTORY);
673         setFactories(FactoryFinder.TAG_HANDLER_DELEGATE_FACTORY, dispenser.getTagHandlerDelegateFactoryIterator(),
674                 DEFAULT_TAG_HANDLER_DELEGATE_FACTORY);
675         setFactories(FactoryFinder.PARTIAL_VIEW_CONTEXT_FACTORY, dispenser.getPartialViewContextFactoryIterator(),
676                 DEFAULT_PARTIAL_VIEW_CONTEXT_FACTORY);
677         setFactories(FactoryFinder.VISIT_CONTEXT_FACTORY, dispenser.getVisitContextFactoryIterator(),
678                 DEFAULT_VISIT_CONTEXT_FACTORY);
679         setFactories(FactoryFinder.VIEW_DECLARATION_LANGUAGE_FACTORY,
680                 dispenser.getViewDeclarationLanguageFactoryIterator(),
681                 DEFAULT_VIEW_DECLARATION_LANGUAGE_FACTORY);
682         setFactories(FactoryFinder.FACELET_CACHE_FACTORY, dispenser.getFaceletCacheFactoryIterator(),
683                 DEFAULT_FACELET_CACHE_FACTORY);
684         setFactories(FactoryFinder.FLASH_FACTORY, dispenser.getFlashFactoryIterator(),
685                 DEFAULT_FLASH_FACTORY);
686         setFactories(FactoryFinder.CLIENT_WINDOW_FACTORY, dispenser.getClientWindowFactoryIterator(),
687                 DEFAULT_CLIENT_WINDOW_FACTORY);
688         setFactories(FactoryFinder.FLOW_HANDLER_FACTORY, dispenser.getFlowHandlerFactoryIterator(),
689                 DEFAULT_FLOW_FACTORY);
690         setFactories(FactoryFinder.SEARCH_EXPRESSION_CONTEXT_FACTORY, 
691                 dispenser.getSearchExpressionContextFactoryIterator(),
692                 DEFAULT_SEARCH_EXPRESSION_CONTEXT_FACTORY);
693     }
694 
695     private void setFactories(String factoryName, Collection<String> factories, String defaultFactory)
696     {
697         FactoryFinder.setFactory(factoryName, defaultFactory);
698         for (String factory : factories)
699         {
700             if (!factory.equals(defaultFactory))
701             {
702                 FactoryFinder.setFactory(factoryName, factory);
703             }
704         }
705     }
706 
707     private void configureApplication()
708     {
709         Application application = ((ApplicationFactory)
710                 FactoryFinder.getFactory(FactoryFinder.APPLICATION_FACTORY)).getApplication();
711 
712         FacesConfigData dispenser = getDispenser();
713         ActionListener actionListener = ClassUtils.buildApplicationObject(ActionListener.class,
714                 dispenser.getActionListenerIterator(), null);
715         _callInjectAndPostConstruct(actionListener);
716         application.setActionListener(actionListener);
717 
718         if (dispenser.getDefaultLocale() != null)
719         {
720             application.setDefaultLocale(LocaleUtils.toLocale(dispenser.getDefaultLocale()));
721         }
722 
723         if (dispenser.getDefaultRenderKitId() != null)
724         {
725             application.setDefaultRenderKitId(dispenser.getDefaultRenderKitId());
726         }
727 
728         if (dispenser.getMessageBundle() != null)
729         {
730             application.setMessageBundle(dispenser.getMessageBundle());
731         }
732         
733         // First build the object
734         NavigationHandler navigationHandler = ClassUtils.buildApplicationObject(NavigationHandler.class,
735                 ConfigurableNavigationHandler.class, null,
736                 dispenser.getNavigationHandlerIterator(),
737                 application.getNavigationHandler());
738         // Invoke inject and post construct
739         _callInjectAndPostConstruct(navigationHandler);
740         // Finally wrap the object with the BackwardsCompatibleNavigationHandlerWrapper if it is not assignable
741         // from ConfigurableNavigationHandler
742         navigationHandler = ClassUtils.wrapBackwardCompatible(NavigationHandler.class,
743                 ConfigurableNavigationHandler.class,
744                 BackwardsCompatibleNavigationHandlerWrapper.class,
745                 application.getNavigationHandler(),
746                 navigationHandler);
747         application.setNavigationHandler(navigationHandler);
748 
749         StateManager stateManager = ClassUtils.buildApplicationObject(StateManager.class,
750                 dispenser.getStateManagerIterator(),
751                 application.getStateManager());
752         _callInjectAndPostConstruct(stateManager);
753         application.setStateManager(stateManager);
754 
755         ResourceHandler resourceHandler = ClassUtils.buildApplicationObject(ResourceHandler.class,
756                 dispenser.getResourceHandlerIterator(),
757                 application.getResourceHandler());
758         _callInjectAndPostConstruct(resourceHandler);
759         application.setResourceHandler(resourceHandler);
760 
761         List<Locale> locales = new ArrayList<Locale>();
762         for (String locale : dispenser.getSupportedLocalesIterator())
763         {
764             locales.add(LocaleUtils.toLocale(locale));
765         }
766 
767         application.setSupportedLocales(locales);
768 
769         application.setViewHandler(ClassUtils.buildApplicationObject(ViewHandler.class,
770                 dispenser.getViewHandlerIterator(),
771                 application.getViewHandler()));
772         
773         application.setSearchExpressionHandler(ClassUtils.buildApplicationObject(SearchExpressionHandler.class,
774                 dispenser.getSearchExpressionHandlerIterator(),
775                 application.getSearchExpressionHandler()));
776         
777         RuntimeConfig runtimeConfig = getRuntimeConfig();
778         
779         for (SystemEventListener systemEventListener : dispenser.getSystemEventListeners())
780         {
781 
782 
783             try
784             {
785                 //note here used to be an instantiation to deal with the explicit source type in the registration,
786                 // that cannot work because all system events need to have the source being passed in the constructor
787                 //instead we now  rely on the standard system event types and map them to their appropriate
788                 // constructor types
789                 Class eventClass = ClassUtils.classForName((systemEventListener.getSystemEventClass() != null)
790                         ? systemEventListener.getSystemEventClass()
791                         : SystemEvent.class.getName());
792 
793                 javax.faces.event.SystemEventListener listener = (javax.faces.event.SystemEventListener) 
794                         ClassUtils.newInstance(systemEventListener.getSystemEventListenerClass());
795                 _callInjectAndPostConstruct(listener);
796                 runtimeConfig.addInjectedObject(listener);
797                 if (systemEventListener.getSourceClass() != null && systemEventListener.getSourceClass().length() > 0)
798                 {
799                     application.subscribeToEvent(
800                             (Class<? extends SystemEvent>) eventClass,
801                             ClassUtils.classForName(systemEventListener.getSourceClass()),
802                                     listener);
803                 }
804                 else
805                 {
806                     application.subscribeToEvent(
807                             (Class<? extends SystemEvent>) eventClass,
808                             listener);
809                 }
810             }
811             catch (ClassNotFoundException e)
812             {
813                 log.log(Level.SEVERE, "System event listener could not be initialized, reason:", e);
814             }
815         }
816 
817         for (Map.Entry<String, String> entry : dispenser.getComponentClassesByType().entrySet())
818         {
819             application.addComponent(entry.getKey(), entry.getValue());
820         }
821 
822         for (Map.Entry<String, String> entry : dispenser.getConverterClassesById().entrySet())
823         {
824             application.addConverter(entry.getKey(), entry.getValue());
825         }
826 
827         for (Map.Entry<String, String> entry : dispenser.getConverterClassesByClass().entrySet())
828         {
829             try
830             {
831                 application.addConverter(ClassUtils.simpleClassForName(entry.getKey()),
832                         entry.getValue());
833             }
834             catch (Exception ex)
835             {
836                 log.log(Level.SEVERE, "Converter could not be added. Reason:", ex);
837             }
838         }
839 
840         for (Map.Entry<String, String> entry : dispenser.getValidatorClassesById().entrySet())
841         {
842             application.addValidator(entry.getKey(), entry.getValue());
843         }
844 
845         // programmatically add the BeanValidator if the following requirements are met:
846         //     - bean validation has not been disabled
847         //     - bean validation is available in the classpath
848         String beanValidatorDisabled = _externalContext.getInitParameter(
849                 BeanValidator.DISABLE_DEFAULT_BEAN_VALIDATOR_PARAM_NAME);
850         final boolean defaultBeanValidatorDisabled = (beanValidatorDisabled != null
851                 && beanValidatorDisabled.toLowerCase().equals("true"));
852         boolean beanValidatorInstalledProgrammatically = false;
853         if (!defaultBeanValidatorDisabled
854                 && ExternalSpecifications.isBeanValidationAvailable())
855         {
856             // add the BeanValidator as default validator
857             application.addDefaultValidatorId(BeanValidator.VALIDATOR_ID);
858             beanValidatorInstalledProgrammatically = true;
859         }
860 
861         // add the default-validators from the config files
862         for (String validatorId : dispenser.getDefaultValidatorIds())
863         {
864             application.addDefaultValidatorId(validatorId);
865         }
866 
867         // do some checks if the BeanValidator was not installed as a
868         // default-validator programmatically, but via a config file.
869         if (!beanValidatorInstalledProgrammatically
870                 && application.getDefaultValidatorInfo()
871                 .containsKey(BeanValidator.VALIDATOR_ID))
872         {
873             if (!ExternalSpecifications.isBeanValidationAvailable())
874             {
875                 // the BeanValidator was installed via a config file,
876                 // but bean validation is not available
877                 log.log(Level.WARNING, "The BeanValidator was installed as a " +
878                         "default-validator from a faces-config file, but bean " +
879                         "validation is not available on the classpath, " +
880                         "thus it will not work!");
881             }
882             else if (defaultBeanValidatorDisabled)
883             {
884                 // the user disabled the default bean validator in web.xml,
885                 // but a config file added it, which is ok with the spec
886                 // (section 11.1.3: "though manual installation is still possible")
887                 // --> inform the user about this scenario
888                 log.log(Level.INFO, "The BeanValidator was disabled as a " +
889                         "default-validator via the config parameter " +
890                         BeanValidator.DISABLE_DEFAULT_BEAN_VALIDATOR_PARAM_NAME +
891                         " in web.xml, but a faces-config file added it, " +
892                         "thus it actually was installed as a default-validator.");
893             }
894         }
895 
896         for (Behavior behavior : dispenser.getBehaviors())
897         {
898             application.addBehavior(behavior.getBehaviorId(), behavior.getBehaviorClass());
899         }
900         
901         //JSF 2.2 set FlowHandler from factory. 
902         FlowHandlerFactory flowHandlerFactory = (FlowHandlerFactory) 
903             FactoryFinder.getFactory(FactoryFinder.FLOW_HANDLER_FACTORY);
904         FlowHandler flowHandler = flowHandlerFactory.createFlowHandler(
905             getFacesContext());
906         application.setFlowHandler(flowHandler);
907 
908         if (MyfacesConfig.getCurrentInstance(_externalContext).isSupportJSPAndFacesEL())
909         {
910             // If no JSP and old Faces EL, there is no need to initialize PropertyResolver
911             // and VariableResolver stuff.
912             runtimeConfig.setPropertyResolverChainHead(ClassUtils.buildApplicationObject(PropertyResolver.class,
913                     dispenser.getPropertyResolverIterator(),
914                     new DefaultPropertyResolver()));
915     
916             runtimeConfig.setVariableResolverChainHead(ClassUtils.buildApplicationObject(VariableResolver.class,
917                     dispenser.getVariableResolverIterator(),
918                     new VariableResolverImpl()));
919         }
920         
921         for (ContractMapping mapping : dispenser.getResourceLibraryContractMappings())
922         {
923             if (mapping.getUrlPattern() != null)
924             {
925                 // Deprecated way
926                 String urlPattern = mapping.getUrlPattern();
927                 String[] contracts = StringUtils.trim(StringUtils.splitShortString(mapping.getContracts(), ' '));
928                 runtimeConfig.addContractMapping(urlPattern, contracts);
929             }
930             else
931             {
932                 List<String> urlMappingsList = mapping.getUrlPatternList();
933                 for (String urlPattern: urlMappingsList)
934                 {
935                     for (String contract : mapping.getContractList())
936                     {
937                         String[] contracts = StringUtils.trim(StringUtils.splitShortString(contract, ' '));
938                         runtimeConfig.addContractMapping(urlPattern, contracts);
939                     }
940                 }
941             }
942         }
943         
944         this.setApplication(application);
945     }
946     
947     private void _callInjectAndPostConstruct(Object instance)
948     {
949         try
950         {
951             //invoke the injection over the inner one first
952             if (instance instanceof FacesWrapper)
953             {
954                 Object innerInstance = ((FacesWrapper)instance).getWrapped();
955                 if (innerInstance != null)
956                 {
957                     _callInjectAndPostConstruct(innerInstance);
958                 }
959             }
960             List<BeanEntry> injectedBeanStorage =
961                     (List<BeanEntry>)_externalContext.getApplicationMap().get(INJECTED_BEAN_STORAGE_KEY);
962 
963             Object creationMetaData = getInjectionProvider().inject(instance);
964 
965             injectedBeanStorage.add(new BeanEntry(instance, creationMetaData));
966 
967             getInjectionProvider().postConstruct(instance, creationMetaData);
968         }
969         catch (InjectionProviderException ex)
970         {
971             log.log(Level.INFO, "Exception on PreDestroy", ex);
972         }
973     }
974 
975     /**
976      * A mapper for the handful of system listener defaults
977      * since every default mapper has the source type embedded
978      * in the constructor we can rely on introspection for the
979      * default mapping
980      *
981      * @param systemEventClass the system listener class which has to be checked
982      * @return
983      */
984     String getDefaultSourcClassForSystemEvent(Class systemEventClass)
985     {
986         Constructor[] constructors = systemEventClass.getConstructors();
987         for (Constructor constr : constructors)
988         {
989             Class[] parms = constr.getParameterTypes();
990             if (parms == null || parms.length != 1)
991             {
992                 //for standard types we have only one parameter representing the type
993                 continue;
994             }
995             return parms[0].getName();
996         }
997         log.warning("The SystemEvent source type for " + systemEventClass.getName()
998                 + " could not be detected, either register it manually or use a constructor argument "
999                 + "for auto detection, defaulting now to java.lang.Object");
1000         return "java.lang.Object";
1001     }
1002 
1003 
1004     protected RuntimeConfig getRuntimeConfig()
1005     {
1006         if (_runtimeConfig == null)
1007         {
1008             _runtimeConfig = RuntimeConfig.getCurrentInstance(_externalContext);
1009         }
1010         return _runtimeConfig;
1011     }
1012 
1013     public void setRuntimeConfig(RuntimeConfig runtimeConfig)
1014     {
1015         _runtimeConfig = runtimeConfig;
1016     }
1017 
1018     private void configureRuntimeConfig()
1019     {
1020         RuntimeConfig runtimeConfig = RuntimeConfig.getCurrentInstance(_externalContext);
1021         FacesConfigData dispenser = getDispenser();
1022         List<String> knownNamespaces = new ArrayList<String>();
1023         
1024         for (ComponentTagDeclaration declaration : dispenser.getComponentTagDeclarations())
1025         {
1026             runtimeConfig.addComponentTagDeclaration(declaration);
1027             if (declaration.getNamespace() != null)
1028             {
1029                 knownNamespaces.add(declaration.getNamespace());
1030             }
1031         }
1032         
1033         for (ManagedBean bean : dispenser.getManagedBeans())
1034         {
1035             if (log.isLoggable(Level.WARNING) && runtimeConfig.getManagedBean(bean.getManagedBeanName()) != null)
1036             {
1037                 log.warning("More than one managed bean w/ the name of '" + bean.getManagedBeanName()
1038                         + "' - only keeping the last ");
1039             }
1040 
1041             runtimeConfig.addManagedBean(bean.getManagedBeanName(), bean);
1042 
1043         }
1044 
1045         removePurgedBeansFromSessionAndApplication(runtimeConfig);
1046 
1047         for (NavigationRule rule : dispenser.getNavigationRules())
1048         {
1049             runtimeConfig.addNavigationRule(rule);
1050         }
1051 
1052         for (String converterClassName : dispenser.getConverterConfigurationByClassName())
1053         {
1054             runtimeConfig.addConverterConfiguration(converterClassName,
1055                     _dispenser.getConverterConfiguration(converterClassName));
1056         }
1057 
1058         for (ResourceBundle bundle : dispenser.getResourceBundles())
1059         {
1060             runtimeConfig.addResourceBundle(bundle);
1061         }
1062 
1063         List<BeanEntry> injectedBeansAndMetaData =
1064                 (List<BeanEntry>)_externalContext.getApplicationMap().get(INJECTED_BEAN_STORAGE_KEY);
1065 
1066         for (String className : dispenser.getElResolvers())
1067         {
1068             ELResolver elResolver = (ELResolver) ClassUtils.newInstance(className, ELResolver.class);
1069             try
1070             {
1071                 Object creationMetaData = getInjectionProvider().inject(elResolver);
1072 
1073                 injectedBeansAndMetaData.add(new BeanEntry(elResolver, creationMetaData));
1074 
1075                 getInjectionProvider().postConstruct(elResolver, creationMetaData);
1076             }
1077             catch (InjectionProviderException e)
1078             {
1079                 log.log(Level.SEVERE, "Error while injecting ELResolver", e);
1080             }
1081             runtimeConfig.addFacesConfigElResolver(elResolver);
1082         }
1083         
1084         for (String className : dispenser.getSearchKeywordResolvers())
1085         {
1086             SearchKeywordResolver searchKeywordResolver = (SearchKeywordResolver) ClassUtils.newInstance(
1087                     className, SearchKeywordResolver.class);
1088             
1089             runtimeConfig.addApplicationSearchExpressionResolver(searchKeywordResolver);
1090         }
1091 
1092         runtimeConfig.setFacesVersion(dispenser.getFacesVersion());
1093 
1094         runtimeConfig.setNamedEventManager(new NamedEventManager());
1095 
1096         for (NamedEvent event : dispenser.getNamedEvents())
1097         {
1098             try
1099             {
1100                 Class<? extends ComponentSystemEvent> clazz = ClassUtils.classForName(event.getEventClass());
1101                 runtimeConfig.getNamedEventManager().addNamedEvent(event.getShortName(), clazz);
1102             }
1103             catch (ClassNotFoundException e)
1104             {
1105                 log.log(Level.SEVERE, "Named event could not be initialized, reason:", e);
1106             }
1107         }
1108 
1109         String elResolverComparatorClass =
1110                 _externalContext.getInitParameter(ResolverBuilderBase.EL_RESOLVER_COMPARATOR);
1111         if (elResolverComparatorClass != null && !elResolverComparatorClass.isEmpty())
1112         {
1113             try
1114             {
1115                 Class<Comparator<ELResolver>> clazz =
1116                         (Class<Comparator<ELResolver>>) ClassUtils.classForName(elResolverComparatorClass);
1117                 Comparator<ELResolver> comparator = ClassUtils.newInstance(clazz);
1118                 runtimeConfig.setELResolverComparator(comparator);
1119             }
1120             catch (Exception e)
1121             {
1122                 if (log.isLoggable(Level.SEVERE))
1123                 {
1124                     log.log(Level.SEVERE, "Cannot instantiate EL Resolver Comparator " + elResolverComparatorClass
1125                             + " . Check " + ResolverBuilderBase.EL_RESOLVER_COMPARATOR + " web config param. "
1126                             + "Initialization continues with no comparator used.", e);
1127                 }
1128             }
1129         }
1130         else
1131         {
1132             runtimeConfig.setELResolverComparator(null);
1133         }
1134 
1135         String elResolverPredicateClass = _externalContext.getInitParameter(ResolverBuilderBase.EL_RESOLVER_PREDICATE);
1136         if (elResolverPredicateClass != null && !elResolverPredicateClass.isEmpty())
1137         {
1138             try
1139             {
1140                 Class<?> clazz = ClassUtils.classForName(elResolverPredicateClass);
1141                 Object elResolverPredicate = ClassUtils.newInstance(clazz);
1142                 if (elResolverPredicate instanceof Predicate)
1143                 {
1144                     runtimeConfig.setELResolverPredicate((Predicate) elResolverPredicate);
1145                 }
1146                 else
1147                 {
1148                     if (log.isLoggable(Level.SEVERE))
1149                     {
1150                         log.log(Level.SEVERE, "EL Resolver Predicate " + elResolverPredicateClass
1151                                 + " must implement " + Predicate.class.getName()
1152                                 + " . Check " + ResolverBuilderBase.EL_RESOLVER_PREDICATE + " web config param. "
1153                                 + "Initialization continues with no predicate used.");
1154                     }
1155                 }
1156             }
1157             catch (Exception e)
1158             {
1159                 if (log.isLoggable(Level.SEVERE))
1160                 {
1161                     log.log(Level.SEVERE, "Cannot instantiate EL Resolver Predicate " + elResolverPredicateClass
1162                             + " . Check " + ResolverBuilderBase.EL_RESOLVER_PREDICATE + " web config param. "
1163                             + "Initialization continues with no predicate used.", e);
1164                 }
1165             }
1166         }
1167         else
1168         {
1169             runtimeConfig.setELResolverPredicate(null);
1170         }
1171 
1172         for (FaceletsProcessing faceletsProcessing : dispenser.getFaceletsProcessing())
1173         {
1174             runtimeConfig.addFaceletProcessingConfiguration(faceletsProcessing.getFileExtension(), faceletsProcessing);
1175         }
1176         
1177         ResourceLibraryContractsProvider rlcp = ResourceLibraryContractsProviderFactory.
1178             getFacesConfigResourceProviderFactory(_externalContext).
1179             createResourceLibraryContractsProvider(_externalContext);
1180         
1181         try
1182         {
1183             // JSF 2.2 section 11.4.2.1 scan for available resource library contracts
1184             // and store the result in a internal data structure, so it can be used 
1185             // later in ViewDeclarationLanguage.calculateResourceLibraryContracts(
1186             //   FacesContext context, String viewId)
1187             runtimeConfig.setExternalContextResourceLibraryContracts(
1188                 rlcp.getExternalContextResourceLibraryContracts(_externalContext));
1189             runtimeConfig.setClassLoaderResourceLibraryContracts(
1190                 rlcp.getClassloaderResourceLibraryContracts(_externalContext));
1191         }
1192         catch (Exception e)
1193         {
1194             if (log.isLoggable(Level.SEVERE))
1195             {
1196                 log.log(Level.SEVERE, 
1197                     "An error was found when scanning for resource library contracts", e);
1198             }
1199         }
1200         
1201         
1202         // JSF 2.2 section 11.4.2.1 check all contracts are loaded
1203         if (log.isLoggable(Level.INFO))
1204         {
1205             for (List<String> list : runtimeConfig.getContractMappings().values())
1206             {
1207                 for (String contract : list)
1208                 {
1209                     if (!runtimeConfig.getResourceLibraryContracts().contains(contract))
1210                     {
1211                         log.log(Level.INFO, 
1212                             "Resource Library Contract "+ contract + " was not found while scanning for "
1213                             + "available contracts.");
1214                     }
1215                 }
1216             }
1217         }
1218         
1219         // JSF 2.2 section 11.4.2.1 if no contractMappings set, all available contracts applies
1220         // to all views.
1221         if (runtimeConfig.getContractMappings().isEmpty())
1222         {
1223             String[] contracts = runtimeConfig.getResourceLibraryContracts().toArray(
1224                 new String[runtimeConfig.getResourceLibraryContracts().size()]);
1225             runtimeConfig.addContractMapping("*", contracts);
1226         }
1227         
1228         for (String resourceResolver : dispenser.getResourceResolvers())
1229         {
1230             runtimeConfig.addResourceResolver(resourceResolver);
1231         }
1232         
1233         for (FaceletTagLibrary faceletTagLibrary : dispenser.getTagLibraries())
1234         {
1235             runtimeConfig.addFaceletTagLibrary(faceletTagLibrary);
1236             if (faceletTagLibrary.getNamespace() != null)
1237             {
1238                 knownNamespaces.add(faceletTagLibrary.getNamespace());
1239             }
1240         }
1241         
1242         // Add default namespaces to the known namespaces
1243         knownNamespaces.add("http://xmlns.jcp.org/jsf/core");
1244         knownNamespaces.add("http://java.sun.com/jsf/core");
1245         knownNamespaces.add("http://xmlns.jcp.org/jsf/html");
1246         knownNamespaces.add("http://java.sun.com/jsf/html");
1247         knownNamespaces.add("http://xmlns.jcp.org/jsf/facelets");
1248         knownNamespaces.add("http://java.sun.com/jsf/facelets");
1249         knownNamespaces.add("http://xmlns.jcp.org/jsp/jstl/core");
1250         knownNamespaces.add("http://java.sun.com/jsp/jstl/core");
1251         knownNamespaces.add("http://java.sun.com/jstl/core");
1252         knownNamespaces.add("http://xmlns.jcp.org/jsp/jstl/functions");
1253         knownNamespaces.add("http://java.sun.com/jsp/jstl/functions");
1254         knownNamespaces.add("http://xmlns.jcp.org/jsf/composite");
1255         knownNamespaces.add("http://java.sun.com/jsf/composite");
1256         knownNamespaces.add("http://xmlns.jcp.org/jsf");
1257         knownNamespaces.add("http://java.sun.com/jsf");
1258         knownNamespaces.add("http://xmlns.jcp.org/jsf/passthrough");
1259         knownNamespaces.add("http://java.sun.com/jsf/passthrough");
1260         
1261         Map<Integer, String> namespaceById = new HashMap<Integer, String>();
1262         Map<String, Integer> idByNamespace = new HashMap<String, Integer>();
1263         // Sort them to ensure the same id 
1264         Collections.sort(knownNamespaces);
1265         for (int i = 0; i < knownNamespaces.size(); i++)
1266         {
1267             namespaceById.put(i, knownNamespaces.get(i));
1268             idByNamespace.put(knownNamespaces.get(i), i);
1269         }
1270         runtimeConfig.setNamespaceById(Collections.unmodifiableMap(namespaceById));
1271         runtimeConfig.setIdByNamespace(Collections.unmodifiableMap(idByNamespace));
1272         
1273         for (ViewPoolMapping viewPoolMapping : dispenser.getViewPoolMappings())
1274         {
1275             runtimeConfig.addViewPoolMapping(viewPoolMapping);
1276         }
1277         
1278         for (FaceletsTemplateMapping faceletsTemplateMapping : dispenser.getFaceletsTemplateMappings())
1279         {
1280             runtimeConfig.addFaceletsTemplateMapping(faceletsTemplateMapping);
1281         }
1282     }
1283 
1284     private void removePurgedBeansFromSessionAndApplication(RuntimeConfig runtimeConfig)
1285     {
1286         Map<String, ManagedBean> oldManagedBeans = runtimeConfig.getManagedBeansNotReaddedAfterPurge();
1287         if (oldManagedBeans != null)
1288         {
1289             for (Map.Entry<String, ManagedBean> entry : oldManagedBeans.entrySet())
1290             {
1291                 ManagedBean bean = entry.getValue();
1292 
1293                 String scope = bean.getManagedBeanScope();
1294 
1295                 if (scope != null && scope.equalsIgnoreCase("session"))
1296                 {
1297                     _externalContext.getSessionMap().remove(entry.getKey());
1298                 }
1299                 else if (scope != null && scope.equalsIgnoreCase("application"))
1300                 {
1301                     _externalContext.getApplicationMap().remove(entry.getKey());
1302                 }
1303             }
1304         }
1305 
1306         runtimeConfig.resetManagedBeansNotReaddedAfterPurge();
1307     }
1308 
1309     private void configureRenderKits()
1310     {
1311         RenderKitFactory renderKitFactory
1312                 = (RenderKitFactory) FactoryFinder.getFactory(FactoryFinder.RENDER_KIT_FACTORY);
1313 
1314         FacesConfigData dispenser = getDispenser();
1315         for (String renderKitId : dispenser.getRenderKitIds())
1316         {
1317             Collection<String> renderKitClass = dispenser.getRenderKitClasses(renderKitId);
1318 
1319             if (renderKitClass.isEmpty())
1320             {
1321                 renderKitClass = new ArrayList<String>(1);
1322                 renderKitClass.add(DEFAULT_RENDER_KIT_CLASS);
1323             }
1324 
1325             //RenderKit renderKit = (RenderKit) ClassUtils.newInstance(renderKitClass);
1326             RenderKit renderKit = (RenderKit) ClassUtils.buildApplicationObject(RenderKit.class, renderKitClass, null);
1327             // If the default html RenderKit instance is wrapped, the top level object will not implement
1328             // LazyRenderKit and all renderers will be added using the standard form.
1329             boolean lazyRenderKit = renderKit instanceof LazyRenderKit;
1330 
1331             for (Renderer element : dispenser.getRenderers(renderKitId))
1332             {
1333                 javax.faces.render.Renderer renderer;
1334                 
1335                 if (element.getRendererClass() != null)
1336                 {
1337                     if (lazyRenderKit)
1338                     {
1339                         // Add renderer using LazyRenderKit interface. This will have the effect of improve startup
1340                         // time avoiding load renderer classes that are not used.
1341                         ((LazyRenderKit)renderKit).addRenderer(element.getComponentFamily(), 
1342                             element.getRendererType(), element.getRendererClass());
1343                     }
1344                     else
1345                     {
1346                         // Use standard form
1347                         try
1348                         {
1349                             renderer = (javax.faces.render.Renderer) ClassUtils.newInstance(
1350                                 element.getRendererClass());
1351                         }
1352                         catch (Throwable e)
1353                         {
1354                             // ignore the failure so that the render kit is configured
1355                             log.log(Level.SEVERE, "failed to configure class " + element.getRendererClass(), e);
1356                             continue;
1357                         }
1358                         if (renderer != null)
1359                         {
1360                             renderKit.addRenderer(element.getComponentFamily(), element.getRendererType(), renderer);
1361                         }
1362                         else
1363                         {
1364                             log.log(Level.INFO, "Renderer instance cannot be created for "+
1365                                     element.getRendererClass()+ ", ignoring..." + 
1366                                     element.getRendererClass());
1367                         }
1368                     }
1369                 }
1370                 else
1371                 {
1372                         log.log(Level.INFO, "Renderer element with no rendererClass found, ignoring..." +
1373                                 element.getRendererClass());
1374                 }
1375 
1376             }
1377             
1378             Collection<ClientBehaviorRenderer> clientBehaviorRenderers
1379                     = dispenser.getClientBehaviorRenderers(renderKitId);
1380 
1381             // Add in client behavior renderers.
1382 
1383             for (ClientBehaviorRenderer clientBehaviorRenderer : clientBehaviorRenderers)
1384             {
1385                 try
1386                 {
1387                     javax.faces.render.ClientBehaviorRenderer behaviorRenderer
1388                             = (javax.faces.render.ClientBehaviorRenderer)
1389                             ClassUtils.newInstance(clientBehaviorRenderer.getRendererClass());
1390 
1391                     renderKit.addClientBehaviorRenderer(clientBehaviorRenderer.getRendererType(), behaviorRenderer);
1392                 }
1393 
1394                 catch (Throwable e)
1395                 {
1396                     // Ignore.
1397 
1398                     if (log.isLoggable(Level.SEVERE))
1399                     {
1400                         log.log(Level.SEVERE, "failed to configure client behavior renderer class " +
1401                                 clientBehaviorRenderer.getRendererClass(), e);
1402                     }
1403                 }
1404             }
1405 
1406             renderKitFactory.addRenderKit(renderKitId, renderKit);
1407         }
1408     }
1409 
1410     private void configureLifecycle()
1411     {
1412         // create the lifecycle used by the app
1413         LifecycleFactory lifecycleFactory
1414                 = (LifecycleFactory) FactoryFinder.getFactory(FactoryFinder.LIFECYCLE_FACTORY);
1415 
1416         List<BeanEntry> injectedBeanStorage =
1417                 (List<BeanEntry>)_externalContext.getApplicationMap().get(INJECTED_BEAN_STORAGE_KEY);
1418 
1419         //Lifecycle lifecycle = lifecycleFactory.getLifecycle(getLifecycleId());
1420         for (Iterator<String> it = lifecycleFactory.getLifecycleIds(); it.hasNext();)
1421         {
1422             Lifecycle lifecycle = lifecycleFactory.getLifecycle(it.next());
1423             
1424             // add phase listeners
1425             for (String listenerClassName : getDispenser().getLifecyclePhaseListeners())
1426             {
1427                 try
1428                 {
1429                     PhaseListener listener = (PhaseListener)
1430                             ClassUtils.newInstance(listenerClassName, PhaseListener.class);
1431 
1432                     Object creationMetaData = getInjectionProvider().inject(listener);
1433 
1434                     injectedBeanStorage.add(new BeanEntry(listener, creationMetaData));
1435 
1436                     getInjectionProvider().postConstruct(listener, creationMetaData);
1437                     lifecycle.addPhaseListener(listener);
1438                 }
1439                 catch (ClassCastException e)
1440                 {
1441                     log.severe("Class " + listenerClassName + " does not implement PhaseListener");
1442                 }
1443                 catch (InjectionProviderException e)
1444                 {
1445                     log.log(Level.SEVERE, "Error while injecting PhaseListener", e);
1446                 }
1447             }
1448 
1449             // if ProjectStage is Development, install the DebugPhaseListener
1450             FacesContext facesContext = getFacesContext();
1451             if (facesContext.isProjectStage(ProjectStage.Development) &&
1452                     MyfacesConfig.getCurrentInstance(facesContext.getExternalContext()).isDebugPhaseListenerEnabled())
1453             {
1454                 lifecycle.addPhaseListener(new DebugPhaseListener());
1455             }
1456         }
1457     }
1458 
1459     /*
1460     private String getLifecycleId()
1461     {
1462         String id = _externalContext.getInitParameter(FacesServlet.LIFECYCLE_ID_ATTR);
1463 
1464         if (id != null)
1465         {
1466             return id;
1467         }
1468 
1469         return LifecycleFactory.DEFAULT_LIFECYCLE;
1470     }*/
1471 
1472     private void handleSerialFactory()
1473     {
1474 
1475         String serialProvider = _externalContext.getInitParameter(StateUtils.SERIAL_FACTORY);
1476         SerialFactory serialFactory = null;
1477 
1478         if (serialProvider == null)
1479         {
1480             serialFactory = new DefaultSerialFactory();
1481         }
1482         else
1483         {
1484             try
1485             {
1486                 serialFactory = (SerialFactory) ClassUtils.newInstance(serialProvider);
1487 
1488             }
1489             catch (ClassCastException e)
1490             {
1491                 log.log(Level.SEVERE, "Make sure '" + serialProvider + "' implements the correct interface", e);
1492             }
1493             catch (Exception e)
1494             {
1495                 log.log(Level.SEVERE, "", e);
1496             }
1497             finally
1498             {
1499                 if (serialFactory == null)
1500                 {
1501                     serialFactory = new DefaultSerialFactory();
1502                     log.severe("Using default serialization provider");
1503                 }
1504             }
1505 
1506         }
1507 
1508         log.info("Serialization provider : " + serialFactory.getClass());
1509         _externalContext.getApplicationMap().put(StateUtils.SERIAL_FACTORY, serialFactory);
1510     }
1511 
1512     private void configureManagedBeanDestroyer()
1513     {
1514         FacesContext facesContext = getFacesContext();
1515         ExternalContext externalContext = facesContext.getExternalContext();
1516         Map<String, Object> applicationMap = externalContext.getApplicationMap();
1517         Application application = facesContext.getApplication();
1518 
1519         // get RuntimeConfig and LifecycleProvider
1520         RuntimeConfig runtimeConfig = RuntimeConfig.getCurrentInstance(externalContext);
1521         LifecycleProvider lifecycleProvider = LifecycleProviderFactory
1522                 .getLifecycleProviderFactory(externalContext).getLifecycleProvider(externalContext);
1523 
1524         // create ManagedBeanDestroyer
1525         ManagedBeanDestroyer mbDestroyer
1526                 = new ManagedBeanDestroyer(lifecycleProvider, runtimeConfig);
1527 
1528         // subscribe ManagedBeanDestroyer as listener for needed events 
1529         application.subscribeToEvent(PreDestroyCustomScopeEvent.class, mbDestroyer);
1530         application.subscribeToEvent(PreDestroyViewMapEvent.class, mbDestroyer);
1531 
1532         // get ManagedBeanDestroyerListener instance 
1533         ManagedBeanDestroyerListener listener = (ManagedBeanDestroyerListener)
1534                 applicationMap.get(ManagedBeanDestroyerListener.APPLICATION_MAP_KEY);
1535         if (listener != null)
1536         {
1537             // set the instance on the listener
1538             listener.setManagedBeanDestroyer(mbDestroyer);
1539         }
1540         else
1541         {
1542             if (MyfacesConfig.getCurrentInstance(externalContext).isSupportManagedBeans())
1543             {
1544                 log.log(Level.SEVERE, "No ManagedBeanDestroyerListener instance found, thus "
1545                         + "@PreDestroy methods won't get called in every case. "
1546                         + "This instance needs to be published before configuration is started.");
1547             }
1548         }
1549     }
1550     
1551     private void configureFlowHandler()
1552     {
1553         FacesContext facesContext = getFacesContext();
1554         Application application = getApplication();
1555         
1556         FacesConfigData dispenser = getDispenser();
1557         
1558         if (!dispenser.getFacesFlowDefinitions().isEmpty())
1559         {
1560             // Faces Flow require client window enabled to work.
1561             FacesConfigurator.enableDefaultWindowMode(facesContext);
1562         }
1563         
1564         for (FacesFlowDefinition flowDefinition : dispenser.getFacesFlowDefinitions())
1565         {
1566             FlowImpl flow = new FlowImpl();
1567             
1568             // TODO: configure flow object
1569             flow.setId(flowDefinition.getId());
1570             flow.setDefiningDocumentId(flowDefinition.getDefiningDocumentId());
1571             
1572             flow.setStartNodeId(flowDefinition.getStartNode());
1573             
1574             if (!isEmptyString(flowDefinition.getInitializer()))
1575             {
1576                 flow.setInitializer(application.getExpressionFactory().createMethodExpression(
1577                     facesContext.getELContext(), flowDefinition.getInitializer(), null, NO_PARAMETER_TYPES));
1578             }
1579             if (!isEmptyString(flowDefinition.getFinalizer()))
1580             {
1581                 flow.setFinalizer(application.getExpressionFactory().createMethodExpression(
1582                     facesContext.getELContext(), flowDefinition.getFinalizer(), null, NO_PARAMETER_TYPES));
1583             }
1584             
1585             for (FacesFlowCall call : flowDefinition.getFlowCallList())
1586             {
1587                 FlowCallNodeImpl node = new FlowCallNodeImpl(call.getId());
1588                 if (call.getFlowReference() != null)
1589                 {
1590                     node.setCalledFlowId(call.getFlowReference().getFlowId());
1591                     node.setCalledFlowDocumentId(call.getFlowReference().getFlowDocumentId());
1592                 }
1593 
1594                 for (FacesFlowParameter parameter : call.getOutboundParameterList())
1595                 {
1596                     node.putOutboundParameter( parameter.getName(),
1597                         new ParameterImpl(parameter.getName(),
1598                         application.getExpressionFactory().createValueExpression(
1599                             facesContext.getELContext(), parameter.getValue(), Object.class)) );
1600                 }
1601                 flow.putFlowCall(node.getId(), node);
1602             }
1603 
1604             for (FacesFlowMethodCall methodCall : flowDefinition.getMethodCallList())
1605             {
1606                 MethodCallNodeImpl node = new MethodCallNodeImpl(methodCall.getId());
1607                 if (!isEmptyString(methodCall.getMethod()))
1608                 {
1609                     node.setMethodExpression(
1610                         application.getExpressionFactory().createMethodExpression(
1611                             facesContext.getELContext(), methodCall.getMethod(), null, NO_PARAMETER_TYPES));
1612                 }
1613                 if (!isEmptyString(methodCall.getDefaultOutcome()))
1614                 {
1615                     node.setOutcome(
1616                         application.getExpressionFactory().createValueExpression(
1617                                 facesContext.getELContext(), methodCall.getDefaultOutcome(), Object.class));
1618                 }
1619                 for (FacesFlowMethodParameter parameter : methodCall.getParameterList())
1620                 {
1621                     node.addParameter(
1622                         new ParameterImpl(parameter.getClassName(),
1623                         application.getExpressionFactory().createValueExpression(
1624                             facesContext.getELContext(), parameter.getValue(), Object.class)) );
1625                 }
1626                 flow.addMethodCall(node);
1627             }
1628             
1629             for (FacesFlowParameter parameter : flowDefinition.getInboundParameterList())
1630             {
1631                 flow.putInboundParameter(parameter.getName(),
1632                     new ParameterImpl(parameter.getName(),
1633                     application.getExpressionFactory().createValueExpression(
1634                         facesContext.getELContext(), parameter.getValue(), Object.class)) );
1635             }
1636             
1637             for (NavigationRule rule : flowDefinition.getNavigationRuleList())
1638             {
1639                 flow.addNavigationCases(rule.getFromViewId(), NavigationUtils.convertNavigationCasesToAPI(rule));
1640             }
1641             
1642             for (FacesFlowSwitch flowSwitch : flowDefinition.getSwitchList())
1643             {
1644                 SwitchNodeImpl node = new SwitchNodeImpl(flowSwitch.getId());
1645                 
1646                 if (flowSwitch.getDefaultOutcome() != null &&
1647                     !isEmptyString(flowSwitch.getDefaultOutcome().getFromOutcome()))
1648                 {
1649                     if (ELText.isLiteral(flowSwitch.getDefaultOutcome().getFromOutcome()))
1650                     {
1651                         node.setDefaultOutcome(flowSwitch.getDefaultOutcome().getFromOutcome());
1652                     }
1653                     else
1654                     {
1655                         node.setDefaultOutcome(
1656                             application.getExpressionFactory().createValueExpression(
1657                                 facesContext.getELContext(), flowSwitch.getDefaultOutcome().getFromOutcome(),
1658                                 Object.class));
1659                     }
1660                 }
1661                 
1662                 for (NavigationCase navCase : flowSwitch.getNavigationCaseList())
1663                 {
1664                     SwitchCaseImpl nodeCase = new SwitchCaseImpl();
1665                     nodeCase.setFromOutcome(navCase.getFromOutcome());
1666                     if (!isEmptyString(navCase.getIf()))
1667                     {
1668                         nodeCase.setCondition(
1669                             application.getExpressionFactory().createValueExpression(
1670                                 facesContext.getELContext(), navCase.getIf(),
1671                                 Object.class));
1672                     }
1673                     node.addCase(nodeCase);
1674                 }
1675                 
1676                 flow.putSwitch(node.getId(), node);
1677             }
1678             
1679             for (FacesFlowView view : flowDefinition.getViewList())
1680             {
1681                 ViewNodeImpl node = new ViewNodeImpl(view.getId(), view.getVdlDocument());
1682                 flow.addView(node);
1683             }
1684 
1685             for (FacesFlowReturn flowReturn : flowDefinition.getReturnList())
1686             {
1687                 ReturnNodeImpl node = new ReturnNodeImpl(flowReturn.getId());
1688                 if (flowReturn.getNavigationCase() != null &&
1689                     !isEmptyString(flowReturn.getNavigationCase().getFromOutcome()))
1690                 {
1691                     if (ELText.isLiteral(flowReturn.getNavigationCase().getFromOutcome()))
1692                     {
1693                         node.setFromOutcome(flowReturn.getNavigationCase().getFromOutcome());
1694                     }
1695                     else
1696                     {
1697                         node.setFromOutcome(
1698                             application.getExpressionFactory().createValueExpression(
1699                                 facesContext.getELContext(), flowReturn.getNavigationCase().getFromOutcome(),
1700                                 Object.class));
1701                     }
1702                 }
1703                 flow.putReturn(node.getId(), node);
1704             }
1705             
1706             flow.freeze();
1707             
1708             // Add the flow, so the config can be processed by the flow system and the
1709             // navigation system.
1710             application.getFlowHandler().addFlow(facesContext, flow);
1711         }
1712         
1713         AnnotatedFlowConfigurator.configureAnnotatedFlows(facesContext);
1714     }
1715     
1716     public static void enableDefaultWindowMode(FacesContext facesContext)
1717     {
1718         if (!isEnableDefaultWindowMode(facesContext))
1719         {
1720             String windowMode = WebConfigParamUtils.getStringInitParameter(
1721                     facesContext.getExternalContext(), 
1722                     ClientWindow.CLIENT_WINDOW_MODE_PARAM_NAME, null);
1723             
1724             if (windowMode == null)
1725             {
1726                 //No window mode set, force window mode to url
1727                 String defaultWindowMode = WebConfigParamUtils.getStringInitParameter(
1728                     facesContext.getExternalContext(), 
1729                     ClientWindowFactoryImpl.INIT_PARAM_DEFAULT_WINDOW_MODE, 
1730                     ClientWindowFactoryImpl.WINDOW_MODE_URL);
1731                 
1732                 log.info("The current configuration requires client window enabled, setting it to '"+
1733                     defaultWindowMode+"'");
1734                 
1735                 facesContext.getExternalContext().getApplicationMap().put(
1736                     ENABLE_DEFAULT_WINDOW_MODE, Boolean.TRUE);
1737             }
1738         }
1739     }
1740     
1741     public static boolean isEnableDefaultWindowMode(FacesContext facesContext)
1742     {
1743         return Boolean.TRUE.equals(facesContext.getExternalContext().
1744             getApplicationMap().get(ENABLE_DEFAULT_WINDOW_MODE));
1745     }
1746     
1747     private boolean isEmptyString(String value)
1748     {
1749         if (value == null)
1750         {
1751             return true;
1752         }
1753         else if (value.length() <= 0)
1754         {
1755             return true;
1756         }
1757         return false;
1758     }
1759 
1760     public void configureProtectedViews()
1761     {
1762         Application application = getApplication();
1763 
1764         FacesConfigData dispenser = getDispenser();
1765         //Protected Views
1766         ViewHandler viewHandler = application.getViewHandler();
1767         for (String urlPattern : dispenser.getProtectedViewUrlPatterns())
1768         {
1769             viewHandler.addProtectedView(urlPattern);
1770         }
1771     }
1772     
1773     protected InjectionProvider getInjectionProvider()
1774     {
1775         if (_injectionProvider == null)
1776         {
1777             _injectionProvider = InjectionProviderFactory.getInjectionProviderFactory(
1778                 _externalContext).getInjectionProvider(_externalContext);
1779         }
1780         return _injectionProvider;
1781     }
1782     
1783     protected FacesContext getFacesContext()
1784     {
1785         if (_facesContext == null)
1786         {
1787             _facesContext = FacesContext.getCurrentInstance();
1788         }
1789         return _facesContext;
1790     }
1791     
1792     protected Application getApplication()
1793     {
1794         if (_application == null)
1795         {
1796             return getFacesContext().getApplication();
1797         }
1798         return _application;
1799     }
1800     
1801     protected void setApplication(Application application)
1802     {
1803         this._application = application;
1804     }
1805 }