/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package org.apache.myfaces.application;

import java.beans.BeanDescriptor;
import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Constructor;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.MissingResourceException;
import java.util.Objects;
import java.util.TimeZone;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.el.CompositeELResolver;
import javax.el.ELContext;
import javax.el.ELContextListener;
import javax.el.ELException;
import javax.el.ELResolver;
import javax.el.ExpressionFactory;
import javax.el.ValueExpression;
import javax.faces.FacesException;
import javax.faces.FacesWrapper;
import javax.faces.application.Application;
import javax.faces.application.NavigationHandler;
import javax.faces.application.ProjectStage;
import javax.faces.application.Resource;
import javax.faces.application.ResourceDependencies;
import javax.faces.application.ResourceDependency;
import javax.faces.application.ResourceHandler;
import javax.faces.application.StateManager;
import javax.faces.application.ViewHandler;
import javax.faces.component.UIComponent;
import javax.faces.component.UIComponentBase;
import javax.faces.component.UINamingContainer;
import javax.faces.component.UIOutput;
import javax.faces.component.UIViewRoot;
import javax.faces.component.behavior.Behavior;
import javax.faces.component.behavior.ClientBehavior;
import javax.faces.component.behavior.ClientBehaviorBase;
import javax.faces.component.behavior.FacesBehavior;
import javax.faces.component.search.SearchExpressionHandler;
import javax.faces.component.search.SearchKeywordResolver;
import javax.faces.context.FacesContext;
import javax.faces.convert.Converter;
import javax.faces.convert.DateTimeConverter;
import javax.faces.convert.FacesConverter;
import javax.faces.event.AbortProcessingException;
import javax.faces.event.ActionListener;
import javax.faces.event.ComponentSystemEventListener;
import javax.faces.event.ListenerFor;
import javax.faces.event.ListenersFor;
import javax.faces.event.SystemEvent;
import javax.faces.event.SystemEventListener;
import javax.faces.event.SystemEventListenerHolder;
import javax.faces.flow.FlowHandler;
import javax.faces.render.ClientBehaviorRenderer;
import javax.faces.render.RenderKit;
import javax.faces.render.Renderer;
import javax.faces.render.RendererWrapper;
import javax.faces.validator.FacesValidator;
import javax.faces.validator.Validator;
import javax.faces.view.ViewDeclarationLanguage;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;

import org.apache.myfaces.cdi.wrapper.FacesBehaviorCDIWrapper;
import org.apache.myfaces.cdi.wrapper.FacesClientBehaviorCDIWrapper;
import org.apache.myfaces.cdi.wrapper.FacesConverterCDIWrapper;
import org.apache.myfaces.cdi.wrapper.FacesValidatorCDIWrapper;
import org.apache.myfaces.component.search.AllSearchKeywordResolver;
import org.apache.myfaces.component.search.ChildSearchKeywordResolver;
import org.apache.myfaces.component.search.CompositeComponentParentSearchKeywordResolver;
import org.apache.myfaces.component.search.CompositeSearchKeywordResolver;
import org.apache.myfaces.component.search.FormSearchKeywordResolver;
import org.apache.myfaces.component.search.IdSearchKeywordResolver;
import org.apache.myfaces.component.search.NamingContainerSearchKeywordResolver;
import org.apache.myfaces.component.search.NextSearchKeywordResolver;
import org.apache.myfaces.component.search.NoneSearchKeywordResolver;
import org.apache.myfaces.component.search.ParentSearchKeywordResolver;
import org.apache.myfaces.component.search.PreviousSearchKeywordResolver;
import org.apache.myfaces.component.search.RootSearchKeywordResolver;
import org.apache.myfaces.component.search.SearchExpressionHandlerImpl;
import org.apache.myfaces.component.search.ThisSearchKeywordResolver;
import org.apache.myfaces.config.RuntimeConfig;
import org.apache.myfaces.config.element.Property;
import org.apache.myfaces.config.element.ResourceBundle;
import org.apache.myfaces.context.RequestViewContext;
import org.apache.myfaces.context.RequestViewMetadata;
import org.apache.myfaces.el.ELResolverBuilder;
import org.apache.myfaces.el.ELResolverBuilderForFaces;
import org.apache.myfaces.el.resolver.FacesCompositeELResolver;
import org.apache.myfaces.el.resolver.FacesCompositeELResolver.Scope;
import org.apache.myfaces.flow.FlowHandlerImpl;
import org.apache.myfaces.lifecycle.LifecycleImpl;
import org.apache.myfaces.config.MyfacesConfig;
import org.apache.myfaces.util.lang.Assert;
import org.apache.myfaces.util.lang.ClassUtils;
import org.apache.myfaces.util.lang.StringUtils;
import org.apache.myfaces.view.facelets.FaceletCompositionContext;
import org.apache.myfaces.view.facelets.el.ELText;

/**
 * DOCUMENT ME!
 * 
 * @author Manfred Geiler (latest modification by $Author$)
 * @author Anton Koinov
 * @author Thomas Spiegl
 * @author Stan Silvert
 * @version $Revision$ $Date$
 */
@SuppressWarnings("deprecation")
public class ApplicationImpl extends Application
{
    private static final Logger log = Logger.getLogger(ApplicationImpl.class.getName());

    // the name for the system property which specifies the current ProjectStage (see MYFACES-2545 for details)
    public final static String PROJECT_STAGE_SYSTEM_PROPERTY_NAME = "faces.PROJECT_STAGE";

    /**
     * Key under UIViewRoot to generated unique ids for components added 
     * by @ResourceDependency effect.
     */
    private static final String RESOURCE_DEPENDENCY_UNIQUE_ID_KEY =
              "oam.view.resourceDependencyUniqueId";

    // ~ Instance fields
    // --------------------------------------------------------------------------
    // --

    private Collection<Locale> _supportedLocales = Collections.emptySet();
    private Locale _defaultLocale;
    private String _messageBundle;

    private ViewHandler _viewHandler;
    private NavigationHandler _navigationHandler;
    private ActionListener _actionListener;
    private String _defaultRenderKitId;
    private ResourceHandler _resourceHandler;
    private StateManager _stateManager;
    private FlowHandler _flowHandler;

    private ArrayList<ELContextListener> _elContextListeners;

    // components, converters, and validators can be added at runtime--must
    // synchronize, uses ConcurrentHashMap to allow concurrent read of map
    private final Map<String, Object> _converterIdToClassMap = new ConcurrentHashMap<>();

    private final Map<Class<?>, Object> _converterTargetClassToConverterClassMap = new ConcurrentHashMap<>();
    
    private final Map<String, Object> _componentClassMap = new ConcurrentHashMap<>();

    private final Map<String, Object> _validatorClassMap = new ConcurrentHashMap<>();

    private final Map<Class<? extends SystemEvent>, SystemListenerEntry> _systemEventListenerClassMap
            = new ConcurrentHashMap<>();

    private final Map<String, String> _defaultValidatorsIds = new HashMap<>();
    
    private volatile Map<String, String> _cachedDefaultValidatorsIds = null;
    
    private final Map<String, Object> _behaviorClassMap = new ConcurrentHashMap<>();

    private final RuntimeConfig _runtimeConfig;
    private final MyfacesConfig _myfacesConfig;

    private ELResolver elResolver;

    private ELResolverBuilder resolverBuilderForFaces;

    private ProjectStage _projectStage;

    private volatile boolean _firstRequestProcessed = false;
    
    // MYFACES-3442 If HashMap or other non thread-safe structure is used, it is
    // possible to fall in a infinite loop under heavy load unless a synchronized block
    // is used to modify it or a ConcurrentHashMap.
    private final Map<Class<?>, List<ListenerFor>> _classToListenerForMap = new ConcurrentHashMap<>() ;

    private final Map<Class<?>, List<ResourceDependency>> _classToResourceDependencyMap = new ConcurrentHashMap<>();
    
    private List<Class<? extends Converter>> _noArgConstructorConverterClasses = new CopyOnWriteArrayList<>();
    
    private Map<Class<? extends Converter>, Boolean> _cdiManagedConverterMap = new ConcurrentHashMap<>();
    
    private Map<Class<? extends Validator>, Boolean> _cdiManagedValidatorMap = new ConcurrentHashMap<>();
    
    private Map<Class<? extends Behavior>, Boolean> _cdiManagedBehaviorMap = new ConcurrentHashMap<>();
    
    /** Value of javax.faces.DATETIMECONVERTER_DEFAULT_TIMEZONE_IS_SYSTEM_TIMEZONE parameter */
    private boolean _dateTimeConverterDefaultTimeZoneIsSystemTimeZone = false; 
    
    private SearchExpressionHandler _searchExpressionHandler;
    
    private SearchKeywordResolver _searchExpressionResolver;
    
    /**
     * Represents semantic null in _componentClassMap. 
     */
    private static final UIComponent NOTHING = new UIComponentBase()
    {
        @Override
        public String getFamily()
        {
            return null;
        }
    };
    
    // ~ Constructors
    // --------------------------------------------------------------------------
    // -----

    public ApplicationImpl()
    {
        this(RuntimeConfig.getCurrentInstance(FacesContext.getCurrentInstance()));
    }

    ApplicationImpl(final RuntimeConfig runtimeConfig)
    {
        if (runtimeConfig == null)
        {
            throw new IllegalArgumentException("runtimeConfig must mot be null");
        }
        // set default implementation in constructor
        // pragmatic approach, no syncronizing will be needed in get methods
        _viewHandler = new ViewHandlerImpl();
        _navigationHandler = new NavigationHandlerImpl();
        _actionListener = new ActionListenerImpl();
        _defaultRenderKitId = "HTML_BASIC";
        _stateManager = new StateManagerImpl();
        _elContextListeners = new ArrayList<ELContextListener>();
        _resourceHandler = new ResourceHandlerImpl();
        _flowHandler = new FlowHandlerImpl();
        _searchExpressionHandler = new SearchExpressionHandlerImpl();
        _runtimeConfig = runtimeConfig;
        _myfacesConfig = MyfacesConfig.getCurrentInstance(getFacesContext());

        if (log.isLoggable(Level.FINEST))
        {
            log.finest("New Application instance created");
        }
        
        String configParam = getFacesContext().getExternalContext().
                getInitParameter(Converter.DATETIMECONVERTER_DEFAULT_TIMEZONE_IS_SYSTEM_TIMEZONE_PARAM_NAME);
        if (configParam != null && configParam.toLowerCase().equals("true"))
        {
            _dateTimeConverterDefaultTimeZoneIsSystemTimeZone = true;
        }
    }

    // ~ Methods
    // --------------------------------------------------------------------------
    // ----------

