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.application;
20  
21  import java.beans.BeanDescriptor;
22  import java.beans.BeanInfo;
23  import java.lang.reflect.Constructor;
24  import java.util.ArrayList;
25  import java.util.Arrays;
26  import java.util.Collection;
27  import java.util.Collections;
28  import java.util.HashMap;
29  import java.util.Iterator;
30  import java.util.List;
31  import java.util.Locale;
32  import java.util.Map;
33  import java.util.MissingResourceException;
34  import java.util.TimeZone;
35  import java.util.concurrent.ConcurrentHashMap;
36  import java.util.concurrent.CopyOnWriteArrayList;
37  import java.util.logging.Level;
38  import java.util.logging.Logger;
39  
40  import javax.el.CompositeELResolver;
41  import javax.el.ELContext;
42  import javax.el.ELContextListener;
43  import javax.el.ELException;
44  import javax.el.ELResolver;
45  import javax.el.ExpressionFactory;
46  import javax.el.MethodExpression;
47  import javax.el.ValueExpression;
48  import javax.faces.FacesException;
49  import javax.faces.application.Application;
50  import javax.faces.application.NavigationHandler;
51  import javax.faces.application.ProjectStage;
52  import javax.faces.application.Resource;
53  import javax.faces.application.ResourceDependencies;
54  import javax.faces.application.ResourceDependency;
55  import javax.faces.application.ResourceHandler;
56  import javax.faces.application.StateManager;
57  import javax.faces.application.ViewHandler;
58  import javax.faces.component.UIComponent;
59  import javax.faces.component.UIComponentBase;
60  import javax.faces.component.UINamingContainer;
61  import javax.faces.component.UIOutput;
62  import javax.faces.component.UIViewRoot;
63  import javax.faces.component.behavior.Behavior;
64  import javax.faces.component.behavior.ClientBehaviorBase;
65  import javax.faces.context.FacesContext;
66  import javax.faces.convert.Converter;
67  import javax.faces.convert.DateTimeConverter;
68  import javax.faces.el.MethodBinding;
69  import javax.faces.el.PropertyResolver;
70  import javax.faces.el.ReferenceSyntaxException;
71  import javax.faces.el.ValueBinding;
72  import javax.faces.el.VariableResolver;
73  import javax.faces.event.AbortProcessingException;
74  import javax.faces.event.ActionListener;
75  import javax.faces.event.ComponentSystemEventListener;
76  import javax.faces.event.ListenerFor;
77  import javax.faces.event.ListenersFor;
78  import javax.faces.event.SystemEvent;
79  import javax.faces.event.SystemEventListener;
80  import javax.faces.event.SystemEventListenerHolder;
81  import javax.faces.render.ClientBehaviorRenderer;
82  import javax.faces.render.Renderer;
83  import javax.faces.validator.Validator;
84  import javax.faces.view.ViewDeclarationLanguage;
85  import javax.naming.Context;
86  import javax.naming.InitialContext;
87  import javax.naming.NamingException;
88  
89  import org.apache.commons.beanutils.BeanUtils;
90  import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFWebConfigParam;
91  import org.apache.myfaces.config.RuntimeConfig;
92  import org.apache.myfaces.config.element.Property;
93  import org.apache.myfaces.config.element.ResourceBundle;
94  import org.apache.myfaces.context.RequestViewContext;
95  import org.apache.myfaces.el.PropertyResolverImpl;
96  import org.apache.myfaces.el.VariableResolverToApplicationELResolverAdapter;
97  import org.apache.myfaces.el.convert.MethodExpressionToMethodBinding;
98  import org.apache.myfaces.el.convert.ValueBindingToValueExpression;
99  import org.apache.myfaces.el.convert.ValueExpressionToValueBinding;
100 import org.apache.myfaces.el.unified.ELResolverBuilder;
101 import org.apache.myfaces.el.unified.ResolverBuilderForFaces;
102 import org.apache.myfaces.el.unified.resolver.FacesCompositeELResolver;
103 import org.apache.myfaces.el.unified.resolver.FacesCompositeELResolver.Scope;
104 import org.apache.myfaces.lifecycle.LifecycleImpl;
105 import org.apache.myfaces.shared.config.MyfacesConfig;
106 import org.apache.myfaces.shared.util.ClassUtils;
107 import org.apache.myfaces.view.facelets.FaceletCompositionContext;
108 import org.apache.myfaces.view.facelets.el.ELText;
109 
110 /**
111  * DOCUMENT ME!
112  * 
113  * @author Manfred Geiler (latest modification by $Author: lu4242 $)
114  * @author Anton Koinov
115  * @author Thomas Spiegl
116  * @author Stan Silvert
117  * @version $Revision: 1505865 $ $Date: 2013-07-22 19:19:31 -0500 (Mon, 22 Jul 2013) $
118  */
119 @SuppressWarnings("deprecation")
120 public class ApplicationImpl extends Application
121 {
122     //private static final Log log = LogFactory.getLog(ApplicationImpl.class);
123     private static final Logger log = Logger.getLogger(ApplicationImpl.class.getName());
124 
125     private final static VariableResolver VARIABLERESOLVER = new VariableResolverToApplicationELResolverAdapter();
126 
127     private final static PropertyResolver PROPERTYRESOLVER = new PropertyResolverImpl();
128 
129     // the name for the system property which specifies the current ProjectStage (see MYFACES-2545 for details)
130     public final static String PROJECT_STAGE_SYSTEM_PROPERTY_NAME = "faces.PROJECT_STAGE";
131     
132     // MyFaces specific System Property to set the ProjectStage, if not present via the standard way
133     @Deprecated
134     public final static String MYFACES_PROJECT_STAGE_SYSTEM_PROPERTY_NAME = "org.apache.myfaces.PROJECT_STAGE";
135     
136     /**
137      * Set the default timezone as system timezone when a converter extending from DateTimeConverter is created.
138      */
139     @JSFWebConfigParam(defaultValue="false", expectedValues="true, false", since="2.0", group="validation")
140     public final static String DATETIMECONVERTER_DEFAULT_TIMEZONE_IS_SYSTEM_TIMEZONE_PARAM_NAME 
141         = "javax.faces.DATETIMECONVERTER_DEFAULT_TIMEZONE_IS_SYSTEM_TIMEZONE";
142     
143     /**
144      * Indicate the stage of the initialized application.
145      */
146     @JSFWebConfigParam(defaultValue="Production",
147             expectedValues="Development, Production, SystemTest, UnitTest",
148             since="2.0")
149     private static final String PROJECT_STAGE_PARAM_NAME = "javax.faces.PROJECT_STAGE";
150 
151     /**
152      * Indicate if the classes associated to components, converters, validators or behaviors
153      * should be loaded as soon as they are added to the current application instance or instead
154      * loaded in a lazy way.
155      */
156     @JSFWebConfigParam(defaultValue="true",since="2.0",tags="performance")
157     private static final String LAZY_LOAD_CONFIG_OBJECTS_PARAM_NAME = "org.apache.myfaces.LAZY_LOAD_CONFIG_OBJECTS";
158     private static final boolean LAZY_LOAD_CONFIG_OBJECTS_DEFAULT_VALUE = true;
159     private Boolean _lazyLoadConfigObjects = null;
160     
161     
162     /**
163      * Key under UIViewRoot to generated unique ids for components added 
164      * by @ResourceDependency effect.
165      */
166     private static final String RESOURCE_DEPENDENCY_UNIQUE_ID_KEY =
167               "oam.view.resourceDependencyUniqueId";
168 
169     // ~ Instance fields
170     // --------------------------------------------------------------------------
171     // --
172 
173     private Collection<Locale> _supportedLocales = Collections.emptySet();
174     private Locale _defaultLocale;
175     private String _messageBundle;
176 
177     private ViewHandler _viewHandler;
178     private NavigationHandler _navigationHandler;
179     private ActionListener _actionListener;
180     private String _defaultRenderKitId;
181     private ResourceHandler _resourceHandler;
182     private StateManager _stateManager;
183 
184     private ArrayList<ELContextListener> _elContextListeners;
185 
186     // components, converters, and validators can be added at runtime--must
187     // synchronize, uses ConcurrentHashMap to allow concurrent read of map
188     private final Map<String, Object> _converterIdToClassMap = new ConcurrentHashMap<String, Object>();
189 
190     private final Map<Class<?>, Object> _converterTargetClassToConverterClassMap
191             = new ConcurrentHashMap<Class<?>, Object>();
192     
193     private final Map<String, Object> _componentClassMap = new ConcurrentHashMap<String, Object>();
194 
195     private final Map<String, Object> _validatorClassMap = new ConcurrentHashMap<String, Object>();
196 
197     private final Map<Class<? extends SystemEvent>, SystemListenerEntry> _systemEventListenerClassMap
198             = new ConcurrentHashMap<Class<? extends SystemEvent>, SystemListenerEntry>();
199 
200     private final Map<String, String> _defaultValidatorsIds = new HashMap<String, String>();
201     
202     private volatile Map<String, String> _cachedDefaultValidatorsIds = null;
203     
204     private final Map<String, Object> _behaviorClassMap = new ConcurrentHashMap<String, Object>();
205 
206     private final RuntimeConfig _runtimeConfig;
207 
208     private ELResolver elResolver;
209 
210     private ELResolverBuilder resolverBuilderForFaces;
211 
212     private ProjectStage _projectStage;
213 
214     private volatile boolean _firstRequestProcessed = false;
215     
216     // MYFACES-3442 If HashMap or other non thread-safe structure is used, it is
217     // possible to fall in a infinite loop under heavy load unless a synchronized block
218     // is used to modify it or a ConcurrentHashMap.
219     private final Map<Class<?>, List<ListenerFor>> _classToListenerForMap
220             = new ConcurrentHashMap<Class<?>, List<ListenerFor>>() ;
221 
222     private final Map<Class<?>, List<ResourceDependency>> _classToResourceDependencyMap
223             = new ConcurrentHashMap<Class<?>, List<ResourceDependency>>() ;
224     
225     private List<Class<? extends Converter>> _noArgConstructorConverterClasses 
226             = new CopyOnWriteArrayList<Class<? extends Converter>>();
227     
228     /** Value of javax.faces.DATETIMECONVERTER_DEFAULT_TIMEZONE_IS_SYSTEM_TIMEZONE parameter */
229     private boolean _dateTimeConverterDefaultTimeZoneIsSystemTimeZone = false; 
230     
231     /**
232      * Represents semantic null in _componentClassMap. 
233      */
234     private static final UIComponent NOTHING = new UIComponentBase()
235     {
236         @Override
237         public String getFamily()
238         {
239             return null;
240         }
241     };
242     
243     // ~ Constructors
244     // --------------------------------------------------------------------------
245     // -----
246 
247     public ApplicationImpl()
248     {
249         this(getRuntimeConfig());
250     }
251 
252     private static RuntimeConfig getRuntimeConfig()
253     {
254         return RuntimeConfig.getCurrentInstance(
255                 FacesContext.getCurrentInstance().getExternalContext());
256     }
257 
258     ApplicationImpl(final RuntimeConfig runtimeConfig)
259     {
260         if (runtimeConfig == null)
261         {
262             throw new IllegalArgumentException("runtimeConfig must mot be null");
263         }
264         // set default implementation in constructor
265         // pragmatic approach, no syncronizing will be needed in get methods
266         _viewHandler = new ViewHandlerImpl();
267         _navigationHandler = new NavigationHandlerImpl();
268         _actionListener = new ActionListenerImpl();
269         _defaultRenderKitId = "HTML_BASIC";
270         _stateManager = new StateManagerImpl();
271         _elContextListeners = new ArrayList<ELContextListener>();
272         _resourceHandler = new ResourceHandlerImpl();
273         _runtimeConfig = runtimeConfig;
274 
275         if (log.isLoggable(Level.FINEST))
276         {
277             log.finest("New Application instance created");
278         }
279         
280         String configParam = getFaceContext().getExternalContext().
281                 getInitParameter(DATETIMECONVERTER_DEFAULT_TIMEZONE_IS_SYSTEM_TIMEZONE_PARAM_NAME);
282         if (configParam != null && configParam.toLowerCase().equals("true"))
283         {
284             _dateTimeConverterDefaultTimeZoneIsSystemTimeZone = true;
285         }
286     }
287 
288     // ~ Methods
289     // --------------------------------------------------------------------------
290     // ----------
291 
292     @Override
293     public final void addELResolver(final ELResolver resolver)
294     {
295         if (isFirstRequestProcessed())
296         {
297             throw new IllegalStateException("It is illegal to add a resolver after the first request is processed");
298         }
299         if (resolver != null)
300         {
301             _runtimeConfig.addApplicationElResolver(resolver);
302         }
303     }
304 
305     @Override
306     public void addDefaultValidatorId(String validatorId)
307     {
308         if (_validatorClassMap.containsKey(validatorId))
309         {
310             Object validatorClass = getObjectFromClassMap(validatorId, _validatorClassMap);
311             String className;
312 
313             if (validatorClass instanceof Class)
314             {
315                 className = ((Class<?>)validatorClass).getName();
316             }
317             else
318             {
319                 className = validatorClass.toString();
320             }
321             // Ensure atomicity between _defaultValidatorsIds and _cachedDefaultValidatorsIds
322             synchronized(_defaultValidatorsIds)
323             {
324                 _defaultValidatorsIds.put(validatorId, className);
325                 _cachedDefaultValidatorsIds = null;
326             }
327         }
328     }
329 
330     @Override
331     public Map<String, String> getDefaultValidatorInfo()
332     {
333         // cachedMap ensures we will not return null if after the check for null
334         // _cachedDefaultValidatorsIds is set to null. In theory the unmodifiable map
335         // always has a reference to _defaultValidatorsIds, so any instance set
336         // in _cachedDefaultValidatorsIds is always the same.
337         Map<String, String> cachedMap = _cachedDefaultValidatorsIds;
338         if (cachedMap == null)
339         {
340             synchronized(_defaultValidatorsIds)
341             {
342                 if (_cachedDefaultValidatorsIds == null)
343                 {
344                     _cachedDefaultValidatorsIds = Collections.unmodifiableMap(_defaultValidatorsIds);
345                 }
346                 cachedMap = _cachedDefaultValidatorsIds;
347             }
348         }
349         return cachedMap;
350     }
351 
352     @Override
353     public final ELResolver getELResolver()
354     {
355         // we don't need synchronization here since it is ok to have multiple
356         // instances of the elresolver
357         if (elResolver == null)
358         {
359             elResolver = createFacesResolver();
360         }
361         return elResolver;
362     }
363 
364     private ELResolver createFacesResolver()
365     {
366         boolean supportJSPAndFacesEL = MyfacesConfig.getCurrentInstance(
367                                 getFaceContext().getExternalContext()).isSupportJSPAndFacesEL();
368         CompositeELResolver resolver;
369         if (supportJSPAndFacesEL)
370         {
371             resolver = new FacesCompositeELResolver(Scope.Faces);
372         }
373         else
374         {
375             resolver = new CompositeELResolver();
376         }
377         getResolverBuilderForFaces().build(resolver);
378         return resolver;
379     }
380 
381     protected final ELResolverBuilder getResolverBuilderForFaces()
382     {
383         if (resolverBuilderForFaces == null)
384         {
385             resolverBuilderForFaces = new ResolverBuilderForFaces(_runtimeConfig);
386         }
387         return resolverBuilderForFaces;
388     }
389 
390     public final void setResolverBuilderForFaces(final ELResolverBuilder factory)
391     {
392         resolverBuilderForFaces = factory;
393     }
394 
395     @Override
396     public final java.util.ResourceBundle getResourceBundle(final FacesContext facesContext, final String name)
397             throws FacesException, NullPointerException
398     {
399 
400         checkNull(facesContext, "facesContext");
401         checkNull(name, "name");
402 
403         final String bundleName = getBundleName(facesContext, name);
404 
405         if (bundleName == null)
406         {
407             return null;
408         }
409 
410         Locale locale = Locale.getDefault();
411 
412         final UIViewRoot viewRoot = facesContext.getViewRoot();
413         if (viewRoot != null && viewRoot.getLocale() != null)
414         {
415             locale = viewRoot.getLocale();
416         }
417 
418         try
419         {
420             return getResourceBundle(bundleName, locale, getClassLoader());
421         }
422         catch (MissingResourceException e)
423         {
424             try
425             {
426                 return getResourceBundle(bundleName, locale, this.getClass().getClassLoader());
427             }
428             catch (MissingResourceException e1)
429             {            
430                 throw new FacesException("Could not load resource bundle for name '"
431                                          + name + "': " + e.getMessage(), e1);
432             }
433         }
434     }
435 
436     private ClassLoader getClassLoader()
437     {
438         return ClassUtils.getContextClassLoader();
439     }
440 
441     String getBundleName(final FacesContext facesContext, final String name)
442     {
443         ResourceBundle bundle = getRuntimeConfig(facesContext).getResourceBundle(name);
444         return bundle != null ? bundle.getBaseName() : null;
445     }
446 
447     java.util.ResourceBundle getResourceBundle(final String name, final Locale locale, final ClassLoader loader)
448             throws MissingResourceException
449     {
450         return java.util.ResourceBundle.getBundle(name, locale, loader);
451     }
452 
453     final RuntimeConfig getRuntimeConfig(final FacesContext facesContext)
454     {
455         return RuntimeConfig.getCurrentInstance(facesContext.getExternalContext());
456     }
457 
458     final FacesContext getFaceContext()
459     {
460         return FacesContext.getCurrentInstance();
461     }
462 
463     @Override
464     public final UIComponent createComponent(final ValueExpression componentExpression,
465                                              final FacesContext facesContext, final String componentType)
466             throws FacesException, NullPointerException
467     {
468 
469         /*
470          * Before the component instance is returned, it must be inspected for the presence of a ListenerFor (or
471          * ListenersFor) or ResourceDependency (or ResourceDependencies) annotation. If any of these annotations are
472          * present, the action listed in ListenerFor or ResourceDependency must be taken on the component, 
473          * before it is
474          * returned from this method. This variant of createComponent must not inspect the Renderer for the 
475          * component to
476          * be returned for any of the afore mentioned annotations. Such inspection is the province of
477          */
478 
479         checkNull(componentExpression, "componentExpression");
480         checkNull(facesContext, "facesContext");
481         checkNull(componentType, "componentType");
482 
483         ELContext elContext = facesContext.getELContext();
484 
485         try
486         {
487             Object retVal = componentExpression.getValue(elContext);
488 
489             UIComponent createdComponent;
490 
491             if (retVal instanceof UIComponent)
492             {
493                 createdComponent = (UIComponent) retVal;
494                 _handleAnnotations(facesContext, createdComponent, createdComponent);
495             }
496             else
497             {
498                 createdComponent = createComponent(facesContext, componentType);
499                 componentExpression.setValue(elContext, createdComponent);
500             }
501 
502             return createdComponent;
503         }
504         catch (FacesException e)
505         {
506             throw e;
507         }
508         catch (Exception e)
509         {
510             throw new FacesException(e);
511         }
512     }
513 
514     @Override
515     public UIComponent createComponent(ValueExpression componentExpression, FacesContext context, 
516                                        String componentType, String rendererType)
517     {
518         // Like createComponent(ValueExpression, FacesContext, String)
519         UIComponent component = createComponent(componentExpression, context, componentType);
520 
521         if (rendererType != null)
522         {
523             _inspectRenderer(context, component, componentType, rendererType);
524         }
525 
526         return component;
527     }
528 
529     @Override
530     public final ExpressionFactory getExpressionFactory()
531     {
532         return _runtimeConfig.getExpressionFactory();
533     }
534 
535     @SuppressWarnings("unchecked")
536     @Override
537     public final <T> T evaluateExpressionGet(final FacesContext context, final String expression,
538                                              final Class<? extends T> expectedType) throws ELException
539     {
540         ELContext elContext = context.getELContext();
541 
542         ExpressionFactory factory = getExpressionFactory();
543 
544         return (T) factory.createValueExpression(elContext, expression, expectedType).getValue(elContext);
545     }
546 
547     @Override
548     public final void addELContextListener(final ELContextListener listener)
549     {
550         synchronized (_elContextListeners)
551         {
552             _elContextListeners.add(listener);
553         }
554     }
555 
556     @Override
557     public void publishEvent(FacesContext facesContext, Class<? extends SystemEvent> systemEventClass,
558                              Class<?> sourceBaseType, Object source)
559     {
560         checkNull(systemEventClass, "systemEventClass");
561         checkNull(source, "source");
562         
563         //Call events only if event processing is enabled.
564         if (!facesContext.isProcessingEvents())
565         {
566             return;
567         }
568         
569         // spec: If this argument is null the return from source.getClass() must be used as the sourceBaseType. 
570         if (sourceBaseType == null)
571         {
572             sourceBaseType = source.getClass();
573         }
574         
575         try
576         {
577             SystemEvent event = null;
578             if (source instanceof SystemEventListenerHolder)
579             {
580                 SystemEventListenerHolder holder = (SystemEventListenerHolder) source;
581 
582                 // If the source argument implements SystemEventListenerHolder, call
583                 // SystemEventListenerHolder.getListenersForEventClass(java.lang.Class) on it, passing the
584                 // systemEventClass
585                 // argument. If the list is not empty, perform algorithm traverseListenerList on the list.
586                 event = _traverseListenerList(holder.getListenersForEventClass(systemEventClass), systemEventClass,
587                                               source, event);
588             }
589             
590             UIViewRoot uiViewRoot = facesContext.getViewRoot();
591             if (uiViewRoot != null)
592             {
593                 //Call listeners on view level
594                 event = _traverseListenerListWithCopy(uiViewRoot.getViewListenersForEventClass(systemEventClass), 
595                         systemEventClass, source, event);
596             }
597 
598             SystemListenerEntry systemListenerEntry = _systemEventListenerClassMap.get(systemEventClass);
599             if (systemListenerEntry != null)
600             {
601                 systemListenerEntry.publish(systemEventClass, sourceBaseType, source, event);
602             }
603         }
604         catch (AbortProcessingException e)
605         {
606             // If the act of invoking the processListener method causes an AbortProcessingException to be thrown,
607             // processing of the listeners must be aborted, no further processing of the listeners for this event must
608             // take place, and the exception must be logged with Level.SEVERE.
609             log.log(Level.SEVERE, "Event processing was aborted", e);
610         }
611     }
612 
613     @Override
614     public void publishEvent(FacesContext facesContext, Class<? extends SystemEvent> systemEventClass, Object source)
615     {
616         publishEvent(facesContext, systemEventClass, source.getClass(), source);
617     }
618 
619     @Override
620     public final void removeELContextListener(final ELContextListener listener)
621     {
622         synchronized (_elContextListeners)
623         {
624             _elContextListeners.remove(listener);
625         }
626     }
627 
628     @Override
629     public final ELContextListener[] getELContextListeners()
630     {
631         // this gets called on every request, so I can't afford to synchronize
632         // I just have to trust that toArray() with do the right thing if the
633         // list is changing (not likely)
634         return _elContextListeners.toArray(new ELContextListener[_elContextListeners.size()]);
635     }
636 
637     @Override
638     public final void setActionListener(final ActionListener actionListener)
639     {
640         checkNull(actionListener, "actionListener");
641 
642         _actionListener = actionListener;
643         if (log.isLoggable(Level.FINEST))
644         {
645             log.finest("set actionListener = " + actionListener.getClass().getName());
646         }
647     }
648 
649     @Override
650     public final ActionListener getActionListener()
651     {
652         return _actionListener;
653     }
654 
655     @Override
656     public Iterator<String> getBehaviorIds()
657     {
658         return _behaviorClassMap.keySet().iterator();
659     }
660 
661     @Override
662     public final Iterator<String> getComponentTypes()
663     {
664         return _componentClassMap.keySet().iterator();
665     }
666 
667     @Override
668     public final Iterator<String> getConverterIds()
669     {
670         return _converterIdToClassMap.keySet().iterator();
671     }
672 
673     @Override
674     public final Iterator<Class<?>> getConverterTypes()
675     {
676         return _converterTargetClassToConverterClassMap.keySet().iterator();
677     }
678 
679     @Override
680     public final void setDefaultLocale(final Locale locale)
681     {
682         checkNull(locale, "locale");
683 
684         _defaultLocale = locale;
685         if (log.isLoggable(Level.FINEST))
686         {
687             log.finest("set defaultLocale = " + locale.getCountry() + " " + locale.getLanguage());
688         }
689     }
690 
691     @Override
692     public final Locale getDefaultLocale()
693     {
694         return _defaultLocale;
695     }
696 
697     @Override
698     public final void setMessageBundle(final String messageBundle)
699     {
700         checkNull(messageBundle, "messageBundle");
701 
702         _messageBundle = messageBundle;
703         if (log.isLoggable(Level.FINEST))
704         {
705             log.finest("set MessageBundle = " + messageBundle);
706         }
707     }
708 
709     @Override
710     public final String getMessageBundle()
711     {
712         return _messageBundle;
713     }
714 
715     @Override
716     public final void setNavigationHandler(final NavigationHandler navigationHandler)
717     {
718         checkNull(navigationHandler, "navigationHandler");
719 
720         _navigationHandler = navigationHandler;
721         if (log.isLoggable(Level.FINEST))
722         {
723             log.finest("set NavigationHandler = " + navigationHandler.getClass().getName());
724         }
725     }
726 
727     @Override
728     public final NavigationHandler getNavigationHandler()
729     {
730         return _navigationHandler;
731     }
732 
733     /**
734      * @deprecated
735      */
736     @Deprecated
737     @Override
738     public final void setPropertyResolver(final PropertyResolver propertyResolver)
739     {
740         checkNull(propertyResolver, "propertyResolver");
741 
742         if (getFaceContext() != null)
743         {
744             throw new IllegalStateException("propertyResolver must be defined before request processing");
745         }
746 
747         _runtimeConfig.setPropertyResolver(propertyResolver);
748 
749         if (log.isLoggable(Level.FINEST))
750         {
751             log.finest("set PropertyResolver = " + propertyResolver.getClass().getName());
752         }
753     }
754 
755     @Override
756     public ProjectStage getProjectStage()
757     {
758         // If the value has already been determined by a previous call to this
759         // method, simply return that value.
760         if (_projectStage == null)
761         {
762             String stageName = null;
763             
764             // try to obtain the ProjectStage from the system property
765             // faces.PROJECT_STAGE as proposed by Ed Burns
766             stageName = System.getProperty(PROJECT_STAGE_SYSTEM_PROPERTY_NAME);
767             
768             if (stageName == null)
769             {
770                 // if not found check for the "old" System Property
771                 // and print a warning message to the log (just to be 
772                 // sure that everyone recognizes the change in the name).
773                 stageName = System.getProperty(MYFACES_PROJECT_STAGE_SYSTEM_PROPERTY_NAME);
774                 if (stageName != null)
775                 {
776                     log.log(Level.WARNING, "The system property " + MYFACES_PROJECT_STAGE_SYSTEM_PROPERTY_NAME
777                             + " has been replaced by " + PROJECT_STAGE_SYSTEM_PROPERTY_NAME + "!"
778                             + " Please change your settings.");
779                 }
780             }
781             
782             if (stageName == null)
783             {
784                 // Look for a JNDI environment entry under the key given by the
785                 // value of ProjectStage.PROJECT_STAGE_JNDI_NAME (return type of
786                 // java.lang.String).
787                 try
788                 {
789                     Context ctx = new InitialContext();
790                     Object temp = ctx.lookup(ProjectStage.PROJECT_STAGE_JNDI_NAME);
791                     if (temp != null)
792                     {
793                         if (temp instanceof String)
794                         {
795                             stageName = (String) temp;
796                         }
797                         else
798                         {
799                             log.severe("JNDI lookup for key " + ProjectStage.PROJECT_STAGE_JNDI_NAME
800                                     + " should return a java.lang.String value");
801                         }
802                     }
803                 }
804                 catch (NamingException e)
805                 {
806                     // no-op
807                 }
808                 catch (NoClassDefFoundError er)
809                 {
810                     //On Google App Engine, javax.naming.Context is a restricted class.
811                     //In that case, NoClassDefFoundError is thrown. stageName needs to be configured
812                     //below by context parameter.
813                     //It can be done with changing the order to look first at
814                     // context param, but it is defined in the spec.
815                     //http://java.sun.com/javaee/6/docs/api/javax/faces/application/Application.html#getProjectStage()
816                     //no-op
817                 }
818             }
819 
820             /*
821              * If found, continue with the algorithm below, otherwise, look for an entry in the initParamMap of the
822              * ExternalContext from the current FacesContext with the key ProjectStage.PROJECT_STAGE_PARAM_NAME
823              */
824             if (stageName == null)
825             {
826                 FacesContext context = FacesContext.getCurrentInstance();
827                 stageName = context.getExternalContext().getInitParameter(ProjectStage.PROJECT_STAGE_PARAM_NAME);
828             }
829 
830             // If a value is found
831             if (stageName != null)
832             {
833                 /*
834                  * see if an enum constant can be obtained by calling ProjectStage.valueOf(), passing 
835                  * the value from the initParamMap. If this succeeds without exception, save the value 
836                  * and return it.
837                  */
838                 try
839                 {
840                     _projectStage = ProjectStage.valueOf(stageName);
841                     return _projectStage;
842                 }
843                 catch (IllegalArgumentException e)
844                 {
845                     log.log(Level.SEVERE, "Couldn't discover the current project stage", e);
846                 }
847             }
848             else
849             {
850                 if (log.isLoggable(Level.INFO))
851                 {
852                     log.info("Couldn't discover the current project stage, using " + ProjectStage.Production);
853                 }
854             }
855 
856             /*
857              * If not found, or any of the previous attempts to discover the enum constant value have failed, log a
858              * descriptive error message, assign the value as ProjectStage.Production and return it.
859              */
860             
861             _projectStage = ProjectStage.Production;
862         }
863 
864         return _projectStage;
865     }
866 
867     /**
868      * @deprecated
869      */
870     @Deprecated
871     @Override
872     public final PropertyResolver getPropertyResolver()
873     {
874         return PROPERTYRESOLVER;
875     }
876 
877     @Override
878     public final void setResourceHandler(ResourceHandler resourceHandler)
879     {
880         checkNull(resourceHandler, "resourceHandler");
881 
882         if(isFirstRequestProcessed())
883         {
884             throw new IllegalStateException(
885                     "setResourceHandler may not be executed after a lifecycle request has been completed");
886         }
887         _resourceHandler = resourceHandler;
888     }
889 
890     @Override
891     public final ResourceHandler getResourceHandler()
892     {
893         return _resourceHandler;
894     }
895 
896     @Override
897     public final void setSupportedLocales(final Collection<Locale> locales)
898     {
899         checkNull(locales, "locales");
900 
901         _supportedLocales = locales;
902         if (log.isLoggable(Level.FINEST))
903         {
904             log.finest("set SupportedLocales");
905         }
906     }
907 
908     @Override
909     public final Iterator<Locale> getSupportedLocales()
910     {
911         return _supportedLocales.iterator();
912     }
913 
914     @Override
915     public final Iterator<String> getValidatorIds()
916     {
917         return _validatorClassMap.keySet().iterator();
918     }
919 
920     /**
921      * @deprecated
922      */
923     @Deprecated
924     @Override
925     public final void setVariableResolver(final VariableResolver variableResolver)
926     {
927         checkNull(variableResolver, "variableResolver");
928 
929         if (isFirstRequestProcessed())
930         {
931             throw new IllegalStateException("variableResolver must be defined before request processing");
932         }
933 
934         _runtimeConfig.setVariableResolver(variableResolver);
935 
936         if (log.isLoggable(Level.FINEST))
937         {
938             log.finest("set VariableResolver = " + variableResolver.getClass().getName());
939         }
940     }
941 
942     /**
943      * @deprecated
944      */
945     @Deprecated
946     @Override
947     public final VariableResolver getVariableResolver()
948     {
949         return VARIABLERESOLVER;
950     }
951 
952     @Override
953     public final void setViewHandler(final ViewHandler viewHandler)
954     {
955         checkNull(viewHandler, "viewHandler");
956 
957         if(isFirstRequestProcessed())
958         {
959             throw new IllegalStateException(
960                     "setViewHandler may not be executed after a lifecycle request has been completed");
961         }
962         _viewHandler = viewHandler;
963         if (log.isLoggable(Level.FINEST))
964         {
965             log.finest("set ViewHandler = " + viewHandler.getClass().getName());
966         }
967     }
968     
969     @Override
970     public void subscribeToEvent(Class<? extends SystemEvent> systemEventClass, SystemEventListener listener)
971     {
972         subscribeToEvent(systemEventClass, null, listener);
973     }
974 
975     @Override
976     public void subscribeToEvent(Class<? extends SystemEvent> systemEventClass, Class<?> sourceClass,
977                                  SystemEventListener listener)
978     {
979         checkNull(systemEventClass, "systemEventClass");
980         checkNull(listener, "listener");
981 
982         SystemListenerEntry systemListenerEntry;
983         synchronized (_systemEventListenerClassMap)
984         {
985             systemListenerEntry = _systemEventListenerClassMap.get(systemEventClass);
986             if (systemListenerEntry == null)
987             {
988                 systemListenerEntry = new SystemListenerEntry();
989                 _systemEventListenerClassMap.put(systemEventClass, systemListenerEntry);
990             }
991         }
992 
993         systemListenerEntry.addListener(listener, sourceClass);
994     }
995     
996     @Override
997     public void unsubscribeFromEvent(Class<? extends SystemEvent> systemEventClass, SystemEventListener listener)
998     {
999         unsubscribeFromEvent(systemEventClass, null, listener);
1000     }
1001 
1002     @Override
1003     public void unsubscribeFromEvent(Class<? extends SystemEvent> systemEventClass, Class<?> sourceClass,
1004                                      SystemEventListener listener)
1005     {
1006         checkNull(systemEventClass, "systemEventClass");
1007         checkNull(listener, "listener");
1008 
1009         SystemListenerEntry systemListenerEntry = _systemEventListenerClassMap.get(systemEventClass);
1010         if (systemListenerEntry != null)
1011         {
1012             systemListenerEntry.removeListener(listener, sourceClass);
1013         }
1014     }
1015 
1016     @Override
1017     public final ViewHandler getViewHandler()
1018     {
1019         return _viewHandler;
1020     }
1021 
1022     @Override
1023     public void addBehavior(String behaviorId, String behaviorClass)
1024     {
1025         checkNull(behaviorId, "behaviorId");
1026         checkEmpty(behaviorId, "behaviorId");
1027         checkNull(behaviorClass, "behaviorClass");
1028         checkEmpty(behaviorClass, "behaviorClass");
1029 
1030         try
1031         {
1032             if(isLazyLoadConfigObjects())
1033             {
1034                 _behaviorClassMap.put(behaviorId, behaviorClass);
1035             }
1036             else
1037             {
1038                 _behaviorClassMap.put(behaviorId, ClassUtils.simpleClassForName(behaviorClass));
1039             }
1040             
1041             if (log.isLoggable(Level.FINEST))
1042             {
1043                 log.finest("add Behavior class = " + behaviorClass + " for id = " + behaviorId);
1044             }
1045         }
1046         catch (Exception e)
1047         {
1048             log.log(Level.SEVERE, "Behavior class " + behaviorClass + " not found", e);
1049         }
1050 
1051     }
1052 
1053     @Override
1054     public final void addComponent(final String componentType, final String componentClassName)
1055     {
1056         checkNull(componentType, "componentType");
1057         checkEmpty(componentType, "componentType");
1058         checkNull(componentClassName, "componentClassName");
1059         checkEmpty(componentClassName, "componentClassName");
1060 
1061         try
1062         {
1063             if(isLazyLoadConfigObjects())
1064             {
1065                 _componentClassMap.put(componentType, componentClassName);
1066             }
1067             else
1068             {
1069                 _componentClassMap.put(componentType, ClassUtils.simpleClassForName(componentClassName));
1070             }
1071             
1072             if (log.isLoggable(Level.FINEST))
1073             {
1074                 log.finest("add Component class = " + componentClassName + " for type = " + componentType);
1075             }
1076         }
1077         catch (Exception e)
1078         {
1079             log.log(Level.SEVERE, "Component class " + componentClassName + " not found", e);
1080         }
1081     }
1082 
1083     @Override
1084     public final void addConverter(final String converterId, final String converterClass)
1085     {
1086         checkNull(converterId, "converterId");
1087         checkEmpty(converterId, "converterId");
1088         checkNull(converterClass, "converterClass");
1089         checkEmpty(converterClass, "converterClass");
1090 
1091         try
1092         {
1093             if(isLazyLoadConfigObjects())
1094             {
1095                 _converterIdToClassMap.put(converterId, converterClass);
1096             }
1097             else
1098             {
1099                 _converterIdToClassMap.put(converterId, ClassUtils.simpleClassForName(converterClass));
1100             }
1101             if (log.isLoggable(Level.FINEST))
1102             {
1103                 log.finest("add Converter id = " + converterId + " converterClass = " + converterClass);
1104             }
1105         }
1106         catch (Exception e)
1107         {
1108             log.log(Level.SEVERE, "Converter class " + converterClass + " not found", e);
1109         }
1110     }
1111 
1112     @Override
1113     public final void addConverter(final Class<?> targetClass, final String converterClass)
1114     {
1115         checkNull(targetClass, "targetClass");
1116         checkNull(converterClass, "converterClass");
1117         checkEmpty(converterClass, "converterClass");
1118 
1119         try
1120         {
1121             if(isLazyLoadConfigObjects())
1122             {
1123                 _converterTargetClassToConverterClassMap.put(targetClass, converterClass);
1124             }
1125             else
1126             {
1127                 _converterTargetClassToConverterClassMap.put(targetClass,
1128                                                              ClassUtils.simpleClassForName(converterClass));
1129             }
1130 
1131             if (log.isLoggable(Level.FINEST))
1132             {
1133                 log.finest("add Converter for class = " + targetClass + " converterClass = " + converterClass);
1134             }
1135         }
1136         catch (Exception e)
1137         {
1138             log.log(Level.SEVERE, "Converter class " + converterClass + " not found", e);
1139         }
1140     }
1141 
1142     @Override
1143     public final void addValidator(final String validatorId, final String validatorClass)
1144     {
1145         checkNull(validatorId, "validatorId");
1146         checkEmpty(validatorId, "validatorId");
1147         checkNull(validatorClass, "validatorClass");
1148         checkEmpty(validatorClass, "validatorClass");
1149 
1150         try
1151         {
1152             if(isLazyLoadConfigObjects())
1153             {
1154                 _validatorClassMap.put(validatorId, validatorClass);
1155             }
1156             else
1157             {
1158                 _validatorClassMap.put(validatorId, ClassUtils.simpleClassForName(validatorClass));
1159             }
1160             
1161             if (log.isLoggable(Level.FINEST))
1162             {
1163                 log.finest("add Validator id = " + validatorId + " class = " + validatorClass);
1164             }
1165         }
1166         catch (Exception e)
1167         {
1168             log.log(Level.SEVERE, "Validator class " + validatorClass + " not found", e);
1169         }
1170     }
1171 
1172     @Override
1173     public Behavior createBehavior(String behaviorId) throws FacesException
1174     {
1175         checkNull(behaviorId, "behaviorId");
1176         checkEmpty(behaviorId, "behaviorId");
1177 
1178         final Class<?> behaviorClass = getObjectFromClassMap(behaviorId, _behaviorClassMap);
1179         
1180         if (behaviorClass == null)
1181         {
1182             throw new FacesException("Could not find any registered behavior-class for behaviorId : " + behaviorId);
1183         }
1184         
1185         try
1186         {
1187             Behavior behavior = (Behavior)behaviorClass.newInstance();
1188             FacesContext facesContext = FacesContext.getCurrentInstance();
1189             _handleAttachedResourceDependencyAnnotations(facesContext, behavior);
1190 
1191             if (behavior instanceof ClientBehaviorBase)
1192             {
1193               ClientBehaviorBase clientBehavior = (ClientBehaviorBase) behavior;
1194               String renderType = clientBehavior.getRendererType();
1195               if (renderType != null)
1196               {
1197                 ClientBehaviorRenderer cbr = facesContext.getRenderKit().getClientBehaviorRenderer(renderType);
1198                 _handleAttachedResourceDependencyAnnotations(facesContext, cbr);
1199               }
1200             }
1201 
1202             return behavior;
1203         }
1204         catch (Exception e)
1205         {
1206             log.log(Level.SEVERE, "Could not instantiate behavior " + behaviorClass, e);
1207             throw new FacesException("Could not instantiate behavior: " + behaviorClass, e);
1208         }
1209     }
1210 
1211     @Override
1212     public UIComponent createComponent(FacesContext context, Resource componentResource)
1213     {
1214         checkNull(context, "context");
1215         checkNull(componentResource, "componentResource");
1216         
1217         UIComponent component = null;
1218         Resource resource;
1219         String fqcn;
1220         Class<? extends UIComponent> componentClass = null;
1221 
1222         /*
1223          * Obtain a reference to the ViewDeclarationLanguage for this Application instance by calling
1224          * ViewHandler.getViewDeclarationLanguage(javax.faces.context.FacesContext, java.lang.String), passing the
1225          * viewId found by calling UIViewRoot.getViewId() on the UIViewRoot in the argument FacesContext.
1226          */
1227         UIViewRoot view = context.getViewRoot();
1228         Application application = context.getApplication();
1229         ViewDeclarationLanguage vdl
1230                 = application.getViewHandler().getViewDeclarationLanguage(context, view.getViewId());
1231 
1232         /*
1233          * Obtain a reference to the composite component metadata for this composite component by calling
1234          * ViewDeclarationLanguage.getComponentMetadata(javax.faces.context.FacesContext,
1235          * javax.faces.application.Resource), passing the facesContext and componentResource arguments to this method.
1236          * This version of JSF specification uses JavaBeans as the API to the component metadata.
1237          */
1238         BeanInfo metadata = vdl.getComponentMetadata(context, componentResource);
1239         if (metadata == null)
1240         {
1241             throw new FacesException("Could not get component metadata for " 
1242                     + componentResource.getResourceName()
1243                     + ". Did you forget to specify <composite:interface>?");
1244         }
1245 
1246         /*
1247          * Determine if the component author declared a component-type for this component instance by obtaining the
1248          * BeanDescriptor from the component metadata and calling its getValue() method, passing
1249          * UIComponent.COMPOSITE_COMPONENT_TYPE_KEY as the argument. If non-null, the result must be a ValueExpression
1250          * whose value is the component-type of the UIComponent to be created for this Resource component. Call through
1251          * to createComponent(java.lang.String) to create the component.
1252          */
1253         BeanDescriptor descriptor = metadata.getBeanDescriptor();
1254         ValueExpression componentType = (ValueExpression) descriptor.getValue(
1255                 UIComponent.COMPOSITE_COMPONENT_TYPE_KEY);
1256         boolean annotationsApplied = false;
1257         if (componentType != null)
1258         {
1259             component = application.createComponent((String) componentType.getValue(context.getELContext()));
1260             annotationsApplied = true;
1261         }
1262         else
1263         {
1264             /*
1265              * Otherwise, determine if a script based component for this Resource can be found by calling
1266              * ViewDeclarationLanguage.getScriptComponentResource(javax.faces.context.FacesContext,
1267              * javax.faces.application.Resource). If the result is non-null, and is a script written in one of the
1268              * languages listed in JSF 4.3 of the specification prose document, create a UIComponent instance from the
1269              * script resource.
1270              */
1271             resource = vdl.getScriptComponentResource(context, componentResource);
1272             if (resource != null)
1273             {
1274                 String name = resource.getResourceName();
1275                 String className = name.substring(0, name.lastIndexOf('.'));
1276 
1277                 component = (UIComponent)ClassUtils.newInstance(className);
1278             }
1279             else
1280             {
1281                 /*
1282                  * Otherwise, let library-name be the return from calling Resource.getLibraryName() on the argument
1283                  * componentResource and resource-name be the return from calling Resource.getResourceName() on the
1284                  * argument componentResource. Create a fully qualified Java class name by removing any file extension
1285                  * from resource-name and let fqcn be library-name + "." + resource-name. If a class with the name of
1286                  * fqcn cannot be found, take no action and continue to the next step. If any of 
1287                  * InstantiationException,
1288                  * IllegalAccessException, or ClassCastException are thrown, wrap the exception in a FacesException and
1289                  * re-throw it. If any other exception is thrown, log the exception and continue to the next step.
1290                  */
1291 
1292                 boolean isProduction = FacesContext.getCurrentInstance().isProjectStage(ProjectStage.Production);
1293                 String name = componentResource.getResourceName();
1294                 String className = name.substring(0, name.lastIndexOf('.'));
1295                 fqcn = componentResource.getLibraryName() + "." + className;
1296                 
1297                 if (isProduction)
1298                 {
1299                     componentClass = (Class<? extends UIComponent>) _componentClassMap.get(fqcn);
1300                 }
1301                 if (componentClass == null)
1302                 {
1303                     try
1304                     {
1305                         componentClass = ClassUtils.classForName(fqcn);
1306                         if (isProduction)
1307                         {
1308                             _componentClassMap.put(fqcn, componentClass);
1309                         }
1310                     }
1311                     catch (ClassNotFoundException e)
1312                     {
1313                         // Remember here that classForName did not find Class
1314                         if (isProduction)
1315                         {
1316                             _componentClassMap.put(fqcn, NOTHING.getClass());
1317                         }
1318                     }
1319                 }
1320 
1321                 if (componentClass != null && NOTHING.getClass() != componentClass)
1322                 {
1323                     try
1324                     {
1325                         component = componentClass.newInstance();
1326                     }
1327                     catch (InstantiationException e)
1328                     {
1329                         log.log(Level.SEVERE, "Could not instantiate component class name = " + fqcn, e);
1330                         throw new FacesException("Could not instantiate component class name = " + fqcn, e);
1331                     }
1332                     catch (IllegalAccessException e)
1333                     {
1334                         log.log(Level.SEVERE, "Could not instantiate component class name = " + fqcn, e);
1335                         throw new FacesException("Could not instantiate component class name = " + fqcn, e);
1336                     }
1337                     catch (Exception e)
1338                     {
1339                         log.log(Level.SEVERE, "Could not instantiate component class name = " + fqcn, e);
1340                     }
1341                 }
1342 
1343                 /*
1344                  * If none of the previous steps have yielded a UIComponent instance, call
1345                  * createComponent(java.lang.String) passing "javax.faces.NamingContainer" as the argument.
1346                  */
1347                 if (component == null)
1348                 {
1349                     component = application.createComponent(context, UINamingContainer.COMPONENT_TYPE, null);
1350                     annotationsApplied = true;
1351                 }
1352             }
1353         }
1354 
1355         /*
1356          * Call UIComponent.setRendererType(java.lang.String) on the UIComponent instance, passing
1357          * "javax.faces.Composite" as the argument.
1358          */
1359         component.setRendererType("javax.faces.Composite");
1360 
1361         /*
1362          * Store the argument Resource in the attributes Map of the UIComponent under the key,
1363          * Resource.COMPONENT_RESOURCE_KEY.
1364          */
1365         component.getAttributes().put(Resource.COMPONENT_RESOURCE_KEY, componentResource);
1366 
1367         /*
1368          * Store composite component metadata in the attributes Map of the UIComponent under the key,
1369          * UIComponent.BEANINFO_KEY.
1370          */
1371         component.getAttributes().put(UIComponent.BEANINFO_KEY, metadata);
1372 
1373         /*
1374          * Before the component instance is returned, it must be inspected for the presence of a 
1375          * ListenerFor annotation.
1376          * If this annotation is present, the action listed in ListenerFor must be taken on the component, 
1377          * before it is
1378          * returned from this method.
1379          */
1380         if (!annotationsApplied)
1381         {
1382             _handleAnnotations(context, component, component);
1383         }
1384 
1385         return component;
1386     }
1387 
1388     @Override
1389     public UIComponent createComponent(FacesContext context, String componentType, String rendererType)
1390     {
1391         checkNull(context, "context");
1392         checkNull(componentType, "componentType");
1393 
1394         // Like createComponent(String)
1395         UIComponent component = createComponent(context, componentType);
1396 
1397         // A null value on this field is valid! If that so, no need to do any log
1398         // or look on RenderKit map for a inexistent renderer!
1399         if (rendererType != null)
1400         {
1401             _inspectRenderer(context, component, componentType, rendererType);
1402         }
1403 
1404         return component;
1405     }
1406 
1407     /**
1408      * This works just like createComponent(String componentType), but without call
1409      * FacesContext.getCurrentInstance()
1410      * 
1411      * @param facesContext
1412      * @param componentType
1413      * @return
1414      * @throws FacesException 
1415      */
1416     private final UIComponent createComponent(FacesContext facesContext, 
1417             final String componentType) throws FacesException
1418     {
1419         checkNull(componentType, "componentType");
1420         checkEmpty(componentType, "componentType");
1421 
1422         final Class<?> componentClass = getObjectFromClassMap(componentType, _componentClassMap);
1423         if (componentClass == null)
1424         {
1425             log.log(Level.SEVERE, "Undefined component type " + componentType);
1426             throw new FacesException("Undefined component type " + componentType);
1427         }
1428 
1429         try
1430         {
1431             UIComponent component = (UIComponent)componentClass.newInstance();            
1432             _handleAnnotations(facesContext, component, component);
1433             return component;
1434         }
1435         catch (Exception e)
1436         {
1437             log.log(Level.SEVERE, "Could not instantiate component componentType = " + componentType, e);
1438             throw new FacesException("Could not instantiate component componentType = " + componentType, e);
1439         }
1440     }
1441     
1442     @Override
1443     public final UIComponent createComponent(final String componentType) throws FacesException
1444     {
1445         checkNull(componentType, "componentType");
1446         checkEmpty(componentType, "componentType");
1447 
1448         final Class<?> componentClass = getObjectFromClassMap(componentType, _componentClassMap);
1449         if (componentClass == null)
1450         {
1451             log.log(Level.SEVERE, "Undefined component type " + componentType);
1452             throw new FacesException("Undefined component type " + componentType);
1453         }
1454 
1455         try
1456         {
1457             UIComponent component = (UIComponent)componentClass.newInstance();            
1458             _handleAnnotations(FacesContext.getCurrentInstance(), component, component);
1459             return component;
1460         }
1461         catch (Exception e)
1462         {
1463             log.log(Level.SEVERE, "Could not instantiate component componentType = " + componentType, e);
1464             throw new FacesException("Could not instantiate component componentType = " + componentType, e);
1465         }
1466     }
1467 
1468     /**
1469      * @deprecated Use createComponent(ValueExpression, FacesContext, String) instead.
1470      */
1471     @Deprecated
1472     @Override
1473     public final UIComponent createComponent(final ValueBinding valueBinding, final FacesContext facesContext,
1474                                              final String componentType) throws FacesException
1475     {
1476 
1477         checkNull(valueBinding, "valueBinding");
1478         checkNull(facesContext, "facesContext");
1479         checkNull(componentType, "componentType");
1480         checkEmpty(componentType, "componentType");
1481 
1482         final ValueExpression valExpression = new ValueBindingToValueExpression(valueBinding);
1483 
1484         return createComponent(valExpression, facesContext, componentType);
1485     }
1486 
1487     /**
1488      * Return an instance of the converter class that has been registered under the specified id.
1489      * <p>
1490      * Converters are registered via faces-config.xml files, and can also be registered via the addConverter(String id,
1491      * Class converterClass) method on this class. Here the the appropriate Class definition is found, then an instance
1492      * is created and returned.
1493      * <p>
1494      * A converter registered via a config file can have any number of nested attribute or property tags. The JSF
1495      * specification is very vague about what effect these nested tags have. This method ignores nested attribute
1496      * definitions, but for each nested property tag the corresponding setter is invoked on the new Converter instance
1497      * passing the property's defaultValuer. Basic typeconversion is done so the target properties on the Converter
1498      * instance can be String, int, boolean, etc. Note that:
1499      * <ol>
1500      * <li>the Sun Mojarra JSF implemenation ignores nested property tags completely, so this behaviour cannot be 
1501      * relied on across implementations.
1502      * <li>there is no equivalent functionality for converter classes registered via the Application.addConverter api
1503      * method.
1504      * </ol>
1505      * <p>
1506      * Note that this method is most commonly called from the standard f:attribute tag. As an alternative, most
1507      * components provide a "converter" attribute which uses an EL expression to create a Converter instance, in which
1508      * case this method is not invoked at all. The converter attribute allows the returned Converter instance to be
1509      * configured via normal dependency-injection, and is generally a better choice than using this method.
1510      */
1511     @Override
1512     public final Converter createConverter(final String converterId)
1513     {
1514         checkNull(converterId, "converterId");
1515         checkEmpty(converterId, "converterId");
1516 
1517         final Class<?> converterClass = getObjectFromClassMap(converterId, _converterIdToClassMap);
1518         if (converterClass == null)
1519         {
1520             throw new FacesException("Could not find any registered converter-class by converterId : " + converterId);
1521         }
1522 
1523         try
1524         {
1525             final Converter converter = (Converter)converterClass.newInstance();
1526 
1527             setConverterProperties(converterClass, converter);
1528             
1529             _handleAttachedResourceDependencyAnnotations(FacesContext.getCurrentInstance(), converter);
1530 
1531             return converter;
1532         }
1533         catch (Exception e)
1534         {
1535             log.log(Level.SEVERE, "Could not instantiate converter " + converterClass, e);
1536             throw new FacesException("Could not instantiate converter: " + converterClass, e);
1537         }
1538     }
1539 
1540     @Override
1541     public final Converter createConverter(final Class<?> targetClass)
1542     {
1543         checkNull(targetClass, "targetClass");
1544 
1545         return internalCreateConverter(targetClass);
1546     }
1547 
1548     @SuppressWarnings("unchecked")
1549     private Converter internalCreateConverter(final Class<?> targetClass)
1550     {
1551         // Locate a Converter registered for the target class itself.
1552         Object converterClassOrClassName = _converterTargetClassToConverterClassMap.get(targetClass);
1553         
1554         // Locate a Converter registered for interfaces that are
1555         // implemented by the target class (directly or indirectly).
1556         // Skip if class is String, for performance reasons 
1557         // (save 3 additional lookups over a concurrent map per request). 
1558         if (converterClassOrClassName == null && !String.class.equals(targetClass))
1559         {
1560             final Class<?> interfaces[] = targetClass.getInterfaces();
1561             if (interfaces != null)
1562             {
1563                 for (int i = 0, len = interfaces.length; i < len; i++)
1564                 {
1565                     // search all superinterfaces for a matching converter,
1566                     // create it
1567                     final Converter converter = internalCreateConverter(interfaces[i]);
1568                     if (converter != null)
1569                     {
1570                         return converter;
1571                     }
1572                 }
1573             }
1574         }
1575 
1576         // Get EnumConverter for enum classes with no special converter, check
1577         // here as recursive call with java.lang.Enum will not work
1578         if (converterClassOrClassName == null && targetClass.isEnum())
1579         {
1580             converterClassOrClassName = _converterTargetClassToConverterClassMap.get(Enum.class);
1581         }
1582 
1583         if (converterClassOrClassName != null)
1584         {
1585             try
1586             {
1587                 Class<? extends Converter> converterClass = null;
1588                 if (converterClassOrClassName instanceof Class<?>)
1589                 {
1590                     converterClass = (Class<? extends Converter>) converterClassOrClassName;
1591                 }
1592                 else if (converterClassOrClassName instanceof String)
1593                 {
1594                     converterClass = ClassUtils.simpleClassForName((String) converterClassOrClassName);
1595                     _converterTargetClassToConverterClassMap.put(targetClass, converterClass);
1596                 }
1597                 else
1598                 {
1599                     //object stored in the map for this id is an invalid type.  remove it and return null
1600                     _converterTargetClassToConverterClassMap.remove(targetClass);
1601                 }
1602                 
1603                 Converter converter = null;
1604                 
1605                 // check cached constructor information
1606                 if (!_noArgConstructorConverterClasses.contains(converterClass))
1607                 {
1608                     // the converter class either supports the one-arg constructor
1609                     // or has never been processed before
1610                     try
1611                     {
1612                         // look for a constructor that takes a single Class object
1613                         // See JSF 1.2 javadoc for Converter
1614                         Constructor<? extends Converter> constructor = converterClass
1615                                 .getConstructor(new Class[] { Class.class });
1616 
1617                         converter = constructor.newInstance(new Object[] { targetClass });
1618                     }
1619                     catch (Exception e)
1620                     {
1621                         // the constructor does not exist
1622                         // add the class to the no-arg constructor classes cache
1623                         _noArgConstructorConverterClasses.add(converterClass);
1624                         
1625                         // use no-arg constructor
1626                         converter = converterClass.newInstance();
1627                     }
1628                 }
1629                 else
1630                 {
1631                     // use no-arg constructor
1632                     converter = converterClass.newInstance();
1633                 }
1634 
1635                 setConverterProperties(converterClass, converter);
1636 
1637                 return converter;
1638             }
1639             catch (Exception e)
1640             {
1641                 log.log(Level.SEVERE, "Could not instantiate converter " + converterClassOrClassName.toString(), e);
1642                 throw new FacesException("Could not instantiate converter: " + converterClassOrClassName.toString(), e);
1643             }
1644         }
1645 
1646         // locate converter for primitive types
1647         if (targetClass == Long.TYPE)
1648         {
1649             return internalCreateConverter(Long.class);
1650         }
1651         else if (targetClass == Boolean.TYPE)
1652         {
1653             return internalCreateConverter(Boolean.class);
1654         }
1655         else if (targetClass == Double.TYPE)
1656         {
1657             return internalCreateConverter(Double.class);
1658         }
1659         else if (targetClass == Byte.TYPE)
1660         {
1661             return internalCreateConverter(Byte.class);
1662         }
1663         else if (targetClass == Short.TYPE)
1664         {
1665             return internalCreateConverter(Short.class);
1666         }
1667         else if (targetClass == Integer.TYPE)
1668         {
1669             return internalCreateConverter(Integer.class);
1670         }
1671         else if (targetClass == Float.TYPE)
1672         {
1673             return internalCreateConverter(Float.class);
1674         }
1675         else if (targetClass == Character.TYPE)
1676         {
1677             return internalCreateConverter(Character.class);
1678         }
1679 
1680         // Locate a Converter registered for the superclass (if any) of the
1681         // target class,
1682         // recursively working up the inheritance hierarchy.
1683         Class<?> superClazz = targetClass.getSuperclass();
1684 
1685         return superClazz != null ? internalCreateConverter(superClazz) : null;
1686 
1687     }
1688 
1689     private void setConverterProperties(final Class<?> converterClass, final Converter converter)
1690     {
1691         final org.apache.myfaces.config.element.Converter converterConfig = _runtimeConfig
1692                 .getConverterConfiguration(converterClass.getName());
1693         
1694         // if the converter is a DataTimeConverter, check the init param for the default timezone (since 2.0)
1695         if (converter instanceof DateTimeConverter && _dateTimeConverterDefaultTimeZoneIsSystemTimeZone)
1696         {    
1697             ((DateTimeConverter) converter).setTimeZone(TimeZone.getDefault());
1698         }
1699 
1700         if (converterConfig != null && converterConfig.getProperties().size() > 0)
1701         {
1702             for (Property property : converterConfig.getProperties())
1703             {
1704                 try
1705                 {
1706                     BeanUtils.setProperty(converter, property.getPropertyName(), property.getDefaultValue());
1707                 }
1708                 catch (Throwable th)
1709                 {
1710                     log.log(Level.SEVERE, "Initializing converter : " + converterClass.getName() + " with property : "
1711                             + property.getPropertyName() + " and value : " + property.getDefaultValue() + " failed.");
1712                 }
1713             }
1714         }
1715     }
1716     
1717     private void _handleAttachedResourceDependencyAnnotations(FacesContext context, Object inspected)
1718     {
1719         if (inspected == null)
1720         {
1721             return;
1722         }
1723         
1724         // This and only this method handles @ResourceDependency and @ResourceDependencies annotations
1725         // The source of these annotations is Class<?> inspectedClass.
1726         // Because Class<?> and its annotations cannot change
1727         // during request/response, it is sufficient to process Class<?> only once per view.
1728         RequestViewContext rvc = RequestViewContext.getCurrentInstance(context);
1729         Class<?> inspectedClass = inspected.getClass();
1730         if (rvc.isClassAlreadyProcessed(inspectedClass))
1731         {
1732             return;
1733         }
1734         boolean classAlreadyProcessed = false;
1735 
1736         
1737         List<ResourceDependency> dependencyList = null;
1738         boolean isCachedList = false;
1739         
1740         if(context.isProjectStage(ProjectStage.Production) && _classToResourceDependencyMap.containsKey(inspectedClass))
1741         {
1742             dependencyList = _classToResourceDependencyMap.get(inspectedClass);
1743             if(dependencyList == null)
1744             {
1745                 return; //class has been inspected and did not contain any resource dependency annotations
1746             }
1747             else if (dependencyList.isEmpty())
1748             {
1749                 return;
1750             }
1751             
1752             isCachedList = true;    // else annotations were found in the cache
1753         }
1754         
1755         if(dependencyList == null)  //not in production or the class hasn't been inspected yet
1756         {   
1757             ResourceDependency dependency = inspectedClass.getAnnotation(ResourceDependency.class);
1758             ResourceDependencies dependencies = inspectedClass.getAnnotation(ResourceDependencies.class);
1759             if(dependency != null || dependencies != null)
1760             {
1761                 //resource dependencies were found using one or both annotations, create and build a new list
1762                 dependencyList = new ArrayList<ResourceDependency>();
1763                 
1764                 if(dependency != null)
1765                 {
1766                     dependencyList.add(dependency);
1767                 }
1768                 
1769                 if(dependencies != null)
1770                 {
1771                     dependencyList.addAll(Arrays.asList(dependencies.value()));
1772                 }
1773             }
1774             else
1775             {
1776                 dependencyList = Collections.emptyList();
1777             }
1778         }
1779 
1780         //resource dependencies were found through inspection or from cache, handle them
1781         if (dependencyList != null && !dependencyList.isEmpty()) 
1782         {
1783             for (int i = 0, size = dependencyList.size(); i < size; i++)
1784             {
1785                 ResourceDependency dependency = dependencyList.get(i);
1786                 if (!rvc.isResourceDependencyAlreadyProcessed(dependency))
1787                 {
1788                     _handleAttachedResourceDependency(context, dependency, inspectedClass);
1789                     rvc.setResourceDependencyAsProcessed(dependency);
1790                 }
1791             }
1792         }
1793         
1794         //if we're in production and the list is not yet cached, store it
1795         if(context.isProjectStage(ProjectStage.Production) && !isCachedList)   
1796         {
1797             // Note at this point listenerForList cannot be null, but just let this
1798             // as a sanity check.
1799             if (dependencyList != null)
1800             {
1801                 _classToResourceDependencyMap.put(inspectedClass, dependencyList);
1802             }
1803         }
1804         
1805         if (!classAlreadyProcessed)
1806         {
1807             rvc.setClassProcessed(inspectedClass);
1808         }
1809     }
1810 
1811     /**
1812      * If the ResourceDependency component is created under facelets processing, it should receive
1813      * an special unique component id. This method check if there is a FaceletCompositionContext
1814      * and if that so, set the id. Components added by the effect of ResourceDependency are special,
1815      * because they do not have state, but they depends on the view structure, so with PSS, 
1816      * each time the view is built they are "recalculated", so they work as if they were transient
1817      * components that needs to be created at each request, but there are some cases were the 
1818      * components needs to be saved and restored fully. If a component is created outside facelets 
1819      * control (render response phase) it is expected to use the default implementation of 
1820      * createUniqueId(), but in that case, note that this happens after markInitialState() is 
1821      * called, and the component in this case is saved and restored fully, as expected.
1822      * 
1823      * This code cannot be called from facelets component tag handler, because in cases where a
1824      * component subtree is created using binding property, facelets lost control over component
1825      * creation and delegates it to the user, but since the binding code is executed each time the
1826      * view is created, the effect over ResourceDependency persists and the binding code takes into
1827      * account in the recalculation step, even if later the node related to the binding property
1828      * is dropped and recreated from the state fully. 
1829      * 
1830      * @param facesContext
1831      * @param component 
1832      */
1833     private void setResourceIdOnFaceletsMode(FacesContext facesContext, UIComponent component,
1834             Class<?> inspectedClass)
1835     {
1836         if (component.getId() == null)
1837         {
1838             FaceletCompositionContext mctx = FaceletCompositionContext.getCurrentInstance(facesContext);
1839             if (mctx != null)
1840             {
1841                 UIViewRoot root = facesContext.getViewRoot();
1842                 root.getAttributes().put(RESOURCE_DEPENDENCY_UNIQUE_ID_KEY, Boolean.TRUE);
1843                 try
1844                 {
1845                     String uid = root.createUniqueId(facesContext, null);
1846                     component.setId(uid);
1847                 }
1848                 finally
1849                 {
1850                     root.getAttributes().put(RESOURCE_DEPENDENCY_UNIQUE_ID_KEY, Boolean.FALSE);
1851                 }
1852                 if (!mctx.isUsingPSSOnThisView())
1853                 {
1854                     // Now set the identifier that will help to know which classes has been already inspected.
1855                     component.getAttributes().put(
1856                             RequestViewContext.RESOURCE_DEPENDENCY_INSPECTED_CLASS, inspectedClass);
1857                 }
1858                 else if (mctx.isRefreshTransientBuildOnPSSPreserveState())
1859                 {
1860                     component.getAttributes().put(
1861                             RequestViewContext.RESOURCE_DEPENDENCY_INSPECTED_CLASS, inspectedClass);
1862                 }
1863             }
1864             else
1865             {
1866                 // This happens when there is a programmatic addition, which means the user has added the
1867                 // components to the tree on render response phase or earlier but outside facelets control.
1868                 // In that case we need to save the dependency.
1869                 component.getAttributes().put(
1870                         RequestViewContext.RESOURCE_DEPENDENCY_INSPECTED_CLASS, inspectedClass);
1871             }
1872         }
1873     }
1874     
1875     private void _handleAttachedResourceDependency(FacesContext context, ResourceDependency annotation, 
1876             Class<?> inspectedClass)
1877     {
1878         // If this annotation is not present on the class in question, no action must be taken. 
1879         if (annotation != null)
1880         {
1881             Application application = context.getApplication();
1882             
1883             // Create a UIOutput instance by passing javax.faces.Output. to 
1884             // Application.createComponent(java.lang.String).
1885             UIOutput output = (UIOutput) application.createComponent(context, UIOutput.COMPONENT_TYPE, null);
1886             
1887             // Get the annotation instance from the class and obtain the values of the name, library, and 
1888             // target attributes.
1889             String name = annotation.name();
1890             if (name != null && name.length() > 0)
1891             {
1892                 name = ELText.parse(getExpressionFactory(),
1893                                     context.getELContext(), name).toString(context.getELContext());
1894             }
1895             
1896             // Obtain the renderer-type for the resource name by passing name to 
1897             // ResourceHandler.getRendererTypeForResourceName(java.lang.String).
1898             String rendererType = application.getResourceHandler().getRendererTypeForResourceName(name);
1899             
1900             // Call setRendererType on the UIOutput instance, passing the renderer-type.
1901             output.setRendererType(rendererType);
1902             
1903             // If the @ResourceDependency was done inside facelets processing,
1904             // call setId() and set a proper id from facelets
1905             setResourceIdOnFaceletsMode(context, output, inspectedClass);
1906             
1907             // Obtain the Map of attributes from the UIOutput component by calling UIComponent.getAttributes().
1908             Map<String, Object> attributes = output.getAttributes();
1909             
1910             // Store the name into the attributes Map under the key "name".
1911             attributes.put("name", name);
1912             
1913             // If library is the empty string, let library be null.
1914             String library = annotation.library();
1915             if (library != null && library.length() > 0)
1916             {
1917                 library = ELText.parse(getExpressionFactory(),
1918                                        context.getELContext(), library).toString(context.getELContext());
1919                 // If library is non-null, store it under the key "library".
1920                 attributes.put("library", library);
1921             }
1922             
1923             // If target is the empty string, let target be null.
1924             String target = annotation.target();
1925             if (target != null && target.length() > 0)
1926             {
1927                 target = ELText.parse(getExpressionFactory(),
1928                                       context.getELContext(), target).toString(context.getELContext());
1929                 // If target is non-null, store it under the key "target".
1930                 attributes.put("target", target);
1931                 context.getViewRoot().addComponentResource(context, output, target);
1932             }
1933             else
1934             {
1935                 // Otherwise, if target is null, call 
1936                 // UIViewRoot.addComponentResource(javax.faces.context.FacesContext, 
1937                 // javax.faces.component.UIComponent), passing the UIOutput instance as the second argument.
1938                 context.getViewRoot().addComponentResource(context, output);
1939             }
1940         }
1941     }
1942 
1943     // Note: this method used to be synchronized in the JSF 1.1 version. Why?
1944     /**
1945      * @deprecated
1946      */
1947     @Deprecated
1948     @Override
1949     public final MethodBinding createMethodBinding(final String reference, Class<?>[] params)
1950             throws ReferenceSyntaxException
1951     {
1952         checkNull(reference, "reference");
1953         checkEmpty(reference, "reference");
1954 
1955         // TODO: this check should be performed by the expression factory. It is
1956         // a requirement of the TCK
1957         if (!(reference.startsWith("#{") && reference.endsWith("}")))
1958         {
1959             throw new ReferenceSyntaxException("Invalid method reference: '" + reference + "'");
1960         }
1961 
1962         if (params == null)
1963         {
1964             params = new Class[0];
1965         }
1966 
1967         MethodExpression methodExpression;
1968 
1969         try
1970         {
1971             methodExpression = getExpressionFactory().createMethodExpression(threadELContext(), reference,
1972                                                                              Object.class, params);
1973         }
1974         catch (ELException e)
1975         {
1976             throw new ReferenceSyntaxException(e);
1977         }
1978 
1979         return new MethodExpressionToMethodBinding(methodExpression);
1980     }
1981 
1982     @Override
1983     public final Validator createValidator(final String validatorId) throws FacesException
1984     {
1985         checkNull(validatorId, "validatorId");
1986         checkEmpty(validatorId, "validatorId");
1987 
1988         Class<?> validatorClass = getObjectFromClassMap(validatorId, _validatorClassMap);
1989         if (validatorClass == null)
1990         {
1991             String message = "Unknown validator id '" + validatorId + "'.";
1992             log.severe(message);
1993             throw new FacesException(message);
1994         }
1995 
1996         try
1997         {
1998             Validator validator = (Validator) validatorClass.newInstance();
1999             
2000             _handleAttachedResourceDependencyAnnotations(FacesContext.getCurrentInstance(), validator);
2001             
2002             return validator;
2003         }
2004         catch (Exception e)
2005         {
2006             log.log(Level.SEVERE, "Could not instantiate validator " + validatorClass, e);
2007             throw new FacesException("Could not instantiate validator: " + validatorClass, e);
2008         }
2009     }
2010 
2011     /**
2012      * @deprecated
2013      */
2014     @Override
2015     public final ValueBinding createValueBinding(final String reference) throws ReferenceSyntaxException
2016     {
2017         checkNull(reference, "reference");
2018         checkEmpty(reference, "reference");
2019 
2020         ValueExpression valueExpression;
2021 
2022         try
2023         {
2024             valueExpression = getExpressionFactory().createValueExpression(
2025                     threadELContext(), reference, Object.class);
2026         }
2027         catch (ELException e)
2028         {
2029             throw new ReferenceSyntaxException(e);
2030         }
2031 
2032         return new ValueExpressionToValueBinding(valueExpression);
2033     }
2034 
2035     // gets the elContext from the current FacesContext()
2036     private final ELContext threadELContext()
2037     {
2038         return getFaceContext().getELContext();
2039     }
2040 
2041     @Override
2042     public final String getDefaultRenderKitId()
2043     {
2044         return _defaultRenderKitId;
2045     }
2046 
2047     @Override
2048     public final void setDefaultRenderKitId(final String defaultRenderKitId)
2049     {
2050         _defaultRenderKitId = defaultRenderKitId;
2051     }
2052 
2053     @Override
2054     public final StateManager getStateManager()
2055     {
2056         return _stateManager;
2057     }
2058 
2059     @Override
2060     public final void setStateManager(final StateManager stateManager)
2061     {
2062         checkNull(stateManager, "stateManager");
2063 
2064         if(isFirstRequestProcessed())
2065         {
2066             throw new IllegalStateException(
2067                     "setStateManager may not be executed after a lifecycle request has been completed");
2068         }
2069         
2070         _stateManager = stateManager;
2071     }
2072 
2073     private void checkNull(final Object param, final String paramName)
2074     {
2075         if (param == null)
2076         {
2077             throw new NullPointerException(paramName + " cannot be null.");
2078         }
2079     }
2080 
2081     private void checkEmpty(final String param, final String paramName)
2082     {
2083         if (param.length() == 0)
2084         {
2085             throw new NullPointerException("String " + paramName + " cannot be empty.");
2086         }
2087     }
2088 
2089     private static SystemEvent _createEvent(Class<? extends SystemEvent> systemEventClass, Object source,
2090                                             SystemEvent event)
2091     {
2092         if (event == null)
2093         {
2094             try
2095             {
2096                 Constructor<?>[] constructors = systemEventClass.getConstructors();
2097                 Constructor<? extends SystemEvent> constructor = null;
2098                 for (Constructor<?> c : constructors)
2099                 {
2100                     if (c.getParameterTypes().length == 1)
2101                     {
2102                         // Safe cast, since the constructor belongs
2103                         // to a class of type SystemEvent
2104                         constructor = (Constructor<? extends SystemEvent>) c;
2105                         break;
2106                     }
2107                 }
2108                 if (constructor != null)
2109                 {
2110                     event = constructor.newInstance(source);
2111                 }
2112 
2113             }
2114             catch (Exception e)
2115             {
2116                 throw new FacesException("Couldn't instanciate system event of type " + 
2117                         systemEventClass.getName(), e);
2118             }
2119         }
2120 
2121         return event;
2122     }
2123 
2124     private void _handleAnnotations(FacesContext context, Object inspected, UIComponent component)
2125     {   
2126         // determine the ProjectStage setting via the given FacesContext
2127         // note that a local getProjectStage() could cause problems in wrapped environments
2128         boolean isProduction = context.isProjectStage(ProjectStage.Production);
2129         
2130         Class<?> inspectedClass = inspected.getClass();
2131         _handleListenerForAnnotations(context, inspected, inspectedClass, component, isProduction);
2132 
2133         _handleResourceDependencyAnnotations(context, inspectedClass, component, isProduction);
2134     }
2135     
2136     private void _handleListenerForAnnotations(FacesContext context, Object inspected, Class<?> inspectedClass,
2137                                                UIComponent component, boolean isProduction)
2138     {
2139         List<ListenerFor> listenerForList = null;
2140         boolean isCachedList = false;
2141         
2142         if(isProduction && _classToListenerForMap.containsKey(inspectedClass))
2143         {
2144             listenerForList = _classToListenerForMap.get(inspectedClass);
2145             if(listenerForList == null)
2146             {
2147                 return; //class has been inspected and did not contain any listener annotations
2148             }
2149             else if (listenerForList.isEmpty())
2150             {
2151                 return;
2152             }
2153             
2154             isCachedList = true;    // else annotations were found in the cache
2155         }
2156 
2157         if(listenerForList == null) //not in production or the class hasn't been inspected yet
2158         {
2159             ListenerFor listener = inspectedClass.getAnnotation(ListenerFor.class);
2160             ListenersFor listeners = inspectedClass.getAnnotation(ListenersFor.class);
2161             if(listener != null || listeners != null)
2162             {
2163                 //listeners were found using one or both annotations, create and build a new list
2164                 listenerForList = new ArrayList<ListenerFor>();
2165                 
2166                 if(listener != null)
2167                 {
2168                     listenerForList.add(listener);
2169                 }
2170                 
2171                 if(listeners != null)
2172                 {
2173                     listenerForList.addAll(Arrays.asList(listeners.value()));
2174                 }
2175             }
2176             else
2177             {
2178                 listenerForList = Collections.emptyList();
2179             }
2180         }        
2181  
2182         // listeners were found through inspection or from cache, handle them
2183         if (listenerForList != null && !listenerForList.isEmpty()) 
2184         {
2185             for (int i = 0, size = listenerForList.size(); i < size; i++)
2186             {
2187                 ListenerFor listenerFor = listenerForList.get(i);
2188                 _handleListenerFor(context, inspected, component, listenerFor);
2189             }
2190         }
2191         
2192         if(isProduction && !isCachedList) //if we're in production and the list is not yet cached, store it
2193         {
2194             // Note at this point listenerForList cannot be null, but just let this
2195             // as a sanity check.
2196             if (listenerForList != null)
2197             {
2198                 _classToListenerForMap.put(inspectedClass, listenerForList);
2199             }
2200         }
2201     }
2202 
2203     private void _handleListenerFor(FacesContext context, Object inspected, UIComponent component,
2204                                     ListenerFor annotation)
2205     {
2206         // If this annotation is not present on the class in question, no action must be taken.
2207         if (annotation != null)
2208         {
2209             // Determine the "target" on which to call subscribeToEvent.
2210             // If the class to which this annotation is attached implements ComponentSystemEventListener
2211             if (inspected instanceof ComponentSystemEventListener)
2212             {
2213                 // If the class to which this annotation is attached is a UIComponent instance, "target" is the
2214                 // UIComponent instance.
2215 
2216                 // If the class to which this annotation is attached is a Renderer instance, "target" is the
2217                 // UIComponent instance.
2218 
2219                 /*
2220                  * If "target" is a UIComponent call UIComponent.subscribeToEvent(Class, ComponentSystemEventListener)
2221                  * passing the systemEventClass() of the annotation as the first argument and the instance of the class
2222                  * to which this annotation is attached (which must implement ComponentSystemEventListener) as the
2223                  * second argument.
2224                  */
2225                 component.subscribeToEvent(annotation.systemEventClass(), (ComponentSystemEventListener) inspected);
2226             }
2227             // If the class to which this annotation is attached implements SystemEventListener and does not implement
2228             // ComponentSystemEventListener, "target" is the Application instance.
2229             else if (component instanceof SystemEventListener)
2230             {
2231                 // use the Application object from the FacesContext (note that a
2232                 // direct use of subscribeToEvent() could cause problems if the
2233                 // Application is wrapped)
2234                 Application application = context.getApplication();
2235                 
2236                 // If "target" is the Application instance, inspect the value of the sourceClass() annotation attribute
2237                 // value.
2238                 if (Void.class.equals(annotation.sourceClass()))
2239                 {
2240                     /*
2241                      * If the value is Void.class, call Application.subscribeToEvent(Class, SystemEventListener),
2242                      * passing the value of systemEventClass() as the first argument and the instance of the class to
2243                      * which this annotation is attached (which must implement SystemEventListener) as the second
2244                      * argument.
2245                      */
2246                     application.subscribeToEvent(annotation.systemEventClass(), (SystemEventListener) inspected);
2247                 }
2248                 else
2249                 {
2250                     /*
2251                      * Otherwise, call Application.subscribeToEvent(Class, Class, SystemEventListener), passing the
2252                      * value of systemEventClass() as the first argument, the value of sourceClass() as the second
2253                      * argument, and the instance of the class to which this annotation is attached (which must
2254                      * implement SystemEventListener) as the third argument.
2255                      */
2256                     application.subscribeToEvent(annotation.systemEventClass(), annotation.sourceClass(),
2257                                      (SystemEventListener) inspected);
2258                 }
2259             }
2260 
2261             /*
2262              * If the class to which this annotation is attached implements ComponentSystemEventListener and is neither
2263              * an instance of Renderer nor UIComponent, the action taken is unspecified. This case must not trigger any
2264              * kind of error.
2265              */
2266         }
2267     }
2268 
2269     private void _handleResourceDependencyAnnotations(FacesContext context, Class<?> inspectedClass,
2270                                                       UIComponent component, boolean isProduction)
2271     {
2272         // This and only this method handles @ResourceDependency and @ResourceDependencies annotations
2273         // The source of these annotations is Class<?> inspectedClass.
2274         // Because Class<?> and its annotations cannot change
2275         // during request/response, it is sufficient to process Class<?> only once per view.
2276         RequestViewContext rvc = RequestViewContext.getCurrentInstance(context);
2277         if (rvc.isClassAlreadyProcessed(inspectedClass))
2278         {
2279             return;
2280         }
2281         boolean classAlreadyProcessed = false;
2282 
2283         
2284         List<ResourceDependency> dependencyList = null;
2285         boolean isCachedList = false;
2286         
2287         if(isProduction && _classToResourceDependencyMap.containsKey(inspectedClass))
2288         {
2289             dependencyList = _classToResourceDependencyMap.get(inspectedClass);
2290             if(dependencyList == null)
2291             {
2292                 return; //class has been inspected and did not contain any resource dependency annotations
2293             }
2294             else if (dependencyList.isEmpty())
2295             {
2296                 return;
2297             }
2298             
2299             isCachedList = true;    // else annotations were found in the cache
2300         }
2301         
2302         if(dependencyList == null)  //not in production or the class hasn't been inspected yet
2303         {   
2304             ResourceDependency dependency = inspectedClass.getAnnotation(ResourceDependency.class);
2305             ResourceDependencies dependencies = inspectedClass.getAnnotation(ResourceDependencies.class);
2306             if(dependency != null || dependencies != null)
2307             {
2308                 //resource dependencies were found using one or both annotations, create and build a new list
2309                 dependencyList = new ArrayList<ResourceDependency>();
2310                 
2311                 if(dependency != null)
2312                 {
2313                     dependencyList.add(dependency);
2314                 }
2315                 
2316                 if(dependencies != null)
2317                 {
2318                     dependencyList.addAll(Arrays.asList(dependencies.value()));
2319                 }
2320             }
2321             else
2322             {
2323                 dependencyList = Collections.emptyList();
2324             }
2325         }        
2326  
2327         // resource dependencies were found through inspection or from cache, handle them
2328         if (dependencyList != null && !dependencyList.isEmpty()) 
2329         {
2330             for (int i = 0, size = dependencyList.size(); i < size; i++)
2331             {
2332                 ResourceDependency dependency = dependencyList.get(i);
2333                 if (!rvc.isResourceDependencyAlreadyProcessed(dependency))
2334                 {
2335                     _handleResourceDependency(context, component, dependency, inspectedClass);
2336                     rvc.setResourceDependencyAsProcessed(dependency);
2337                 }
2338             }
2339         }
2340         
2341         if(isProduction && !isCachedList)   //if we're in production and the list is not yet cached, store it
2342         {
2343             // Note at this point listenerForList cannot be null, but just let this
2344             // as a sanity check.
2345             if (dependencyList != null)
2346             {
2347                 _classToResourceDependencyMap.put(inspectedClass, dependencyList);
2348             }
2349         }
2350         
2351         if (!classAlreadyProcessed)
2352         {
2353             rvc.setClassProcessed(inspectedClass);
2354         }
2355     }
2356     
2357     private void _handleResourceDependency(FacesContext context, UIComponent component, ResourceDependency annotation,
2358             Class<?> inspectedClass)
2359     {
2360         // If this annotation is not present on the class in question, no action must be taken.
2361         if (annotation != null)
2362         {
2363             // Create a UIOutput instance by passing javax.faces.Output. to
2364             // Application.createComponent(java.lang.String).
2365             UIOutput output = (UIOutput) createComponent(context, UIOutput.COMPONENT_TYPE, null);
2366 
2367             // Get the annotation instance from the class and obtain the values of the name, library, and
2368             // target attributes.
2369             String name = annotation.name();
2370             if (name != null && name.length() > 0)
2371             {
2372                 name = ELText.parse(getExpressionFactory(),
2373                                     context.getELContext(), name).toString(context.getELContext());
2374             }
2375 
2376             // Obtain the renderer-type for the resource name by passing name to
2377             // ResourceHandler.getRendererTypeForResourceName(java.lang.String).
2378             // (note that we can not use this.getResourceHandler(), because the Application might be wrapped)
2379             String rendererType = context.getApplication().getResourceHandler().getRendererTypeForResourceName(name);
2380 
2381             // Call setRendererType on the UIOutput instance, passing the renderer-type.
2382             output.setRendererType(rendererType);
2383             
2384             // If the @ResourceDependency was done inside facelets processing,
2385             // call setId() and set a proper id from facelets
2386             setResourceIdOnFaceletsMode(context, output, inspectedClass);
2387 
2388             // Obtain the Map of attributes from the UIOutput component by calling UIComponent.getAttributes().
2389             Map<String, Object> attributes = output.getAttributes();
2390 
2391             // Store the name into the attributes Map under the key "name".
2392             attributes.put("name", name);
2393 
2394             // If library is the empty string, let library be null.
2395             String library = annotation.library();
2396             if (library != null && library.length() > 0)
2397             {
2398                 library = ELText.parse(getExpressionFactory(),
2399                                        context.getELContext(), library).toString(context.getELContext());
2400                 // If library is non-null, store it under the key "library".
2401                 if ("this".equals(library))
2402                 {
2403                     // Special "this" behavior
2404                     Resource resource = (Resource)component.getAttributes().get(Resource.COMPONENT_RESOURCE_KEY);
2405                     if (resource != null)
2406                     {
2407                         attributes.put("library", resource.getLibraryName());
2408                     }
2409                 }
2410                 else
2411                 {
2412                     attributes.put("library", library);
2413                 }
2414             }
2415 
2416             // If target is the empty string, let target be null.
2417             String target = annotation.target();
2418             if (target != null && target.length() > 0)
2419             {
2420                 target = ELText.parse(getExpressionFactory(),
2421                                       context.getELContext(), target).toString(context.getELContext());
2422                 // If target is non-null, store it under the key "target".
2423                 attributes.put("target", target);
2424                 context.getViewRoot().addComponentResource(context, output, target);
2425             }
2426             else
2427             {
2428                 // Otherwise, if target is null, call UIViewRoot.addComponentResource(javax.faces.context.FacesContext,
2429                 // javax.faces.component.UIComponent), passing the UIOutput instance as the second argument.
2430                 context.getViewRoot().addComponentResource(context, output);
2431             }
2432         }
2433     }
2434     
2435     private void _inspectRenderer(FacesContext context, UIComponent component,
2436                                   String componentType, String rendererType)
2437     {
2438         /*
2439          * The Renderer instance to inspect must be obtained by calling FacesContext.getRenderKit() and calling
2440          * RenderKit.getRenderer(java.lang.String, java.lang.String) on the result, passing the argument componentFamily
2441          * of the newly created component as the first argument and the argument rendererType as the second argument.
2442          */
2443         Renderer renderer = context.getRenderKit().getRenderer(component.getFamily(), rendererType);
2444         if (renderer == null)
2445         {
2446             // If no such Renderer can be found, a message must be logged with a helpful error message.
2447             log.severe("renderer cannot be found for component type " + componentType + " and renderer type "
2448                     + rendererType);
2449         }
2450         else
2451         {
2452             // Otherwise, UIComponent.setRendererType(java.lang.String) must be called on the newly created
2453             // UIComponent instance, passing the argument rendererType as the argument.
2454             component.setRendererType(rendererType);
2455 
2456             /*
2457              * except the Renderer for the component to be returned must be inspected for the annotations mentioned in
2458              * createComponent(ValueExpression, FacesContext, String) as specified in the documentation for that method.
2459              */
2460             _handleAnnotations(context, renderer, component);
2461         }
2462     }
2463 
2464     private static SystemEvent _traverseListenerList(List<? extends SystemEventListener> listeners,
2465                                                      Class<? extends SystemEvent> systemEventClass, Object source,
2466                                                      SystemEvent event)
2467     {
2468         if (listeners != null && !listeners.isEmpty())
2469         {
2470             // perf: org.apache.myfaces.application.ApplicationImpl.
2471             //    SystemListenerEntry.getSpecificSourceListenersNotNull(Class<?>)
2472             // or javax.faces.component.UIComponent.subscribeToEvent(
2473             //      Class<? extends SystemEvent>, ComponentSystemEventListener)
2474             // creates a ArrayList:
2475             for (int i  = 0, size = listeners.size(); i < size; i++)
2476             {
2477                 SystemEventListener listener = listeners.get(i);
2478                 // Call SystemEventListener.isListenerForSource(java.lang.Object), passing the source argument.
2479                 // If this returns false, take no action on the listener.
2480                 if (listener.isListenerForSource(source))
2481                 {
2482                     // Otherwise, if the event to be passed to the listener instances has not yet been constructed,
2483                     // construct the event, passing source as the argument to the one-argument constructor that takes
2484                     // an Object. This same event instance must be passed to all listener instances.
2485                     event = _createEvent(systemEventClass, source, event);
2486 
2487                     // Call SystemEvent.isAppropriateListener(javax.faces.event.FacesListener), passing the listener
2488                     // instance as the argument. If this returns false, take no action on the listener.
2489                     if (event.isAppropriateListener(listener))
2490                     {
2491                         // Call SystemEvent.processListener(javax.faces.event.FacesListener), passing the listener
2492                         // instance.
2493                         event.processListener(listener);
2494                     }
2495                 }
2496             }
2497         }
2498 
2499         return event;
2500     }
2501     
2502     private static SystemEvent _traverseListenerListWithCopy(List<? extends SystemEventListener> listeners,
2503             Class<? extends SystemEvent> systemEventClass, Object source,
2504             SystemEvent event)
2505     {
2506         if (listeners != null && !listeners.isEmpty())
2507         {
2508             List<SystemEventListener> listenersCopy = new ArrayList<SystemEventListener>();
2509             int processedListenerIndex = 0;
2510             
2511             for (int i = 0; i < listeners.size(); i++)
2512             {
2513                 listenersCopy.add(listeners.get(i));
2514             }
2515             
2516             // If the inner for is succesful, processedListenerIndex == listenersCopy.size()
2517             // and the loop will be complete.
2518             while (processedListenerIndex < listenersCopy.size())
2519             {                
2520                 for (; processedListenerIndex < listenersCopy.size(); processedListenerIndex++ )
2521                 {
2522                     SystemEventListener listener = listenersCopy.get(processedListenerIndex);
2523                     // Call SystemEventListener.isListenerForSource(java.lang.Object), passing the source argument.
2524                     // If this returns false, take no action on the listener.
2525                     if (listener.isListenerForSource(source))
2526                     {
2527                         // Otherwise, if the event to be passed to the listener instances has not yet been constructed,
2528                         // construct the event, passing source as the argument
2529                         // to the one-argument constructor that takes
2530                         // an Object. This same event instance must be passed to all listener instances.
2531                         event = _createEvent(systemEventClass, source, event);
2532     
2533                         // Call SystemEvent.isAppropriateListener(javax.faces.event.FacesListener), passing the listener
2534                         // instance as the argument. If this returns false, take no action on the listener.
2535                         if (event.isAppropriateListener(listener))
2536                         {
2537                             // Call SystemEvent.processListener(javax.faces.event.FacesListener), passing the listener
2538                             // instance.
2539                             event.processListener(listener);
2540                         }
2541                     }
2542                 }
2543                 
2544                 boolean listChanged = false;
2545                 if (listeners.size() == listenersCopy.size())
2546                 {
2547                     for (int i = 0; i < listenersCopy.size(); i++)
2548                     {
2549                         if (listenersCopy.get(i) != listeners.get(i))
2550                         {
2551                             listChanged = true;
2552                             break;
2553                         }
2554                     }
2555                 }
2556                 else
2557                 {
2558                     listChanged = true;
2559                 }
2560                 
2561                 if (listChanged)
2562                 {
2563                     for (int i = 0; i < listeners.size(); i++)
2564                     {
2565                         SystemEventListener listener = listeners.get(i);
2566                         
2567                         // check if listenersCopy.get(i) is valid
2568                         if (i < listenersCopy.size())
2569                         {
2570                             // The normal case is a listener was added, 
2571                             // so as heuristic, check first
2572                             // if we can find it at the same location
2573                             if (!listener.equals(listenersCopy.get(i)))
2574                             {
2575                                 if (!listenersCopy.contains(listener))
2576                                 {
2577                                     listenersCopy.add(listener);
2578                                 }
2579                             }
2580                         }
2581                         else
2582                         {
2583                             if (!listenersCopy.contains(listener))
2584                             {
2585                                 listenersCopy.add(listener);
2586                             }
2587                         }
2588                     }
2589                 }
2590             }
2591         }
2592 
2593         return event;
2594     }
2595 
2596     /**
2597      * Method to handle determining if the first request has 
2598      * been handled by the associated LifecycleImpl.
2599      * @return true if the first request has already been processed, false otherwise
2600      */
2601     private boolean isFirstRequestProcessed()
2602     {
2603         FacesContext context = FacesContext.getCurrentInstance();
2604         
2605         //if firstRequestProcessed is not set, check the application map
2606         if(!_firstRequestProcessed && context != null 
2607                 && Boolean.TRUE.equals(context.getExternalContext().getApplicationMap()
2608                         .containsKey(LifecycleImpl.FIRST_REQUEST_PROCESSED_PARAM)))
2609         {
2610             _firstRequestProcessed = true;
2611         }
2612         return _firstRequestProcessed;
2613     }
2614     
2615     private static class SystemListenerEntry
2616     {
2617         private List<SystemEventListener> _lstSystemEventListener;
2618         private Map<Class<?>, List<SystemEventListener>> _sourceClassMap;
2619 
2620         public SystemListenerEntry()
2621         {
2622         }
2623 
2624         public void addListener(SystemEventListener listener)
2625         {
2626             assert listener != null;
2627 
2628             addListenerNoDuplicate(getAnySourceListenersNotNull(), listener);
2629         }
2630 
2631         public void addListener(SystemEventListener listener, Class<?> source)
2632         {
2633             assert listener != null;
2634 
2635             if (source == null)
2636             {
2637                 addListener(listener);
2638             }
2639             else
2640             {
2641                 addListenerNoDuplicate(getSpecificSourceListenersNotNull(source), listener);
2642             }
2643         }
2644 
2645         public void removeListener(SystemEventListener listener)
2646         {
2647             assert listener != null;
2648 
2649             if (_lstSystemEventListener != null)
2650             {
2651                 _lstSystemEventListener.remove(listener);
2652             }
2653         }
2654 
2655         public void removeListener(SystemEventListener listener, Class<?> sourceClass)
2656         {
2657             assert listener != null;
2658 
2659             if (sourceClass == null)
2660             {
2661                 removeListener(listener);
2662             }
2663             else
2664             {
2665                 if (_sourceClassMap != null)
2666                 {
2667                     List<SystemEventListener> listeners = _sourceClassMap.get(sourceClass);
2668                     if (listeners != null)
2669                     {
2670                         listeners.remove(listener);
2671                     }
2672                 }
2673             }
2674         }
2675 
2676         public void publish(Class<? extends SystemEvent> systemEventClass, Class<?> classSource, Object source,
2677                             SystemEvent event)
2678         {
2679             if (source != null && _sourceClassMap != null)
2680             {
2681                 event = _traverseListenerList(_sourceClassMap.get(classSource), systemEventClass, source, event);
2682             }
2683 
2684             _traverseListenerList(_lstSystemEventListener, systemEventClass, source, event);
2685         }
2686 
2687         private void addListenerNoDuplicate(List<SystemEventListener> listeners, SystemEventListener listener)
2688         {
2689             if (!listeners.contains(listener))
2690             {
2691                 listeners.add(listener);
2692             }
2693         }
2694 
2695         private synchronized List<SystemEventListener> getAnySourceListenersNotNull()
2696         {
2697             if (_lstSystemEventListener == null)
2698             {
2699                 /*
2700                  * TODO: Check if modification occurs often or not, might have to use a synchronized list instead.
2701                  * 
2702                  * Registrations found:
2703                  */
2704                 _lstSystemEventListener = new CopyOnWriteArrayList<SystemEventListener>();
2705             }
2706 
2707             return _lstSystemEventListener;
2708         }
2709 
2710         private synchronized List<SystemEventListener> getSpecificSourceListenersNotNull(Class<?> sourceClass)
2711         {
2712             if (_sourceClassMap == null)
2713             {
2714                 _sourceClassMap = new ConcurrentHashMap<Class<?>, List<SystemEventListener>>();
2715             }
2716 
2717             List<SystemEventListener> list = _sourceClassMap.get(sourceClass);
2718             if (list == null)
2719             {
2720                 /*
2721                  * TODO: Check if modification occurs often or not, might have to use a synchronized list instead.
2722                  * 
2723                  * Registrations found:
2724                  */
2725                 list = new CopyOnWriteArrayList<SystemEventListener>();
2726                 _sourceClassMap.put(sourceClass, list);
2727             }
2728 
2729             return list;
2730         }
2731     }
2732     
2733     /*
2734      * private method to look for config objects on a classmap.  The objects can be either a type string
2735      * or a Class<?> object.  This is done to facilitate lazy loading of config objects.   
2736      * @param id 
2737      * @param classMap 
2738      * @return
2739      */
2740     private Class<?> getObjectFromClassMap(String id, Map<String, Object> classMap)
2741     {
2742         Object obj = classMap.get(id);
2743         
2744         if(obj == null)
2745         {
2746             return null;    //object for this id wasn't found on the map
2747         }
2748         
2749         if(obj instanceof Class<?>)
2750         {
2751             return (Class<?>)obj;
2752         }
2753         else if (obj instanceof String )
2754         {
2755             Class<?> clazz = ClassUtils.simpleClassForName((String)obj);
2756             classMap.put(id, clazz);
2757             return clazz;
2758         }
2759         
2760         //object stored in the map for this id is an invalid type.  remove it and return null
2761         classMap.remove(id);
2762         return null;        
2763     }
2764     
2765     private boolean isLazyLoadConfigObjects()
2766     {
2767         if (_lazyLoadConfigObjects == null)
2768         {
2769             String configParam
2770                     = getFaceContext().getExternalContext().getInitParameter(LAZY_LOAD_CONFIG_OBJECTS_PARAM_NAME);
2771             _lazyLoadConfigObjects = configParam == null
2772                                      ? LAZY_LOAD_CONFIG_OBJECTS_DEFAULT_VALUE
2773                                      : Boolean.parseBoolean(configParam);
2774         }
2775         return _lazyLoadConfigObjects;
2776     }
2777 }