/* * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * * Copyright (c) 1997-2010 Oracle and/or its affiliates. All rights reserved. * * The contents of this file are subject to the terms of either the GNU * General Public License Version 2 only ("GPL") or the Common Development * and Distribution License("CDDL") (collectively, the "License"). You * may not use this file except in compliance with the License. You can * obtain a copy of the License at * https://glassfish.java.net/public/CDDL+GPL_1_1.html * or packager/legal/LICENSE.txt. See the License for the specific * language governing permissions and limitations under the License. * * When distributing the software, include this License Header Notice in each * file and include the License file at packager/legal/LICENSE.txt. * * GPL Classpath Exception: * Oracle designates this particular file as subject to the "Classpath" * exception as provided by Oracle in the GPL Version 2 section of the License * file that accompanied this code. * * Modifications: * If applicable, add the following below the License Header, with the fields * enclosed by brackets [] replaced by your own identifying information: * "Portions Copyright [year] [name of copyright owner]" * * Contributor(s): * If you wish your version of this file to be governed by only the CDDL or * only the GPL Version 2, indicate your decision by adding "[Contributor] * elects to include this software in this distribution under the [CDDL or GPL * Version 2] license." If you don't indicate a single choice of license, a * recipient has the option to distribute your version of this file under * either the CDDL, the GPL Version 2 or to extend the choice of license to * its licensees as provided above. However, if you add GPL Version 2 code * and therefore, elected the GPL Version 2 license, then the option applies * only if the new code is made subject to such option by the copyright * holder. */ package com.sun.faces.application; import static com.sun.faces.RIConstants.FACES_CONFIG_VERSION; import static com.sun.faces.RIConstants.FACES_PREFIX; import static com.sun.faces.config.ConfigManager.getAnnotatedClasses; 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.EnableFaceletsResourceResolverResolveCompositeComponents; import static com.sun.faces.config.WebConfiguration.BooleanWebContextInitParameter.EnableLazyBeanValidation; import static com.sun.faces.config.WebConfiguration.BooleanWebContextInitParameter.FaceletsSkipComments; import static com.sun.faces.config.WebConfiguration.WebContextInitParameter.FaceletCache; import static com.sun.faces.config.WebConfiguration.WebContextInitParameter.FaceletsDecorators; import static com.sun.faces.config.WebConfiguration.WebContextInitParameter.FaceletsDefaultRefreshPeriod; import static com.sun.faces.config.WebConfiguration.WebContextInitParameter.FaceletsDefaultRefreshPeriodDeprecated; import static com.sun.faces.config.WebConfiguration.WebContextInitParameter.FaceletsResourceResolver; import static com.sun.faces.el.ELUtils.buildFacesResolver; import static com.sun.faces.el.FacesCompositeELResolver.ELResolverChainType.Faces; import static com.sun.faces.facelets.impl.DefaultResourceResolver.NON_DEFAULT_RESOURCE_RESOLVER_PARAM_NAME; import static com.sun.faces.facelets.util.ReflectionUtil.decorateInstance; import static com.sun.faces.facelets.util.ReflectionUtil.forName; import static com.sun.faces.lifecycle.ELResolverInitPhaseListener.populateFacesELResolverForJsp; import static com.sun.faces.util.MessageUtils.APPLICATION_ASSOCIATE_EXISTS_ID; import static com.sun.faces.util.MessageUtils.getExceptionMessageString; import static com.sun.faces.util.Util.getFacesConfigXmlVersion; import static com.sun.faces.util.Util.isCdiAvailable; import static com.sun.faces.util.Util.split; import static java.lang.Long.parseLong; import static java.util.Collections.emptyList; import static java.util.Collections.emptyMap; import static java.util.logging.Level.FINE; import static java.util.logging.Level.INFO; import static java.util.logging.Level.SEVERE; import static javax.faces.FactoryFinder.FACELET_CACHE_FACTORY; import static javax.faces.FactoryFinder.FLOW_HANDLER_FACTORY; import static javax.faces.application.ProjectStage.Development; import static javax.faces.application.ProjectStage.Production; import java.io.IOException; import java.net.URL; import java.util.ArrayList; import java.util.HashMap; import java.util.LinkedHashSet; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.ResourceBundle; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.logging.Logger; import javax.el.CompositeELResolver; import javax.el.ELResolver; import javax.el.ExpressionFactory; import javax.faces.FacesException; import javax.faces.FactoryFinder; import javax.faces.application.Application; import javax.faces.application.NavigationCase; import javax.faces.application.ViewHandler; import javax.faces.component.UIViewRoot; import javax.faces.component.search.SearchExpressionHandler; import javax.faces.component.search.SearchKeywordResolver; import javax.faces.context.ExternalContext; import javax.faces.context.FacesContext; import javax.faces.el.PropertyResolver; import javax.faces.el.VariableResolver; import javax.faces.event.PostConstructApplicationEvent; import javax.faces.event.PreDestroyCustomScopeEvent; import javax.faces.event.ScopeContext; import javax.faces.event.SystemEvent; import javax.faces.event.SystemEventListener; import javax.faces.flow.FlowHandler; import javax.faces.flow.FlowHandlerFactory; import javax.faces.view.facelets.FaceletCache; import javax.faces.view.facelets.FaceletCacheFactory; import javax.faces.view.facelets.FaceletsResourceResolver; import javax.faces.view.facelets.ResourceResolver; import javax.faces.view.facelets.TagDecorator; import javax.servlet.ServletContext; import com.sun.faces.RIConstants; import com.sun.faces.application.annotation.AnnotationManager; import com.sun.faces.application.annotation.FacesComponentUsage; import com.sun.faces.application.resource.ResourceCache; import com.sun.faces.application.resource.ResourceManager; import com.sun.faces.component.search.SearchExpressionHandlerImpl; import com.sun.faces.config.ConfigManager; import com.sun.faces.config.WebConfiguration; import com.sun.faces.el.DemuxCompositeELResolver; import com.sun.faces.el.FacesCompositeELResolver; import com.sun.faces.el.VariableResolverChainWrapper; import com.sun.faces.facelets.PrivateApiFaceletCacheAdapter; import com.sun.faces.facelets.compiler.Compiler; import com.sun.faces.facelets.compiler.SAXCompiler; import com.sun.faces.facelets.impl.DefaultFaceletFactory; import com.sun.faces.facelets.impl.DefaultResourceResolver; import com.sun.faces.facelets.tag.composite.CompositeLibrary; import com.sun.faces.facelets.tag.jsf.PassThroughAttributeLibrary; import com.sun.faces.facelets.tag.jsf.PassThroughElementLibrary; import com.sun.faces.facelets.tag.jsf.core.CoreLibrary; import com.sun.faces.facelets.tag.jsf.html.HtmlLibrary; import com.sun.faces.facelets.tag.jstl.core.JstlCoreLibrary; import com.sun.faces.facelets.tag.jstl.fn.JstlFunction; import com.sun.faces.facelets.tag.ui.UILibrary; import com.sun.faces.facelets.util.DevTools; import com.sun.faces.facelets.util.FunctionLibrary; import com.sun.faces.facelets.util.ReflectionUtil; import com.sun.faces.mgbean.BeanManager; import com.sun.faces.spi.InjectionProvider; import com.sun.faces.util.FacesLogger; /** * <p> * Break out the things that are associated with the Application, but need to be present even when * the user has replaced the Application instance. * </p> * <p/> * <p> * For example: the user replaces ApplicationFactory, and wants to intercept calls to * createValueExpression() and createMethodExpression() for certain kinds of expressions, but allow * the existing application to handle the rest. * </p> */ public class ApplicationAssociate { private static final Logger LOGGER = FacesLogger.APPLICATION.getLogger(); private ApplicationImpl app; /** * Overall Map containing <code>from-view-id</code> key and <code>Set</code> of * <code>NavigationCase</code> objects for that key; The <code>from-view-id</code> strings in * this map will be stored as specified in the configuration file - some of them will have a * trailing asterisk "*" signifying wild card, and some may be specified as an asterisk "*". */ private Map<String, Set<NavigationCase>> navigationMap; /* * The FacesComponentTagLibrary uses the information in this map to help it fabricate tag * handlers for components annotated with FacesComponent. Key: namespace */ private Map<String, List<FacesComponentUsage>> facesComponentsByNamespace; // Flag indicating that a response has been rendered. private boolean responseRendered; private static final String ASSOCIATE_KEY = RIConstants.FACES_PREFIX + "ApplicationAssociate"; private static ThreadLocal<ApplicationAssociate> instance = new ThreadLocal<ApplicationAssociate>() { @Override protected ApplicationAssociate initialValue() { return null; } }; private List<ELResolver> elResolversFromFacesConfig; private List<SearchKeywordResolver> searchKeywordResolversFromFacesConfig; @SuppressWarnings("deprecation") private VariableResolver legacyVRChainHead; private VariableResolverChainWrapper legacyVRChainHeadWrapperForJsp; private VariableResolverChainWrapper legacyVRChainHeadWrapperForFaces; @SuppressWarnings("deprecation") private PropertyResolver legacyPRChainHead; private ExpressionFactory expressionFactory; @SuppressWarnings("deprecation") private PropertyResolver legacyPropertyResolver; @SuppressWarnings("deprecation") private VariableResolver legacyVariableResolver; private FacesCompositeELResolver facesELResolverForJsp; private InjectionProvider injectionProvider; private ResourceCache resourceCache; private String contextName; private boolean requestServiced; private boolean errorPagePresent; private BeanManager beanManager; private AnnotationManager annotationManager; private boolean devModeEnabled; private Compiler compiler; private DefaultFaceletFactory faceletFactory; private ResourceManager resourceManager; private ApplicationStateInfo applicationStateInfo; private PropertyEditorHelper propertyEditorHelper; private NamedEventManager namedEventManager; private WebConfiguration webConfig; private FlowHandler flowHandler; private SearchExpressionHandler searchExpressionHandler; private Map<String, String> definingDocumentIdsToTruncatedJarUrls; private long timeOfInstantiation; private Map<String, List<String>> resourceLibraryContracts; Map<String, ApplicationResourceBundle> resourceBundles = new HashMap<>(); public ApplicationAssociate(ApplicationImpl appImpl) { app = appImpl; propertyEditorHelper = new PropertyEditorHelper(appImpl); FacesContext ctx = FacesContext.getCurrentInstance(); if (ctx == null) { throw new IllegalStateException("ApplicationAssociate ctor not called in same callstack as ConfigureListener.contextInitialized()"); } ExternalContext externalContext = ctx.getExternalContext(); if (externalContext.getApplicationMap().get(ASSOCIATE_KEY) != null) { throw new IllegalStateException(getExceptionMessageString(APPLICATION_ASSOCIATE_EXISTS_ID)); } Map<String, Object> appMap = externalContext.getApplicationMap(); appMap.put(ASSOCIATE_KEY, this); navigationMap = new ConcurrentHashMap<>(); injectionProvider = (InjectionProvider) ctx.getAttributes().get(ConfigManager.INJECTION_PROVIDER_KEY); webConfig = WebConfiguration.getInstance(externalContext); beanManager = new BeanManager(injectionProvider, webConfig.isOptionEnabled(EnableLazyBeanValidation)); // install the bean manager as a system event listener for custom // scopes being destoryed. app.subscribeToEvent(PreDestroyCustomScopeEvent.class, ScopeContext.class, beanManager); annotationManager = new AnnotationManager(); devModeEnabled = appImpl.getProjectStage() == Development; if (!devModeEnabled) { resourceCache = new ResourceCache(); } resourceManager = new ResourceManager(appMap, resourceCache); namedEventManager = new NamedEventManager(); applicationStateInfo = new ApplicationStateInfo(); appImpl.subscribeToEvent(PostConstructApplicationEvent.class, Application.class, new PostConstructApplicationListener()); definingDocumentIdsToTruncatedJarUrls = new ConcurrentHashMap<>(); timeOfInstantiation = System.currentTimeMillis(); } public Application getApplication() { return app; } public void setResourceLibraryContracts(Map<String, List<String>> map) { this.resourceLibraryContracts = map; } private class PostConstructApplicationListener implements SystemEventListener { @Override public boolean isListenerForSource(Object source) { return source instanceof Application; } @Override public void processEvent(SystemEvent event) { ApplicationAssociate.this.initializeFacelets(); if (ApplicationAssociate.this.flowHandler == null) { FlowHandlerFactory flowHandlerFactory = (FlowHandlerFactory) FactoryFinder.getFactory(FLOW_HANDLER_FACTORY); ApplicationAssociate.this.flowHandler = flowHandlerFactory.createFlowHandler(FacesContext.getCurrentInstance()); } if (ApplicationAssociate.this.searchExpressionHandler == null) { ApplicationAssociate.this.searchExpressionHandler = new SearchExpressionHandlerImpl(); } FacesContext context = FacesContext.getCurrentInstance(); if (isCdiAvailable(context)) { try { new JavaFlowLoaderHelper().loadFlows(context, ApplicationAssociate.this.flowHandler); } catch (IOException ex) { LOGGER.log(SEVERE, null, ex); } } // cause the Facelet VDL to be instantiated eagerly, so it can // become aware of the resource library contracts ViewHandler viewHandler = context.getApplication().getViewHandler(); // FindBugs: ignore the return value, this is just to get the // ctor called at this time. viewHandler.getViewDeclarationLanguage(context, FACES_PREFIX + "xhtml"); String facesConfigVersion = getFacesConfigXmlVersion(context); context.getExternalContext().getApplicationMap().put(FACES_CONFIG_VERSION, facesConfigVersion); } } public void initializeFacelets() { if (compiler != null) { return; } FacesContext ctx = FacesContext.getCurrentInstance(); if (!webConfig.isOptionEnabled(DisableFaceletJSFViewHandler) && !webConfig.isOptionEnabled(DisableFaceletJSFViewHandlerDeprecated)) { Map<String, Object> appMap = ctx.getExternalContext().getApplicationMap(); compiler = createCompiler(appMap, webConfig); faceletFactory = createFaceletFactory(ctx, compiler, webConfig); } } public static ApplicationAssociate getInstance(ExternalContext externalContext) { if (externalContext == null) { return null; } return (ApplicationAssociate) externalContext.getApplicationMap().get(ASSOCIATE_KEY); } public long getTimeOfInstantiation() { return timeOfInstantiation; } public static ApplicationAssociate getInstance(ServletContext context) { if (context == null) { return null; } return (ApplicationAssociate) context.getAttribute(ASSOCIATE_KEY); } public static void setCurrentInstance(ApplicationAssociate associate) { if (associate == null) { instance.remove(); } else { instance.set(associate); } } public static ApplicationAssociate getCurrentInstance() { ApplicationAssociate associate = instance.get(); if (associate == null) { // Fallback to ExternalContext lookup FacesContext facesContext = FacesContext.getCurrentInstance(); if (facesContext != null) { ExternalContext extContext = facesContext.getExternalContext(); if (extContext != null) { return ApplicationAssociate.getInstance(extContext); } } } return associate; } public ApplicationStateInfo getApplicationStateInfo() { return applicationStateInfo; } public ResourceManager getResourceManager() { return resourceManager; } // Return the resource library contracts and mappings from the // application configuration resources public Map<String, List<String>> getResourceLibraryContracts() { return resourceLibraryContracts; } public void setResourceManager(ResourceManager resourceManager) { this.resourceManager = resourceManager; } public ResourceCache getResourceCache() { return resourceCache; } public AnnotationManager getAnnotationManager() { return annotationManager; } public Compiler getCompiler() { if (compiler == null) { initializeFacelets(); } return compiler; } public boolean isErrorPagePresent() { return errorPagePresent; } public void setErrorPagePresent(boolean errorPagePresent) { this.errorPagePresent = errorPagePresent; } public DefaultFaceletFactory getFaceletFactory() { return faceletFactory; } public static void clearInstance(ExternalContext externalContext) { Map<String, Object> applicationMap = externalContext.getApplicationMap(); ApplicationAssociate me = (ApplicationAssociate) applicationMap.get(ASSOCIATE_KEY); if (me != null && me.resourceBundles != null) { me.resourceBundles.clear(); } applicationMap.remove(ASSOCIATE_KEY); } public static void clearInstance(ServletContext servletContext) { ApplicationAssociate me = (ApplicationAssociate) servletContext.getAttribute(ASSOCIATE_KEY); if (me != null && me.resourceBundles != null) { me.resourceBundles.clear(); } servletContext.removeAttribute(ASSOCIATE_KEY); } public BeanManager getBeanManager() { return beanManager; } public void initializeELResolverChains() { // 1. initialize the chains with default values if (app.getCompositeELResolver() == null) { app.setCompositeELResolver(new DemuxCompositeELResolver(Faces)); buildFacesResolver(app.getCompositeELResolver(), this); populateFacesELResolverForJsp(app, this); } } public void installProgrammaticallyAddedResolvers() { // Ensure custom resolvers are inserted at the correct place. VariableResolver variableResolver = this.getLegacyVariableResolver(); if (variableResolver != null) { getLegacyVRChainHeadWrapperForJsp().setWrapped(variableResolver); getLegacyVRChainHeadWrapperForFaces().setWrapped(variableResolver); } } public boolean isDevModeEnabled() { return devModeEnabled; } /** * Obtain the PropertyEditorHelper instance for this app. * * @return The PropertyEditorHeler instance for this app. */ public PropertyEditorHelper getPropertyEditorHelper() { return propertyEditorHelper; } /** * This method is called by <code>ConfigureListener</code> and will contain any * <code>VariableResolvers</code> defined within faces-config configuration files. * * @param resolver VariableResolver */ @SuppressWarnings("deprecation") public void setLegacyVRChainHead(VariableResolver resolver) { this.legacyVRChainHead = resolver; } @SuppressWarnings("deprecation") public VariableResolver getLegacyVRChainHead() { return legacyVRChainHead; } public VariableResolverChainWrapper getLegacyVRChainHeadWrapperForJsp() { return legacyVRChainHeadWrapperForJsp; } public void setLegacyVRChainHeadWrapperForJsp(VariableResolverChainWrapper legacyVRChainHeadWrapper) { this.legacyVRChainHeadWrapperForJsp = legacyVRChainHeadWrapper; } public VariableResolverChainWrapper getLegacyVRChainHeadWrapperForFaces() { return legacyVRChainHeadWrapperForFaces; } public void setLegacyVRChainHeadWrapperForFaces(VariableResolverChainWrapper legacyVRChainHeadWrapperForFaces) { this.legacyVRChainHeadWrapperForFaces = legacyVRChainHeadWrapperForFaces; } /** * This method is called by <code>ConfigureListener</code> and will contain any * <code>PropertyResolvers</code> defined within faces-config configuration files. * * @param resolver PropertyResolver */ @SuppressWarnings("deprecation") public void setLegacyPRChainHead(PropertyResolver resolver) { this.legacyPRChainHead = resolver; } @SuppressWarnings("deprecation") public PropertyResolver getLegacyPRChainHead() { return legacyPRChainHead; } public FacesCompositeELResolver getFacesELResolverForJsp() { return facesELResolverForJsp; } public FlowHandler getFlowHandler() { return flowHandler; } public void setFlowHandler(FlowHandler flowHandler) { this.flowHandler = flowHandler; } public SearchExpressionHandler getSearchExpressionHandler() { return searchExpressionHandler; } public void setSearchExpressionHandler(SearchExpressionHandler searchExpressionHandler) { this.searchExpressionHandler = searchExpressionHandler; } public void setFacesELResolverForJsp(FacesCompositeELResolver celr) { facesELResolverForJsp = celr; } public void setELResolversFromFacesConfig(List<ELResolver> resolvers) { this.elResolversFromFacesConfig = resolvers; } public List<ELResolver> getELResolversFromFacesConfig() { return elResolversFromFacesConfig; } public void setSearchKeywordResolversFromFacesConfig(List<SearchKeywordResolver> searchKeywordResolversFromFacesConfig) { this.searchKeywordResolversFromFacesConfig = searchKeywordResolversFromFacesConfig; } public List<SearchKeywordResolver> getSearchKeywordResolversFromFacesConfig() { return searchKeywordResolversFromFacesConfig; } public void setExpressionFactory(ExpressionFactory expressionFactory) { this.expressionFactory = expressionFactory; } public ExpressionFactory getExpressionFactory() { return this.expressionFactory; } public CompositeELResolver getApplicationELResolvers() { return app.getApplicationELResolvers(); } public InjectionProvider getInjectionProvider() { return injectionProvider; } public void setContextName(String contextName) { this.contextName = contextName; } public String getContextName() { return contextName; } /** * Maintains the PropertyResolver called through Application.setPropertyResolver() * * @param resolver PropertyResolver */ @SuppressWarnings("deprecation") public void setLegacyPropertyResolver(PropertyResolver resolver) { this.legacyPropertyResolver = resolver; } /** * @return the PropertyResolver called through Application.getPropertyResolver() */ @SuppressWarnings("deprecation") public PropertyResolver getLegacyPropertyResolver() { return legacyPropertyResolver; } /** * Maintains the PropertyResolver called through Application.setVariableResolver() * * @param resolver VariableResolver */ @SuppressWarnings("deprecation") public void setLegacyVariableResolver(VariableResolver resolver) { this.legacyVariableResolver = resolver; } /** * @return the VariableResolver called through Application.getVariableResolver() */ @SuppressWarnings("deprecation") public VariableResolver getLegacyVariableResolver() { return legacyVariableResolver; } /** * Called by application code to indicate we've processed the first request to the application. */ public void setRequestServiced() { this.requestServiced = true; } /** * @return <code>true</code> if we've processed a request, otherwise <code>false</code> */ public boolean hasRequestBeenServiced() { return requestServiced; } public void addFacesComponent(FacesComponentUsage facesComponentUsage) { if (facesComponentsByNamespace == null) { facesComponentsByNamespace = new HashMap<>(); } facesComponentsByNamespace.computeIfAbsent(facesComponentUsage.getAnnotation().namespace(), k -> new ArrayList<>()).add(facesComponentUsage); } public List<FacesComponentUsage> getComponentsForNamespace(String namespace) { if (facesComponentsByNamespace != null && facesComponentsByNamespace.containsKey(namespace)) { return facesComponentsByNamespace.get(namespace); } return emptyList(); } /** * Add a navigation case to the internal case set. If a case set does not already exist in the * case list map containing this case (identified by <code>from-view-id</code>), start a new * list, add the case to it, and store the set in the case set map. If a case set already * exists, overwrite the previous case. * * @param navigationCase the navigation case containing navigation mapping information from the * configuration file. */ public void addNavigationCase(NavigationCase navigationCase) { // If there already is a case existing for the fromviewid/fromaction.fromoutcome // combination, // replace it ... (last one wins). navigationMap.computeIfAbsent(navigationCase.getFromViewId(), k -> new LinkedHashSet<>()).add(navigationCase); } public NamedEventManager getNamedEventManager() { return namedEventManager; } /** * Return a <code>Map</code> of navigation mappings loaded from the configuration system. The * key for the returned <code>Map</code> is <code>from-view-id</code>, and the value is a * <code>List</code> of navigation cases. * * @return Map the map of navigation mappings. */ public Map<String, Set<NavigationCase>> getNavigationCaseListMappings() { if (navigationMap == null) { return emptyMap(); } return navigationMap; } public ResourceBundle getResourceBundle(FacesContext context, String var) { ApplicationResourceBundle bundle = resourceBundles.get(var); if (bundle == null) { return null; } // Start out with the default locale Locale defaultLocale = Locale.getDefault(); Locale locale = defaultLocale; // See if this FacesContext has a ViewRoot UIViewRoot root = context.getViewRoot(); if (root != null) { locale = root.getLocale(); if (locale == null) { // If the ViewRoot has no Locale, fall back to the default. locale = defaultLocale; } } return bundle.getResourceBundle(locale); } /** * keys: <var> element from faces-config * <p> * <p/> * values: ResourceBundleBean instances. */ public void addResourceBundle(String var, ApplicationResourceBundle bundle) { resourceBundles.put(var, bundle); } public Map<String, ApplicationResourceBundle> getResourceBundles() { return resourceBundles; } // This is called by ViewHandlerImpl.renderView(). public void responseRendered() { responseRendered = true; } public boolean isResponseRendered() { return responseRendered; } public boolean urlIsRelatedToDefiningDocumentInJar(URL candidateUrl, String definingDocumentId) { boolean result = false; String match = definingDocumentIdsToTruncatedJarUrls.get(definingDocumentId); if (match != null) { String candidate = candidateUrl.toExternalForm(); if (candidate != null) { int i = candidate.lastIndexOf("/META-INF"); if (i == -1) { throw new FacesException("Invalid url for application configuration resources file with respect to faces flows"); } candidate = candidate.substring(0, i); result = candidate.equals(match); } } return result; } public void relateUrlToDefiningDocumentInJar(URL url, String definingDocumentId) { String candidate = url.toExternalForm(); int i = candidate.lastIndexOf("/META-INF"); if (i == -1) { return; } candidate = candidate.substring(0, i); definingDocumentIdsToTruncatedJarUrls.put(definingDocumentId, candidate); } protected DefaultFaceletFactory createFaceletFactory(FacesContext ctx, Compiler compiler, WebConfiguration webConfig) { // refresh period boolean isProduction = app.getProjectStage() == Production; String refreshPeriod; if (webConfig.isSet(FaceletsDefaultRefreshPeriod) || webConfig.isSet(FaceletsDefaultRefreshPeriodDeprecated)) { refreshPeriod = webConfig.getOptionValue(FaceletsDefaultRefreshPeriod); } else if (isProduction) { refreshPeriod = "-1"; } else { refreshPeriod = FaceletsDefaultRefreshPeriod.getDefaultValue(); } long period = parseLong(refreshPeriod); // resource resolver ResourceResolver defaultResourceResolver = new DefaultResourceResolver(app.getResourceHandler()); ResourceResolver resolver = defaultResourceResolver; String resolverName = webConfig.getOptionValue(FaceletsResourceResolver); if (resolverName != null && resolverName.length() > 0) { resolver = (ResourceResolver) ReflectionUtil.decorateInstance(resolverName, ResourceResolver.class, resolver); } else { Set<? extends Class<?>> resourceResolvers = getAnnotatedClasses(ctx).get(FaceletsResourceResolver.class); if ((null != resourceResolvers) && !resourceResolvers.isEmpty()) { Class<?> resolverClass = resourceResolvers.iterator().next(); if (resourceResolvers.size() > 1 && LOGGER.isLoggable(SEVERE)) { LOGGER.log(SEVERE, "Found more than one class " + "annotated with FaceletsResourceResolver. Will " + "use {0} and ignore the others", resolverClass); } resolver = (ResourceResolver) decorateInstance(resolverClass, ResourceResolver.class, resolver); } } // If our resourceResolver is not the one we created above // and the use of this ResousrecResolver for Composite Components // is acceptable. if (resolver != defaultResourceResolver && webConfig.isOptionEnabled(EnableFaceletsResourceResolverResolveCompositeComponents)) { ctx.getExternalContext().getApplicationMap().put(NON_DEFAULT_RESOURCE_RESOLVER_PARAM_NAME, resolver); } FaceletCache cache = null; String faceletCacheName = webConfig.getOptionValue(FaceletCache); if (faceletCacheName != null && faceletCacheName.length() > 0) { try { com.sun.faces.facelets.FaceletCache privateApiCache = (com.sun.faces.facelets.FaceletCache) ReflectionUtil.forName(faceletCacheName) .newInstance(); cache = new PrivateApiFaceletCacheAdapter(privateApiCache); } catch (ClassCastException e) { if (LOGGER.isLoggable(INFO)) { LOGGER.log(INFO, "Please remove context-param when using javax.faces.view.facelets.FaceletCache class with name:" + faceletCacheName + "and use the new FaceletCacheFactory API", e); } } catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) { if (LOGGER.isLoggable(SEVERE)) { LOGGER.log(SEVERE, "Error Loading Facelet cache: " + faceletCacheName, e); } } } if (cache == null) { FaceletCacheFactory cacheFactory = (FaceletCacheFactory) FactoryFinder.getFactory(FACELET_CACHE_FACTORY); cache = cacheFactory.getFaceletCache(); } DefaultFaceletFactory toReturn = new DefaultFaceletFactory(); toReturn.init(compiler, resolver, period, cache); return toReturn; } protected Compiler createCompiler(Map<String, Object> appMap, WebConfiguration webConfig) { Compiler newCompiler = new SAXCompiler(); loadDecorators(appMap, newCompiler); // Skip params? newCompiler.setTrimmingComments(webConfig.isOptionEnabled(FaceletsSkipComments)); addTagLibraries(newCompiler); return newCompiler; } protected void loadDecorators(Map<String, Object> appMap, Compiler newCompiler) { String decoratorsParamValue = webConfig.getOptionValue(FaceletsDecorators); if (decoratorsParamValue != null) { for (String decorator : split(appMap, decoratorsParamValue.trim(), ";")) { try { newCompiler.addTagDecorator((TagDecorator) forName(decorator).newInstance()); if (LOGGER.isLoggable(FINE)) { LOGGER.log(FINE, "Successfully Loaded Decorator: {0}", decorator); } } catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) { if (LOGGER.isLoggable(SEVERE)) { LOGGER.log(SEVERE, "Error Loading Decorator: " + decorator, e); } } } } } protected void addTagLibraries(Compiler newCompiler) { newCompiler.addTagLibrary(new CoreLibrary()); newCompiler.addTagLibrary(new CoreLibrary(CoreLibrary.XMLNSNamespace)); newCompiler.addTagLibrary(new HtmlLibrary()); newCompiler.addTagLibrary(new HtmlLibrary(HtmlLibrary.XMLNSNamespace)); newCompiler.addTagLibrary(new UILibrary()); newCompiler.addTagLibrary(new UILibrary(UILibrary.XMLNSNamespace)); newCompiler.addTagLibrary(new JstlCoreLibrary()); newCompiler.addTagLibrary(new JstlCoreLibrary(JstlCoreLibrary.IncorrectNamespace)); newCompiler.addTagLibrary(new JstlCoreLibrary(JstlCoreLibrary.XMLNSNamespace)); newCompiler.addTagLibrary(new PassThroughAttributeLibrary()); newCompiler.addTagLibrary(new PassThroughElementLibrary()); newCompiler.addTagLibrary(new FunctionLibrary(JstlFunction.class, FunctionLibrary.Namespace)); newCompiler.addTagLibrary(new FunctionLibrary(JstlFunction.class, FunctionLibrary.XMLNSNamespace)); if (isDevModeEnabled()) { newCompiler.addTagLibrary(new FunctionLibrary(DevTools.class, DevTools.Namespace)); newCompiler.addTagLibrary(new FunctionLibrary(DevTools.class, DevTools.NewNamespace)); } newCompiler.addTagLibrary(new CompositeLibrary()); newCompiler.addTagLibrary(new CompositeLibrary(CompositeLibrary.XMLNSNamespace)); } }