Class ServiceCollector<S,T>
- java.lang.Object
-
- de.mnl.osgi.coreutils.ServiceCollector<S,T>
-
- Type Parameters:
S- the type of the serviceT- the type of service instances returned by queries, usually the same type as the type of the service (seesetServiceGetter(BiFunction))
- All Implemented Interfaces:
AutoCloseable
public class ServiceCollector<S,T> extends Object implements AutoCloseable
Maintains a collection of services matching some criteria.An instance can be created with different criteria for matching services of a given type. While the instance is open, it maintains a collection of all matching services provided by the framework. Changes of the collection are reported using the registered handlers.
Because OSGi is a threaded environment, the registered services can vary any time. Results from queries on the collection are therefore only reliable while synchronizing on the
ServiceCollectorinstance. The synchronization puts other threads that attempt to change the collection on hold. Note that this implies a certain risk of creating deadlocks. Also note that this does not prevent modifications by the holder of the lock.Callbacks are always synchronized on this collector, else the state of the collector during the execution of the callback might no longer be the state that triggered the callback.
Instead of using the services from the framework directly, they may optionally be adapted to another type by setting a service getter function. The invocation of this function is also synchronized on this collector.
-
-
Constructor Summary
Constructors Constructor Description ServiceCollector(BundleContext context, Class<S> clazz)Instantiates a newServiceCollectorthat collects services of the specified class.ServiceCollector(BundleContext context, String className)Instantiates a newServiceCollectorthat collects services on the specified class name.ServiceCollector(BundleContext context, Filter filter)Instantiates a newServiceCollectorthat collects services matches by the specified filter.ServiceCollector(BundleContext context, ServiceReference<S> reference)Instantiates a newServiceCollectorthat collects services on the specified service reference.
-
Method Summary
All Methods Instance Methods Concrete Methods Modifier and Type Method Description voidclose()Stops collecting services.SortedMap<ServiceReference<S>,T>collected()Return aSortedMapof theServiceReferences and service objects for all services collected by thisServiceCollector.BundleContextgetContext()Returns the context passed to the constructor.booleanisEmpty()Return if thisServiceCollectoris empty.booleanisOpen()Checks if thisServiceCollectoris open.intmodificationCount()Returns the modification count for thisServiceCollector.voidopen()Starts collecting of service providers.voidopen(boolean collectAllServices)Starts collecting services.voidremove(ServiceReference<S> reference)Remove a service from thisServiceCollector.Optional<T>service()Returns a service object for one of the services collected by thisServiceCollector.Optional<T>service(ServiceReference<S> reference)Returns the service object for the specifiedServiceReferenceif the specified referenced service has been collected by thisServiceCollector.Optional<ServiceReference<S>>serviceReference()Returns aServiceReferencefor one of the services collected by thisServiceCollector.List<ServiceReference<S>>serviceReferences()Return the current set ofServiceReferences for all services collected by thisServiceCollector.List<T>services()Return the list of service objects for all services collected by thisServiceCollector.ServiceCollector<S,T>setOnAdded(BiConsumer<ServiceReference<S>,T> onAdded)Sets a function to be called when a new service instance was added to the collection.ServiceCollector<S,T>setOnBound(BiConsumer<ServiceReference<S>,T> onBound)Sets a function to be called when the first service instance was added to the collection.ServiceCollector<S,T>setOnModfied(BiConsumer<ServiceReference<S>,T> onModified)Sets a function to be called when the preferred service changes.ServiceCollector<S,T>setOnRemoving(BiConsumer<ServiceReference<S>,T> onRemoving)Sets a function to be called before one of the collected service instances becomes unavailable.ServiceCollector<S,T>setOnUnbinding(BiConsumer<ServiceReference<S>,T> onUnbinding)Sets a function to be called before the last of the collected service instances becomes unavailable.ServiceCollector<S,T>setServiceGetter(BiFunction<BundleContext,ServiceReference<S>,T> serviceGetter)Sets the service getter function.intsize()Return the number of services collected by thisServiceCollector.StringtoString()Optional<T>waitForService(long timeout)Wait for at least one service to be collected by thisServiceCollector.<R> Optional<R>withService(Function<T,? extends R> function)Convenience method to invoke the a function with the result fromservice()(if it is available) while holding a lock on this service collector.
-
-
-
Constructor Detail
-
ServiceCollector
public ServiceCollector(BundleContext context, Class<S> clazz)
Instantiates a newServiceCollectorthat collects services of the specified class.- Parameters:
context- the bundle context used to interact with the frameworkclazz- the clazz
-
ServiceCollector
public ServiceCollector(BundleContext context, Filter filter)
Instantiates a newServiceCollectorthat collects services matches by the specified filter.- Parameters:
context- the bundle context used to interact with the frameworkfilter- the filter
-
ServiceCollector
public ServiceCollector(BundleContext context, ServiceReference<S> reference)
Instantiates a newServiceCollectorthat collects services on the specified service reference.- Parameters:
context- the bundle context used to interact with the frameworkreference- the reference
-
ServiceCollector
public ServiceCollector(BundleContext context, String className)
Instantiates a newServiceCollectorthat collects services on the specified class name.- Parameters:
context- the bundle context used to interact with the frameworkclassName- the class name
-
-
Method Detail
-
setServiceGetter
public ServiceCollector<S,T> setServiceGetter(BiFunction<BundleContext,ServiceReference<S>,T> serviceGetter)
Sets the service getter function. Instead of simply getting the service from the bundle using the givenServiceReferencesome additional processing may be performed such as adapting the service obtained to another interface.A possible use case scenario for this feature consists of two service types with different APIs but overlapping functionality. If the consumer needs only the common functionality, it may collect both service types and adapt the services obtained.
If the function returns
null, no service is added to the collection. The function can thus also be used as a filter.- Parameters:
serviceGetter- the function- Returns:
- the service collector
-
setOnBound
public ServiceCollector<S,T> setOnBound(BiConsumer<ServiceReference<S>,T> onBound)
Sets a function to be called when the first service instance was added to the collection. The reference to the new service and the service instance are passed as arguments.The function is called before a callback set by
setOnAdded(BiConsumer).- Parameters:
onBound- the function to be called- Returns:
- the
ServiceCollector
-
setOnAdded
public ServiceCollector<S,T> setOnAdded(BiConsumer<ServiceReference<S>,T> onAdded)
Sets a function to be called when a new service instance was added to the collection. The reference to the new service and the service instance are passed as arguments.- Parameters:
onAdded- the function to be called- Returns:
- the
ServiceCollector
-
setOnRemoving
public ServiceCollector<S,T> setOnRemoving(BiConsumer<ServiceReference<S>,T> onRemoving)
Sets a function to be called before one of the collected service instances becomes unavailable. The reference to the service to be removed and the service instance are passed as arguments.- Parameters:
onRemoving- the function to call- Returns:
- the
ServiceCollector
-
setOnUnbinding
public ServiceCollector<S,T> setOnUnbinding(BiConsumer<ServiceReference<S>,T> onUnbinding)
Sets a function to be called before the last of the collected service instances becomes unavailable. The reference to the service to be removed and the service instance are passed as arguments.The function is called after a callback set by
setOnRemoving(BiConsumer)).- Parameters:
onUnbinding- the function to call- Returns:
- the
ServiceCollector
-
setOnModfied
public ServiceCollector<S,T> setOnModfied(BiConsumer<ServiceReference<S>,T> onModified)
Sets a function to be called when the preferred service changes. This may either be a change of the preferred service's properties (reported by the framework) or the replacement of the preferred service by another service. The service reference to the modified service and the service are passed as arguments.If the preferred service is replaced by another service, this function is called after the "onAdded" or "onRemoved" callback.
- Parameters:
onModified- the function to call- Returns:
- the
ServiceCollector
-
getContext
public BundleContext getContext()
Returns the context passed to the constructor.- Returns:
- the context
-
open
public void open() throws IllegalStateException
Starts collecting of service providers. Short for callingopen(false).- Throws:
IllegalStateException- If theBundleConetxtwith which thisServiceCollectorwas created is no longer valid.
-
open
public void open(boolean collectAllServices) throws IllegalStateException
Starts collecting services. Short for callingopen(false).- Parameters:
collectAllServices- iftrue, then thisServiceCollectorwill collect all matching services regardless of class loader accessibility. Iffalse, then thisServiceCollectorwill only collect matching services which are class loader accessible to the bundle whoseBundleContextis used by thisServiceCollector.- Throws:
IllegalStateException- If theBundleConetxtwith which thisServiceCollectorwas created is no longer valid.
-
close
public void close()
Stops collecting services.- Specified by:
closein interfaceAutoCloseable
-
waitForService
public Optional<T> waitForService(long timeout) throws InterruptedException
Wait for at least one service to be collected by thisServiceCollector. This method will also return when thisServiceCollectoris closed from another thread.It is strongly recommended that
waitForServiceis not used during the calling of theBundleActivatormethods.BundleActivatormethods are expected to complete in a short period of time.- Parameters:
timeout- The time interval in milliseconds to wait. If zero, the method will wait indefinitely.- Returns:
- Returns the result of
service(). - Throws:
InterruptedException- If another thread has interrupted the current thread.IllegalArgumentException- If the value of timeout is negative.
-
serviceReferences
public List<ServiceReference<S>> serviceReferences()
Return the current set ofServiceReferences for all services collected by thisServiceCollector.- Returns:
- the set.
-
serviceReference
public Optional<ServiceReference<S>> serviceReference()
Returns aServiceReferencefor one of the services collected by thisServiceCollector.If multiple services have been collected, the service with the highest ranking (as specified in its
service.rankingproperty) is returned. If there is a tie in ranking, the service with the lowest service id (as specified in itsservice.idproperty); that is, the service that was registered first is returned. This is the same algorithm used byBundleContext.getServiceReference.- Returns:
- an optional
ServiceReference
-
service
public Optional<T> service(ServiceReference<S> reference)
Returns the service object for the specifiedServiceReferenceif the specified referenced service has been collected by thisServiceCollector.- Parameters:
reference- the reference to the desired service.- Returns:
- an optional service object
-
service
public Optional<T> service()
Returns a service object for one of the services collected by thisServiceCollector. This is effectively the same asserviceReference().flatMap(ref -> service(ref)).The result value is cached, so refrain from implementing another cache in the invoking code.
- Returns:
- an optional service object
-
withService
public <R> Optional<R> withService(Function<T,? extends R> function)
Convenience method to invoke the a function with the result fromservice()(if it is available) while holding a lock on this service collector.- Type Parameters:
R- the result type- Parameters:
function- the function to invoke with the service as argument- Returns:
- the result or
Optional.empty()of the service was not available.
-
services
public List<T> services()
Return the list of service objects for all services collected by thisServiceCollector. This is effectively a mapping ofserviceReferences()to services.- Returns:
- a list of service objects which may be empty
-
size
public int size()
Return the number of services collected by thisServiceCollector. This value may not be correct during the execution of handlers.- Returns:
- The number of services collected
-
modificationCount
public int modificationCount()
Returns the modification count for thisServiceCollector. The modification count is initialized to 0 when thisServiceCollectoris opened. Every time a service is added, modified or removed from thisServiceCollector, the modification count is incremented.The modification count can be used to determine if this
ServiceCollectorhas added, modified or removed a service by comparing a modification count value previously collected with the current modification count value. If the value has not changed, then no service has been added, modified or removed from thisServiceCollectorsince the previous modification count was collected.- Returns:
- The modification count for this
ServiceCollectoror -1 if thisServiceCollectoris not open.
-
isOpen
public boolean isOpen()
Checks if thisServiceCollectoris open.- Returns:
- true, if is open
-
collected
public SortedMap<ServiceReference<S>,T> collected()
Return aSortedMapof theServiceReferences and service objects for all services collected by thisServiceCollector. The map is sorted in reverse natural order ofServiceReference. That is, the first entry is the service with the highest ranking and the lowest service id.- Returns:
- A
SortedMapwith theServiceReferences and service objects for all services collected by thisServiceCollector. If no services have been collected, then the returned map is empty.
-
isEmpty
public boolean isEmpty()
Return if thisServiceCollectoris empty.- Returns:
trueif thisServiceCollectorhas not collected any services.
-
remove
public void remove(ServiceReference<S> reference)
Remove a service from thisServiceCollector. The specified service will be removed from thisServiceCollector.- Parameters:
reference- The reference to the service to be removed.
-
-