javax.faces.FactoryFinderInstance Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jboss-jsf-api_2.3_spec Show documentation
Show all versions of jboss-jsf-api_2.3_spec Show documentation
JSR-000372: JavaServer(TM) Faces 2.3 API
/*
* Copyright (c) 1997, 2018 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 javax.faces;
import static com.sun.faces.util.Util.generateCreatedBy;
import static com.sun.faces.util.Util.getContextClassLoader2;
import static com.sun.faces.util.Util.isAnyNull;
import static com.sun.faces.util.Util.isOneOf;
import static java.text.MessageFormat.format;
import static java.util.Collections.binarySearch;
import static java.util.Collections.unmodifiableMap;
import static java.util.logging.Level.SEVERE;
import static javax.faces.FactoryFinder.APPLICATION_FACTORY;
import static javax.faces.FactoryFinder.CLIENT_WINDOW_FACTORY;
import static javax.faces.FactoryFinder.EXCEPTION_HANDLER_FACTORY;
import static javax.faces.FactoryFinder.EXTERNAL_CONTEXT_FACTORY;
import static javax.faces.FactoryFinder.FACELET_CACHE_FACTORY;
import static javax.faces.FactoryFinder.FACES_CONTEXT_FACTORY;
import static javax.faces.FactoryFinder.FACTORIES_CACHE;
import static javax.faces.FactoryFinder.FLASH_FACTORY;
import static javax.faces.FactoryFinder.FLOW_HANDLER_FACTORY;
import static javax.faces.FactoryFinder.LIFECYCLE_FACTORY;
import static javax.faces.FactoryFinder.PARTIAL_VIEW_CONTEXT_FACTORY;
import static javax.faces.FactoryFinder.RENDER_KIT_FACTORY;
import static javax.faces.FactoryFinder.SEARCH_EXPRESSION_CONTEXT_FACTORY;
import static javax.faces.FactoryFinder.TAG_HANDLER_DELEGATE_FACTORY;
import static javax.faces.FactoryFinder.VIEW_DECLARATION_LANGUAGE_FACTORY;
import static javax.faces.FactoryFinder.VISIT_CONTEXT_FACTORY;
import static javax.faces.ServletContextFacesContextFactory.SERVLET_CONTEXT_FINDER_NAME;
import static javax.faces.ServletContextFacesContextFactory.SERVLET_CONTEXT_FINDER_REMOVAL_NAME;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.InvocationTargetException;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.logging.Logger;
import javax.faces.context.FacesContext;
import javax.servlet.ServletContext;
import com.sun.faces.config.ConfigManager;
import com.sun.faces.config.WebConfiguration;
import com.sun.faces.spi.InjectionProvider;
final class FactoryFinderInstance {
private static final Logger LOGGER = Logger.getLogger("javax.faces", "javax.faces.LogStrings");
private static final String INJECTION_PROVIDER_KEY = FactoryFinder.class.getPackage().getName() + "INJECTION_PROVIDER_KEY";
private final Map factories = new ConcurrentHashMap<>();
private final Map> savedFactoryNames = new ConcurrentHashMap<>();
private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(true);
private final String createdBy;
private ServletContextFacesContextFactory servletContextFinder = new ServletContextFacesContextFactory();
/**
*
* The set of Jakarta Server Faces factory classes for which the factory discovery mechanism is
* supported. The entries in this list must be alphabetically ordered according to the entire
* string of the *value* of each of the literals, not just the last part of the literal!
*
*/
private final List factoryNames = asSortedList(
APPLICATION_FACTORY,
VISIT_CONTEXT_FACTORY,
EXCEPTION_HANDLER_FACTORY,
EXTERNAL_CONTEXT_FACTORY,
FACES_CONTEXT_FACTORY,
FLASH_FACTORY,
FLOW_HANDLER_FACTORY,
PARTIAL_VIEW_CONTEXT_FACTORY,
CLIENT_WINDOW_FACTORY,
LIFECYCLE_FACTORY,
RENDER_KIT_FACTORY,
VIEW_DECLARATION_LANGUAGE_FACTORY,
FACELET_CACHE_FACTORY,
TAG_HANDLER_DELEGATE_FACTORY,
SEARCH_EXPRESSION_CONTEXT_FACTORY);
/**
*
* Map of Class instances for our factory names.
*
*/
private final Map> factoryClasses = buildFactoryClassesMap();
// -------------------------------------------------------- Constructors
FactoryFinderInstance(FacesContext facesContext) {
for (String name : factoryNames) {
factories.put(name, new ArrayList<>(4)); // NOPMD
}
copyInjectionProviderFromFacesContext(facesContext);
createdBy = generateCreatedBy(facesContext);
}
FactoryFinderInstance(FacesContext facesContext, FactoryFinderInstance toCopy) {
factories.putAll(toCopy.savedFactoryNames);
copyInjectionProviderFromFacesContext(facesContext);
createdBy = generateCreatedBy(facesContext);
}
@Override
public String toString() {
return super.toString() + " created by" + createdBy;
}
// ------------------------------------------------------ Package Private Methods
void addFactory(String factoryName, String implementationClassName) {
validateFactoryName(factoryName);
Object result = factories.get(factoryName);
lock.writeLock().lock();
try {
if (result instanceof List) {
TypedCollections.dynamicallyCastList((List>) result, String.class).add(0, implementationClassName);
}
} finally {
lock.writeLock().unlock();
}
}
@SuppressWarnings("unchecked")
Object getFactory(String factoryName) {
validateFactoryName(factoryName);
if (factoryName.equals(SERVLET_CONTEXT_FINDER_NAME)) {
return servletContextFinder;
}
if (factoryName.equals(SERVLET_CONTEXT_FINDER_REMOVAL_NAME)) {
try {
lock.writeLock().lock();
servletContextFinder = null;
return null;
} finally {
lock.writeLock().unlock();
}
}
Object factoryOrList;
lock.readLock().lock();
try {
factoryOrList = factories.get(factoryName);
if (!(factoryOrList instanceof List)) {
return factoryOrList;
}
} finally {
lock.readLock().unlock();
}
// Factory hasn't been constructed
lock.writeLock().lock();
try {
// Double check the current value. Another thread
// may have completed the initialization by the time
// this thread entered this block
factoryOrList = factories.get(factoryName);
if (!(factoryOrList instanceof List)) {
return factoryOrList;
}
savedFactoryNames.put(factoryName, new ArrayList((List) factoryOrList));
Object factory = getImplementationInstance(getContextClassLoader2(), factoryName, (List) factoryOrList);
if (factory == null) {
logNoFactory(factoryName);
factory = FACTORIES_CACHE.getFallbackFactory(this, factoryName);
notNullFactory(factoryName, factory);
}
// Record and return the new instance
factories.put(factoryName, factory);
return factory;
} finally {
lock.writeLock().unlock();
}
}
InjectionProvider getInjectionProvider() {
return (InjectionProvider) factories.get(INJECTION_PROVIDER_KEY);
}
void clearInjectionProvider() {
factories.remove(INJECTION_PROVIDER_KEY);
}
void releaseFactories() {
InjectionProvider provider = getInjectionProvider();
if (provider != null) {
lock.writeLock().lock();
try {
for (Entry entry : factories.entrySet()) {
Object curFactory = entry.getValue();
// If the current entry is not the injectionProvider itself
// and the current entry has a non-null value
// and the value is not a string...
if (!INJECTION_PROVIDER_KEY.equals(entry.getKey()) && curFactory != null && !(curFactory instanceof String)) {
try {
provider.invokePreDestroy(curFactory);
} catch (Exception ex) {
logPreDestroyFail(entry.getValue(), ex);
}
}
}
} finally {
factories.clear();
lock.writeLock().unlock();
}
} else {
FacesContext facesContext = FacesContext.getCurrentInstance();
if (facesContext != null && WebConfiguration.getInstanceWithoutCreating((ServletContext) facesContext.getExternalContext().getContext()) != null) {
LOGGER.log(SEVERE,
"Unable to obtain InjectionProvider from init time FacesContext. Does this container implement the Mojarra Injection SPI?");
}
}
}
Collection