The OSGi framework has built-in support for the normal service primitives: publish, find, and bind. Despite their simplicity, these primitives are surprisingly powerful and have become quite popular. However, these primitives operate on information that is not completely visible to the bundles. For example, it is impossible to find out what services are being waited upon by other bundles. This information can be useful to provide a service just in time to that bundle. Additionally, it is also not possible to allow bundles functionality that interacts with the service engine. For example, a bundle could proxy another service but to do this transparently, it is required to hide the original service and offer the proxy only to a specific bundle. With the current primitives this is also not possible.
Therefore, this service hook specification provides a number of new mechanisms that closely interact with the service engine. These interactions are not intended for use by application bundles. The service primitives appear simple but require surprisingly complex code to make them appear simple to the bundle developer. Modifying the behavior of the service engine requires developers to closely follow the semantics of the OSGi service model and this is often hard, requiring a significant amount of code.
However, the service hooks provide a more symmetric model for service based programming that can act as a multiplier for the framework. The basic framework provides a powerful service engine and this specification allows a bundle to interact with this service engine
-
Robust - The service primitives are very simple and work reliably in many scenarios. The specified hooks interact with this robust service engine. This interaction must not cause disruption of the normal operations.
-
Find listeners - Provide information about the services specific bundles are interested in.
-
Control visibility - Provide a mechanism to hide the visibility of a service to one or more bundles.
-
Intercept finds - Provide a mechanism to detect the searches of a bundle in the service registry and restrict the set of found service references.
-
Whiteboard based - Use the [1] Whiteboard Pattern to simplify the writing of the interceptors.
-
Client - The bundle that finds services, gets services, and/or receives events about services.
-
Handler - The bundle that registers a hook service and uses this to view or modify the state.
-
Target - A client bundle being targeted by a Handler.
-
Publisher - A client bundle that publishes services.
-
Consumer - A client bundle that consumes services.
-
Service Engine - The internal framework machinery that makes the service registry work.
-
Event Listener Hook - An Event Listener Hook intercepts service events before they are delivered to the client. The hook can select to remove events for specific bundles, which effective allows the hook to hide service events from a bundle.
-
Find Hook - A find hook intercepts the
getServiceReference(s)
call just before it is returns the result to the client. The result can be influenced by removing service entries. The find hook can be used to hide specific services for specific bundles. -
Listener Hook - The listener hook provides insight into what services are being waited for in the system. It gets updated as service listeners are added and removed from the service registry.
A bundle that needs to hide service references from other bundles, or wants to be informed about the service events another bundle sees, can register a Find and Event Listener hook by registering a Find Hook service and an Event Listener Hook service with the framework. If a service event is generated, it will pass this event to the hook. The Event Listener Hook method can then inspect the arguments and optionally remove bundles from the event delivery list.
When a bundle uses the Bundle Context getServiceReference or
getServiceReferences
method, the Find Hook is notified with
the list of discovered services. The hook can then remove any service
references it wants to hide for the target bundle.
A bundle that wants to be aware of the services bundles are waiting for to be registered can register a Listener Hook. The framework will notify such hooks of all existing listeners as well as any changes in this list. The interceptor can use the filter information registered with the listener to detect the services that are being listened for.
Service hooks provide an interaction with the service engine. This service engine provides the following primitives to the bundle:
-
Register a service under an interface/class name with a set of properties
-
Modify the set of properties of a service
-
Unregister a service
-
Find services based on their interface class name and/or property values
-
Listen for the life cycle events of a service
These primitives provide the cornerstone for service oriented programming. Service oriented programming consists of a code base that is de-coupled from the outside world through services. It can provide services to other bundles and it can consume services from other bundles. In the OSGi variation of service oriented programming, a service is a plain Java object that can be registered and unregistered at runtime.
The dynamics of OSGi services forces bundles to consider the absence, presence, and arrival of services. The cause of these dynamics can be external events, the result of an update, a bundle that is stopped, or the disappearance of a dependent service. A number of support libraries have been developed to minimize the amount of work for the developer that these dynamics can bring. The dynamic nature of services have made them an excellent tool to handle a wide array of dependency scenarios. Services can easily model a real world concept that a bundle depends upon. The features of the service model combined with support libraries like iPOJO, Declarative Services, Spring DM, and others have made the OSGi service model easy to use and very powerful.
A key aspect of the service model is the centrality of the OSGi framework. The service model acts as a guard between bundles. All service primitives pass through the framework and bundles can not intercept the result of other bundles interacting with the service registry. This design was intentional because it creates a boundary between bundles that increases robustness and security. However, the success of the service model also means that it becomes very attractive to interact with the service engine because all inter-bundle communication runs through this engine.
For complexity reasons, this specification does not introduce any ordering dependencies between the handlers and the client bundles.
All Service Hooks must be called in a privileged block, see Privileged Callbacks.
The service hooks are general mechanisms but they were designed for some specific use cases. The following sections detail some of those use cases.
In an OSGi system, all communication is normally tunneled through services. This makes it a very interesting place for a handler to intercept the service communications. These handlers can provide facilities like proxying, extra security, authentication, and other functions completely transparent to the parties that interact through services.
Proxying an existing service for a specific bundle requires the following steps:
-
Hide the existing service X
-
Register a proxy X' with the same properties as X
Registering a proxy service X' is trivial with the OSGi API, there are no special requirements on the service. As long as it implements the listed interfaces and provides the same attributes then it can pose as service X.
Hiding service X can be implemented with a combination of the
Event Listener Hook and the Find Hook. The Event Listener Hook can be
used to hide any service events from the target bundle and the Find Hook
can be used to remove X from the delivered results of the
getServiceReference(s)
methods.
In the following figure the difference between a normal service interaction and a proxied interaction is depicted. In the normal case, Bundle A directly uses Service X, in the proxying case, the Proxy Bundle hides the original and provides an alternative.
However, there is one complication with the service hiding: what is the observing state of the target bundle when proxying begins? The Event Listener Hook must be registered to act as a filter on the service events. Just after this registration it can not determine what events have been seen by the target bundle. If it has already checked out X, the hook has no possibility to make the target bundle unget the service. A solution is to transiently stop the target bundle before the hook is registered and then transiently started it again, if the bundle is active. It is usually not advised to start/stop other bundles but this seems to be the only reliable solution. The problem can be alleviated when the start level is used to start the proxying handler bundle before the target bundles, in that case the target bundle is not started when the proxy is created. Though this optimizes the normal case, stopping the target bundle remains necessary because any of the bundles can be updated or stopped at any moment in time.
The following example shows how to hide a specific Service Reference from a specific bundle.
public class Hide implements EventListenerHook, FindHook {
final Bundle bundle;
final ServiceReference reference;
final BundleContext context;
ServiceRegistration reg;
Hide(BundleContext context,
ServiceReference reference,
Bundle bundle) {
this.context = context;
this.bundle = bundle;
this.reference = reference;
}
void open() {
boolean active =
bundle.getBundleState() == Bundle.ACTIVE;
if ( active )
bundle.stop(Bundle.STOP_TRANSIENTLY);
reg = context.registerService(
new String[] {
FindHook.class.getName(),
EventListenerHook.class.getName() }, this, null);
if ( active )
bundle.start(Bundle.START_TRANSIENTLY);
}
public void close() { reg.unregister();}
The Hide
class registers a Event Listener Hook and
Find Hook service in the open method. Once registered, these services
will receive their event callbacks. In the find hook, the target Service
Reference is removed from the results if the bundle that called the
getServiceReference(s)
method is the target bundle.
public void find(BundleContext ctx,
String name, String filter,
boolean allServices, Collection refs) {
if (ctx.getBundle() == bundle) {
refs.remove(reference);
}
}
The event method is the opposite of the find method. In this method, the target bundle is removed from the event destinations if the related Service Reference is the target Service Reference.
public void event(ServiceEvent event,
Collection bundles) {
if (event.getServiceReference().equals(
reference))
bundles.remove(bundle);
}
}
Once the Hide class is working, a proxy can be registered. For example:
void startProxy(ServiceReference ref,Bundlefor,
Object proxy ) {
Hide hide = new Hide(ctx, ref, for);
hide.open();
ServiceRegistration reg = ctx.registerService(
(String[]) ref.getProperty("objectClass"),
proxy,
makeProperties(ref) // copy the properties
);
}
...
The Listener Hook provides information about services that bundles are listening for. This makes it possible to look outside the OSGi framework to see if a listened for service could be provided in another way. For example, this service could come from Jini, SLP, or through some other means.
A Listener Hook receives events every time a bundle adds or
removes a Service Listener. The Listener Hook is called with an
added
and removed
method that take a
collection of ListenerInfo
objects. These objects provide
the identity of the bundle that added a Service Listener and the
optional filter string. The Listener Hook can use this filter string to
look for specific properties, for example the objectClass
property to determine the type that is being sought. Extracting the
property from this filter string is non-trivial though regular
expressions can in general be used to extract the needed
information.
The following class uses an unexplained Track object to do the low level details. The example only shows how the Listener Hook can interact with these track objects.
public class OnDemand implements ListenerHook{
final BundleContext context;
final Map tracked = HashMap();
ServiceRegistration reg;
The constructor saves the Bundle Context. The registration is done in an open method.
public OnDemand(BundleContext context) {
this.context = context; }
public void open() {
reg = context.registerService(
ListenerHook.class.getName(), this, null); }
The Listener Hook has added and removed methods that take collections. It is easier to handle the concurrency per object.
public void added(Collection listeners) {
for (Iterator i=listeners.iterator(); i.hasNext();) {
add((ListenerHook.ListenerInfo) i.next());
} }
public void removed(Collection listeners) {
for (Iterator i=listeners.iterator(); i.hasNext();) {
remove((ListenerHook.ListenerInfo) i.next());
} }
In the add hook, a ListenerInfo
object provides the
information about the Service Listener. In this example, a
Track
object is created for each active listener and
associated with the given info object. This requires proper
synchronization and should handle the rare case that the events are
delivered out of order. The ListenerInfo
object contains an
isRemoved
method that provides this information. If it is
true, the corresponding removed event has already been called or will be
called very soon. In that case, it is safe to discard the added event.
For proper cleanup, the reg field is tested to see if it is set, if not,
this call is during closing and should be ignored.
synchronized void add(ListenerHook.ListenerInfoinfo) {
if ( reg == null || info.isRemoved() )
return;
Track t = new Track(info);
tracked.put(info, t);
t.open();
}
To remove a Track object it is necessary to consult the tracked
map. If the track object is in the map, it must be closed. If not, there
is an out of order delivery and this event can be ignored, the add
method will ignore the corresponding ListenerInfo
object
because the isRemoved
flag will be set. For proper closing,
the reg field is tested for null
.
synchronized void remove(ListenerHook.ListenerInfoinfo){
if ( reg == null )
return;
Track t = tracked.remove(info);
if ( t != null )
t.close();
}
The close method is straightforward. The hook services are
unregistered and all the remaining Track
objects are
closed. The reg field is used to make sure the event methods are
ignoring any outstanding calls by setting it to null
. After
the synchronized block, any incoming event is ignored.
public void close() {
reg.unregister();
synchronized(this) { reg = null; }
for ( Track t : tracked.values() ) { t.close(); }
tracked.clear(); } }
To intercept events being delivered to bundles, a handler must register an EventListenerHook object as a service with the framework. The framework must then send a service events to all the registered hooks. The calling order of the hooks is defined by ranking order, see Service Ranking Order. That is, the service with the highest ranking is called first. Event Listener Hooks are called after the event is generated but before they are filtered by the optional filter expressions of the service listeners. Before the return, the handler can remove bundles from the given list. This allows an Event Listener Hook to hide service events for specific bundles.
The model is depicted in the Figure 55.4. A target bundle listens for service events but these events can be filtered by the handler because it has registered an Event Listener Hook service that is accepted by the Framework.
An Event Listener Hook receives all events, REGISTERED
,
MODIFIED
, UNREGISTERING
, and
MODIFIED_ENDMATCH
, that are to be delivered to all Service
Listener objects registered with the framework, regardless of the presence
of a service listener filter.
The EventListenerHook class has a single method:
-
event(ServiceEvent,Map) - A service event has been generated. The implementer of this method can optionally shrink the given map of target bundles to service listeners.
One of the parameters of the event
method is a map of
target bundles to a collection of ListenerInfo
objects. The
handler can shrink this map by removing bundles as well as specific
service listeners from the collection of ListenerHook.ListenerInfo objects. Both the map and the collection must
therefore implement the appropriate remove methods.
Removing a bundle from the list of target bundles will effectively hide the service event from the target bundle. The target bundle can still get the service, though the Find Hook can be used to block this access to the service.
Implementers of the Event Listener Hook must ensure that target
bundles continue to see a consistent set of service events. Service events
are normally used in a state machine. Such state machines can get confused
if some events are missed. For example, if a Service Tracker sees a
REGISTERED
event but is hidden from the corresponding
UNREGISTERING
event then the service will never be released.
A simple solution is to stop the target bundle when the filter is put in
place. However, when the bundle that implements the Event Listener Hook is
stopped, it will of course no longer be able to filter events and the
target bundle might see an service events for services it was not aware
of.
Service Listeners may be registered with the system bundle's
BundleContext
. If at least one Service Listener is
registered with the system bundle's BundleContext
then the
system bundle's BundleContext
must be contained in the keys
of the shrinkable map passed to the event(ServiceEvent,Map) method. Just like other
BundleContext
keys contained in the shrinkable map, the
system bundle's BundleContext
may be removed. If the system
bundle's BundleContext
is removed by a service Event
Listener Hook then the BundleContext
will not be contained
in the map for the remaining service Event Listener Hooks called. Unlike
other BundleContext
objects, if the system bundle's
BundleContext
is removed from the shrinkable map then the
service event is still delivered to the Service Listeners added to the
system bundle's BundleContext
.
The Find Hook is called when a target bundle searches the service
registry with the getServiceReference
or
getServiceReferences
methods. A registered Find Hook service
gets a chance to inspect the returned set of service references and can
optionally shrink the set of returned services. The calling order of the
hooks is defined by ranking order, see Service Ranking Order. That is, the service
with the highest ranking number must be called first.
-
find(BundleContext,String,String,boolean,Collection) - The callback when a bundle calls the
getServiceReference
,getServiceReferences
, orgetAllServiceReferences
method. As parameters, it gets the bundle context of the calling bundle, the service name, the filter name, the flag that indicates that all services are considered or only the ones that are class compatible with the target bundle. The last parameter is the set of service references that will be returned. This list can be shortened by removing service references form the given list.
The purpose of the Find Hook is to limit the visibility of services to selected target bundles. For this reason, the hook implementation can remove selected service references from the result collection.
When one of the getServiceReference
or
getServiceReferences
methods is called using the system
bundle's BundleContext
then the service Find Hooks are
called in the same way the hooks are called when a normal
BundleContext
is used. The system bundle's
BundleContext
along with the shrinkable candidate service
references collection is passed to the find(BundleContext,String,String,boolean,Collection) method. Service Find Hooks may remove service
references from the shrinkable collection. If a service reference is
removed by a service Find Hook then the service reference will not be
contained in the collection for the remaining service find hooks called.
Unlike other BundleContext
objects, if the system bundle's
BundleContext
is used to find services then the Framework
ignores the service reference removals performed by the service Find
Hooks and allows the service references removed to remain visible in the
find results.
The Framework API provides extensive insight in the registration, modification, and unregistration of services. However, it does not provide the information about what services bundles are waiting for. It is a common pattern that a bundle waits for a service to arrive before it is able to perform its function, having the knowledge what bundles are waiting for, allows a number of interesting scenarios.
The Listener Hook is a [1] Whiteboard Pattern service that is informed about the coming and going of all service listeners. When a Listener Hook service is registered with the Framework, the Framework will inform this service of all existing listeners and keep it updated of all removed and newly registered service listeners. The events are dispatched in order of the Listener Hook service registration.
In the following figure, it is depicted how the interceptor can find out about target bundles listening for services. It listens to registration and unregistration of Service Listeners.
The ListenerHook
interface is composed of the following
methods:
-
added(Collection) - Inform the hook of the registered listeners. The collection is immutable and contains
ListenerInfo
objects. These objects identify a uniqueServiceListener
object registration with the framework. They provide the registering bundle as well as the optional filter. TheListenerInfo
class is nested class of theListenerHook
class. -
removed(Collection) -Inform the hook of listeners that have been removed because the bundle is stopped or the bundle implementation has unregistered a listener. The
ListenerInfo
objects are equal to their corresponding Info Listener object during the addition.
The ListenerHook.ListenerInfo
class provides the
following methods:
-
getBundleContext() - The Bundle Context of the bundle that registered the service listener.
-
getFilter() - The filter used in the registration.
-
isRemoved() - Provides information if this Listener Info is still valid.
A ListenerInfo
object is related to the registration of
a ServiceListener
with the Framework. The Framework maintains
only one registration for a specific, identity based, Service Listener
object. That is, registering the same object again, even with a different
filter, will automatically unregister the previous registration. This will
be visible as a removed
- added
pair of
calls.
The equality
and hashCode
method of a
ListenerInfo
object must guarantee that the hook can place
the Listener Info objects in hashed collections, such that an
ListenerInfo
object received in the added
method's collection parameter matches its corresponding
ListenerInfo
object in the removed
method's
collection parameter. This is trivially met by the identity
equals
and hashCode
methods if the same objects
are used in both methods.
The reason the Listener Hook provides methods that take collection
instead of a single ListenerInfo
object is because of
performance optimization. When a Listener Hook service gets registered,
there can already be a large number of Service Listeners available.
Similarly, when a bundle gets stopped, it could have registered a number
of service listeners that then need to be unregistered. Being able to
provide all changes in a batch improves performance.
The framework must report each registration of a Service Listener
with the Bundle Context with a new ListenerInfo
object that
is unequal to any other ListenerInfo
object. If the same
Service Listener object is registered multiple times, each previous
registration must be removed before the listener is added again.
The event
method in a Listener Hook is called
synchronously with the registration of the Service Listener to minimize
the overhead for the framework. However, this does not imply that delivery
is always ordered. There are rare cases where a removal is reported before
the corresponding addition. Handling this case is simplified by the
isRemoved
method. If the removed
and
added
methods are synchronized, then the
isRemoved
method can be used in the added
method
to detect the out of order delivery. A simple strategy is to ignore
removed events without corresponding added events and ignore added events
where the ListenerInfo
object is already removed.
The following code shows a skeleton of how the Listener Hook methods can be implemented.
final HashMap tracked = new HashMap();
public void added( Collection lis ) {
for ( Iterator li = lis.iterator(); li.hasNext(); ) {
ListenerHook.ListenerInfo li =
(ListenerHook.ListenerInfo) li.next();
synchronized(tracked) {
if ( li.isRemoved() )
return;
... create some object t
tracked.put( li, t );
}
}
}
public void removed( Collection lis ) {
for ( Iterator li = lis.iterator(); li.hasNext(); ) {
ListenerHook.ListenerInfo li =
(ListenerHook.ListenerInfo) li.next();
synchronized(tracked) {
Object t = tracked.remove( li );
if ( t != null )
... dispose object t
}
}
}
A key concept in the Listener Hook is the filter. When a bundle is
interested in a specific set of services, it registers a service
listener with a filter. This filter is an indication of what services
are interesting to the target bundle. The objectclass
property holds the names of the interfaces and classes. However, just
searching for this property with a regular expression is not guaranteed
to return a usable value. The form of the sub-expressions can make the
property part of an and or even negate. For example, looking for the
objectclass
in the following expression gives a result that
is the opposite of what is searched.
(!(objectclass=org.osgi.service.cm.ConfigurationAdmin))
However, understanding a full filter expression is quite difficult. An acceptable strategy is to look for the object classes in the filter string with a regular expression but evaluate the filter against any conclusions that are being drawn. That is, testing a Configuration Admin service against the filter in the previous example will not match.
Realistically, many scenarios that are enabled by the Listener Hook will require the filters to have a simple structure.
The Event Listener Hook and Find Hook both allow the interceptor to remove elements from a collection and not add elements. The reason is that adding almost inevitably violates framework invariants that can trip the receivers. These invariants are very important to keep the programming model for the bundle developers simple.
All service hooks are treated as ordinary services. If the framework uses them, their Service References will show that the system bundle is using them, and if a hook is a Service Factory, then the actual instance will be properly created.
The only special treatment of the service hooks is that the framework must not use them for the hooks themselves. That is, the Event and Find Hooks can not be used to hide the services from the framework.
The hooks are very sensitive to ordering because they modify the basic behavior of the OSGi Framework. Before a hook is registered, a client bundle interacts with the framework directly. However, ordering in an OSGi Framework can never be relied upon from an programmer's perspective. It is bad practice to rely on start level ordering in a program because updates and other disturbances will inevitably break this ordering. Start level ordering is a tool for deployers to smoothen initialization problems, not to handle ordering dependencies.
Implementers of the hooks must therefore be intricately aware that they can be started before or after their target bundles are started.
Many scenarios for the hooks specified here could be simplified by
being able to intercept the getService
call of the target
bundle. This design was investigated and rejected because it created a
dependency graph (registering bundle, proxying bundle, and target
bundle) that could not be properly managed in a dynamic OSGi system. For
example, if a proxying bundle provides an alternative implementation for
a service, how does the receiving bundle know that it should stop using
this service? It has no knowledge that the proxying bundle even exists.
Instead of creating a much more complex service registry, it was decided
to keep the model simple and reuse the existing primitives. This puts
the complexity at implementing the hooks, but leaves the overall service
model simple.
All hooks in this specification must be thread safe because the hooks can be called any time. All hook methods must be re-entrant, the framework can enter them at any time, and in rare cases in the wrong order. Most methods will be called synchronously with framework activities. It is fully allowed to call the framework from any of the hook methods. However, even more than usual, it is highly recommended to not hold any locks while calling the framework.
All hooks described in this specification are highly complex facilities that require great care in their implementation to maintain the Framework invariants concerning the service registry. It is therefore important that in a secure system the permission to register these hooks is only given to privileged bundles.
In this case, the user of the hook services is the framework. Therefore, there is never a need to provide:
-
ServicePermission[..EventListenerHook,GET]
, -
ServicePermission[..FindHook,GET]
, or -
ServicePermission[..ListenerHook,GET]
Implementers of these hooks must have:
-
ServicePermission[..EventListenerHook,REGISTER]
for Event Listener Hook services. -
ServicePermission[..FindHook,REGISTER]
for Find Hook services -
ServicePermission[..ListenerHook,REGISTER]
for Listener Hook services
Framework Service Hooks Package Version 1.1.
Bundles wishing to use this package must list the package in the Import-Package header of the bundle's manifest.
Example import for consumers using the API in this package:
Import-Package: org.osgi.framework.hooks.service; version="[1.1,2.0)"
-
EventHook
- OSGi Framework Service Event Hook Service. -
EventListenerHook
- OSGi Framework Service Event Listener Hook Service. -
FindHook
- OSGi Framework Service Find Hook Service. -
ListenerHook
- OSGi Framework Service Listener Hook Service. -
ListenerHook.ListenerInfo
- Information about a Service Listener.
OSGi Framework Service Event Hook Service.
Bundles registering this service will be called during framework service (register, modify, and unregister service) operations.
As of 1.1. Replaced by EventListenerHook.
Thread-safe
The service event to be delivered.
A collection of Bundle Contexts for bundles which have
listeners to which the specified event will be delivered. The
implementation of this method may remove bundle contexts from the
collection to prevent the event from being delivered to the
associated bundles. The collection supports all the optional
Collection
operations except add
and
addAll
. Attempting to add to the collection will result in
an UnsupportedOperationException
. The collection is not
synchronized.
Event hook method. This method is called prior to service event delivery when a publishing bundle registers, modifies or unregisters a service. This method can filter the bundles which receive the event.
OSGi Framework Service Event Listener Hook Service.
Bundles registering this service will be called during framework service (register, modify, and unregister service) operations.
1.1
Thread-safe
The service event to be delivered.
A map of Bundle Contexts to a collection of Listener
Infos for the bundle's listeners to which the specified event will
be delivered. The implementation of this method may remove bundle
contexts from the map and listener infos from the collection
values to prevent the event from being delivered to the associated
listeners. The map supports all the optional Map
operations except put
and putAll
. Attempting to
add to the map will result in an
UnsupportedOperationException
. The collection values in
the map supports all the optional Collection
operations
except add
and addAll
. Attempting to add to a
collection will result in an UnsupportedOperationException
. The map and the collections are not synchronized.
Event listener hook method. This method is called prior to service event delivery when a publishing bundle registers, modifies or unregisters a service. This method can filter the listeners which receive the event.
OSGi Framework Service Find Hook Service.
Bundles registering this service will be called during framework service find (get service references) operations.
Thread-safe
The bundle context of the bundle performing the find operation.
The class name of the services to find or null
to
find all services.
The filter criteria of the services to find or null
for no filter criteria.
true
if the find operation is the result of a
call to
BundleContext.getAllServiceReferences(String, String)
A collection of Service References to be returned as a
result of the find operation. The implementation of this method
may remove service references from the collection to prevent the
references from being returned to the bundle performing the find
operation. The collection supports all the optional
Collection
operations except add
and
addAll
. Attempting to add to the collection will result in
an UnsupportedOperationException
. The collection is not
synchronized.
Find hook method. This method is called during the service find operation (for example, BundleContext.getServiceReferences(String, String) ). This method can filter the result of the find operation.
OSGi Framework Service Listener Hook Service.
Bundles registering this service will be called during service listener addition and removal.
Thread-safe
A collection of ListenerInfos for newly added
service listeners which are now listening to service events.
Attempting to add to or remove from the collection will result in
an UnsupportedOperationException
. The collection is not
synchronized.
Added listeners hook method. This method is called to provide the hook implementation with information on newly added service listeners. This method will be called as service listeners are added while this hook is registered. Also, immediately after registration of this hook, this method will be called to provide the current collection of service listeners which had been added prior to the hook being registered.
A collection of ListenerInfos for newly removed
service listeners which are no longer listening to service events.
Attempting to add to or remove from the collection will result in
an UnsupportedOperationException
. The collection is not
synchronized.
Removed listeners hook method. This method is called to provide the hook implementation with information on newly removed service listeners. This method will be called as service listeners are removed while this hook is registered.
Information about a Service Listener. This interface describes the bundle which added the Service Listener and the filter with which it was added.
Thread-safe
Consumers of this API must not implement this type
The object to compare against this ListenerInfo
.
Compares this ListenerInfo
to another ListenerInfo
.
Two ListenerInfo
s are equals if they refer to the same
listener for a given addition and removal life cycle. If the same
listener is added again, it must have a different
ListenerInfo
which is not equal to this ListenerInfo
.
true
if the other object is a ListenerInfo
object and both objects refer to the same listener for a
given addition and removal life cycle.
Return the context of the bundle which added the listener.
The context of the bundle which added the listener.
Return the filter string with which the listener was added.
The filter string with which the listener was added. This may
be null
if the listener was added without a filter.
Returns the hash code for this ListenerInfo
.
The hash code of this ListenerInfo
.
Return the state of the listener for this addition and removal life
cycle. Initially this method will return false
indicating the
listener has been added but has not been removed. After the listener
has been removed, this method must always return true
.
There is an extremely rare case in which removed notification to ListenerHooks can be made before added notification if two threads are racing to add and remove the same service listener. Because ListenerHooks are called synchronously during service listener addition and removal, the Framework cannot guarantee in-order delivery of added and removed notification for a given service listener. This method can be used to detect this rare occurrence.
false
if the listener has not been removed,
true
otherwise.
[1]Whiteboard Patternhttps://docs.osgi.org/whitepaper/whiteboard-pattern/