    @Override
    public final void addELResolver(final ELResolver resolver)
    {
        if (isFirstRequestProcessed())
        {
            throw new IllegalStateException("It is illegal to add a resolver after the first request is processed");
        }
        if (resolver != null)
        {
            _runtimeConfig.addApplicationElResolver(resolver);
        }
    }

    @Override
    public void addDefaultValidatorId(String validatorId)
    {
        if (_validatorClassMap.containsKey(validatorId))
        {
            Class<? extends Validator> validatorClass =
                    getObjectFromClassMap(validatorId, _validatorClassMap);

            // Ensure atomicity between _defaultValidatorsIds and _cachedDefaultValidatorsIds
            synchronized(_defaultValidatorsIds)
            {
                _defaultValidatorsIds.put(validatorId, validatorClass.getName());
                _cachedDefaultValidatorsIds = null;
            }
        }
    }

    @Override
    public Map<String, String> getDefaultValidatorInfo()
    {
        // cachedMap ensures we will not return null if after the check for null
        // _cachedDefaultValidatorsIds is set to null. In theory the unmodifiable map
        // always has a reference to _defaultValidatorsIds, so any instance set
        // in _cachedDefaultValidatorsIds is always the same.
        Map<String, String> cachedMap = _cachedDefaultValidatorsIds;
        if (cachedMap == null)
        {
            synchronized(_defaultValidatorsIds)
            {
                if (_cachedDefaultValidatorsIds == null)
                {
                    _cachedDefaultValidatorsIds = Collections.unmodifiableMap(_defaultValidatorsIds);
                }
                cachedMap = _cachedDefaultValidatorsIds;
            }
        }
        return cachedMap;
    }

    @Override
    public final ELResolver getELResolver()
    {
        // we don't need synchronization here since it is ok to have multiple
        // instances of the elresolver
        if (elResolver == null)
        {
            elResolver = createFacesResolver();
        }
        return elResolver;
    }

    private ELResolver createFacesResolver()
    {
        FacesContext facesContext = getFacesContext();
        boolean supportJSP = _myfacesConfig.isSupportJSP();
        CompositeELResolver resolver;
        if (supportJSP)
        {
            resolver = new FacesCompositeELResolver(Scope.Faces);
        }
        else
        {
            resolver = new CompositeELResolver();
        }
        getResolverBuilderForFaces().build(facesContext, resolver);
        return resolver;
    }

    protected final ELResolverBuilder getResolverBuilderForFaces()
    {
        if (resolverBuilderForFaces == null)
        {
            resolverBuilderForFaces = new ELResolverBuilderForFaces(_runtimeConfig, _myfacesConfig);
        }
        return resolverBuilderForFaces;
    }

    public final void setResolverBuilderForFaces(final ELResolverBuilder factory)
    {
        resolverBuilderForFaces = factory;
    }

    @Override
    public final java.util.ResourceBundle getResourceBundle(final FacesContext facesContext, final String name)
            throws FacesException, NullPointerException
    {

        Assert.notNull(facesContext, "facesContext");
        Assert.notNull(name, "name");

        final String bundleName = getBundleName(facesContext, name);

        if (bundleName == null)
        {
            return null;
        }

        Locale locale = Locale.getDefault();

        final UIViewRoot viewRoot = facesContext.getViewRoot();
        if (viewRoot != null && viewRoot.getLocale() != null)
        {
            locale = viewRoot.getLocale();
        }

        try
        {
            return getResourceBundle(bundleName, locale, ClassUtils.getContextClassLoader());
        }
        catch (MissingResourceException e)
        {
            try
            {
                return getResourceBundle(bundleName, locale, this.getClass().getClassLoader());
            }
            catch (MissingResourceException e1)
            {            
                throw new FacesException("Could not load resource bundle for name '"
                                         + name + "': " + e.getMessage(), e1);
            }
        }
    }

    String getBundleName(final FacesContext facesContext, final String name)
    {
        ResourceBundle bundle = _runtimeConfig.getResourceBundle(name);
        return bundle != null ? bundle.getBaseName() : null;
    }

    java.util.ResourceBundle getResourceBundle(final String name, final Locale locale, final ClassLoader loader)
            throws MissingResourceException
    {
        return java.util.ResourceBundle.getBundle(name, locale, loader);
    }

    final FacesContext getFacesContext()
    {
        return FacesContext.getCurrentInstance();
    }

    @Override
    public final UIComponent createComponent(final ValueExpression componentExpression,
                                             final FacesContext facesContext, final String componentType)
            throws FacesException, NullPointerException
    {

        /*
         * Before the component instance is returned, it must be inspected for the presence of a ListenerFor (or
         * ListenersFor) or ResourceDependency (or ResourceDependencies) annotation. If any of these annotations are
         * present, the action listed in ListenerFor or ResourceDependency must be taken on the component, 
         * before it is
         * returned from this method. This variant of createComponent must not inspect the Renderer for the 
         * component to
         * be returned for any of the afore mentioned annotations. Such inspection is the province of
         */

        Assert.notNull(componentExpression, "componentExpression");
        Assert.notNull(facesContext, "facesContext");
        Assert.notNull(componentType, "componentType");

        ELContext elContext = facesContext.getELContext();

        try
        {
            Object retVal = componentExpression.getValue(elContext);

            UIComponent createdComponent;

            if (retVal instanceof UIComponent)
            {
                createdComponent = (UIComponent) retVal;
                _handleAnnotations(facesContext, createdComponent, createdComponent);
            }
            else
            {
                createdComponent = createComponent(facesContext, componentType);
                componentExpression.setValue(elContext, createdComponent);
            }

            return createdComponent;
        }
        catch (FacesException e)
        {
            throw e;
        }
        catch (Exception e)
        {
            throw new FacesException(e);
        }
    }

    @Override
    public UIComponent createComponent(ValueExpression componentExpression, FacesContext context, 
                                       String componentType, String rendererType)
    {
        // Like createComponent(ValueExpression, FacesContext, String)
        UIComponent component = createComponent(componentExpression, context, componentType);

        if (rendererType != null)
        {
            _inspectRenderer(context, component, componentType, rendererType);
        }

        return component;
    }

    @Override
    public final ExpressionFactory getExpressionFactory()
    {
        return _runtimeConfig.getExpressionFactory();
    }

    @SuppressWarnings("unchecked")
    @Override
    public final <T> T evaluateExpressionGet(final FacesContext context, final String expression,
                                             final Class<? extends T> expectedType) throws ELException
    {
        ELContext elContext = context.getELContext();

        ExpressionFactory factory = getExpressionFactory();

        return (T) factory.createValueExpression(elContext, expression, expectedType).getValue(elContext);
    }

    @Override
    public final void addELContextListener(final ELContextListener listener)
    {
        synchronized (_elContextListeners)
        {
            _elContextListeners.add(listener);
        }
    }

    @Override
    public void publishEvent(FacesContext facesContext, Class<? extends SystemEvent> systemEventClass,
                             Class<?> sourceBaseType, Object source)
    {
        Assert.notNull(systemEventClass, "systemEventClass");
        Assert.notNull(source, "source");
        
        //Call events only if event processing is enabled.
        if (!facesContext.isProcessingEvents())
        {
            return;
        }
        
        // spec: If this argument is null the return from source.getClass() must be used as the sourceBaseType. 
        if (sourceBaseType == null)
        {
            sourceBaseType = source.getClass();
        }
        
        try
        {
            SystemEvent event = null;
            if (source instanceof SystemEventListenerHolder)
            {
                SystemEventListenerHolder holder = (SystemEventListenerHolder) source;

                // If the source argument implements SystemEventListenerHolder, call
                // SystemEventListenerHolder.getListenersForEventClass(java.lang.Class) on it, passing the
                // systemEventClass
                // argument. If the list is not empty, perform algorithm traverseListenerList on the list.
                event = _ApplicationUtils._traverseListenerList(
                        facesContext, holder.getListenersForEventClass(systemEventClass),
                        systemEventClass, source, event);
            }
            
            UIViewRoot uiViewRoot = facesContext.getViewRoot();
            if (uiViewRoot != null)
            {
                //Call listeners on view level
                event = _ApplicationUtils._traverseListenerListWithCopy(
                        facesContext, uiViewRoot.getViewListenersForEventClass(systemEventClass), 
                        systemEventClass, source, event);
            }

            SystemListenerEntry systemListenerEntry = _systemEventListenerClassMap.get(systemEventClass);
            if (systemListenerEntry != null)
            {
                systemListenerEntry.publish(facesContext, systemEventClass, sourceBaseType, source, event);
            }
        }
        catch (AbortProcessingException e)
        {
            // If the act of invoking the processListener method causes an AbortProcessingException to be thrown,
            // processing of the listeners must be aborted, no further processing of the listeners for this event must
            // take place, and the exception must be logged with Level.SEVERE.
            log.log(Level.SEVERE, "Event processing was aborted", e);
        }
    }

    @Override
    public void publishEvent(FacesContext facesContext, Class<? extends SystemEvent> systemEventClass, Object source)
    {
        publishEvent(facesContext, systemEventClass, source.getClass(), source);
    }

    @Override
    public final void removeELContextListener(final ELContextListener listener)
    {
        synchronized (_elContextListeners)
        {
            _elContextListeners.remove(listener);
        }
    }

    @Override
    public final ELContextListener[] getELContextListeners()
    {
        // this gets called on every request, so I can't afford to synchronize
        // I just have to trust that toArray() with do the right thing if the
        // list is changing (not likely)
        return _elContextListeners.toArray(new ELContextListener[_elContextListeners.size()]);
    }

    @Override
    public final void setActionListener(final ActionListener actionListener)
    {
        Assert.notNull(actionListener, "actionListener");

        _actionListener = actionListener;
        if (log.isLoggable(Level.FINEST))
        {
            log.finest("set actionListener = " + actionListener.getClass().getName());
        }
    }

    @Override
    public final ActionListener getActionListener()
    {
        return _actionListener;
    }

    @Override
    public Iterator<String> getBehaviorIds()
    {
        return _behaviorClassMap.keySet().iterator();
    }

    @Override
    public final Iterator<String> getComponentTypes()
    {
        return _componentClassMap.keySet().iterator();
    }

    @Override
    public final Iterator<String> getConverterIds()
    {
        return _converterIdToClassMap.keySet().iterator();
    }

    @Override
    public final Iterator<Class<?>> getConverterTypes()
    {
        return _converterTargetClassToConverterClassMap.keySet().iterator();
    }

    @Override
    public final void setDefaultLocale(final Locale locale)
    {
        Assert.notNull(locale, "locale");

        _defaultLocale = locale;
        if (log.isLoggable(Level.FINEST))
        {
            log.finest("set defaultLocale = " + locale.getCountry() + ' ' + locale.getLanguage());
        }
    }

