- java.lang.Object
-
- org.tentackle.common.ServiceFactory
-
public class ServiceFactory extends java.lang.ObjectFactory for services based onServiceFinder.A replacement for
ServiceLoaderproviding 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,ServiceFinders 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.
ModuleHookand 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
ServiceLoaderand can be replaced via META-INF/services. If no such configuration is found, an instance ofServiceFactoryis used, i.e. the fallback and default implementation isServiceFactoryitself. However, applications can replace it, if necessary.- Author:
- harald
-
-
Field Summary
Fields Modifier and Type Field Description static ServiceFactoryINSTANCEthe singleton instance.
-
Constructor Summary
Constructors Constructor Description ServiceFactory()Creates the factory.
-
Method Summary
All Methods Static Methods Instance Methods Concrete Methods Modifier and Type Method Description static voidaddExplicitClassLoader(java.lang.String servicePath, java.lang.String serviceName, java.lang.ClassLoader classLoader)Adds an explict classloader for a given service path and name.
Loaders are kept in a linked list for each path and name combination.protected voidaddExplicitClassLoaderImpl(java.lang.String servicePath, java.lang.String serviceName, java.lang.ClassLoader classLoader)Adds an explict classloader for a given service path and name.
Loaders are kept in a linked list for each path and name combination.static voidapplyResourceIndex(java.lang.ClassLoader classLoader, java.lang.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 voidapplyResourceIndexImpl(java.lang.ClassLoader classLoader, java.lang.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> TcreateService(java.lang.Class<T> serviceClass)Utility method to create a service instance.
This is the standard way to instantiate singletons.static <T> TcreateService(java.lang.Class<T> serviceClass, java.lang.Class<? extends T> defaultClass)Utility method to create a service instance with a default if not found.static <T> TcreateService(java.lang.Class<T> serviceClass, java.lang.Class<? extends T> defaultClass, boolean logDefault)Utility method to create a service instance with a default if not found.static <T> java.lang.Class<T>createServiceClass(java.lang.Class<T> serviceClass)Utility method to create a service instance.
This is the standard way to instantiate singletons.protected java.lang.ClassLoadergetClassLoader()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 java.lang.ClassLoadergetClassLoader(java.lang.String servicePath, java.lang.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 java.lang.ClassLoadergetClassLoaderImpl(java.lang.String servicePath, java.lang.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 java.lang.ClassLoadergetExplicitClassLoader(java.lang.String servicePath, java.lang.String serviceName)Gets the explicit classloader for a given service path and name.protected java.lang.ClassLoadergetExplicitClassLoaderImpl(java.lang.String servicePath, java.lang.String serviceName)Gets the explicit classloader for a given service path and name.static java.lang.ClassLoadergetFactoryClassloader()Gets the classloader to load the service factorty.static java.lang.StringgetFactoryClassname()Gets the classname of the service factory.java.util.Map<ServiceFinderKey,ServiceFinder>getFinderMap()Gets the finder map.
Allows applications to modify or add finders programmatically.
The map is threadsafe.java.lang.ClassLoadergetFixedClassLoader()Gets the fixed classloader.static ServiceFindergetServiceFinder()Gets a service finder.
If the finder does not exist yet, it will be created.static ServiceFindergetServiceFinder(java.lang.ClassLoader loader, java.lang.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 ServiceFindergetServiceFinder(java.lang.String servicePath)Gets a service finder for a given service path.
If the finder does not exist yet, it will be created.protected java.lang.Class<? extends ServiceFinder>getServiceFinderClass()Gets the class of the service finder.protected ServiceFindergetServiceFinderImpl()Gets a service finder.
If the finder does not exist yet, it will be created.protected ServiceFindergetServiceFinderImpl(java.lang.ClassLoader loader, java.lang.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 ServiceFindergetServiceFinderImpl(java.lang.String servicePath)Gets a service finder for a given service path.
If the finder does not exist yet, it will be created.static voidremoveExplicitClassLoader(java.lang.String servicePath, java.lang.String serviceName, java.lang.ClassLoader classLoader)Remove]s an explict classloader for a given service path and name.
Loaders are kept in a linked list for each path and name combination.protected voidremoveExplicitClassLoaderImpl(java.lang.String servicePath, java.lang.String serviceName, java.lang.ClassLoader classLoader)Remove]s an explict classloader for a given service path and name.
Loaders are kept in a linked list for each path and name combination.static voidsetFactoryClassloader(java.lang.ClassLoader factoryClassloader)Sets the classloader to load the service factorty.static voidsetFactoryClassname(java.lang.String factoryClassname)Sets the classname of the service factory.voidsetFixedClassLoader(java.lang.ClassLoader classLoader)Sets the fixed classloader.
Default is Thread.currentThread().getContextClassLoader().
-
-
-
Field Detail
-
INSTANCE
public static final ServiceFactory INSTANCE
the singleton instance.
-
-
Method Detail
-
setFactoryClassname
public static void setFactoryClassname(java.lang.String factoryClassname)
Sets the classname of the service factory.If this value is null, the
ServiceFactoryis loaded via theServiceLoader. However, if for whatever reason, the loader doesn't find the service configuration or cannot be used, the class defined byfactoryClassnamecan be instantiated. Applications must change this at a very early stage of startup, for example in the main-method.- Parameters:
factoryClassname- the classname
-
getFactoryClassname
public static java.lang.String getFactoryClassname()
Gets the classname of the service factory.- Returns:
- the classname, default is null
-
setFactoryClassloader
public static void setFactoryClassloader(java.lang.ClassLoader factoryClassloader)
Sets the classloader to load the service factorty.If this value is null, the the
ServiceFactoryis loaded via a default classloader.- Parameters:
factoryClassloader- the classloader
-
getFactoryClassloader
public static java.lang.ClassLoader getFactoryClassloader()
Gets the classloader to load the service factorty.- Returns:
- the classloader, default is null
-
getServiceFinder
public static ServiceFinder getServiceFinder(java.lang.ClassLoader loader, java.lang.String servicePath)
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
public static ServiceFinder getServiceFinder(java.lang.String servicePath)
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
public static ServiceFinder 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
public static <T> java.lang.Class<T> createServiceClass(java.lang.Class<T> serviceClass)
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(java.lang.Class<T> serviceClass)
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(java.lang.Class<T> serviceClass, java.lang.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 default class if no service foundlogDefault- true if log warning with stacktrace if default implementation is used- Returns:
- an instance of the service
-
createService
public static <T> T createService(java.lang.Class<T> serviceClass, java.lang.Class<? extends T> defaultClass)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
public static java.lang.ClassLoader getClassLoader(java.lang.String servicePath, java.lang.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. Otherwise the default classloader is returned.- Parameters:
servicePath- the service pathserviceName- the service name- Returns:
- the classloader, never null
-
getExplicitClassLoader
public static java.lang.ClassLoader getExplicitClassLoader(java.lang.String servicePath, java.lang.String serviceName)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(java.lang.String servicePath, java.lang.String serviceName, java.lang.ClassLoader classLoader)Adds an explict 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(java.lang.String servicePath, java.lang.String serviceName, java.lang.ClassLoader classLoader)Remove]s an explict 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
public static void applyResourceIndex(java.lang.ClassLoader classLoader, java.lang.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".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
public java.lang.ClassLoader getFixedClassLoader()
Gets the fixed classloader.- Returns:
- the classloader, null if default
-
setFixedClassLoader
public void setFixedClassLoader(java.lang.ClassLoader classLoader)
Sets the fixed classloader.
Default is Thread.currentThread().getContextClassLoader().- Parameters:
classLoader- the classloader, null if default
-
getClassLoader
protected java.lang.ClassLoader 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
protected java.lang.ClassLoader getClassLoaderImpl(java.lang.String servicePath, java.lang.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. Otherwise the default classloader is returned.- Parameters:
servicePath- the service pathserviceName- the service name- Returns:
- the classloader, never null
-
getExplicitClassLoaderImpl
protected java.lang.ClassLoader getExplicitClassLoaderImpl(java.lang.String servicePath, java.lang.String serviceName)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(java.lang.String servicePath, java.lang.String serviceName, java.lang.ClassLoader classLoader)Adds an explict 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(java.lang.String servicePath, java.lang.String serviceName, java.lang.ClassLoader classLoader)Remove]s an explict 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
protected void applyResourceIndexImpl(java.lang.ClassLoader classLoader, java.lang.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".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
public java.util.Map<ServiceFinderKey,ServiceFinder> getFinderMap()
Gets the finder map.
Allows applications to modify or add finders programmatically.
The map is threadsafe.- Returns:
- the finder map
-
getServiceFinderClass
protected java.lang.Class<? extends ServiceFinder> getServiceFinderClass()
Gets the class of the service finder.- Returns:
- the class of the service finder, never null
-
getServiceFinderImpl
protected ServiceFinder getServiceFinderImpl(java.lang.ClassLoader loader, java.lang.String servicePath)
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
protected ServiceFinder getServiceFinderImpl(java.lang.String servicePath)
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
protected ServiceFinder 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
-
-