Package de.mnl.osgi.coreutils
Class ServiceResolver
- java.lang.Object
-
- de.mnl.osgi.coreutils.ServiceResolver
-
- All Implemented Interfaces:
AutoCloseable
,BundleActivator
public class ServiceResolver extends Object implements AutoCloseable, BundleActivator
Maintains and attempts to resolve dependencies on services.The class supports two usage pattern. The first is to use the
ServiceResolver
as base class for the bundle's activator. The derived class must overrideconfigure()
to add at least one dependency.The methods
onResolved()
,onDissolving()
andonRebound(String)
can be overridden as required.public class Activator extends ServiceResolver { @Override protected void configure() { addDependency(...); } @Override protected void onResolved() { // Enable usage or register as service or start worker thread ... } @Override protected void onDissolving() { // Disable usage or unregister or stop and join worker thread ... } @Override protected void onRebound(String dependency) { // Only required if there is a "long term" usage of a dependency. } }
The second usage pattern is to create aServiceResolver
with aBundleContext
, add dependencies and callbacks as required and callopen()
. When resolving is no longer required,close()
must be called.// Usually executed during bundle start... ServiceResolver resolver = new ServiceResolver(context); // Add dependencies resolver.addDependency(...); resolver.setOnResolved(() -> ...); resolver.setOnDissolving(() -> ...); resolver.setOnRebound(name -> ...); resolver.open(); // Usually executed during bundle stop... resolver.close();
In addition to the management of mandatory dependencies, theServiceResolver
can also keep track of optional service dependencies. This allows theServiceResolver
to be provided as unified service access point. Apart from a singleopen()
andclose()
function, theServiceProvider
does not implement additional functions for optional service dependencies compared to the underlyingServiceCollector
s.
-
-
Field Summary
Fields Modifier and Type Field Description protected BundleContext
context
The bundle context.
-
Constructor Summary
Constructors Modifier Constructor Description protected
ServiceResolver()
Constructor for using theServiceResolver
as base class for aBundleActivator
.ServiceResolver(BundleContext context)
Creates a new resolver that uses the given context.
-
Method Summary
All Methods Instance Methods Concrete Methods Modifier and Type Method Description ServiceResolver
addDependency(Class<?> clazz)
Adds a mandatory dependency on the service specified by the class.ServiceResolver
addDependency(String name, String className)
Adds a mandatory dependency on the service specified by the service reference.ServiceResolver
addDependency(String name, Filter filter)
Adds a mandatory dependency on the service specified by the filter.ServiceResolver
addDependency(String name, ServiceReference<?> reference)
Adds a mandatory dependency on the service specified by the service reference.ServiceResolver
addOptionalDependency(Class<?> clazz)
Adds an optional dependency on the service specified by the class.ServiceResolver
addOptionalDependency(String name, String className)
Adds an optional dependency on the service specified by the service reference.ServiceResolver
addOptionalDependency(String name, Filter filter)
Adds an optional dependency on the service specified by the filter.ServiceResolver
addOptionalDependency(String name, ServiceReference<?> reference)
Adds an optional dependency on the service specified by the service reference.void
close()
Stops the resolver.protected void
configure()
Configures theServiceResolver
.<T> T
get(Class<T> clazz)
Returns the service found for the mandatory dependency using the name of the class as name of the dependency.<T> T
get(String name, Class<T> clazz)
Returns the service found for the mandatory dependency with the given name.boolean
isOpen()
Checks if the resolver is open.boolean
isResolved()
Checks if the resolver is in the resolved state.protected void
onDissolving()
Called when the resolver is about to leave the resolved state, i.e.protected void
onRebound(String dependency)
Called when the preferred service of a resolved dependency changes.protected void
onResolved()
Called when all dependencies have been resolved.void
open()
Starts the resolver.<T> Optional<T>
optional(Class<T> clazz)
Returns the service found for the optional dependency using the name of the class as name of the dependency, if it exists.<T> Optional<T>
optional(String name, Class<T> clazz)
Returns the service found for the optional dependency with the given name, if it exists.ServiceResolver
setOnDissolving(Runnable onDissolving)
Sets the function to called when the resolver is about to leave the resolved state, i.e.ServiceResolver
setOnRebound(Consumer<String> onRebound)
Sets the function to be called when the preferred service of a resolved dependency changes.ServiceResolver
setOnResolved(Runnable onResolved)
Sets the function to called when the resolver has entered the resolved state, i.e.void
start(BundleContext context)
Called by the framework when using theServiceResolver
as base class for a bundle activator.void
stop(BundleContext context)
Called by the framework when using theServiceResolver
as base class for a bundle activator.<T,R>
Optional<R>with(Class<T> clazz, Function<T,? extends R> function)
Convenience method to invoke the a function with the service registered as mandatory or optional dependency while holding a lock on the underlying service collector.<T,R>
Optional<R>with(String name, Function<T,? extends R> function)
Convenience method to invoke the a function with the service registered as mandatory or optional dependency while holding a lock on the underlying service collector.
-
-
-
Field Detail
-
context
protected BundleContext context
The bundle context. Made available for derived classes.
-
-
Constructor Detail
-
ServiceResolver
public ServiceResolver(BundleContext context)
Creates a new resolver that uses the given context.- Parameters:
context
- the context
-
ServiceResolver
protected ServiceResolver()
Constructor for using theServiceResolver
as base class for aBundleActivator
.
-
-
Method Detail
-
start
public void start(BundleContext context) throws Exception
Called by the framework when using theServiceResolver
as base class for a bundle activator.The implementation sets the
context
attribute and callsconfigure()
andopen()
.- Specified by:
start
in interfaceBundleActivator
- Parameters:
context
- the context- Throws:
Exception
- if a problem occurs
-
configure
protected void configure()
Configures theServiceResolver
. Must be overridden by the derived class when using theServiceResolver
as base class for a bundle activator. The derived class must configure the resolver with calls to at least one of theaddDependency
methods.The default implementation does nothing.
-
onResolved
protected void onResolved()
Called when all dependencies have been resolved. Overriding this method is an alternative to setting a callback withsetOnResolved(Runnable)
.
-
onDissolving
protected void onDissolving()
Called when the resolver is about to leave the resolved state, i.e. when one of the mandatory services is going to be unbound. Overriding this method is an alternative to setting a callback withsetOnDissolving(Runnable)
.
-
onRebound
protected void onRebound(String dependency)
Called when the preferred service of a resolved dependency changes. The change may either be a change of properties reported by the framework or the replacement of the preferred service with another service. Overriding this method is an alternative to setting a callback withsetOnRebound(Consumer)
.- Parameters:
dependency
- the dependency that has been rebound
-
stop
public void stop(BundleContext context) throws Exception
Called by the framework when using theServiceResolver
as base class for a bundle activator. The implementatoin callsclose()
.- Specified by:
stop
in interfaceBundleActivator
- Parameters:
context
- the context- Throws:
Exception
- if a problem occurs
-
setOnResolved
public ServiceResolver setOnResolved(Runnable onResolved)
Sets the function to called when the resolver has entered the resolved state, i.e. when all mandatory services have been bound.- Parameters:
onResolved
- the function- Returns:
- the service resolver
-
setOnDissolving
public ServiceResolver setOnDissolving(Runnable onDissolving)
Sets the function to called when the resolver is about to leave the resolved state, i.e. when one of the mandatory services is going to be unbound.- Parameters:
onDissolving
- the function- Returns:
- the service resolver
-
setOnRebound
public ServiceResolver setOnRebound(Consumer<String> onRebound)
Sets the function to be called when the preferred service of a resolved dependency changes. The change may either be a change of properties reported by the framework or the replacement of the preferred service with another service.- Parameters:
onRebound
- the on rebound- Returns:
- the service resolver
-
addDependency
public ServiceResolver addDependency(Class<?> clazz)
Adds a mandatory dependency on the service specified by the class. The name of the class is used as name of the dependency.- Parameters:
clazz
- the class- Returns:
- the service resolver
-
addDependency
public ServiceResolver addDependency(String name, Filter filter)
Adds a mandatory dependency on the service specified by the filter.- Parameters:
name
- the name of the dependencyfilter
- the filter- Returns:
- the service resolver
-
addDependency
public ServiceResolver addDependency(String name, ServiceReference<?> reference)
Adds a mandatory dependency on the service specified by the service reference.- Parameters:
name
- the name of the dependencyreference
- the reference- Returns:
- the service resolver
-
addDependency
public ServiceResolver addDependency(String name, String className)
Adds a mandatory dependency on the service specified by the service reference.- Parameters:
name
- the name of the dependencyclassName
- the class name- Returns:
- the service resolver
-
addOptionalDependency
public ServiceResolver addOptionalDependency(Class<?> clazz)
Adds an optional dependency on the service specified by the class. The name of the class is used as identifier for the dependency.- Parameters:
clazz
- the class- Returns:
- the service resolver
-
addOptionalDependency
public ServiceResolver addOptionalDependency(String name, Filter filter)
Adds an optional dependency on the service specified by the filter.- Parameters:
name
- the name of the dependencyfilter
- the filter- Returns:
- the service resolver
-
addOptionalDependency
public ServiceResolver addOptionalDependency(String name, ServiceReference<?> reference)
Adds an optional dependency on the service specified by the service reference.- Parameters:
name
- the name of the dependencyreference
- the reference- Returns:
- the service resolver
-
addOptionalDependency
public ServiceResolver addOptionalDependency(String name, String className)
Adds an optional dependency on the service specified by the service reference.- Parameters:
name
- the name of the dependencyclassName
- the class name- Returns:
- the service resolver
-
open
public void open()
Starts the resolver. While open, the resolver attempts to obtain service implementation for all registered service dependencies.
-
close
public void close()
Stops the resolver. All maintained services are released.- Specified by:
close
in interfaceAutoCloseable
-
isOpen
public boolean isOpen()
Checks if the resolver is open.- Returns:
- true, if open
-
isResolved
public boolean isResolved()
Checks if the resolver is in the resolved state.- Returns:
- the result
-
get
public <T> T get(String name, Class<T> clazz)
Returns the service found for the mandatory dependency with the given name. This method should only be called when the resolver is in state resolved. Note that due to the threaded nature of the environment, this method can returnnull
, even if the resolver was in state resolved before its invocation, because the service can go away between the check and the invocation of this method. If you want to be sure that services haven't been unregistered concurrently, the check for resolved and the invocation of this method must be in a block synchronized on this resolver. Consider usingwith(String, Function)
orwith(Class, Function)
as an alternative.- Type Parameters:
T
- the type of the service- Parameters:
name
- the name of the dependencyclazz
- the class of the service- Returns:
- the service or
null
if called in unresolved state and the dependency is not resolved
-
get
public <T> T get(Class<T> clazz)
Returns the service found for the mandatory dependency using the name of the class as name of the dependency.- Type Parameters:
T
- the type of the service- Parameters:
clazz
- the class of the service- Returns:
- the service or
null
if called in unresolved state and the dependency is not resolved - See Also:
get(String, Class)
-
optional
public <T> Optional<T> optional(String name, Class<T> clazz)
Returns the service found for the optional dependency with the given name, if it exists.- Type Parameters:
T
- the type of the service- Parameters:
name
- the name of the dependencyclazz
- the class of the service- Returns:
- the result
-
optional
public <T> Optional<T> optional(Class<T> clazz)
Returns the service found for the optional dependency using the name of the class as name of the dependency, if it exists.- Type Parameters:
T
- the type of the service- Parameters:
clazz
- the class of the service- Returns:
- the result
-
with
public <T,R> Optional<R> with(String name, Function<T,? extends R> function)
Convenience method to invoke the a function with the service registered as mandatory or optional dependency while holding a lock on the underlying service collector.- Type Parameters:
T
- the type of the serviceR
- the result type- Parameters:
name
- the name of the dependencyfunction
- the function to invoke with the service as argument- Returns:
- the result or
Optional.empty()
of the service was not available.
-
with
public <T,R> Optional<R> with(Class<T> clazz, Function<T,? extends R> function)
Convenience method to invoke the a function with the service registered as mandatory or optional dependency while holding a lock on the underlying service collector.- Type Parameters:
T
- the type of the serviceR
- the result type- Parameters:
clazz
- the class of the servicefunction
- the function to invoke with the service as argument- Returns:
- the result or
Optional.empty()
of the service was not available.
-
-