    @Override
    public final Locale getDefaultLocale()
    {
        return _defaultLocale;
    }

    @Override
    public final void setMessageBundle(final String messageBundle)
    {
        Assert.notNull(messageBundle, "messageBundle");

        _messageBundle = messageBundle;
        if (log.isLoggable(Level.FINEST))
        {
            log.finest("set MessageBundle = " + messageBundle);
        }
    }

    @Override
    public final String getMessageBundle()
    {
        return _messageBundle;
    }

    @Override
    public final void setNavigationHandler(final NavigationHandler navigationHandler)
    {
        Assert.notNull(navigationHandler, "navigationHandler");

        _navigationHandler = navigationHandler;
        if (log.isLoggable(Level.FINEST))
        {
            log.finest("set NavigationHandler = " + navigationHandler.getClass().getName());
        }
    }

    @Override
    public final NavigationHandler getNavigationHandler()
    {
        return _navigationHandler;
    }

    @Override
    public ProjectStage getProjectStage()
    {
        // If the value has already been determined by a previous call to this
        // method, simply return that value.
        if (_projectStage == null)
        {
            String stageName = null;
            
            // try to obtain the ProjectStage from the system property
            // faces.PROJECT_STAGE as proposed by Ed Burns
            stageName = System.getProperty(PROJECT_STAGE_SYSTEM_PROPERTY_NAME);
            
            if (stageName == null)
            {
                // Look for a JNDI environment entry under the key given by the
                // value of ProjectStage.PROJECT_STAGE_JNDI_NAME (return type of
                // java.lang.String).
                try
                {
                    Context ctx = new InitialContext();
                    Object temp = ctx.lookup(ProjectStage.PROJECT_STAGE_JNDI_NAME);
                    if (temp != null)
                    {
                        if (temp instanceof String)
                        {
                            stageName = (String) temp;
                        }
                        else
                        {
                            log.severe("JNDI lookup for key " + ProjectStage.PROJECT_STAGE_JNDI_NAME
                                    + " should return a java.lang.String value");
                        }
                    }
                }
                catch (NamingException e)
                {
                    // no-op
                }
                catch (NoClassDefFoundError er)
                {
                    //On Google App Engine, javax.naming.Context is a restricted class.
                    //In that case, NoClassDefFoundError is thrown. stageName needs to be configured
                    //below by context parameter.
                    //It can be done with changing the order to look first at
                    // context param, but it is defined in the spec.
                    //http://java.sun.com/javaee/6/docs/api/javax/faces/application/Application.html#getProjectStage()
                    //no-op
                }
            }

            /*
             * If found, continue with the algorithm below, otherwise, look for an entry in the initParamMap of the
             * ExternalContext from the current FacesContext with the key ProjectStage.PROJECT_STAGE_PARAM_NAME
             */
            if (stageName == null)
            {
                stageName = getFacesContext().getExternalContext()
                        .getInitParameter(ProjectStage.PROJECT_STAGE_PARAM_NAME);
            }

            // If a value is found
            if (stageName != null)
            {
                /*
                 * see if an enum constant can be obtained by calling ProjectStage.valueOf(), passing 
                 * the value from the initParamMap. If this succeeds without exception, save the value 
                 * and return it.
                 */
                try
                {
                    _projectStage = ProjectStage.valueOf(stageName);
                    return _projectStage;
                }
                catch (IllegalArgumentException e)
                {
                    log.log(Level.INFO, "Couldn't discover the current project stage: "+stageName);
                }
            }
            else
            {
                if (log.isLoggable(Level.INFO))
                {
                    log.info("Couldn't discover the current project stage, using " + ProjectStage.Production);
                }
            }

            /*
             * If not found, or any of the previous attempts to discover the enum constant value have failed, log a
             * descriptive error message, assign the value as ProjectStage.Production and return it.
             */
            
            _projectStage = ProjectStage.Production;
        }

        return _projectStage;
    }


    @Override
    public final void setResourceHandler(ResourceHandler resourceHandler)
    {
        Assert.notNull(resourceHandler, "resourceHandler");

        if(isFirstRequestProcessed())
        {
            throw new IllegalStateException(
                    "setResourceHandler may not be executed after a lifecycle request has been completed");
        }
        _resourceHandler = resourceHandler;
    }

    @Override
    public final ResourceHandler getResourceHandler()
    {
        return _resourceHandler;
    }

    @Override
    public final void setSupportedLocales(final Collection<Locale> locales)
    {
        Assert.notNull(locales, "locales");

        _supportedLocales = locales;
        if (log.isLoggable(Level.FINEST))
        {
            log.finest("set SupportedLocales");
        }
    }

    @Override
    public final Iterator<Locale> getSupportedLocales()
    {
        return _supportedLocales.iterator();
    }

    @Override
    public final Iterator<String> getValidatorIds()
    {
        return _validatorClassMap.keySet().iterator();
    }

    @Override
    public final void setViewHandler(final ViewHandler viewHandler)
    {
        Assert.notNull(viewHandler, "viewHandler");

        if(isFirstRequestProcessed())
        {
            throw new IllegalStateException(
                    "setViewHandler may not be executed after a lifecycle request has been completed");
        }
        _viewHandler = viewHandler;
        if (log.isLoggable(Level.FINEST))
        {
            log.finest("set ViewHandler = " + viewHandler.getClass().getName());
        }
    }
    
    @Override
    public void subscribeToEvent(Class<? extends SystemEvent> systemEventClass, SystemEventListener listener)
    {
        subscribeToEvent(systemEventClass, null, listener);
    }

    @Override
    public void subscribeToEvent(Class<? extends SystemEvent> systemEventClass, Class<?> sourceClass,
                                 SystemEventListener listener)
    {
        Assert.notNull(systemEventClass, "systemEventClass");
        Assert.notNull(listener, "listener");

        SystemListenerEntry systemListenerEntry;
        synchronized (_systemEventListenerClassMap)
        {
            systemListenerEntry = _systemEventListenerClassMap.get(systemEventClass);
            if (systemListenerEntry == null)
            {
                systemListenerEntry = new SystemListenerEntry();
                _systemEventListenerClassMap.put(systemEventClass, systemListenerEntry);
            }
        }

        systemListenerEntry.addListener(listener, sourceClass);
    }
    
    @Override
    public void unsubscribeFromEvent(Class<? extends SystemEvent> systemEventClass, SystemEventListener listener)
    {
        unsubscribeFromEvent(systemEventClass, null, listener);
    }

    @Override
    public void unsubscribeFromEvent(Class<? extends SystemEvent> systemEventClass, Class<?> sourceClass,
                                     SystemEventListener listener)
    {
        Assert.notNull(systemEventClass, "systemEventClass");
        Assert.notNull(listener, "listener");

        SystemListenerEntry systemListenerEntry = _systemEventListenerClassMap.get(systemEventClass);
        if (systemListenerEntry != null)
        {
            systemListenerEntry.removeListener(listener, sourceClass);
        }
    }

    @Override
    public final ViewHandler getViewHandler()
    {
        return _viewHandler;
    }

    @Override
    public void addBehavior(String behaviorId, String behaviorClass)
    {
        Assert.notEmpty(behaviorId, "behaviorId");
        Assert.notEmpty(behaviorClass, "behaviorClass");

        try
        {
            if (_myfacesConfig.isLazyLoadConfigObjects())
            {
                _behaviorClassMap.put(behaviorId, behaviorClass);
            }
            else
            {
                _behaviorClassMap.put(behaviorId, ClassUtils.simpleClassForName(behaviorClass));
            }
            
            if (log.isLoggable(Level.FINEST))
            {
                log.finest("add Behavior class = " + behaviorClass + " for id = " + behaviorId);
            }
        }
        catch (Exception e)
        {
            log.log(Level.SEVERE, "Behavior class " + behaviorClass + " not found", e);
        }

    }

    @Override
    public final void addComponent(final String componentType, final String componentClassName)
    {
        Assert.notEmpty(componentType, "componentType");
        Assert.notEmpty(componentClassName, "componentClassName");

        try
        {
            if (_myfacesConfig.isLazyLoadConfigObjects())
            {
                _componentClassMap.put(componentType, componentClassName);
            }
            else
            {
                _componentClassMap.put(componentType, ClassUtils.simpleClassForName(componentClassName));
            }
            
            if (log.isLoggable(Level.FINEST))
            {
                log.finest("add Component class = " + componentClassName + " for type = " + componentType);
            }
        }
        catch (Exception e)
        {
            log.log(Level.SEVERE, "Component class " + componentClassName + " not found", e);
        }
    }

    @Override
    public final void addConverter(final String converterId, final String converterClass)
    {
        Assert.notEmpty(converterId, "converterId");
        Assert.notEmpty(converterClass, "converterClass");

        try
        {
            if (_myfacesConfig.isLazyLoadConfigObjects())
            {
                _converterIdToClassMap.put(converterId, converterClass);
            }
            else
            {
                _converterIdToClassMap.put(converterId, ClassUtils.simpleClassForName(converterClass));
            }
            if (log.isLoggable(Level.FINEST))
            {
                log.finest("add Converter id = " + converterId + " converterClass = " + converterClass);
            }
        }
        catch (Exception e)
        {
            log.log(Level.SEVERE, "Converter class " + converterClass + " not found", e);
        }
    }

    @Override
    public final void addConverter(final Class<?> targetClass, final String converterClass)
    {
        Assert.notNull(targetClass, "targetClass");
        Assert.notEmpty(converterClass, "converterClass");

        try
        {
            if (_myfacesConfig.isLazyLoadConfigObjects())
            {
                _converterTargetClassToConverterClassMap.put(targetClass, converterClass);
            }
            else
            {
                _converterTargetClassToConverterClassMap.put(targetClass,
                                                             ClassUtils.simpleClassForName(converterClass));
            }

            if (log.isLoggable(Level.FINEST))
            {
                log.finest("add Converter for class = " + targetClass + " converterClass = " + converterClass);
            }
        }
        catch (Exception e)
        {
            log.log(Level.SEVERE, "Converter class " + converterClass + " not found", e);
        }
    }

    @Override
    public final void addValidator(final String validatorId, final String validatorClass)
    {
        Assert.notEmpty(validatorId, "validatorId");
        Assert.notEmpty(validatorClass, "validatorClass");

        try
        {
            if (_myfacesConfig.isLazyLoadConfigObjects())
            {
                _validatorClassMap.put(validatorId, validatorClass);
            }
            else
            {
                _validatorClassMap.put(validatorId, ClassUtils.simpleClassForName(validatorClass));
            }
            
            if (log.isLoggable(Level.FINEST))
            {
                log.finest("add Validator id = " + validatorId + " class = " + validatorClass);
            }
        }
        catch (Exception e)
        {
            log.log(Level.SEVERE, "Validator class " + validatorClass + " not found", e);
        }
    }

