public final class FactoryFinder
extends java.lang.Object
FactoryFinder 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:
If the JavaServer Faces configuration file bundled into the
WEB-INF
directory of the webapp contains a
factory
entry of the given factory class name, that
factory is used.
If the JavaServer Faces configuration files named by the
javax.faces.CONFIG_FILES
ServletContext
init
parameter contain any factory
entries of the given
factory class name, those result are used, with the last one taking
precedence.
If there are any JavaServer Faces configuration files bundled
into the META-INF
directory of any jars on the
ServletContext
's resource paths, the
factory
entries of the given factory class name in those
files are used, with the last one taking precedence.
If a META-INF/services/{factory-class-name}
resource is visible to the web application class loader for the
calling application (typically as a result 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.
If none of the above steps yield a match, the JavaServer Faces implementation specific class is used.
If any of the result 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 FacesContextFactory
, and identified it in
META-INF/services/javax.faces.context.FacesContextFactory
in a jar on the webapp ClassLoader. Also say this implementation
provided by the container vendor had a one argument constructor that
took a FacesContextFactory
instance. The
FactoryFinder
system would call that one-argument
constructor, passing the implementation of
FacesContextFactory
provided by the JavaServer Faces
implementation.
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.
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.
Modifier and Type | Class and Description |
---|---|
private static class |
FactoryFinder.FactoryManager
Maintains the result for a single web application.
|
private static class |
FactoryFinder.FactoryManagerCache
Managed the mappings between a web application and its configured
result.
|
private static class |
FactoryFinder.FactoryManagerCacheKey |
Modifier and Type | Field and Description |
---|---|
static java.lang.String |
APPLICATION_FACTORY
The property name for the
ApplicationFactory class name. |
static java.lang.String |
EXCEPTION_HANDLER_FACTORY
The property name for the |
static java.lang.String |
EXTERNAL_CONTEXT_FACTORY
The property name for the |
static java.lang.String |
FACELET_CACHE_FACTORY
The property name for the
|
static java.lang.String |
FACES_CONTEXT_FACTORY
The property name for the
FacesContextFactory class name. |
private static FactoryFinder.FactoryManagerCache |
FACTORIES_CACHE |
private static java.lang.String[] |
FACTORY_NAMES
The set of JavaServer Faces factory classes for which the factory
discovery mechanism is supported.
|
private static java.util.Map<java.lang.String,java.lang.Class> |
factoryClasses
Map of Class instances for the our factory names.
|
static java.lang.String |
LIFECYCLE_FACTORY
The property name for the
LifecycleFactory class name. |
private static java.util.logging.Logger |
LOGGER |
static java.lang.String |
PARTIAL_VIEW_CONTEXT_FACTORY
The property name for the |
static java.lang.String |
RENDER_KIT_FACTORY
The property name for the
RenderKitFactory class name. |
static java.lang.String |
TAG_HANDLER_DELEGATE_FACTORY
The property name for the |
static java.lang.String |
VIEW_DECLARATION_LANGUAGE_FACTORY
The property name for the |
static java.lang.String |
VISIT_CONTEXT_FACTORY
The property name for the |
Constructor and Description |
---|
FactoryFinder()
Package-private constructor to disable instantiation of this class.
|
Modifier and Type | Method and Description |
---|---|
private static java.lang.ClassLoader |
getClassLoader()
Identify and return the class loader that is associated with the
calling web application.
|
static java.lang.Object |
getFactory(java.lang.String factoryName)
Create (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.
|
private static java.lang.Class |
getFactoryClass(java.lang.String factoryClassName) |
private static java.lang.Object |
getImplementationInstance(java.lang.ClassLoader classLoader,
java.lang.String factoryName,
java.util.List implementations)
Load and return an instance of the specified implementation
class using the following algorithm.
|
private static java.lang.Object |
getImplGivenPreviousImpl(java.lang.ClassLoader classLoader,
java.lang.String factoryName,
java.lang.String implName,
java.lang.Object previousImpl)
Implement the decorator pattern for the factory
implementation.
|
private static java.util.List<java.lang.String> |
getImplNameFromServices(java.lang.ClassLoader classLoader,
java.lang.String factoryName)
Perform the logic to get the implementation class for the
second step of
getImplementationInstance(ClassLoader, String, java.util.List) . |
private static void |
reInitializeFactoryManager() |
static void |
releaseFactories()
Release any
references to factory instances associated with the class loader
for the calling web application.
|
static void |
setFactory(java.lang.String factoryName,
java.lang.String implName)
This method will store the argument
factoryName/implName mapping in such a way that
getFactory(java.lang.String) will find this mapping when searching for a
match. |
private static void |
validateFactoryName(java.lang.String factoryName)
Ensure the provided factory name is valid.
|
public static final java.lang.String APPLICATION_FACTORY
The property name for the
ApplicationFactory
class name.
public static final java.lang.String EXCEPTION_HANDLER_FACTORY
The property name for the ExceptionHandlerFactory
class name.
public static final java.lang.String EXTERNAL_CONTEXT_FACTORY
The property name for the ExternalContextFactory
class name.
public static final java.lang.String FACES_CONTEXT_FACTORY
The property name for the
FacesContextFactory
class name.
public static final java.lang.String FACELET_CACHE_FACTORY
The property name for the
FaceletCacheFactory
class name.
public static final java.lang.String PARTIAL_VIEW_CONTEXT_FACTORY
The property name for the PartialViewContextFactory
class name.
public static final java.lang.String VISIT_CONTEXT_FACTORY
The property name for the VisitContextFactory
class name.
public static final java.lang.String LIFECYCLE_FACTORY
The property name for the
LifecycleFactory
class name.
public static final java.lang.String RENDER_KIT_FACTORY
The property name for the
RenderKitFactory
class name.
public static final java.lang.String VIEW_DECLARATION_LANGUAGE_FACTORY
The property name for the ViewDeclarationLanguage
class name.
public static final java.lang.String TAG_HANDLER_DELEGATE_FACTORY
The property name for the TagHandlerDelegate
class name.
private static final FactoryFinder.FactoryManagerCache FACTORIES_CACHE
private static final java.lang.String[] FACTORY_NAMES
The set of JavaServer 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 static java.util.Map<java.lang.String,java.lang.Class> factoryClasses
Map of Class instances for the our factory names.
private static final java.util.logging.Logger LOGGER
FactoryFinder()
public static java.lang.Object getFactory(java.lang.String factoryName) throws FacesException
Create (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.
The standard result and wrappers
in JSF all implement the interface FacesWrapper
. If the
returned Object
is an implementation of one of the
standard result, it must be legal to cast it to an instance of
FacesWrapper
and call FacesWrapper.getWrapped()
on the instance.
factoryName
- Fully qualified name of the JavaServer Faces factory
for which an implementation instance is requestedFacesException
- if the web application class loader
cannot be identifiedFacesException
- if an instance of the configured factory
implementation class cannot be loadedFacesException
- if an instance of the configured factory
implementation class cannot be instantiatedjava.lang.IllegalArgumentException
- if factoryName
does not
identify a standard JavaServer Faces factory namejava.lang.IllegalStateException
- if there is no configured factory
implementation class for the specified factory namejava.lang.NullPointerException
- if factoryname
is nullpublic static void setFactory(java.lang.String factoryName, java.lang.String implName)
This method will store the argument
factoryName/implName
mapping in such a way that
getFactory(java.lang.String)
will find this mapping when searching for a
match.
This method has no effect if getFactory()
has
already been called looking for a factory for this
factoryName
.
This method can be used by implementations to store a factory mapping while parsing the Faces configuration file
java.lang.IllegalArgumentException
- if factoryName
does not
identify a standard JavaServer Faces factory namejava.lang.NullPointerException
- if factoryname
is nullpublic static void releaseFactories() throws FacesException
Release any references to factory instances associated with the class loader for the calling web application. This method must be called during of web application shutdown.
FacesException
- if the web application class loader
cannot be identifiedprivate static java.lang.ClassLoader getClassLoader() throws FacesException
Identify and return the class loader that is associated with the calling web application.
FacesException
- if the web application class loader
cannot be identifiedprivate static java.lang.Object getImplementationInstance(java.lang.ClassLoader classLoader, java.lang.String factoryName, java.util.List implementations) throws FacesException
Load and return an instance of the specified implementation class using the following algorithm.
If the argument implementations
list has
more than one element, or exactly one element, interpret the
last element in the list to be the fully qualified class name of
a class implementing factoryName
. Instantiate that
class and save it for return. If the
implementations
list has only one element, skip
this step.
Look for a resource called
/META-INF/services/<factoryName>
. If found,
interpret it as a properties file, and read out the first entry.
Interpret the first entry as a fully qualify class name of a
class that implements factoryName
. If we have an
instantiated factory from the previous step and the
implementing class has a one arg constructor of the type for
factoryName
, instantiate it, passing the
instantiated factory from the previous step. If there is no one
arg constructor, just instantiate the zero arg constructor. Save
the newly instantiated factory for return, replacing the
instantiated factory from the previous step.
Treat each remaining element in the
implementations
list as a fully qualified class name
of a class implementing factoryName
. If the current
element has a one arg constructor of the type for
factoryName
, instantiate it, passing the
instantiated factory from the previous or step iteration. If
there is no one arg constructor, just instantiate the zero arg
constructor, replacing the instantiated factory from the previous
step or iteration.
Return the saved factory
classLoader
- Class loader for the web application that will
be loading the implementation classimplementations
- A List of implementations for a given
factory class.FacesException
- if the specified implementation class
cannot be loadedFacesException
- if an instance of the specified implementation
class cannot be instantiatedprivate static java.util.List<java.lang.String> getImplNameFromServices(java.lang.ClassLoader classLoader, java.lang.String factoryName)
Perform the logic to get the implementation class for the
second step of getImplementationInstance(ClassLoader, String, java.util.List)
.
private static java.lang.Object getImplGivenPreviousImpl(java.lang.ClassLoader classLoader, java.lang.String factoryName, java.lang.String implName, java.lang.Object previousImpl)
Implement the decorator pattern for the factory implementation.
If previousImpl
is non-null
and the
class named by the argument implName
has a one arg
contstructor of type factoryName
, instantiate it,
passing previousImpl to the constructor.
Otherwise, we just instantiate and return
implName
.
classLoader
- the ClassLoader from which to load the classfactoryName
- the fully qualified class name of the factory.implName
- the fully qualified class name of a class that
implements the factory.previousImpl
- if non-null
, the factory
instance to be passed to the constructor of the new factory.private static java.lang.Class getFactoryClass(java.lang.String factoryClassName)
java.lang.Class
for the argument
factory.private static void validateFactoryName(java.lang.String factoryName)
private static void reInitializeFactoryManager()