/* * 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.dev.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 javax.faces; /** * <p><strong class="changed_modified_2_0 changed_modified_2_1 changed_modified_2_2">FactoryFinder</strong> * implements the standard discovery algorithm for all factory objects * specified in the JavaServer Faces APIs. For a given factory class * name, a corresponding implementation class is searched for based on * the following algorithm. Items are listed in order of decreasing * search precedence:</p> * <ul> * <li><p>If the JavaServer Faces configuration file bundled into the * <code>WEB-INF</code> directory of the webapp contains a * <code>factory</code> entry of the given factory class name, that * factory is used.<p></li> * <li><p>If the JavaServer Faces configuration files named by the * <code>javax.faces.CONFIG_FILES</code> <code>ServletContext</code> init * parameter contain any <code>factory</code> entries of the given * factory class name, those injectionProvider are used, with the last one taking * precedence.</p></li> * <li><p>If there are any JavaServer Faces configuration files bundled * into the <code>META-INF</code> directory of any jars on the * <code>ServletContext</code>'s resource paths, the * <code>factory</code> entries of the given factory class name in those * files are used, with the last one taking precedence.</p></li> * <li><p>If a <code>META-INF/services/{factory-class-name}</code> * resource is visible to the web application class loader for the * calling application (typically as a injectionProvider of being present in the * manifest of a JAR file), its first line is read and assumed to be the * name of the factory implementation class to use.</p></li> * <li><p>If none of the above steps yield a match, the JavaServer Faces * implementation specific class is used.</p></li> * </ul> * <p>If any of the injectionProvider found on any of the steps above happen to * have a one-argument constructor, with argument the type being the * abstract factory class, that constructor is invoked, and the previous * match is passed to the constructor. For example, say the container * vendor provided an implementation of {@link * javax.faces.context.FacesContextFactory}, and identified it in * <code>META-INF/services/javax.faces.context.FacesContextFactory</code> * in a jar on the webapp ClassLoader. Also say this implementation * provided by the container vendor had a one argument constructor that * took a <code>FacesContextFactory</code> instance. The * <code>FactoryFinder</code> system would call that one-argument * constructor, passing the implementation of * <code>FacesContextFactory</code> provided by the JavaServer Faces * implementation.</p> * <p>If a Factory implementation does not provide a proper one-argument * constructor, it must provide a zero-arguments constructor in order to * be successfully instantiated.</p> * <p>Once the name of the factory implementation class is located, the * web application class loader for the calling application is requested * to load this class, and a corresponding instance of the class will be * created. A side effect of this rule is that each web application * will receive its own instance of each factory class, whether the * JavaServer Faces implementation is included within the web * application or is made visible through the container's facilities for * shared libraries.</p> */ public final class FactoryFinder { // ----------------------------------------------------------- Constructors /** * Package-private constructor to disable instantiation of this class. */ FactoryFinder() { } // ----------------------------------------------------- Manifest Constants /** * <p>The property name for the * {@link javax.faces.application.ApplicationFactory} class name.</p> */ public final static String APPLICATION_FACTORY = "javax.faces.application.ApplicationFactory"; /** * <p>The property name for the * {@link javax.faces.lifecycle.ClientWindowFactory} class name.</p> * @since 2.2 */ public final static String CLIENT_WINDOW_FACTORY = "javax.faces.lifecycle.ClientWindowFactory"; /** * <p class="changed_added_2_0">The property name for the {@link * javax.faces.context.ExceptionHandlerFactory} class name.</p> */ public final static String EXCEPTION_HANDLER_FACTORY = "javax.faces.context.ExceptionHandlerFactory"; /** * <p class="changed_added_2_0">The property name for the {@link * javax.faces.context.ExternalContextFactory} class name.</p> */ public final static String EXTERNAL_CONTEXT_FACTORY = "javax.faces.context.ExternalContextFactory"; /** * <p>The property name for the * {@link javax.faces.context.FacesContextFactory} class name.</p> */ public final static String FACES_CONTEXT_FACTORY = "javax.faces.context.FacesContextFactory"; /** * <p class="changed_added_2_1">The property name for the * {@link javax.faces.view.facelets.FaceletCacheFactory} class name.</p> * * @since 2.1 */ public final static String FACELET_CACHE_FACTORY = "javax.faces.view.facelets.FaceletCacheFactory"; /** * <p class="changed_added_2_2">The property name for the * {@link javax.faces.context.FlashFactory} class name.</p> * * @since 2.2 */ public final static String FLASH_FACTORY = "javax.faces.context.FlashFactory"; /** * <p class="changed_added_2_2">The property name for the * {@link javax.faces.flow.FlowHandlerFactory} class name.</p> * * @since 2.2 */ public final static String FLOW_HANDLER_FACTORY = "javax.faces.flow.FlowHandlerFactory"; /** * <p class="changed_added_2_0">The property name for the {@link * javax.faces.context.PartialViewContextFactory} class name.</p> */ public final static String PARTIAL_VIEW_CONTEXT_FACTORY = "javax.faces.context.PartialViewContextFactory"; /** * <p class="changed_added_2_0">The property name for the {@link * javax.faces.component.visit.VisitContextFactory} class name.</p> */ public final static String VISIT_CONTEXT_FACTORY = "javax.faces.component.visit.VisitContextFactory"; /** * <p>The property name for the * {@link javax.faces.lifecycle.LifecycleFactory} class name.</p> */ public final static String LIFECYCLE_FACTORY = "javax.faces.lifecycle.LifecycleFactory"; /** * <p>The property name for the * {@link javax.faces.render.RenderKitFactory} class name.</p> */ public final static String RENDER_KIT_FACTORY = "javax.faces.render.RenderKitFactory"; /** * <p class="changed_added_2_0">The property name for the {@link * javax.faces.view.ViewDeclarationLanguage} class name.</p> */ public final static String VIEW_DECLARATION_LANGUAGE_FACTORY = "javax.faces.view.ViewDeclarationLanguageFactory"; /** * <p class="changed_added_2_0">The property name for the {@link * javax.faces.view.facelets.TagHandlerDelegate} class name.</p> */ public final static String TAG_HANDLER_DELEGATE_FACTORY = "javax.faces.view.facelets.TagHandlerDelegateFactory"; // ------------------------------------------------------- Static Variables static final CurrentThreadToServletContext FACTORIES_CACHE; static { FACTORIES_CACHE = new CurrentThreadToServletContext(); } // --------------------------------------------------------- Public Methods /** * <p><span class="changed_modified_2_0">Create</span> (if * necessary) and return a per-web-application instance of the * appropriate implementation class for the specified JavaServer * Faces factory class, based on the discovery algorithm described * in the class description.</p> * * <p class="changed_added_2_0">The standard injectionProvider and wrappers * in JSF all implement the interface {@link FacesWrapper}. If the * returned <code>Object</code> is an implementation of one of the * standard injectionProvider, it must be legal to cast it to an instance of * <code>FacesWrapper</code> and call {@link * FacesWrapper#getWrapped} on the instance.</p> * * @param factoryName Fully qualified name of the JavaServer Faces factory * for which an implementation instance is requested * @throws FacesException if the web application class loader * cannot be identified * @throws FacesException if an instance of the configured factory * implementation class cannot be loaded * @throws FacesException if an instance of the configured factory * implementation class cannot be instantiated * @throws IllegalArgumentException if <code>factoryName</code> does not * identify a standard JavaServer Faces factory name * @throws IllegalStateException if there is no configured factory * implementation class for the specified factory name * @throws NullPointerException if <code>factoryname</code> * is null */ public static Object getFactory(String factoryName) throws FacesException { FactoryFinderInstance manager; // Bug 20458755: If the factory being requested is the special // SERVLET_CONTEXT_FINDER, do not lazily create the FactoryFinderInstance. if (null != factoryName && factoryName.equals(ServletContextFacesContextFactory.SERVLET_CONTEXT_FINDER_NAME)) { manager = FACTORIES_CACHE.getApplicationFactoryManager(false); } else { manager = FACTORIES_CACHE.getApplicationFactoryManager(); } Object result = null; if (null != manager) { result = manager.getFactory(factoryName); } return result; } /** * <p>This method will store the argument * <code>factoryName/implName</code> mapping in such a way that * {@link #getFactory} will find this mapping when searching for a * match.</p> * <p/> * <p>This method has no effect if <code>getFactory()</code> has * already been called looking for a factory for this * <code>factoryName</code>.</p> * <p/> * <p>This method can be used by implementations to store a factory * mapping while parsing the Faces configuration file</p> * * @throws IllegalArgumentException if <code>factoryName</code> does not * identify a standard JavaServer Faces factory name * @throws NullPointerException if <code>factoryname</code> * is null */ public static void setFactory(String factoryName, String implName) { FactoryFinderInstance manager = FACTORIES_CACHE.getApplicationFactoryManager(); manager.addFactory(factoryName, implName); } /** * <p><span class="changed_modified_2_0">Release</span> any * references to factory instances associated with the class loader * for the calling web application. <span * class="changed_modified_2_0">This method must be called during of * web application shutdown.</span></p> * * @throws FacesException if the web application class loader * cannot be identified */ public static void releaseFactories() throws FacesException { synchronized(FACTORIES_CACHE) { if (!FACTORIES_CACHE.applicationMap.isEmpty()) { FactoryFinderInstance fm = FACTORIES_CACHE.getApplicationFactoryManager(); fm.releaseFactories(); } FACTORIES_CACHE.removeApplicationFactoryManager(); } } // -------------------------------------------------------- Private Methods // Called via reflection from automated tests. private static void reInitializeFactoryManager() { FACTORIES_CACHE.resetSpecialInitializationCaseFlags(); } }