    @Override
    public Behavior createBehavior(String behaviorId) throws FacesException
    {
        Assert.notEmpty(behaviorId, "behaviorId");

        final Class<? extends Behavior> behaviorClass =
                getObjectFromClassMap(behaviorId, _behaviorClassMap);
        
        if (behaviorClass == null)
        {
            throw new FacesException("Could not find any registered behavior-class for behaviorId : " + behaviorId);
        }
        
        if (!_cdiManagedBehaviorMap.containsKey(behaviorClass))
        {
            FacesBehavior annotation = behaviorClass.getAnnotation(FacesBehavior.class);
            if (annotation != null && annotation.managed())
            {
                _cdiManagedBehaviorMap.put(behaviorClass, true);
            }
            else
            {
                _cdiManagedBehaviorMap.put(behaviorClass, false);
            }
        }
        
        try
        {
            Behavior behavior = null;
            if (Boolean.TRUE.equals(_cdiManagedBehaviorMap.get(behaviorClass)))
            {
                if (ClientBehavior.class.isAssignableFrom(behaviorClass))
                {
                    behavior = new FacesClientBehaviorCDIWrapper((Class<ClientBehavior>)behaviorClass, behaviorId);
                }
                else
                {
                    behavior = new FacesBehaviorCDIWrapper(behaviorClass, behaviorId);
                }
                Behavior innerBehavior = ((FacesWrapper<Behavior>)behavior).getWrapped();

                FacesContext facesContext = getFacesContext();
                _handleAttachedResourceDependencyAnnotations(facesContext, innerBehavior);

                if (innerBehavior instanceof ClientBehaviorBase)
                {
                  ClientBehaviorBase clientBehavior = (ClientBehaviorBase) innerBehavior;
                  String renderType = clientBehavior.getRendererType();
                  if (renderType != null)
                  {
                    ClientBehaviorRenderer cbr = facesContext.getRenderKit().getClientBehaviorRenderer(renderType);
                    _handleAttachedResourceDependencyAnnotations(facesContext, cbr);
                  }
                }
            }
            else
            {
                behavior = behaviorClass.newInstance();
                FacesContext facesContext = getFacesContext();
                _handleAttachedResourceDependencyAnnotations(facesContext, behavior);

                if (behavior instanceof ClientBehaviorBase)
                {
                  ClientBehaviorBase clientBehavior = (ClientBehaviorBase) behavior;
                  String renderType = clientBehavior.getRendererType();
                  if (renderType != null)
                  {
                    ClientBehaviorRenderer cbr = facesContext.getRenderKit().getClientBehaviorRenderer(renderType);
                    _handleAttachedResourceDependencyAnnotations(facesContext, cbr);
                  }
                }
            }

            return behavior;
        }
        catch (Exception e)
        {
            log.log(Level.SEVERE, "Could not instantiate behavior " + behaviorClass, e);
            throw new FacesException("Could not instantiate behavior: " + behaviorClass, e);
        }
    }

    @Override
    public UIComponent createComponent(FacesContext context, Resource componentResource)
    {
        Assert.notNull(context, "context");
        Assert.notNull(componentResource, "componentResource");
        
        UIComponent component = null;
        Resource resource;
        String fqcn;
        Class<? extends UIComponent> componentClass = null;

        /*
         * Obtain a reference to the ViewDeclarationLanguage for this Application instance by calling
         * ViewHandler.getViewDeclarationLanguage(javax.faces.context.FacesContext, java.lang.String), passing the
         * viewId found by calling UIViewRoot.getViewId() on the UIViewRoot in the argument FacesContext.
         */
        UIViewRoot view = context.getViewRoot();
        Application application = context.getApplication();
        ViewDeclarationLanguage vdl
                = application.getViewHandler().getViewDeclarationLanguage(context, view.getViewId());

        /*
         * Obtain a reference to the composite component metadata for this composite component by calling
         * ViewDeclarationLanguage.getComponentMetadata(javax.faces.context.FacesContext,
         * javax.faces.application.Resource), passing the facesContext and componentResource arguments to this method.
         * This version of JSF specification uses JavaBeans as the API to the component metadata.
         */
        BeanInfo metadata = vdl.getComponentMetadata(context, componentResource);
        if (metadata == null)
        {
            throw new FacesException("Could not get component metadata for " 
                    + componentResource.getResourceName()
                    + ". Did you forget to specify <composite:interface>?");
        }

        /*
         * Determine if the component author declared a component-type for this component instance by obtaining the
         * BeanDescriptor from the component metadata and calling its getValue() method, passing
         * UIComponent.COMPOSITE_COMPONENT_TYPE_KEY as the argument. If non-null, the result must be a ValueExpression
         * whose value is the component-type of the UIComponent to be created for this Resource component. Call through
         * to createComponent(java.lang.String) to create the component.
         */
        BeanDescriptor descriptor = metadata.getBeanDescriptor();
        ValueExpression componentType = (ValueExpression) descriptor.getValue(
                UIComponent.COMPOSITE_COMPONENT_TYPE_KEY);
        boolean annotationsApplied = false;
        if (componentType != null)
        {
            component = application.createComponent((String) componentType.getValue(context.getELContext()));
            annotationsApplied = true;
        }
        else
        {
            /*
             * Otherwise, determine if a script based component for this Resource can be found by calling
             * ViewDeclarationLanguage.getScriptComponentResource(javax.faces.context.FacesContext,
             * javax.faces.application.Resource). If the result is non-null, and is a script written in one of the
             * languages listed in JSF 4.3 of the specification prose document, create a UIComponent instance from the
             * script resource.
             */
            resource = vdl.getScriptComponentResource(context, componentResource);
            if (resource != null)
            {
                String name = resource.getResourceName();
                String className = name.substring(0, name.lastIndexOf('.'));

                component = (UIComponent)ClassUtils.newInstance(className);
            }
            else
            {
                /*
                 * Otherwise, let library-name be the return from calling Resource.getLibraryName() on the argument
                 * componentResource and resource-name be the return from calling Resource.getResourceName() on the
                 * argument componentResource. Create a fully qualified Java class name by removing any file extension
                 * from resource-name and let fqcn be library-name + "." + resource-name. If a class with the name of
                 * fqcn cannot be found, take no action and continue to the next step. If any of 
                 * InstantiationException,
                 * IllegalAccessException, or ClassCastException are thrown, wrap the exception in a FacesException and
                 * re-throw it. If any other exception is thrown, log the exception and continue to the next step.
                 */

                boolean isProduction = FacesContext.getCurrentInstance().isProjectStage(ProjectStage.Production);
                String name = componentResource.getResourceName();
                String className = name.substring(0, name.lastIndexOf('.'));
                fqcn = componentResource.getLibraryName() + '.' + className;
                
                if (isProduction)
                {
                    componentClass = (Class<? extends UIComponent>) _componentClassMap.get(fqcn);
                }
                if (componentClass == null)
                {
                    try
                    {
                        componentClass = ClassUtils.classForName(fqcn);
                        if (isProduction)
                        {
                            _componentClassMap.put(fqcn, componentClass);
                        }
                    }
                    catch (ClassNotFoundException e)
                    {
                        // Remember here that classForName did not find Class
                        if (isProduction)
                        {
                            _componentClassMap.put(fqcn, NOTHING.getClass());
                        }
                    }
                }

                if (componentClass != null && NOTHING.getClass() != componentClass)
                {
                    try
                    {
                        component = componentClass.newInstance();
                    }
                    catch (InstantiationException e)
                    {
                        log.log(Level.SEVERE, "Could not instantiate component class name = " + fqcn, e);
                        throw new FacesException("Could not instantiate component class name = " + fqcn, e);
                    }
                    catch (IllegalAccessException e)
                    {
                        log.log(Level.SEVERE, "Could not instantiate component class name = " + fqcn, e);
                        throw new FacesException("Could not instantiate component class name = " + fqcn, e);
                    }
                    catch (Exception e)
                    {
                        log.log(Level.SEVERE, "Could not instantiate component class name = " + fqcn, e);
                    }
                }

                /*
                 * If none of the previous steps have yielded a UIComponent instance, call
                 * createComponent(java.lang.String) passing "javax.faces.NamingContainer" as the argument.
                 */
                if (component == null)
                {
                    component = application.createComponent(context, UINamingContainer.COMPONENT_TYPE, null);
                    annotationsApplied = true;
                }
            }
        }

        /*
         * Call UIComponent.setRendererType(java.lang.String) on the UIComponent instance, passing
         * "javax.faces.Composite" as the argument.
         */
        component.setRendererType("javax.faces.Composite");

        /*
         * Store the argument Resource in the attributes Map of the UIComponent under the key,
         * Resource.COMPONENT_RESOURCE_KEY.
         */
        component.getAttributes().put(Resource.COMPONENT_RESOURCE_KEY, componentResource);

        /*
         * Store composite component metadata in the attributes Map of the UIComponent under the key,
         * UIComponent.BEANINFO_KEY.
         */
        component.getAttributes().put(UIComponent.BEANINFO_KEY, metadata);

        /*
         * Before the component instance is returned, it must be inspected for the presence of a 
         * ListenerFor annotation.
         * If this annotation is present, the action listed in ListenerFor must be taken on the component, 
         * before it is
         * returned from this method.
         */
        if (!annotationsApplied)
        {
            _handleAnnotations(context, component, component);
        }

        return component;
    }

    @Override
    public UIComponent createComponent(FacesContext context, String componentType, String rendererType)
    {
        Assert.notNull(context, "context");
        Assert.notNull(componentType, "componentType");

        // Like createComponent(String)
        UIComponent component = createComponent(context, componentType);

        // A null value on this field is valid! If that so, no need to do any log
        // or look on RenderKit map for a inexistent renderer!
        if (rendererType != null)
        {
            _inspectRenderer(context, component, componentType, rendererType);
        }

        return component;
    }

    /**
     * This works just like createComponent(String componentType), but without call
     * FacesContext.getCurrentInstance()
     * 
     * @param facesContext
     * @param componentType
     * @return
     * @throws FacesException 
     */
    private final UIComponent createComponent(FacesContext facesContext, 
            final String componentType) throws FacesException
    {
        Assert.notEmpty(componentType, "componentType");

        final Class<? extends UIComponent> componentClass =
                getObjectFromClassMap(componentType, _componentClassMap);
        if (componentClass == null)
        {
            log.log(Level.SEVERE, "Undefined component type " + componentType);
            throw new FacesException("Undefined component type " + componentType);
        }

        try
        {
            UIComponent component = componentClass.newInstance();
            _handleAnnotations(facesContext, component, component);
            return component;
        }
        catch (Exception e)
        {
            log.log(Level.SEVERE, "Could not instantiate component componentType = " + componentType, e);
            throw new FacesException("Could not instantiate component componentType = " + componentType, e);
        }
    }
    
