ServiceFinder
.
A replacement for ServiceLoader
providing the following additional features:
- Not limited to load classes. Can load any kind of configuration.
- Supports different service types. Each type gets its own directory in META-INF.
- Each service (type + name) may have its own classloader. Useful for OSGi.
- Works for modular (jigsaw) and non-modular applications.
- As opposed to
ServiceLoader
,ServiceFinder
s retain the module dependency order for service URLs. The first URL is guaranteed to belong to the topmost relevant module. Unnamed, i.e. classpath comes last.
ModuleHook
and a provides-clause
in module-info. Example:
provides org.tentackle.common.ModuleHook with com.myapp.somepackage.Hook;
The factory itself is loaded via the standard JDK ServiceLoader
and can
be replaced via META-INF/services. If no such configuration is found, an instance of ServiceFactory
is used,
i.e. the fallback and default implementation is ServiceFactory
itself.
However, applications can replace it, if necessary.
- Author:
- harald
-
Field Summary
Fields -
Constructor Summary
Constructors -
Method Summary
Modifier and TypeMethodDescriptionstatic void
addExplicitClassLoader
(String servicePath, String serviceName, ClassLoader classLoader) Adds an explicit classloader for a given service path and name.
Loaders are kept in a linked list for each path and name combination.protected void
addExplicitClassLoaderImpl
(String servicePath, String serviceName, ClassLoader classLoader) Adds an explicit classloader for a given service path and name.
Loaders are kept in a linked list for each path and name combination.static void
applyResourceIndex
(ClassLoader classLoader, String indexName, boolean set) Apply a given resource index.
The index is usually created via the tentackle-maven-plugin's analyze goal with the index option set to something like"META-INF/RESOURCES-INDEX.LIST"
.protected void
applyResourceIndexImpl
(ClassLoader classLoader, String indexName, boolean set) Apply a given resource index.
The index is usually created via the tentackle-maven-plugin's analyze goal with the index option set to something like"META-INF/RESOURCES-INDEX.LIST"
.static <T> T
createService
(Class<T> serviceClass) Utility method to create a service instance.
This is the standard way to instantiate singletons.static <T> T
createService
(Class<T> serviceClass, Class<? extends T> defaultClass) Utility method to create a service instance with a default if not found.static <T> T
createService
(Class<T> serviceClass, Class<? extends T> defaultClass, boolean logDefault) Utility method to create a service instance with a default if not found.static <T> Class
<T> createServiceClass
(Class<T> serviceClass) Utility method to create a service instance.
This is the standard way to instantiate singletons.protected ClassLoader
Gets the default classloader.
The classloader to use is determined as follows: use the fixed classloader set bysetFixedClassLoader(java.lang.ClassLoader)
, if not null else tryThread.currentThread().getContextClassLoader()
if the context classloader is null, use the classloader that loaded the service factorystatic ClassLoader
getClassLoader
(String servicePath, String serviceName) Gets the classloader for a given service path and name.
If an explicit classloader is set, the last defined classloader for the given path and name is returned.protected ClassLoader
getClassLoaderImpl
(String servicePath, String serviceName) Gets the classloader for a given service path and name.
If an explicit classloader is set, the last defined classloader for the given path and name is returned.static ClassLoader
getExplicitClassLoader
(String servicePath, String serviceName) Gets the explicit classloader for a given service path and name.protected ClassLoader
getExplicitClassLoaderImpl
(String servicePath, String serviceName) Gets the explicit classloader for a given service path and name.static ClassLoader
Gets the classloader to load the service factory.static String
Gets the classname of the service factory.Gets the finder map.
Allows applications to modify or add finders programmatically.
The map is threadsafe.Gets the fixed classloader.static ServiceFinder
Gets a service finder.
If the finder does not exist yet, it will be created.static ServiceFinder
getServiceFinder
(ClassLoader loader, String servicePath) Gets a service finder for a given classloader and service path.
If the finder does not exist yet, it will be created.static ServiceFinder
getServiceFinder
(String servicePath) Gets a service finder for a given service path.
If the finder does not exist yet, it will be created.protected Class
<? extends ServiceFinder> Gets the class of the service finder.protected ServiceFinder
Gets a service finder.
If the finder does not exist yet, it will be created.protected ServiceFinder
getServiceFinderImpl
(ClassLoader loader, String servicePath) Gets a service finder for a given classloader and service path.
If the finder does not exist yet, it will be created.protected ServiceFinder
getServiceFinderImpl
(String servicePath) Gets a service finder for a given service path.
If the finder does not exist yet, it will be created.static void
removeExplicitClassLoader
(String servicePath, String serviceName, ClassLoader classLoader) Removes an explicit classloader for a given service path and name.
Loaders are kept in a linked list for each path and name combination.protected void
removeExplicitClassLoaderImpl
(String servicePath, String serviceName, ClassLoader classLoader) Removes an explicit classloader for a given service path and name.
Loaders are kept in a linked list for each path and name combination.static void
setFactoryClassloader
(ClassLoader factoryClassloader) Sets the classloader to load the service factory.static void
setFactoryClassname
(String factoryClassname) Sets the classname of the service factory.void
setFixedClassLoader
(ClassLoader classLoader) Sets the fixed classloader.
Default is Thread.currentThread().getContextClassLoader().
-
Field Details
-
INSTANCE
the singleton instance.
-
-
Constructor Details
-
ServiceFactory
public ServiceFactory()Creates the factory.
-
-
Method Details
-
setFactoryClassname
Sets the classname of the service factory.If this value is null, the
ServiceFactory
is loaded via theServiceLoader
. However, if for whatever reason, the loader doesn't find the service configuration or cannot be used, the class defined byfactoryClassname
can be instantiated. Applications must change this at a very early stage of startup, for example in the main-method.- Parameters:
factoryClassname
- the classname
-
getFactoryClassname
Gets the classname of the service factory.- Returns:
- the classname, default is null
-
setFactoryClassloader
Sets the classloader to load the service factory.If this value is null, the
ServiceFactory
is loaded via a default classloader.- Parameters:
factoryClassloader
- the classloader
-
getFactoryClassloader
Gets the classloader to load the service factory.- Returns:
- the classloader, default is null
-
getServiceFinder
Gets a service finder for a given classloader and service path.
If the finder does not exist yet, it will be created.- Parameters:
loader
- the classloaderservicePath
- the service path prefix- Returns:
- the finder
-
getServiceFinder
Gets a service finder for a given service path.
If the finder does not exist yet, it will be created. The classloader used isThread.currentThread().getContextClassLoader()
.- Parameters:
servicePath
- the service path prefix- Returns:
- the finder, never null
-
getServiceFinder
Gets a service finder.
If the finder does not exist yet, it will be created. The classloader used isThread.currentThread().getContextClassLoader()
and the service path is"META_INF/services/"
.- Returns:
- the finder
-
createServiceClass
Utility method to create a service instance.
This is the standard way to instantiate singletons. Finds the first service implementation along the classpath.- Type Parameters:
T
- the service type- Parameters:
serviceClass
- the service class- Returns:
- an instance of the service
-
createService
Utility method to create a service instance.
This is the standard way to instantiate singletons. Finds the first service implementation along the classpath.- Type Parameters:
T
- the service type- Parameters:
serviceClass
- the service class- Returns:
- an instance of the service
-
createService
public static <T> T createService(Class<T> serviceClass, Class<? extends T> defaultClass, boolean logDefault) Utility method to create a service instance with a default if not found.- Type Parameters:
T
- the service type- Parameters:
serviceClass
- the service classdefaultClass
- the fallback class if no service found or could not be instantiatedlogDefault
- true if log warning with stacktrace if default implementation is used- Returns:
- an instance of the service
-
createService
Utility method to create a service instance with a default if not found.- Type Parameters:
T
- the service type- Parameters:
serviceClass
- the service classdefaultClass
- the default class if no service found- Returns:
- an instance of the service
-
getClassLoader
Gets the classloader for a given service path and name.
If an explicit classloader is set, the last defined classloader for the given path and name is returned. Otherwise, the default classloader is returned.- Parameters:
servicePath
- the service pathserviceName
- the service name- Returns:
- the classloader, never null
-
getExplicitClassLoader
Gets the explicit classloader for a given service path and name.- Parameters:
servicePath
- the service pathserviceName
- the service name- Returns:
- the classloader, null if no explicit classloader set
-
addExplicitClassLoader
public static void addExplicitClassLoader(String servicePath, String serviceName, ClassLoader classLoader) Adds an explicit classloader for a given service path and name.
Loaders are kept in a linked list for each path and name combination. Setting a classloader performs a push, clearing a pop. Thus, removing a loader activates the previously set loader, if any. This allows activation and deactivation as it used in OSGi, for example.- Parameters:
servicePath
- the service pathserviceName
- the service nameclassLoader
- the classloader, null if remove
-
removeExplicitClassLoader
public static void removeExplicitClassLoader(String servicePath, String serviceName, ClassLoader classLoader) Removes an explicit classloader for a given service path and name.
Loaders are kept in a linked list for each path and name combination. Setting a classloader performs a push, clearing a pop. Thus, removing a loader activates the previously set loader, if any. This allows activation and deactivation as it used in OSGi, for example.- Parameters:
servicePath
- the service pathserviceName
- the service nameclassLoader
- the classloader, null if remove
-
applyResourceIndex
Apply a given resource index.
The index is usually created via the tentackle-maven-plugin's analyze goal with the index option set to something like"META-INF/RESOURCES-INDEX.LIST"
.This is a utility method, that can be used during the activation within an OSGI-bundle, for example.
- Parameters:
classLoader
- the classloader to load the index resourceindexName
- the name of the index resourceset
- true if set loaders, else remove loaders from the services index
-
getFixedClassLoader
Gets the fixed classloader.- Returns:
- the classloader, null if default
-
setFixedClassLoader
Sets the fixed classloader.
Default is Thread.currentThread().getContextClassLoader().- Parameters:
classLoader
- the classloader, null if default
-
getClassLoader
Gets the default classloader.
The classloader to use is determined as follows:- use the fixed classloader set by
setFixedClassLoader(java.lang.ClassLoader)
, if not null - else try
Thread.currentThread().getContextClassLoader()
- if the context classloader is null, use the classloader that loaded the service factory
- Returns:
- the loader, never null
- use the fixed classloader set by
-
getClassLoaderImpl
Gets the classloader for a given service path and name.
If an explicit classloader is set, the last defined classloader for the given path and name is returned. Otherwise, the default classloader is returned.- Parameters:
servicePath
- the service pathserviceName
- the service name- Returns:
- the classloader, never null
-
getExplicitClassLoaderImpl
Gets the explicit classloader for a given service path and name.- Parameters:
servicePath
- the service pathserviceName
- the service name- Returns:
- the classloader, null if no explicit classloader set
-
addExplicitClassLoaderImpl
protected void addExplicitClassLoaderImpl(String servicePath, String serviceName, ClassLoader classLoader) Adds an explicit classloader for a given service path and name.
Loaders are kept in a linked list for each path and name combination. Setting a classloader performs a push, clearing a pop. Thus, removing a loader activates the previously set loader, if any. This allows activation and deactivation as it used in OSGi, for example.- Parameters:
servicePath
- the service pathserviceName
- the service nameclassLoader
- the classloader, null if remove
-
removeExplicitClassLoaderImpl
protected void removeExplicitClassLoaderImpl(String servicePath, String serviceName, ClassLoader classLoader) Removes an explicit classloader for a given service path and name.
Loaders are kept in a linked list for each path and name combination. Setting a classloader performs a push, clearing a pop. Thus, removing a loader activates the previously set loader, if any. This allows activation and deactivation as it used in OSGi, for example.- Parameters:
servicePath
- the service pathserviceName
- the service nameclassLoader
- the classloader, null if remove
-
applyResourceIndexImpl
Apply a given resource index.
The index is usually created via the tentackle-maven-plugin's analyze goal with the index option set to something like"META-INF/RESOURCES-INDEX.LIST"
.This is a utility method, that can be used during the activation within an OSGI-bundle, for example.
- Parameters:
classLoader
- the classloader to load the index resourceindexName
- the name of the index resourceset
- true if set loaders, else remove loaders from the services index
-
getFinderMap
Gets the finder map.
Allows applications to modify or add finders programmatically.
The map is threadsafe.- Returns:
- the finder map
-
getServiceFinderClass
Gets the class of the service finder.- Returns:
- the class of the service finder, never null
-
getServiceFinderImpl
Gets a service finder for a given classloader and service path.
If the finder does not exist yet, it will be created.- Parameters:
loader
- the classloaderservicePath
- the service path prefix- Returns:
- the finder, never null
-
getServiceFinderImpl
Gets a service finder for a given service path.
If the finder does not exist yet, it will be created. The classloader to use is determined as follows:- use the fixed classloader set by
setFixedClassLoader(java.lang.ClassLoader)
, if not null - else try
Thread.currentThread().getContextClassLoader()
- if the context classloader is null, use the classloader that loaded the service factory
- Parameters:
servicePath
- the service path prefix- Returns:
- the finder, never null
- use the fixed classloader set by
-
getServiceFinderImpl
Gets a service finder.
If the finder does not exist yet, it will be created. The classloader used isThread.currentThread().getContextClassLoader()
and the service path is"META_INF/services/"
.- Returns:
- the finder
-