com.sun.faces.config.ConfigManager Maven / Gradle / Ivy
Show all versions of jakarta.faces Show documentation
/* * Copyright (c) 1997, 2020 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v. 2.0, which is available at * http://www.eclipse.org/legal/epl-2.0. * * This Source Code may also be made available under the following Secondary * Licenses when the conditions for such availability set forth in the * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, * version 2 with the GNU Classpath Exception, which is available at * https://www.gnu.org/software/classpath/license.html. * * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 */ package com.sun.faces.config; import static com.sun.faces.RIConstants.FACES_PREFIX; import static com.sun.faces.config.WebConfiguration.BooleanWebContextInitParameter.DisableFaceletJSFViewHandler; import static com.sun.faces.config.WebConfiguration.BooleanWebContextInitParameter.DisableFaceletJSFViewHandlerDeprecated; import static com.sun.faces.config.WebConfiguration.BooleanWebContextInitParameter.EnableThreading; import static com.sun.faces.config.WebConfiguration.BooleanWebContextInitParameter.ValidateFacesConfigFiles; import static com.sun.faces.config.manager.Documents.getProgrammaticDocuments; import static com.sun.faces.config.manager.Documents.getXMLDocuments; import static com.sun.faces.config.manager.Documents.mergeDocuments; import static com.sun.faces.config.manager.Documents.sortDocuments; import static com.sun.faces.spi.ConfigurationResourceProviderFactory.createProviders; import static com.sun.faces.spi.ConfigurationResourceProviderFactory.ProviderType.FaceletConfig; import static com.sun.faces.spi.ConfigurationResourceProviderFactory.ProviderType.FacesConfig; import static java.util.Arrays.asList; import static java.util.Collections.emptyMap; import static java.util.Collections.unmodifiableList; import static java.util.logging.Level.FINE; import java.lang.annotation.Annotation; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.ServiceLoader; import java.util.Set; import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; import java.util.concurrent.FutureTask; import java.util.logging.Logger; import javax.naming.InitialContext; import javax.naming.NamingException; import com.sun.faces.config.configpopulator.JsfRIRuntimePopulator; import com.sun.faces.config.configprovider.MetaInfFaceletTaglibraryConfigProvider; import com.sun.faces.config.configprovider.MetaInfFacesConfigResourceProvider; import com.sun.faces.config.configprovider.WebAppFlowConfigResourceProvider; import com.sun.faces.config.configprovider.WebFaceletTaglibResourceProvider; import com.sun.faces.config.configprovider.WebFacesConfigResourceProvider; import com.sun.faces.config.manager.DbfFactory; import com.sun.faces.config.manager.FacesConfigInfo; import com.sun.faces.config.manager.documents.DocumentInfo; import com.sun.faces.config.manager.tasks.FindAnnotatedConfigClasses; import com.sun.faces.config.manager.tasks.ProvideMetadataToAnnotationScanTask; import com.sun.faces.config.processor.ApplicationConfigProcessor; import com.sun.faces.config.processor.BehaviorConfigProcessor; import com.sun.faces.config.processor.ComponentConfigProcessor; import com.sun.faces.config.processor.ConfigProcessor; import com.sun.faces.config.processor.ConverterConfigProcessor; import com.sun.faces.config.processor.FaceletTaglibConfigProcessor; import com.sun.faces.config.processor.FacesConfigExtensionProcessor; import com.sun.faces.config.processor.FacesFlowDefinitionConfigProcessor; import com.sun.faces.config.processor.FactoryConfigProcessor; import com.sun.faces.config.processor.LifecycleConfigProcessor; import com.sun.faces.config.processor.ManagedBeanConfigProcessor; import com.sun.faces.config.processor.NavigationConfigProcessor; import com.sun.faces.config.processor.ProtectedViewsConfigProcessor; import com.sun.faces.config.processor.RenderKitConfigProcessor; import com.sun.faces.config.processor.ResourceLibraryContractsConfigProcessor; import com.sun.faces.config.processor.ValidatorConfigProcessor; import com.sun.faces.el.ELContextImpl; import com.sun.faces.el.ELUtils; import com.sun.faces.spi.ConfigurationResourceProvider; import com.sun.faces.spi.ConfigurationResourceProviderFactory; import com.sun.faces.spi.HighAvailabilityEnabler; import com.sun.faces.spi.InjectionProvider; import com.sun.faces.spi.InjectionProviderFactory; import com.sun.faces.spi.ThreadContext; import com.sun.faces.util.FacesLogger; import jakarta.el.ELContext; import jakarta.el.ELContextEvent; import jakarta.el.ELContextListener; import jakarta.el.ExpressionFactory; import jakarta.faces.FacesException; import jakarta.faces.FactoryFinder; import jakarta.faces.application.Application; import jakarta.faces.application.ApplicationConfigurationPopulator; import jakarta.faces.component.UIViewRoot; import jakarta.faces.context.FacesContext; import jakarta.faces.event.PostConstructApplicationEvent; import jakarta.servlet.ServletContext; /** *
fase */ public boolean hasBeenInitialized(ServletContext servletContext) { return initializedContexts.contains(servletContext); } // --------------------------------------------------------- Private Methods /** * Execute the Task responsible for finding annotation classes * */ private void findAnnotations(DocumentInfo[] facesDocuments, InjectionProvider containerConnector, ServletContext servletContext, InitFacesContext context, ExecutorService executor) { ProvideMetadataToAnnotationScanTask taskMetadata = new ProvideMetadataToAnnotationScanTask(facesDocuments, containerConnector); Future* This class manages the initialization of each web application that uses Faces. *
*/ public class ConfigManager { private static final Logger LOGGER = FacesLogger.CONFIG.getLogger(); /** * The initialization time FacesContext scoped key under which the InjectionProvider is stored. */ public static final String INJECTION_PROVIDER_KEY = ConfigManager.class.getName() + "_INJECTION_PROVIDER_TASK"; /** ** The
*/ private static final int NUMBER_OF_TASK_THREADS = 5; private static final String CONFIG_MANAGER_INSTANCE_KEY = FACES_PREFIX + "CONFIG_MANAGER_KEY"; /** * The application-scoped key under which the Future responsible for annotation scanning is associated with. */ private static final String ANNOTATIONS_SCAN_TASK_KEY = ConfigManager.class.getName() + "_ANNOTATION_SCAN_TASK"; /** *ConfigManager
will multithread the calls to theConfigurationResourceProvider
s as well * as any calls to parse a resources into a DOM. By default, we'll use only 5 threads per web application. ** Contains each
*/ private ListServletContext
that we've initialized. TheServletContext
will be removed * when the application is destroyed. *initializedContexts = new CopyOnWriteArrayList<>(); private final List configProcessors = unmodifiableList( asList(new FactoryConfigProcessor(), new LifecycleConfigProcessor(), new ApplicationConfigProcessor(), new ComponentConfigProcessor(), new ConverterConfigProcessor(), new ValidatorConfigProcessor(), new ManagedBeanConfigProcessor(), new RenderKitConfigProcessor(), new NavigationConfigProcessor(), new BehaviorConfigProcessor(), new FacesConfigExtensionProcessor(), new ProtectedViewsConfigProcessor(), new FacesFlowDefinitionConfigProcessor(), new ResourceLibraryContractsConfigProcessor())); /** * * A List of resource providers that search for faces-config documents. By default, this contains a provider for the * Mojarra, and two other providers to satisfy the requirements of the specification. *
*/ private final ListfacesConfigProviders = unmodifiableList( asList(new MetaInfFacesConfigResourceProvider(), new WebAppFlowConfigResourceProvider(), new WebFacesConfigResourceProvider())); /** * * A List of resource providers that search for faces-config documents. By default, this contains a provider for the * Mojarra, and one other providers to satisfy the requirements of the specification. *
*/ private final ListfacesletsTagLibConfigProviders = unmodifiableList( asList(new MetaInfFaceletTaglibraryConfigProvider(), new WebFaceletTaglibResourceProvider())); /** * * The chain of {@link ConfigProcessor} instances to processing of facelet-taglib documents. *
*/ private final ConfigProcessor faceletTaglibConfigProcessor = new FaceletTaglibConfigProcessor(); // ---------------------------------------------------------- Public STATIC Methods public static ConfigManager createInstance(ServletContext servletContext) { ConfigManager result = new ConfigManager(); servletContext.setAttribute(CONFIG_MANAGER_INSTANCE_KEY, result); return result; } /** * @return aConfigManager
instance */ public static ConfigManager getInstance(ServletContext servletContext) { return (ConfigManager) servletContext.getAttribute(CONFIG_MANAGER_INSTANCE_KEY); } /** * @return the results of the annotation scan task */ public static Map, Set >> getAnnotatedClasses(FacesContext ctx) { Map appMap = ctx.getExternalContext().getApplicationMap(); @SuppressWarnings("unchecked") Future , Set >>> annotationScan; if (executor != null) { annotationScan = executor.submit(new FindAnnotatedConfigClasses(servletContext, context, taskMetadata)); } else { annotationScan = new FutureTask<>(new FindAnnotatedConfigClasses(servletContext, context, taskMetadata)); ((FutureTask , Set >>>) annotationScan).run(); } pushTaskToContext(servletContext, annotationScan); } /** * Push the provided Future
to the specifiedServletContext
. */ private void pushTaskToContext(ServletContext sc, Future, Set >>> scanTask) { sc.setAttribute(ANNOTATIONS_SCAN_TASK_KEY, scanTask); } private boolean useThreads(ServletContext ctx) { return WebConfiguration.getInstance(ctx).isOptionEnabled(EnableThreading); } private List getFacesConfigResourceProviders() { return getConfigurationResourceProviders(facesConfigProviders, FacesConfig); } private List getFaceletConfigResourceProviders() { return getConfigurationResourceProviders(facesletsTagLibConfigProviders, FaceletConfig); } private List getConfigurationResourceProviders(List defaultProviders, ConfigurationResourceProviderFactory.ProviderType providerType) { ConfigurationResourceProvider[] customProviders = createProviders(providerType); if (customProviders.length == 0) { return defaultProviders; } List providers = new ArrayList<>(defaultProviders); // Insert the custom providers after the META-INF providers and // before those that scan /WEB-INF providers.addAll(defaultProviders.size() - 1, asList(customProviders)); return unmodifiableList(providers); } private void initializeConfigProcessers(ServletContext servletContext, FacesContext facesContext) { configProcessors.stream().parallel().forEach(e -> e.initializeClassMetadataMap(servletContext, facesContext)); } private List getConfigPopulators() { List configPopulators = new ArrayList<>(); configPopulators.add(new JsfRIRuntimePopulator()); ServiceLoader.load(ApplicationConfigurationPopulator.class).forEach(e -> configPopulators.add(e)); return configPopulators; } /** * Utility method to check if JSF 2.0 Facelets should be disabled, but that doesn't perform the check unless * lastFacesConfigInfo
is indeed *the* WEB-INF/faces-config.xml * * @param webConfig configuration for this application * @param lastFacesConfigInfo object representing WEB-INF/faces-config.xml * @returntrue
if Facelets should be disabled */ private boolean isFaceletsDisabled(WebConfiguration webConfig, FacesConfigInfo lastFacesConfigInfo) { if (lastFacesConfigInfo.isWebInfFacesConfig()) { return _isFaceletsDisabled(webConfig, lastFacesConfigInfo); } return webConfig.isOptionEnabled(DisableFaceletJSFViewHandler) || webConfig.isOptionEnabled(DisableFaceletJSFViewHandlerDeprecated); } /** * Utility method to check if JSF 2.0 Facelets should be disabled. * ** If it's not explicitly disabled by the context init parameter, then check the version of the WEB-INF/faces-config.xml * document. If the version is less than 2.0, then override the default value for the context init parameter so that * other parts of the system that use that config option will know it has been disabled. *
* ** NOTE: Since this method overrides a configuration value, it should be called before *any* document parsing * is performed the configuration value may be queried by the
* * @param webconfig configuration for this application * @param facesConfigInfo object representing WEB-INF/faces-config.xml * @returnConfigParser
s. *true
if Facelets should be disabled */ private boolean _isFaceletsDisabled(WebConfiguration webconfig, FacesConfigInfo facesConfigInfo) { boolean isFaceletsDisabled = webconfig.isOptionEnabled(DisableFaceletJSFViewHandler) || webconfig.isOptionEnabled(DisableFaceletJSFViewHandlerDeprecated); if (!isFaceletsDisabled) { // if not explicitly disabled, make a sanity check against // /WEB-INF/faces-config.xml isFaceletsDisabled = !facesConfigInfo.isVersionGreaterOrEqual(2.0); webconfig.overrideContextInitParameter(DisableFaceletJSFViewHandler, isFaceletsDisabled); } return isFaceletsDisabled; } /** * Publishes a {@link jakarta.faces.event.PostConstructApplicationEvent} event for the current {@link Application} * instance. */ void publishPostConfigEvent() { FacesContext ctx = FacesContext.getCurrentInstance(); Application app = ctx.getApplication(); if (null == ((InitFacesContext) ctx).getELContext()) { ELContext elContext = new ELContextImpl(app.getELResolver()); elContext.putContext(FacesContext.class, ctx); ExpressionFactory exFactory = ELUtils.getDefaultExpressionFactory(ctx); if (null != exFactory) { elContext.putContext(ExpressionFactory.class, exFactory); } UIViewRoot root = ctx.getViewRoot(); if (null != root) { elContext.setLocale(root.getLocale()); } ELContextListener[] listeners = app.getELContextListeners(); if (listeners.length > 0) { ELContextEvent event = new ELContextEvent(elContext); for (ELContextListener listener : listeners) { listener.contextCreated(event); } } ((InitFacesContext) ctx).setELContext(elContext); } app.publishEvent(ctx, PostConstructApplicationEvent.class, Application.class, app); } /** * Create a newExecutorService
with {@link #NUMBER_OF_TASK_THREADS} threads. */ private static ExecutorService createExecutorService() { int tc = Runtime.getRuntime().availableProcessors(); if (tc > NUMBER_OF_TASK_THREADS) { tc = NUMBER_OF_TASK_THREADS; } try { return (ExecutorService) new InitialContext().lookup("java:comp/env/concurrent/ThreadPool"); } catch (NamingException e) { // Ignore } return Executors.newFixedThreadPool(tc); } private ThreadContext getThreadContext(InjectionProvider containerConnector) { if (containerConnector instanceof ThreadContext) { return (ThreadContext) containerConnector; } return null; } /** * Calls through to {@link jakarta.faces.FactoryFinder#releaseFactories()} ignoring any exceptions. */ private void releaseFactories() { try { FactoryFinder.releaseFactories(); } catch (FacesException ignored) { LOGGER.log(FINE, "Exception thrown from FactoryFinder.releaseFactories()", ignored); } } /** * This method will remove any information about the application. * * @param facesContext theFacesContext
for the application that needs to be removed * @param servletContext theServletContext
for the application that needs to be removed */ public void destroy(ServletContext servletContext, FacesContext facesContext) { configProcessors.stream().forEach(e -> e.destroy(servletContext, facesContext)); initializedContexts.remove(servletContext); } }