    @Override
    public final UIComponent createComponent(final String componentType) throws FacesException
    {
        Assert.notEmpty(componentType, "componentType");

        final Class<? extends UIComponent> componentClass =
                getObjectFromClassMap(componentType, _componentClassMap);
        if (componentClass == null)
        {
            log.log(Level.SEVERE, "Undefined component type " + componentType);
            throw new FacesException("Undefined component type " + componentType);
        }

        try
        {
            UIComponent component = componentClass.newInstance();
            _handleAnnotations(getFacesContext(), component, component);
            return component;
        }
        catch (Exception e)
        {
            log.log(Level.SEVERE, "Could not instantiate component componentType = " + componentType, e);
            throw new FacesException("Could not instantiate component componentType = " + componentType, e);
        }
    }

    /**
     * Return an instance of the converter class that has been registered under the specified id.
     * <p>
     * Converters are registered via faces-config.xml files, and can also be registered via the addConverter(String id,
     * Class converterClass) method on this class. Here the the appropriate Class definition is found, then an instance
     * is created and returned.
     * <p>
     * A converter registered via a config file can have any number of nested attribute or property tags. The JSF
     * specification is very vague about what effect these nested tags have. This method ignores nested attribute
     * definitions, but for each nested property tag the corresponding setter is invoked on the new Converter instance
     * passing the property's defaultValuer. Basic typeconversion is done so the target properties on the Converter
     * instance can be String, int, boolean, etc. Note that:
     * <ol>
     * <li>the Sun Mojarra JSF implemenation ignores nested property tags completely, so this behaviour cannot be 
     * relied on across implementations.
     * <li>there is no equivalent functionality for converter classes registered via the Application.addConverter api
     * method.
     * </ol>
     * <p>
     * Note that this method is most commonly called from the standard f:attribute tag. As an alternative, most
     * components provide a "converter" attribute which uses an EL expression to create a Converter instance, in which
     * case this method is not invoked at all. The converter attribute allows the returned Converter instance to be
     * configured via normal dependency-injection, and is generally a better choice than using this method.
     */
    @Override
    public final Converter createConverter(final String converterId)
    {
        Assert.notEmpty(converterId, "converterId");

        final Class<? extends Converter> converterClass =
                getObjectFromClassMap(converterId, _converterIdToClassMap);
        if (converterClass == null)
        {
            throw new FacesException("Could not find any registered converter-class by converterId : " + converterId);
        }

        if (!_cdiManagedConverterMap.containsKey(converterClass))
        {
            FacesConverter annotation = converterClass.getAnnotation(FacesConverter.class);
            if (annotation != null && annotation.managed())
            {
                _cdiManagedConverterMap.put(converterClass, true);
            }
            else
            {
                _cdiManagedConverterMap.put(converterClass, false);
            }
        }
        
        try
        {
            Converter converter = null;
            
            if (Boolean.TRUE.equals(_cdiManagedConverterMap.get(converterClass)))
            {
                converter = new FacesConverterCDIWrapper(converterClass, null, converterId);
                
                setConverterProperties(converterClass, ((FacesWrapper<Converter>)converter).getWrapped());

                _handleAttachedResourceDependencyAnnotations(getFacesContext(), 
                        ((FacesWrapper<Converter>)converter).getWrapped());
            }
            else
            {
                converter = createConverterInstance(converterClass);

                setConverterProperties(converterClass, converter);

                _handleAttachedResourceDependencyAnnotations(getFacesContext(), converter);
            }

            return converter;
        }
        catch (Exception e)
        {
            log.log(Level.SEVERE, "Could not instantiate converter " + converterClass, e);
            throw new FacesException("Could not instantiate converter: " + converterClass, e);
        }
    }

    private Converter createConverterInstance(Class<? extends Converter> converterClass)
            throws InstantiationException, IllegalAccessException
    {
        return converterClass.newInstance();
    }

    @Override
    public final Converter createConverter(final Class<?> targetClass)
    {
        Assert.notNull(targetClass, "targetClass");

        return internalCreateConverter(targetClass);
    }

    @SuppressWarnings("unchecked")
    private Converter internalCreateConverter(final Class<?> targetClass)
    {
        // Locate a Converter registered for the target class itself.
        Object converterClassOrClassName = _converterTargetClassToConverterClassMap.get(targetClass);
        
        // Locate a Converter registered for interfaces that are
        // implemented by the target class (directly or indirectly).
        // Skip if class is String, for performance reasons 
        // (save 3 additional lookups over a concurrent map per request). 
        if (converterClassOrClassName == null && !String.class.equals(targetClass))
        {
            final Class<?> interfaces[] = targetClass.getInterfaces();
            if (interfaces != null)
            {
                for (int i = 0, len = interfaces.length; i < len; i++)
                {
                    // search all superinterfaces for a matching converter,
                    // create it
                    final Converter converter = internalCreateConverter(interfaces[i]);
                    if (converter != null)
                    {
                        return converter;
                    }
                }
            }
        }

        // Get EnumConverter for enum classes with no special converter, check
        // here as recursive call with java.lang.Enum will not work
        if (converterClassOrClassName == null && targetClass.isEnum())
        {
            converterClassOrClassName = _converterTargetClassToConverterClassMap.get(Enum.class);
        }

        if (converterClassOrClassName != null)
        {
            try
            {
                Class<? extends Converter> converterClass = null;
                if (converterClassOrClassName instanceof Class<?>)
                {
                    converterClass = (Class<? extends Converter>) converterClassOrClassName;
                }
                else if (converterClassOrClassName instanceof String)
                {
                    converterClass = ClassUtils.simpleClassForName((String) converterClassOrClassName);
                    _converterTargetClassToConverterClassMap.put(targetClass, converterClass);
                }
                else
                {
                    //object stored in the map for this id is an invalid type.  remove it and return null
                    _converterTargetClassToConverterClassMap.remove(targetClass);
                }

                if (!_cdiManagedConverterMap.containsKey(converterClass))
                {
                    FacesConverter annotation = converterClass.getAnnotation(FacesConverter.class);
                    if (annotation != null && annotation.managed())
                    {
                        _cdiManagedConverterMap.put(converterClass, true);
                    }
                    else
                    {
                        _cdiManagedConverterMap.put(converterClass, false);
                    }
                }
                
                Converter converter = null;
                
                if (Boolean.TRUE.equals(_cdiManagedConverterMap.get(converterClass)))
                {
                    converter = new FacesConverterCDIWrapper(converterClass, targetClass, null);
                    
                    setConverterProperties(converterClass, ((FacesWrapper<Converter>)converter).getWrapped());
                }
                else
                {
                    // check cached constructor information
                    if (!_noArgConstructorConverterClasses.contains(converterClass))
                    {
                        // the converter class either supports the one-arg constructor
                        // or has never been processed before
                        try
                        {
                            // look for a constructor that takes a single Class object
                            // See JSF 1.2 javadoc for Converter
                            Constructor<? extends Converter> constructor = converterClass
                                    .getConstructor(new Class[] { Class.class });

                            converter = constructor.newInstance(new Object[] { targetClass });
                        }
                        catch (Exception e)
                        {
                            // the constructor does not exist
                            // add the class to the no-arg constructor classes cache
                            _noArgConstructorConverterClasses.add(converterClass);

                            // use no-arg constructor
                            converter = createConverterInstance(converterClass);
                        }
                    }
                    else
                    {
                        // use no-arg constructor
                        converter = createConverterInstance(converterClass);
                    }
                    
                    setConverterProperties(converterClass, converter);
                }

                return converter;
            }
            catch (Exception e)
            {
                log.log(Level.SEVERE, "Could not instantiate converter " + converterClassOrClassName.toString(), e);
                throw new FacesException("Could not instantiate converter: " + converterClassOrClassName.toString(), e);
            }
        }

        // locate converter for primitive types
        if (targetClass == Long.TYPE)
        {
            return internalCreateConverter(Long.class);
        }
        else if (targetClass == Boolean.TYPE)
        {
            return internalCreateConverter(Boolean.class);
        }
        else if (targetClass == Double.TYPE)
        {
            return internalCreateConverter(Double.class);
        }
        else if (targetClass == Byte.TYPE)
        {
            return internalCreateConverter(Byte.class);
        }
        else if (targetClass == Short.TYPE)
        {
            return internalCreateConverter(Short.class);
        }
        else if (targetClass == Integer.TYPE)
        {
            return internalCreateConverter(Integer.class);
        }
        else if (targetClass == Float.TYPE)
        {
            return internalCreateConverter(Float.class);
        }
        else if (targetClass == Character.TYPE)
        {
            return internalCreateConverter(Character.class);
        }

        // Locate a Converter registered for the superclass (if any) of the
        // target class,
        // recursively working up the inheritance hierarchy.
        Class<?> superClazz = targetClass.getSuperclass();

        return superClazz != null ? internalCreateConverter(superClazz) : null;

    }

    private Map<Class<?>, Map<String, PropertyDescriptor>> converterPDCache
            = new ConcurrentHashMap<>();
            
    private void setConverterProperties(final Class<?> converterClass, final Converter converter)
    {
        final org.apache.myfaces.config.element.Converter converterConfig = _runtimeConfig
                .getConverterConfiguration(converterClass.getName());
        
        // if the converter is a DataTimeConverter, check the init param for the default timezone (since 2.0)
        if (converter instanceof DateTimeConverter && _dateTimeConverterDefaultTimeZoneIsSystemTimeZone)
        {    
            ((DateTimeConverter) converter).setTimeZone(TimeZone.getDefault());
        }

        if (converterConfig != null && !converterConfig.getProperties().isEmpty())
        {
            Map<String, PropertyDescriptor> pds = converterPDCache.computeIfAbsent(converterClass, c ->
            {
                HashMap<String, PropertyDescriptor> map = new HashMap<>(converterConfig.getProperties().size());
                try
                {
                    for (PropertyDescriptor pd : Introspector.getBeanInfo(c).getPropertyDescriptors())
                    {
                        for (Property property : converterConfig.getProperties())
                        {
                            if (Objects.equals(pd.getName(), property.getPropertyName()))
                            {
                                map.put(property.getPropertyName(), pd);
                            }
                        }
                    }
                }
                catch (IntrospectionException e)
                {
                    log.log(Level.SEVERE,
                            "Could not read properties for setting default values of converter: "
                                    + converterClass.getSimpleName(),
                            e);
                }
                return map;
            });

            for (int i = 0; i < converterConfig.getProperties().size(); i++)
            {
                Property property = converterConfig.getProperties().get(i);
                try
                {
                    PropertyDescriptor pd = pds.get(property.getPropertyName());
                    Object convertedValue = ClassUtils.convertToType(property.getDefaultValue(), pd.getPropertyType());
                    pd.getWriteMethod().invoke(converter, convertedValue);
                }
                catch (Throwable th)
                {
                    log.log(Level.SEVERE, "Initializing converter : " + converterClass.getName() + " with property : "
                            + property.getPropertyName() + " and value : " + property.getDefaultValue() + " failed.");
                }
            }
        }
    }
    
