org.apache.commons.discovery.tools
public class: DiscoverSingleton [javadoc |
source]
java.lang.Object
org.apache.commons.discovery.tools.DiscoverSingleton
Discover singleton service providers.
This
DiscoverSingleton instances are cached by the Discovery service,
keyed by a combination of
- thread context class loader,
- groupContext, and
- SPI.
This DOES allow multiple instances of a given
singleton class
to exist for different class loaders and different group contexts.
In the context of this package, a service interface is defined by a
Service Provider Interface (SPI). The SPI is expressed as a Java interface,
abstract class, or (base) class that defines an expected programming
interface.
DiscoverSingleton provides the find methods for locating and
instantiating a singleton instance of an implementation of a service (SPI).
Each form of find varies slightly, but they all perform the
same basic function.
The simplest find methods are intended for direct use by
components looking for a service. If you are not sure which finder(s)
to use, you can narrow your search to one of these:
- static Object find(Class spi);
- static Object find(Class spi, Properties properties);
- static Object find(Class spi, String defaultImpl);
- static Object find(Class spi,
Properties properties, String defaultImpl);
- static Object find(Class spi,
String propertiesFileName, String defaultImpl);
- static Object find(String groupContext, Class spi,
Properties properties, String defaultImpl);
- static Object find(String groupContext, Class spi,
String propertiesFileName, String defaultImpl);
The
DiscoverSingleton.find methods proceed as follows:
-
Examine an internal cache to determine if the desired service was
previously identified and instantiated. If found in cache, return it.
-
Get the name of an implementation class. The name is the first
non-null value obtained from the following resources:
-
If the name of the implementation class is non-null, load that class.
The class loaded is the first class loaded by the following sequence
of class loaders:
- Thread Context Class Loader
- DiscoverSingleton's Caller's Class Loader
- SPI's Class Loader
- DiscoverSingleton's (this class or wrapper) Class Loader
- System Class Loader
An exception is thrown if the class cannot be loaded.
-
If the name of the implementation class is null, AND the default
implementation class (
defaultImpl) is null,
then an exception is thrown.
-
If the name of the implementation class is null, AND the default
implementation class (
defaultImpl) is non-null,
then load the default implementation class. The class loaded is the
first class loaded by the following sequence of class loaders:
- SPI's Class Loader
- DiscoverSingleton's (this class or wrapper) Class Loader
- System Class Loader
This limits the scope in which the default class loader can be found
to the SPI, DiscoverSingleton, and System class loaders. The assumption
here is that the default implementation is closely associated with the SPI
or system, and is not defined in the user's application space.
An exception is thrown if the class cannot be loaded.
-
Verify that the loaded class implements the SPI: an exception is thrown
if the loaded class does not implement the SPI.
-
Create an instance of the class.
Variances for various forms of the find
methods are discussed with each such method.
Variances include the following concepts:
- rootFinderClass - a wrapper encapsulating a finder method
(factory or other helper class). The root finder class is used to
determine the 'real' caller, and hence the caller's class loader -
thereby preserving knowledge that is relevant to finding the
correct/expected implementation class.
- propertiesFileName -
Properties may be specified
directly, or by property file name. A property file is loaded using the
same sequence of class loaders used to load the SPI implementation:
- Thread Context Class Loader
- DiscoverSingleton's Caller's Class Loader
- SPI's Class Loader
- DiscoverSingleton's (this class) Class Loader
- System Class Loader
- groupContext - differentiates service providers for different
logical groups of service users, that might otherwise be forced to share
a common service and, more importantly, a common configuration of that
service.
The groupContext is used to qualify the name of the property file
name: groupContext + '.' + propertiesFileName. If that
file is not found, then the unqualified propertyFileName is used.
In addition, groupContext is used to qualify the name of the system
property used to find the service implementation by prepending the value
of groupContext to the property name:
groupContext> + '.' + SPI.class.getName().
Again, if a system property cannot be found by that name, then the
unqualified property name is used.
IMPLEMENTATION NOTE - This implementation is modelled
after the SAXParserFactory and DocumentBuilderFactory implementations
(corresponding to the JAXP pluggability APIs) found in Apache Xerces.
- author:
Richard - A. Sitze
- author:
Craig - R. McClanahan
- author:
Costin - Manolache
- version:
$ - Revision: 480374 $ $Date: 2006-11-28 19:33:25 -0800 (Tue, 28 Nov 2006) $
| Method from org.apache.commons.discovery.tools.DiscoverSingleton Detail: |
public static Object find(Class spiClass) throws DiscoveryException {
return find(null,
new SPInterface(spiClass),
DiscoverClass.nullProperties,
DiscoverClass.nullDefaultImpl);
}
Find implementation of SPI. |
public static Object find(Class spiClass,
Properties properties) throws DiscoveryException {
return find(null,
new SPInterface(spiClass),
new PropertiesHolder(properties),
DiscoverClass.nullDefaultImpl);
}
Find implementation of SPI. |
public static Object find(Class spiClass,
String defaultImpl) throws DiscoveryException {
return find(null,
new SPInterface(spiClass),
DiscoverClass.nullProperties,
new DefaultClassHolder(defaultImpl));
}
Find implementation of SPI. |
public static Object find(Class spiClass,
Properties properties,
String defaultImpl) throws DiscoveryException {
return find(null,
new SPInterface(spiClass),
new PropertiesHolder(properties),
new DefaultClassHolder(defaultImpl));
}
Find implementation of SPI. |
public static Object find(Class spiClass,
String propertiesFileName,
String defaultImpl) throws DiscoveryException {
return find(null,
new SPInterface(spiClass),
new PropertiesHolder(propertiesFileName),
new DefaultClassHolder(defaultImpl));
}
Find implementation of SPI. |
public static Object find(ClassLoaders loaders,
SPInterface spi,
PropertiesHolder properties,
DefaultClassHolder defaultImpl) throws DiscoveryException {
ClassLoader contextLoader = JDKHooks.getJDKHooks().getThreadContextClassLoader();
Object obj = get(contextLoader, spi.getSPName());
if (obj == null) {
try {
obj = DiscoverClass.newInstance(loaders, spi, properties, defaultImpl);
if (obj != null) {
put(contextLoader, spi.getSPName(), obj);
}
} catch (DiscoveryException de) {
throw de;
} catch (Exception e) {
throw new DiscoveryException("Unable to instantiate implementation class for " + spi.getSPName(), e);
}
}
return obj;
}
Find implementation of SPI. |
public static synchronized void release() {
EnvironmentCache.release();
}
Release all internal references to previously created service
instances associated with the current thread context class loader.
The release() method is called for service instances that
implement the Service interface.
This is useful in environments like servlet containers,
which implement application reloading by throwing away a ClassLoader.
Dangling references to objects in that class loader would prevent
garbage collection. |
public static synchronized void release(Class spiClass) {
HashMap spis = (HashMap)EnvironmentCache.get(JDKHooks.getJDKHooks().getThreadContextClassLoader());
if (spis != null) {
spis.remove(spiClass.getName());
}
}
Release any internal references to a previously created service
instance associated with the current thread context class loader.
If the SPI instance implements Service, then call
release(). |