    private void _handleAttachedResourceDependencyAnnotations(FacesContext context, Object inspected)
    {
        if (inspected == null)
        {
            return;
        }
        
        // This and only this method handles @ResourceDependency and @ResourceDependencies annotations
        // The source of these annotations is Class<?> inspectedClass.
        // Because Class<?> and its annotations cannot change
        // during request/response, it is sufficient to process Class<?> only once per view.
        RequestViewContext rvc = RequestViewContext.getCurrentInstance(context);
        Class<?> inspectedClass = inspected.getClass();
        if (rvc.isClassAlreadyProcessed(inspectedClass))
        {
            return;
        }
        boolean classAlreadyProcessed = false;

        
        List<ResourceDependency> dependencyList = null;
        boolean isCachedList = false;
        
        if(context.isProjectStage(ProjectStage.Production) && _classToResourceDependencyMap.containsKey(inspectedClass))
        {
            dependencyList = _classToResourceDependencyMap.get(inspectedClass);
            if(dependencyList == null)
            {
                return; //class has been inspected and did not contain any resource dependency annotations
            }
            else if (dependencyList.isEmpty())
            {
                return;
            }
            
            isCachedList = true;    // else annotations were found in the cache
        }
        
        if(dependencyList == null)  //not in production or the class hasn't been inspected yet
        {   
            ResourceDependency dependency = inspectedClass.getAnnotation(ResourceDependency.class);
            ResourceDependencies dependencies = inspectedClass.getAnnotation(ResourceDependencies.class);
            if(dependency != null || dependencies != null)
            {
                //resource dependencies were found using one or both annotations, create and build a new list
                dependencyList = new ArrayList<ResourceDependency>();
                
                if(dependency != null)
                {
                    dependencyList.add(dependency);
                }
                
                if(dependencies != null)
                {
                    dependencyList.addAll(Arrays.asList(dependencies.value()));
                }
            }
            else
            {
                dependencyList = Collections.emptyList();
            }
        }

        //resource dependencies were found through inspection or from cache, handle them
        if (dependencyList != null && !dependencyList.isEmpty()) 
        {
            for (int i = 0, size = dependencyList.size(); i < size; i++)
            {
                ResourceDependency dependency = dependencyList.get(i);
                if (!rvc.isResourceDependencyAlreadyProcessed(dependency))
                {
                    _handleAttachedResourceDependency(context, dependency, inspectedClass);
                    rvc.setResourceDependencyAsProcessed(dependency);
                }
            }
        }
        
        //if we're in production and the list is not yet cached, store it
        if(context.isProjectStage(ProjectStage.Production) && !isCachedList && dependencyList != null)
        {
            // Note at this point dependencyList cannot be null, but just let this
            // as a sanity check.
            _classToResourceDependencyMap.put(inspectedClass, dependencyList);
        }
        
        if (!classAlreadyProcessed)
        {
            rvc.setClassProcessed(inspectedClass);
        }
    }

    /**
     * If the ResourceDependency component is created under facelets processing, it should receive
     * an special unique component id. This method check if there is a FaceletCompositionContext
     * and if that so, set the id. Components added by the effect of ResourceDependency are special,
     * because they do not have state, but they depends on the view structure, so with PSS, 
     * each time the view is built they are "recalculated", so they work as if they were transient
     * components that needs to be created at each request, but there are some cases were the 
     * components needs to be saved and restored fully. If a component is created outside facelets 
     * control (render response phase) it is expected to use the default implementation of 
     * createUniqueId(), but in that case, note that this happens after markInitialState() is 
     * called, and the component in this case is saved and restored fully, as expected.
     * 
     * This code cannot be called from facelets component tag handler, because in cases where a
     * component subtree is created using binding property, facelets lost control over component
     * creation and delegates it to the user, but since the binding code is executed each time the
     * view is created, the effect over ResourceDependency persists and the binding code takes into
     * account in the recalculation step, even if later the node related to the binding property
     * is dropped and recreated from the state fully. 
     * 
     * @param facesContext
     * @param component 
     */
    private void setResourceIdOnFaceletsMode(FacesContext facesContext, UIComponent component,
            Class<?> inspectedClass)
    {
        if (component.getId() == null)
        {
            FaceletCompositionContext mctx = FaceletCompositionContext.getCurrentInstance(facesContext);
            if (mctx != null)
            {
                UIViewRoot root = facesContext.getViewRoot();
                root.getAttributes().put(RESOURCE_DEPENDENCY_UNIQUE_ID_KEY, Boolean.TRUE);
                try
                {
                    String uid = root.createUniqueId(facesContext, null);
                    component.setId(uid);
                }
                finally
                {
                    root.getAttributes().put(RESOURCE_DEPENDENCY_UNIQUE_ID_KEY, Boolean.FALSE);
                }
                if (!mctx.isUsingPSSOnThisView())
                {
                    // Now set the identifier that will help to know which classes has been already inspected.
                    component.getAttributes().put(
                            RequestViewContext.RESOURCE_DEPENDENCY_INSPECTED_CLASS, inspectedClass);
                }
                else if (mctx.isRefreshTransientBuildOnPSSPreserveState())
                {
                    component.getAttributes().put(
                            RequestViewContext.RESOURCE_DEPENDENCY_INSPECTED_CLASS, inspectedClass);
                }
            }
            else
            {
                // This happens when there is a programmatic addition, which means the user has added the
                // components to the tree on render response phase or earlier but outside facelets control.
                // In that case we need to save the dependency.
                component.getAttributes().put(
                        RequestViewContext.RESOURCE_DEPENDENCY_INSPECTED_CLASS, inspectedClass);
            }
        }
    }
    
    private void _handleAttachedResourceDependency(FacesContext context, ResourceDependency annotation, 
            Class<?> inspectedClass)
    {
        // If this annotation is not present on the class in question, no action must be taken. 
        if (annotation != null)
        {
            Application application = context.getApplication();
            
            // Create a UIOutput instance by passing javax.faces.Output. to 
            // Application.createComponent(java.lang.String).
            UIOutput output = (UIOutput) application.createComponent(context, UIOutput.COMPONENT_TYPE, null);
            
            // Get the annotation instance from the class and obtain the values of the name, library, and 
            // target attributes.
            String name = annotation.name();
            if (StringUtils.isNotEmpty(name))
            {
                name = ELText.parse(getExpressionFactory(),context.getELContext(), name)
                        .toString(context.getELContext());
            }
            
            // Obtain the renderer-type for the resource name by passing name to 
            // ResourceHandler.getRendererTypeForResourceName(java.lang.String).
            String rendererType = application.getResourceHandler().getRendererTypeForResourceName(name);
            
            // Call setRendererType on the UIOutput instance, passing the renderer-type.
            output.setRendererType(rendererType);
            
            // If the @ResourceDependency was done inside facelets processing,
            // call setId() and set a proper id from facelets
            setResourceIdOnFaceletsMode(context, output, inspectedClass);
            
            // Obtain the Map of attributes from the UIOutput component by calling UIComponent.getAttributes().
            Map<String, Object> attributes = output.getAttributes();
            
            // Store the name into the attributes Map under the key "name".
            attributes.put("name", name);
            
            // If library is the empty string, let library be null.
            String library = annotation.library();
            if (StringUtils.isNotEmpty(library))
            {
                library = ELText.parse(getExpressionFactory(), context.getELContext(), library)
                        .toString(context.getELContext());
                // If library is non-null, store it under the key "library".
                attributes.put("library", library);
            }
            
            // Identify the resource as created by effect of a @ResourceDependency annotation.
            output.getAttributes().put(RequestViewMetadata.RESOURCE_DEPENDENCY_KEY, 
                new Object[]{annotation.library(), annotation.name()});
            
            // If target is the empty string, let target be null.
            String target = annotation.target();
            if (StringUtils.isNotEmpty(target))
            {
                target = ELText.parse(getExpressionFactory(),context.getELContext(), target)
                        .toString(context.getELContext());
                // If target is non-null, store it under the key "target".
                attributes.put("target", target);
                context.getViewRoot().addComponentResource(context, output, target);
            }
            else
            {
                // Otherwise, if target is null, call 
                // UIViewRoot.addComponentResource(javax.faces.context.FacesContext, 
                // javax.faces.component.UIComponent), passing the UIOutput instance as the second argument.
                context.getViewRoot().addComponentResource(context, output);
            }
        }
    }

    @Override
    public final Validator createValidator(final String validatorId) throws FacesException
    {
        Assert.notEmpty(validatorId, "validatorId");

        Class<? extends Validator> validatorClass =
                getObjectFromClassMap(validatorId, _validatorClassMap);
        if (validatorClass == null)
        {
            String message = "Unknown validator id '" + validatorId + "'.";
            log.severe(message);
            throw new FacesException(message);
        }
        
        if (!_cdiManagedValidatorMap.containsKey(validatorClass))
        {
            FacesValidator annotation = validatorClass.getAnnotation(FacesValidator.class);
            if (annotation != null && annotation.managed())
            {
                _cdiManagedValidatorMap.put(validatorClass, true);
            }
            else
            {
                _cdiManagedValidatorMap.put(validatorClass, false);
            }
        }

        try
        {
            Validator validator = null;
            
            if (Boolean.TRUE.equals(_cdiManagedValidatorMap.get(validatorClass)))
            {
                validator = new FacesValidatorCDIWrapper(validatorClass, validatorId);
                
                _handleAttachedResourceDependencyAnnotations(getFacesContext(), 
                        ((FacesWrapper<Validator>)validator).getWrapped());
            }
            else
            {
                validator = createValidatorInstance(validatorClass);
        
                _handleAttachedResourceDependencyAnnotations(getFacesContext(), validator);
            }
            
            return validator;
        }
        catch (Exception e)
        {
            log.log(Level.SEVERE, "Could not instantiate validator " + validatorClass, e);
            throw new FacesException("Could not instantiate validator: " + validatorClass, e);
        }
    }

    private Validator createValidatorInstance(Class<? extends Validator> validatorClass)
            throws InstantiationException, IllegalAccessException
    {
        return validatorClass.newInstance();
    }

    @Override
    public final String getDefaultRenderKitId()
    {
        return _defaultRenderKitId;
    }

    @Override
    public final void setDefaultRenderKitId(final String defaultRenderKitId)
    {
        _defaultRenderKitId = defaultRenderKitId;
    }

    @Override
    public final StateManager getStateManager()
    {
        return _stateManager;
    }

    @Override
    public final void setStateManager(final StateManager stateManager)
    {
        Assert.notNull(stateManager, "stateManager");

        if(isFirstRequestProcessed())
        {
            throw new IllegalStateException(
                    "setStateManager may not be executed after a lifecycle request has been completed");
        }
        
        _stateManager = stateManager;
    }
    
    @Override
    public final void setFlowHandler(FlowHandler flowHandler)
    {
        Assert.notNull(flowHandler, "flowHandler");

        if(isFirstRequestProcessed())
        {
            throw new IllegalStateException(
                    "setFlowHandler may not be executed after a lifecycle request has been completed");
        }
        _flowHandler = flowHandler;
    }

    @Override
    public final FlowHandler getFlowHandler()
    {
        return _flowHandler;
    }

    private void _handleAnnotations(FacesContext context, Object inspected, UIComponent component)
    {   
        // determine the ProjectStage setting via the given FacesContext
        // note that a local getProjectStage() could cause problems in wrapped environments
        boolean isProduction = context.isProjectStage(ProjectStage.Production);
        
        Class<?> inspectedClass = inspected.getClass();
        _handleListenerForAnnotations(context, inspected, inspectedClass, component, isProduction);

        _handleResourceDependencyAnnotations(context, inspectedClass, component, isProduction);
    }

    private void _handleRendererAnnotations(FacesContext context, Renderer inspected, UIComponent component)
    {   
        // determine the ProjectStage setting via the given FacesContext
        // note that a local getProjectStage() could cause problems in wrapped environments
        boolean isProduction = context.isProjectStage(ProjectStage.Production);
        Renderer innerRenderer = inspected;
        while (innerRenderer != null)
        {
            if (innerRenderer instanceof RendererWrapper)
            {
                Class<?> inspectedClass = innerRenderer.getClass();
                _handleListenerForAnnotations(context, innerRenderer, inspectedClass, component, isProduction);

                _handleResourceDependencyAnnotations(context, inspectedClass, component, isProduction);
                
                // get the inner wrapper
                innerRenderer = ((RendererWrapper)innerRenderer).getWrapped();
            }
            else
            {
                Class<?> inspectedClass = innerRenderer.getClass();
                _handleListenerForAnnotations(context, innerRenderer, inspectedClass, component, isProduction);

                _handleResourceDependencyAnnotations(context, inspectedClass, component, isProduction);
                
                innerRenderer = null;
            }
        }
    }

    private void _handleListenerForAnnotations(FacesContext context, Object inspected, Class<?> inspectedClass,
                                               UIComponent component, boolean isProduction)
    {
        List<ListenerFor> listenerForList = null;
        boolean isCachedList = false;
        
        if(isProduction)
        {
            listenerForList = _classToListenerForMap.get(inspectedClass);

            if (listenerForList != null)
            {
                if (listenerForList.isEmpty())
                {
                    return; //class has been inspected and did not contain any listener annotations
                }
                
                isCachedList = true;    // else annotations were found in the cache
            }
        }

        if(listenerForList == null) //not in production or the class hasn't been inspected yet
        {
            ListenerFor listener = inspectedClass.getAnnotation(ListenerFor.class);
            ListenersFor listeners = inspectedClass.getAnnotation(ListenersFor.class);
            if(listener != null || listeners != null)
            {
                //listeners were found using one or both annotations, create and build a new list
                listenerForList = new ArrayList<ListenerFor>();
                
                if(listener != null)
                {
                    listenerForList.add(listener);
                }
                
                if(listeners != null)
                {
                    listenerForList.addAll(Arrays.asList(listeners.value()));
                }
            }
            else
            {
                listenerForList = Collections.emptyList();
            }
        }        
 
        // listeners were found through inspection or from cache, handle them
        if (listenerForList != null && !listenerForList.isEmpty()) 
        {
            for (int i = 0, size = listenerForList.size(); i < size; i++)
            {
                ListenerFor listenerFor = listenerForList.get(i);
                _handleListenerFor(context, inspected, component, listenerFor);
            }
        }
        
        //if we're in production and the list is not yet cached, store it
        if(isProduction && !isCachedList && listenerForList != null) 
        {
            // Note at this point listenerForList cannot be null, but just let listenerForList != null
            // as a sanity check.
            _classToListenerForMap.put(inspectedClass, listenerForList);
        }
    }

    private void _handleListenerFor(FacesContext context, Object inspected, UIComponent component,
                                    ListenerFor annotation)
    {
        // If this annotation is not present on the class in question, no action must be taken.
        if (annotation != null)
        {
            // Determine the "target" on which to call subscribeToEvent.
            // If the class to which this annotation is attached implements ComponentSystemEventListener
            if (inspected instanceof ComponentSystemEventListener)
            {
                // If the class to which this annotation is attached is a UIComponent instance, "target" is the
                // UIComponent instance.

                // If the class to which this annotation is attached is a Renderer instance, "target" is the
                // UIComponent instance.

                /*
                 * If "target" is a UIComponent call UIComponent.subscribeToEvent(Class, ComponentSystemEventListener)
                 * passing the systemEventClass() of the annotation as the first argument and the instance of the class
                 * to which this annotation is attached (which must implement ComponentSystemEventListener) as the
                 * second argument.
                 */
                component.subscribeToEvent(annotation.systemEventClass(), (ComponentSystemEventListener) inspected);
            }
            // If the class to which this annotation is attached implements SystemEventListener and does not implement
            // ComponentSystemEventListener, "target" is the Application instance.
            else if (component instanceof SystemEventListener)
            {
                // use the Application object from the FacesContext (note that a
                // direct use of subscribeToEvent() could cause problems if the
                // Application is wrapped)
                Application application = context.getApplication();
                
                // If "target" is the Application instance, inspect the value of the sourceClass() annotation attribute
                // value.
                if (Void.class.equals(annotation.sourceClass()))
                {
                    /*
                     * If the value is Void.class, call Application.subscribeToEvent(Class, SystemEventListener),
                     * passing the value of systemEventClass() as the first argument and the instance of the class to
                     * which this annotation is attached (which must implement SystemEventListener) as the second
                     * argument.
                     */
                    application.subscribeToEvent(annotation.systemEventClass(), (SystemEventListener) inspected);
                }
                else
                {
                    /*
                     * Otherwise, call Application.subscribeToEvent(Class, Class, SystemEventListener), passing the
                     * value of systemEventClass() as the first argument, the value of sourceClass() as the second
                     * argument, and the instance of the class to which this annotation is attached (which must
                     * implement SystemEventListener) as the third argument.
                     */
                    application.subscribeToEvent(annotation.systemEventClass(), annotation.sourceClass(),
                                     (SystemEventListener) inspected);
                }
            }

            /*
             * If the class to which this annotation is attached implements ComponentSystemEventListener and is neither
             * an instance of Renderer nor UIComponent, the action taken is unspecified. This case must not trigger any
             * kind of error.
             */
        }
    }

    private void _handleResourceDependencyAnnotations(FacesContext context, Class<?> inspectedClass,
                                                      UIComponent component, boolean isProduction)
    {
        // This and only this method handles @ResourceDependency and @ResourceDependencies annotations
        // The source of these annotations is Class<?> inspectedClass.
        // Because Class<?> and its annotations cannot change
        // during request/response, it is sufficient to process Class<?> only once per view.
        RequestViewContext rvc = RequestViewContext.getCurrentInstance(context);
        if (rvc.isClassAlreadyProcessed(inspectedClass))
        {
            return;
        }
        boolean classAlreadyProcessed = false;

        
        List<ResourceDependency> dependencyList = null;
        boolean isCachedList = false;
        
        if(isProduction)
        {
            dependencyList = _classToResourceDependencyMap.get(inspectedClass);

            if (dependencyList != null)
            {
                if (dependencyList.isEmpty())
                {
                    return; //class has been inspected and did not contain any resource dependency annotations
                }
                
                isCachedList = true;    // else annotations were found in the cache
            }
        }
        
        if(dependencyList == null)  //not in production or the class hasn't been inspected yet
        {   
            ResourceDependency dependency = inspectedClass.getAnnotation(ResourceDependency.class);
            ResourceDependencies dependencies = inspectedClass.getAnnotation(ResourceDependencies.class);
            if(dependency != null || dependencies != null)
            {
                //resource dependencies were found using one or both annotations, create and build a new list
                dependencyList = new ArrayList<ResourceDependency>();
                
                if(dependency != null)
                {
                    dependencyList.add(dependency);
                }
                
                if(dependencies != null)
                {
                    dependencyList.addAll(Arrays.asList(dependencies.value()));
                }
            }
            else
            {
                dependencyList = Collections.emptyList();
            }
        }        
 
        // resource dependencies were found through inspection or from cache, handle them
        if (dependencyList != null && !dependencyList.isEmpty()) 
        {
            for (int i = 0, size = dependencyList.size(); i < size; i++)
            {
                ResourceDependency dependency = dependencyList.get(i);
                if (!rvc.isResourceDependencyAlreadyProcessed(dependency))
                {
                    _handleResourceDependency(context, component, dependency, inspectedClass);
                    rvc.setResourceDependencyAsProcessed(dependency);
                }
            }
        }
        
        //if we're in production and the list is not yet cached, store it
        if(isProduction && !isCachedList && dependencyList != null)   
        {
            // Note at this point listenerForList cannot be null, but just let dependencyList != null
            // as a sanity check.
            _classToResourceDependencyMap.put(inspectedClass, dependencyList);
        }
        
        if (!classAlreadyProcessed)
        {
            rvc.setClassProcessed(inspectedClass);
        }
    }
    
    private void _handleResourceDependency(FacesContext context, UIComponent component, ResourceDependency annotation,
            Class<?> inspectedClass)
    {
        // If this annotation is not present on the class in question, no action must be taken.
        if (annotation != null)
        {
            // Create a UIOutput instance by passing javax.faces.Output. to
            // Application.createComponent(java.lang.String).
            UIOutput output = (UIOutput) createComponent(context, UIOutput.COMPONENT_TYPE, null);

            // Get the annotation instance from the class and obtain the values of the name, library, and
            // target attributes.
            String name = annotation.name();
            if (StringUtils.isNotEmpty(name))
            {
                name = ELText.parse(getExpressionFactory(), context.getELContext(), name)
                        .toString(context.getELContext());
            }

            // Obtain the renderer-type for the resource name by passing name to
            // ResourceHandler.getRendererTypeForResourceName(java.lang.String).
            // (note that we can not use this.getResourceHandler(), because the Application might be wrapped)
            String rendererType = context.getApplication().getResourceHandler().getRendererTypeForResourceName(name);

            // Call setRendererType on the UIOutput instance, passing the renderer-type.
            output.setRendererType(rendererType);
            
            // If the @ResourceDependency was done inside facelets processing,
            // call setId() and set a proper id from facelets
            setResourceIdOnFaceletsMode(context, output, inspectedClass);

            // Obtain the Map of attributes from the UIOutput component by calling UIComponent.getAttributes().
            Map<String, Object> attributes = output.getAttributes();

            // Store the name into the attributes Map under the key "name".
            attributes.put("name", name);

            // If library is the empty string, let library be null.
            String library = annotation.library();
            if (StringUtils.isNotEmpty(library))
            {
                library = ELText.parse(getExpressionFactory(), context.getELContext(), library)
                        .toString(context.getELContext());
                // If library is non-null, store it under the key "library".
                if ("this".equals(library))
                {
                    // Special "this" behavior
                    Resource resource = (Resource)component.getAttributes().get(Resource.COMPONENT_RESOURCE_KEY);
                    if (resource != null)
                    {
                        attributes.put("library", resource.getLibraryName());
                    }
                }
                else
                {
                    attributes.put("library", library);
                }
            }
            
            // Identify the resource as created by effect of a @ResourceDependency annotation.
            output.getAttributes().put(RequestViewMetadata.RESOURCE_DEPENDENCY_KEY, 
                new Object[]{annotation.library(), annotation.name()});

            // If target is the empty string, let target be null.
            String target = annotation.target();
            if (StringUtils.isNotEmpty(target))
            {
                target = ELText.parse(getExpressionFactory(), context.getELContext(), target)
                        .toString(context.getELContext());
                // If target is non-null, store it under the key "target".
                attributes.put("target", target);
                context.getViewRoot().addComponentResource(context, output, target);
            }
            else
            {
                // Otherwise, if target is null, call UIViewRoot.addComponentResource(javax.faces.context.FacesContext,
                // javax.faces.component.UIComponent), passing the UIOutput instance as the second argument.
                context.getViewRoot().addComponentResource(context, output);
            }
        }
    }
    
    private void _inspectRenderer(FacesContext context, UIComponent component,
                                  String componentType, String rendererType)
    {
        /*
         * The Renderer instance to inspect must be obtained by calling FacesContext.getRenderKit() and calling
         * RenderKit.getRenderer(java.lang.String, java.lang.String) on the result, passing the argument componentFamily
         * of the newly created component as the first argument and the argument rendererType as the second argument.
         */
        RenderKit renderKit = context.getRenderKit();
        if (renderKit == null)
        {
            // If no renderKit is set, it means we are on initialization step, skip this step.
            return;
        }
        Renderer renderer = renderKit.getRenderer(component.getFamily(), rendererType);
        if (renderer == null)
        {
            // If no such Renderer can be found, a message must be logged with a helpful error message.
            log.severe("renderer cannot be found for component type " + componentType + " and renderer type "
                    + rendererType);
        }
        else
        {
            // Otherwise, UIComponent.setRendererType(java.lang.String) must be called on the newly created
            // UIComponent instance, passing the argument rendererType as the argument.
            component.setRendererType(rendererType);

            /*
             * except the Renderer for the component to be returned must be inspected for the annotations mentioned in
             * createComponent(ValueExpression, FacesContext, String) as specified in the documentation for that method.
             */
            _handleRendererAnnotations(context, renderer, component);
        }
    }

    /**
     * Method to handle determining if the first request has 
     * been handled by the associated LifecycleImpl.
     * @return true if the first request has already been processed, false otherwise
     */
    private boolean isFirstRequestProcessed()
    {
        FacesContext context = getFacesContext();
        
        //if firstRequestProcessed is not set, check the application map
        if(!_firstRequestProcessed && context != null 
                && Boolean.TRUE.equals(context.getExternalContext().getApplicationMap()
                        .containsKey(LifecycleImpl.FIRST_REQUEST_PROCESSED_PARAM)))
        {
            _firstRequestProcessed = true;
        }
        return _firstRequestProcessed;
    }
    
    private static class SystemListenerEntry
    {
        private List<SystemEventListener> _lstSystemEventListener;
        private Map<Class<?>, List<SystemEventListener>> _sourceClassMap;

        public SystemListenerEntry()
        {
        }

        public void addListener(SystemEventListener listener)
        {
            assert listener != null;

            addListenerNoDuplicate(getAnySourceListenersNotNull(), listener);
        }

        public void addListener(SystemEventListener listener, Class<?> source)
        {
            assert listener != null;

            if (source == null)
            {
                addListener(listener);
            }
            else
            {
                addListenerNoDuplicate(getSpecificSourceListenersNotNull(source), listener);
            }
        }

        public void removeListener(SystemEventListener listener)
        {
            assert listener != null;

            if (_lstSystemEventListener != null)
            {
                _lstSystemEventListener.remove(listener);
            }
        }

        public void removeListener(SystemEventListener listener, Class<?> sourceClass)
        {
            assert listener != null;

            if (sourceClass == null)
            {
                removeListener(listener);
            }
            else
            {
                if (_sourceClassMap != null)
                {
                    List<SystemEventListener> listeners = _sourceClassMap.get(sourceClass);
                    if (listeners != null)
                    {
                        listeners.remove(listener);
                    }
                }
            }
        }

        public void publish(FacesContext facesContext, Class<? extends SystemEvent> systemEventClass,
                Class<?> classSource, Object source, SystemEvent event)
        {
            if (source != null && _sourceClassMap != null)
            {
                event = _ApplicationUtils._traverseListenerList(facesContext, _sourceClassMap.get(classSource),
                        systemEventClass, source, event);
            }

            _ApplicationUtils._traverseListenerList(facesContext, _lstSystemEventListener,
                    systemEventClass, source, event);
        }

        private void addListenerNoDuplicate(List<SystemEventListener> listeners, SystemEventListener listener)
        {
            if (!listeners.contains(listener))
            {
                listeners.add(listener);
            }
        }

        private synchronized List<SystemEventListener> getAnySourceListenersNotNull()
        {
            if (_lstSystemEventListener == null)
            {
                /*
                 * TODO: Check if modification occurs often or not, might have to use a synchronized list instead.
                 * 
                 * Registrations found:
                 */
                _lstSystemEventListener = new CopyOnWriteArrayList<>();
            }

            return _lstSystemEventListener;
        }

        private synchronized List<SystemEventListener> getSpecificSourceListenersNotNull(Class<?> sourceClass)
        {
            if (_sourceClassMap == null)
            {
                _sourceClassMap = new ConcurrentHashMap<>();
            }

            /*
             * TODO: Check if modification occurs often or not, might have to use a synchronized list instead.
             * 
             * Registrations found:
             */
            return _sourceClassMap.computeIfAbsent(sourceClass, k -> new CopyOnWriteArrayList<>());
        }
    }
    
    /*
     * private method to look for config objects on a classmap.  The objects can be either a type string
     * or a Class<?> object.  This is done to facilitate lazy loading of config objects.   
     * @param id 
     * @param classMap 
     * @return
     */
    private <T> Class<? extends T> getObjectFromClassMap(String id, Map<String, Object> classMap)
    {
        Object obj = classMap.get(id);
        
        if(obj == null)
        {
            return null;    //object for this id wasn't found on the map
        }
        
        if(obj instanceof Class<?>)
        {
            return (Class<? extends T>)obj;
        }
        else if (obj instanceof String )
        {
            Class<?> clazz = ClassUtils.simpleClassForName((String)obj);
            classMap.put(id, clazz);
            return (Class<? extends T>)clazz;
        }
        
        //object stored in the map for this id is an invalid type.  remove it and return null
        classMap.remove(id);
        return null;        
    }

    
    @Override
    public final void setSearchExpressionHandler(SearchExpressionHandler searchExpressionHandler)
    {
        Assert.notNull(searchExpressionHandler, "searchExpressionHandler");

        if(isFirstRequestProcessed())
        {
            throw new IllegalStateException(
                    "setFlowHandler may not be executed after a lifecycle request has been completed");
        }
        _searchExpressionHandler = searchExpressionHandler;
    }

    @Override
    public final SearchExpressionHandler getSearchExpressionHandler()
    {
        return _searchExpressionHandler;
    }

    @Override
    public SearchKeywordResolver getSearchKeywordResolver()
    {
        // we don't need synchronization here since it is ok to have multiple
        // instances of the elresolver
        if (_searchExpressionResolver == null)
        {
            _searchExpressionResolver = createSearchExpressionResolver();
        }
        return _searchExpressionResolver;
    }
    
    private SearchKeywordResolver createSearchExpressionResolver()
    {
        // Chain of responsibility pattern
        CompositeSearchKeywordResolver baseResolver = new CompositeSearchKeywordResolver();
        
        for (SearchKeywordResolver child : _runtimeConfig.getApplicationSearchExpressionResolvers())
        {
            baseResolver.add(child);
        }
        
        baseResolver.add(new ThisSearchKeywordResolver());
        baseResolver.add(new ParentSearchKeywordResolver());
        baseResolver.add(new ChildSearchKeywordResolver());
        baseResolver.add(new CompositeComponentParentSearchKeywordResolver());
        baseResolver.add(new FormSearchKeywordResolver());
        baseResolver.add(new NamingContainerSearchKeywordResolver());
        baseResolver.add(new NextSearchKeywordResolver());
        baseResolver.add(new NoneSearchKeywordResolver());
        baseResolver.add(new PreviousSearchKeywordResolver());
        baseResolver.add(new RootSearchKeywordResolver());
        baseResolver.add(new IdSearchKeywordResolver());
        baseResolver.add(new AllSearchKeywordResolver());
        
        return baseResolver;
    }

    @Override
    public void addSearchKeywordResolver(SearchKeywordResolver resolver)
    {
        if (isFirstRequestProcessed())
        {
            throw new IllegalStateException(
                    "It is illegal to add a search expression resolver after the first request is processed");
        }
        if (resolver != null)
        {
            _runtimeConfig.addApplicationSearchExpressionResolver(resolver);
        }
    }
}
