The Framework provides a powerful and very dynamic programming environment: Bundles are installed, started, stopped, updated, and uninstalled without shutting down the Framework. Dependencies between bundles are monitored by the Framework, but bundles must cooperate in handling these dependencies correctly. Two important dynamic aspects of the Framework are the service registry and the set of installed bundles.
Bundle developers must be careful not to use service objects that have been unregistered and are therefore stale. The dynamic nature of the Framework service registry makes it necessary to track the service objects as they are registered and unregistered to prevent problems. It is easy to overlook race conditions or boundary conditions that will lead to random errors. Similar problems exist when tracking the set of installed bundles and their state.
This specification defines two utility classes,
ServiceTracker
and BundleTracker
, that make
tracking services and bundles easier. A ServiceTracker
class
can be customized by implementing the
ServiceTrackerCustomizer
interface or by sub-classing the
ServiceTracker
class. Similarly, a BundleTracker
class can be customized by sub-classing or implementing the
BundleTrackerCustomizer
interface.
These utility classes significantly reduce the complexity of tracking services in the service registry and the set of installed bundles.
-
Simplify - Make it simple to tracking services or bundles.
-
Customizable - Allow a default implementation to be customized so that bundle developers can start simply and later extend the implementation to meet their needs.
-
Small - Every Framework implementation should have this utility implemented. It should therefore be very small because some Framework implementations target minimal OSGi frameworks.
-
Services - Track a set of services, optionally filtered, or track a single service.
-
Bundles - Track bundles based on their state.
-
Cleanup - Properly clean up when tracking is no longer necessary
-
Generified - Generics are used to promote type safety.
The fundamental tasks of a tracker are:
-
To create an initial list of targets (service or bundle).
-
To listen to the appropriate events so that the targets are properly tracked.
-
To allow the client to customize the tracking process through programmatic selection of the services/bundles to be tracked, as well as to perform client code when a service/bundle is added or removed.
A ServiceTracker
object is populated with a set of
services that match given search criteria, and then listens to
ServiceEvent
objects which correspond to those services. A
Bundle Tracker is populated with the set of installed bundles and then
listens to BundleEvent
objects to notify the customizer of
changes in the state of the bundles.
The OSGi Framework is a dynamic multi-threaded environment. In such an environments callbacks can occur on different threads at the same time. This dynamism causes many complexities. One of the surprisingly hard aspects of this environment is to reliably track services and bundles (called targets from now on).
The complexity is caused by the fact that the
BundleListener
and ServiceListener
interfaces
are only providing access to the changed state, not
to the existing state when the listener is registered. This leaves the
programmer with the problem to merge the set of existing targets with the
changes to the state as signified by the events, without unwantedly
duplicating a target or missing a remove event that would leave a target
in the tracked map while it is in reality gone. These problems are caused
by the multi-threaded nature of OSGi.
The problem is illustrated with the following (quite popular) code:
// Bad Example! Do not do this!
Bundle[] bundles = context.getBundles();
for ( Bundle bundle : bundles ) {
map.put(bundle.getLocation(), bundle );
}
context.addBundleListener( new BundleListener() {
public void bundleChanged(BundleEvent event) {
Bundle bundle = event.getBundle();
switch(event.getType()) {
case BundleEvent.INSTALLED:
map.put(bundle.getLocation(), bundle );
break;
case BundleEvent.UNINSTALLED:
map.remove(bundle.getLocation());
break;
default:
// ignore
}
}
});
Assume the code runs the first part, getting the existing targets. If during this time a targets state changes, for example bundle is installed or uninstalled, then the event is missed and the map will miss a bundle or it will contain a bundle that is already gone. An easy solution seems to be to first register the listener and then get the existing targets. This solves the earlier problem but will be introduce other problems. In this case, an uninstall event can occur before the bundle has been discovered.
Proper locking can alleviate the problem but it turns out that this easily create solutions that are very prone to deadlocks. Solving this tracking problem is surprisingly hard. For this reason, the OSGi specifications contain a bundle tracker and a service tracker that are properly implemented. These classes significantly reduce the complexity of the dynamics in an OSGi framework.
Trackers can be used with the following patterns:
-
As-is - Each tracker can be used without further customizing. A tracker actively tracks a map of targets and this map can be consulted with a number of methods when the information is needed. This is especially useful for the Service Tracker because it provides convenience methods to wait for services to arrive.
-
Callback object - Each tracker provides a call back interface that can be implemented by the client code.
-
Sub-classing - The trackers are designed to be sub-classed. Sub-classes have access to the bundle context and only have to override the callback methods they need.
A tracker hides the mechanisms in the way the targets are stored
and evented. From a high level, a tracker maintains a
map of targets to wrapper
objects. The wrapper object can be defined by the client, though the
Bundle Tracker uses the Bundle
object and the Service
Tracker uses the service object as default wrapper. The tracker notifies
the client of any changes in the state of the target.
A tracker must be constructed with a Bundle Context. This context
is used to register listeners and obtain the initial list of targets
during the call to the open
method. At the end of the life
of a tracker it must be closed to release any remaining objects. It is
advised to properly close all trackers in the bundle activator's stop
method.
A tracker provides a uniform callback interface, which has 3 different methods.
-
Adding - Provide a new object, obtained from the store or from an event and return the wrapper or a related object. The adding method can decide not to track the target by returning a
null
object. When null is returned, no modified or remove methods are further called. However, it is possible that the adding method is called again for the same target. -
Modified - The target is modified. For example, the service properties have changed or the bundle has changed state. This callback provides a mechanism for the client to update its internal structures. The callback provides the wrapper object.
-
Removing - The target is no longer tracked. This callback is provided the wrapper object returned from the adding method. This allows for simplified cleanup if the client maintains state about the target.
Each tracker is associated with a callback interface, which it
implements itself. That is, a Service Tracker implements the
ServiceTrackerCustomizer
interface. By implementing this
customizer, the tracker can also be sub-classed, this can be quite
useful in many cases. Sub-classing can override only one or two of the
methods instead of having to implement all methods. When overriding the
callback methods, it must be ensured that the wrapper object is treated
accordingly to the base implementation in all methods. For example, the
Service Tracker's default implementation for the adding method checks
out the service and therefore the remove method must unget this same
service. Changing the wrapper object type to something else can
therefore clash with the default implementations.
Trackers can provide all the objects that are tracked, return the mapped wrapper from the target, and deliver the number of tracked targets.
The tracker also maintains a count that is updated each time that an object is added, modified, or removed, that is any change to the implied map. This tracking count makes it straightforward to verify that a tracker has changed; just store the tracking count and compare it later to see if it has changed.
The dynamic environment of OSGi requires that tracker are thread safe. However, the tracker closely interacts with the client through a callback interface. The tracker implementation must provide the following guarantees:
-
The tracker code calling a callback must not hold any locks
Clients must be aware that their callbacks are reentrant though the tracker implementations guarantee that the add/modified/remove methods can only called in this order for a specific target. A tracker must not call these methods out of order.
The purpose of a Service Tracker is to track service
references, that is, the target is the
ServiceReference
object. The Service Tracker uses generics to
provide a type safe interface. It has two type arguments:
-
S
- The service type. -
T
- The type used by the program.T
can differ from S if the program creates a wrapper around the service object, a common pattern.
The ServiceTracker
interface defines
three constructors to create ServiceTracker
objects, each
providing different search criteria:
-
ServiceTracker(BundleContext,String,ServiceTrackerCustomizer) - This constructor takes a service interface name as the search criterion. The
ServiceTracker
object must then track all services that are registered under the specified service interface name. -
ServiceTracker(BundleContext,Filter,ServiceTrackerCustomizer) - This constructor uses a
Filter
object to specify the services to be tracked. TheServiceTracker
must then track all services that match the specified filter. -
ServiceTracker(BundleContext,ServiceReference,ServiceTrackerCustomizer) - This constructor takes a
ServiceReference
object as the search criterion. TheServiceTracker
must then track only the service that corresponds to the specifiedServiceReference
. Using this constructor, no more than one service must ever be tracked, because aServiceReference
refers to a specific service. -
ServiceTracker(BundleContext,Class,ServiceTrackerCustomizer) - This constructor takes a class as argument. The tracker must only track services registered with this name. This is in general the most convenient way to use the Service Tracker.
Each of the ServiceTracker
constructors takes a
BundleContext
object as a parameter. This
BundleContext
object must be used by a
ServiceTracker
object to track, get, and unget
services.
A new ServiceTracker
object must not begin tracking
services until its open
method is called. There are 2
versions of the open method:
-
open() - This method is identical to
open(false)
. It is provided for backward compatibility reasons. -
open(boolean) - The tracker must start tracking the services as were specified in its constructor. If the boolean parameter is
true
, it must track all services, regardless if they are compatible with the bundle that created the Service Tracker or not. See Multiple Version Export Considerations for a description of the compatibility issues when multiple variations of the same package can exist. If the parameter isfalse
, the Service Tracker must only track compatible versions.
Once a ServiceTracker
object is opened, it begins
tracking services immediately. A number of methods are available to the
bundle developer to monitor the services that are being tracked,
including the ones that are in the service registry at that time. The
ServiceTracker
class defines these methods:
-
getService() - Returns one of the services being tracked or
null
if there are no active services being tracked. -
getServices() - Returns an array of all the tracked services. The number of tracked services is returned by the
size
method. -
getServices(T[]) - Like getServices() but provides a convenient way to get these services into a correctly typed array.
-
getServiceReference() - Returns a
ServiceReference
object for one of the services being tracked. The service object for this service may be returned by calling theServiceTracker
object'sgetService()
method. -
getServiceReferences() - Returns a list of the
ServiceReference
objects for services being tracked. The service object for a specific tracked service may be returned by calling theServiceTracker
object'sgetService(ServiceReference)
method. -
waitForService(long) - Allows the caller to wait until at least one instance of a service is tracked or until the time-out expires. If the time-out is zero, the caller must wait until at least one instance of a service is tracked.
waitForService
must not used within theBundleActivator
methods, as these methods are expected to complete in a short period of time. A Framework could wait for the start method to complete before starting the bundle that registers the service for which the caller is waiting, creating a deadlock situation. -
remove(ServiceReference) - This method may be used to remove a specific service from being tracked by the
ServiceTracker
object, causingremovedService
to be called for that service. -
close() - This method must remove all services being tracked by the
ServiceTracker
object, causingremovedService
to be called for all tracked services. -
getTrackingCount() - A Service Tracker can have services added, modified, or removed at any moment in time. The
getTrackingCount
method is intended to efficiently detect changes in a Service Tracker. Every time the Service Tracker is changed, it must increase the tracking count. -
isEmpty() - To detect that the tracker has no tracked services.
-
getTracked() - Return the tracked objects.
The behavior of the ServiceTracker
class can be
customized either by providing a ServiceTrackerCustomizer
object, implementing the desired behavior when the
ServiceTracker
object is constructed, or by sub-classing
the ServiceTracker
class and overriding the
ServiceTrackerCustomizer
methods.
The ServiceTrackerCustomizer
interface defines these
methods:
-
addingService(ServiceReference) - Called whenever a service is being added to the
ServiceTracker
object. -
modifiedService(ServiceReference,T) - Called whenever a tracked service is modified.
-
removedService(ServiceReference,T) - Called whenever a tracked service is removed from the
ServiceTracker
object.
When a service is being added to the ServiceTracker
object or when a tracked service is modified or removed from the
ServiceTracker
object, it must call
addingService
, modifiedService
, or
removedService
, respectively, on the
ServiceTrackerCustomizer
object (if specified when the
ServiceTracker
object was created); otherwise it must call
these methods on itself.
A bundle developer may customize the action when a service is
tracked. Another reason for customizing the ServiceTracker
class is to programmatically select which services are tracked. A filter
may not sufficiently specify the services that the bundle developer is
interested in tracking. By implementing addingService
, the
bundle developer can use additional runtime information to determine if
the service should be tracked. If null
is returned by the
addingService
method, the service must not be
tracked.
Finally, the bundle developer can return a specialized object from
addingService
that differs from the service object. This
specialized object could contain the service object and any associated
information. This returned object is then tracked instead of the service
object. When the removedService
method is called, the
object that is passed along with the ServiceReference
object is the one that was returned from the earlier call to the
addingService
method.
An example of customizing the action taken when a service is
tracked might be registering a MyServlet
object with each
Http Service that is tracked. This customization could be done by
sub-classing the ServiceTracker
class and overriding the
addingService
and removedService
methods as
follows:
new ServiceTracker<HttpService,MyServlet>(context,HttpService.class,null){
public MyServlet addingService( ServiceReference<HttpService>reference) {
HttpService svc = context.getService(reference);
MyServlet ms = new MyServlet(scv); return ms;
}
public void removedService( ServiceReference<HttpService>reference,
MyServlet ms) {
ms.close();
context.ungetService(reference);
}
}
In this example, the service type is the HttpService
class and the wrapper type is the servlet.
The purpose of the Bundle Tracker is to simplify tracking bundles. A popular example where bundles need to be tracked is the extender pattern. An extender uses information in other bundles to provide its function. For example, a Declarative Services implementation reads the component XML file from the bundle to learn of the presence of any components in that bundle.
There are, however, other places where it is necessary to track bundles. The Bundle Tracker significantly simplifies this task.
The state diagram of a Bundle is significantly more complex than that of a service. However, the interface is simpler because there is only a need to specify for which states the bundle tracker should track a service.
Bundle states are defined as a bit in an integer, allowing the
specifications of multiple states by setting multiple bits. The Bundle
Tracker therefore uses a bit mask to specify which
states are of interest. For example, if a client is interested in active
and resolved bundles, it is possible to specify the Bundle
ACTIVE | RESOLVED | STARTING
states in the mask.
The Bundle Tracker tracks bundles whose state matches the mask. That is, when a bundle is not tracked it adds that bundle to the tracked map when its state matches the mask. If the bundle reaches a new state that is not listed in the mask, the bundle will be removed from the tracked map. If the state changes but the bundle should still be tracked, then the bundle is considered to be modified.
The BundleTracker
interface defines the following
constructors to create BundleTracker
objects:
-
BundleTracker(BundleContext,int,BundleTrackerCustomizer) - Create a Bundle Tracker that tracks the bundles which state is listed in the mask. The customizer may be
null
, in that case the callbacks can be implemented in a subclass.
A new BundleTracker
object must not begin tracking
services until its open
method is called.
-
open() - Start tracking the bundles, callbacks can occur before this method is called.
Once a BundleTracker
object is opened, it begins
tracking bundles immediately. A number of methods are available to the
bundle developer to monitor the bundles that are being tracked. The
BundleTracker
class defines the following methods:
-
getBundles() - Returns an array of all the tracked bundles.
-
getObject(Bundle) - Returns the wrapper object that was returned from the
addingBundle
method. -
remove(Bundle) - Removes the bundle from the tracked bundles. The
removedBundle
method is called when the bundle is not in the tracked map. -
size() - Returns the number of bundles being tracked.
-
getTrackingCount() - A Bundle Tracker can have bundles added, modified, or removed at any moment in time. The
getTrackingCount
method is intended to efficiently detect changes in a Bundle Tracker. Every time the Bundle Tracker is changed, it must increase the tracking count. -
isEmpty() - To detect that the tracker has no tracked bundles.
-
getTracked() - Return the tracked objects.
The behavior of the BundleTracker
class can be
customized either by providing a BundleTrackerCustomizer
object when the BundleTracker
object is constructed, or by
sub-classing the BundleTracker
class and overriding the
BundleTrackerCustomizer
methods on the
BundleTracker
class.
The BundleTrackerCustomizer
interface defines these
methods:
-
addingBundle(Bundle,BundleEvent) - Called whenever a bundle is being added to the
BundleTracker
object. This method should return a wrapper object, which can be theBundle
object itself. Ifnull
is returned, the Bundle must not be further tracked. -
modifiedBundle(Bundle,BundleEvent,T) - Called whenever a tracked bundle is modified. The object that is passed is the object returned from the
addingBundle
method, the wrapper object. -
removedBundle(Bundle,BundleEvent,T) - Called whenever a tracked bundle is removed from the
BundleTracker
object. The passed object is the wrapper returned from theaddingBundle
method.
The BundleEvent
object in the previous methods can be
null
.
When a bundle is being added the OSGi Framework, or when a tracked
bundle is modified or uninstalled from the OSGi Framework, the Bundle
Tracker must call addingBundle
,
modifiedBundle
, or removedBundle
,
respectively, on the BundleTrackerCustomizer
object (if
specified when the BundleTracker
object was created);
otherwise it must call these methods on itself, allowing them to be
overridden in a subclass.
The bundle developer can return a specialized object from
addingBundle
that differs from the Bundle
object. This wrapper object could contain the Bundle
object
and any associated client specific information. This returned object is
then used as the wrapper instead of the Bundle
object. When
the removedBundle
method is called, the wrapper is passed
as an argument.
The Bundle Tracker allows the implementation of extenders with surprisingly little effort. The following example checks a manifest header (Http-Mapper) in all active bundles to see if the bundle has resources that need to be mapped to the HTTP service. This extender enables bundles that have no code, just content.
This example is implemented with a
BundleTrackerCustomizer
implementation, though sub-classing
the BundleTracker
class is slightly simpler because the
open/close methods would be inherited, the tracker field is not
necessary and it is not necessary to provide a dummy implementation of
modifiedBundle
method. However, the Service Tracker example
already showed how to use inheritance.
The Extender class must implement the customizer and declare fields for the Http Service and a Bundle Tracker.
public class Extender implements BundleTrackerCustomizer<ExtenderContext>{
final HttpService http;
final BundleTracker<ExtenderContext> tracker;
It is necessary to parse the Http-Mapper header. Regular expression allow this to be done very concise.
final static Pattern HTTPMAPPER =
Pattern.compile(
"\\s*([-/\\w.]+)\\s*=\\s*([-/\\w.]+)\\s*");
The Bundle Tracker requires a specialized constructor. This example only works for active bundles. This implies that a bundle only provides contents when it is started, enabling an administrator to control the availability.
Extender(BundleContext context, HttpServicehttp) {
tracker = new BundleTracker<ExtenderContext>(
context,Bundle.ACTIVE, this );
this.http = http;
}
The following method implements the callback from the Bundle
Tracker when a new bundle is discovered. In this method a specialized
HttpContext
object is created that knows how to retrieve
its resources from the bundle that was just discovered. This context is
registered with the Http Service. If no header is found
null
is returned so that non-participating bundles are no
longer tracked.
public ExtenderContext addingBundle(Bundlebundle,
BundleEvent event) {
String header = bundle.getHeaders()
.get("Http-Mapper") + "";
Matcher match = HTTPMAPPER.matcher(header);
if (match.matches()) {
try {
ExtenderContext wrapper =
new ExtenderContext(bundle, match.group(1));
http.registerResources(
match.group(1), // alias
match.group(2), // resource path
wrapper // the http context
);
return wrapper;
} catch (NamespaceException nspe) {
// error is handled in the fall through
}
}
System.err.println(
"Invalid header for Http-Mapper: " + header);
return null;
}
The modifiedBundle
method does not have to be
implemented because this example is not interested in state changes
because the only state of interest is the ACTIVE
state.
Therefore, the remaining method left to implement is the
removedBundle
method. If the wrapper object is non-null
then we need to unregister the alias to prevent collisions in the http
namespace when the bundle is reinstalled or updated.
public void removedBundle(
Bundle bundle, BundleEvent event,
ExtenderContext wrapper) {
http.unregister(wrapper.alias);
}
The remaining methods would be unnecessary if the
Extender
class had extended the BundleTracker
class. The BundleTrackerCustomizer
interface requires a
dummy implementation of the modifiedBundle
method:
public void modifiedBundle(
Bundle bundle, BundleEvent event, ExtenderContext object){
// Nothing to do
}
It is usually not a good idea to start a tracker in a constructor
because opening a service tracker will immediately cause a number of
callbacks for the existing bundles. If the Extender
class
was sub-classed, then this could call back the uninitialized sub class
methods. It is therefore better to separate the initialization from the
opening. There is therefore a need for an open
and
close
method.
public void close() {
tracker.close();
}
public void open() {
tracker.open();
}
}
The previous example uses an HttpContext
subclass
that can retrieve resources from the target bundle:
public class ExtenderContext implements HttpContext{
final Bundle bundle;
final String alias;
ExtenderContext(Bundle bundle, String alias) {
this.bundle = bundle;
this.alias = alias;
}
public boolean handleSecurity(
HttpServletRequest rq, HttpServletResponse rsp) {
return true;
}
public String getMimeType(String name) {
return null;
}
public URL getResource(String name) {
return bundle.getResource(name);
}
}
A tracker contains a BundleContext
instance variable
that is accessible to the methods in a subclass. A
BundleContext
object should never be given to other bundles
because it is a capability. The framework makes
allocations based on the bundle context with respect to security and
resource management.
The tracker implementations do not have a method to get the
BundleContext
object, however, subclasses should be careful
not to provide such a method if the tracker is given to other
bundles.
The services that are being tracked are available via a
ServiceTracker
. These services are dependent on the
BundleContext
as well. It is therefore necessary to do a
careful security analysis when ServiceTracker
objects are
given to other bundles. The same counts for the Bundle Tracker. It is
strongly advised to not pass trackers to other bundles.
The Bundle Tracker uses the synchronous bundle listener because it
is impossible to provide some of the guarantees the Bundle Tracker
provides without handling the events synchronously. Synchronous events
can block the complete system, therefore Synchronous Bundle Listeners
require AdminPermission[*,LISTENER]
. The wildcard * can be
replaced with a specifier for the bundles that should be visible to the
Bundle Tracker. See Admin Permission for more
information.
Code that calls the open
and close
methods of Bundle Trackers must therefore have the appropriate Admin
Permission.
Tracker Package Version 1.5.
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.util.tracker; version="[1.5,2.0)"
-
BundleTracker
- TheBundleTracker
class simplifies tracking bundles much like theServiceTracker
simplifies tracking services. -
BundleTrackerCustomizer
- TheBundleTrackerCustomizer
interface allows aBundleTracker
to customize theBundle
s that are tracked. -
ServiceTracker
- TheServiceTracker
class simplifies using services from the Framework's service registry. -
ServiceTrackerCustomizer
- TheServiceTrackerCustomizer
interface allows aServiceTracker
to customize the service objects that are tracked.
The type of the tracked object.
The BundleTracker
class simplifies tracking bundles much like the
ServiceTracker
simplifies tracking services.
A BundleTracker
is constructed with state criteria and a
BundleTrackerCustomizer
object. A BundleTracker
can use the
BundleTrackerCustomizer
to select which bundles are tracked and to
create a customized object to be tracked with the bundle. The
BundleTracker
can then be opened to begin tracking all bundles whose
state matches the specified state criteria.
The getBundles
method can be called to get the Bundle
objects
of the bundles being tracked. The getObject
method can be called to
get the customized object for a tracked bundle.
The BundleTracker
class is thread-safe. It does not call a
BundleTrackerCustomizer
while holding any locks.
BundleTrackerCustomizer
implementations must also be thread-safe.
1.4
Thread-safe
The BundleContext
against which the tracking is
done.
The bit mask of the OR
ing of the bundle states
to be tracked.
The customizer object to call when bundles are added,
modified, or removed in this BundleTracker
. If customizer
is null
, then this BundleTracker
will be used as
the BundleTrackerCustomizer
and this BundleTracker
will call the BundleTrackerCustomizer
methods on itself.
Create a BundleTracker
for bundles whose state is present in the
specified state mask.
Bundles whose state is present on the specified state mask will be
tracked by this BundleTracker
.
The Bundle
being added to this
BundleTracker
object.
The bundle event which caused this customizer method to be
called or null
if there is no bundle event associated with
the call to this method.
Default implementation of the
BundleTrackerCustomizer.addingBundle
method.
This method is only called when this BundleTracker
has been
constructed with a null BundleTrackerCustomizer
argument.
This implementation simply returns the specified Bundle
.
This method can be overridden in a subclass to customize the object to be tracked for the bundle being added.
The specified bundle.
Close this BundleTracker
.
This method should be called when this BundleTracker
should end
the tracking of bundles.
This implementation calls getBundles() to get the list of tracked bundles to remove.
Return an array of Bundle
s for all bundles being tracked by this
BundleTracker
.
An array of Bundle
s or null
if no bundles are
being tracked.
The Bundle
being tracked.
Returns the customized object for the specified Bundle
if the
specified bundle is being tracked by this BundleTracker
.
The customized object for the specified Bundle
or
null
if the specified Bundle
is not being
tracked.
Return a Map
with the Bundle
s and customized objects for
all bundles being tracked by this BundleTracker
.
A Map
with the Bundle
s and customized objects for
all services being tracked by this BundleTracker
. If no
bundles are being tracked, then the returned map is empty.
1.5
Returns the tracking count for this BundleTracker
.
The tracking count is initialized to 0 when this BundleTracker
is
opened. Every time a bundle is added, modified or removed from this
BundleTracker
the tracking count is incremented.
The tracking count can be used to determine if this BundleTracker
has added, modified or removed a bundle by comparing a tracking count
value previously collected with the current tracking count value. If the
value has not changed, then no bundle has been added, modified or removed
from this BundleTracker
since the previous tracking count was
collected.
The tracking count for this BundleTracker
or -1 if this
BundleTracker
is not open.
Return if this BundleTracker
is empty.
true
if this BundleTracker
is not tracking any
bundles.
1.5
The Bundle
whose state has been modified.
The bundle event which caused this customizer method to be
called or null
if there is no bundle event associated with
the call to this method.
The customized object for the specified Bundle.
Default implementation of the
BundleTrackerCustomizer.modifiedBundle
method.
This method is only called when this BundleTracker
has been
constructed with a null BundleTrackerCustomizer
argument.
This implementation does nothing.
BundleTrackerCustomizer.modifiedBundle(Bundle, BundleEvent, Object)
Open this BundleTracker
and begin tracking bundles.
Bundle which match the state criteria specified when this
BundleTracker
was created are now tracked by this
BundleTracker
.
IllegalStateException
– If the BundleContext
with
which this BundleTracker
was created is no longer valid.
SecurityException
– If the caller and this class do not
have the appropriate
AdminPermission[context bundle,LISTENER]
, and the Java
Runtime Environment supports permissions.
The Bundle
to be removed.
Remove a bundle from this BundleTracker
.
The specified bundle will be removed from this BundleTracker
. If
the specified bundle was being tracked then the
BundleTrackerCustomizer.removedBundle
method will be called for
that bundle.
The Bundle
being removed.
The bundle event which caused this customizer method to be
called or null
if there is no bundle event associated with
the call to this method.
The customized object for the specified bundle.
Default implementation of the
BundleTrackerCustomizer.removedBundle
method.
This method is only called when this BundleTracker
has been
constructed with a null BundleTrackerCustomizer
argument.
This implementation does nothing.
BundleTrackerCustomizer.removedBundle(Bundle, BundleEvent, Object)
The type of the tracked object.
The BundleTrackerCustomizer
interface allows a BundleTracker
to customize the Bundle
s that are tracked. A
BundleTrackerCustomizer
is called when a bundle is being added to a
BundleTracker
. The BundleTrackerCustomizer
can then return an
object for the tracked bundle. A BundleTrackerCustomizer
is also
called when a tracked bundle is modified or has been removed from a
BundleTracker
.
The methods in this interface may be called as the result of a
BundleEvent
being received by a BundleTracker
. Since
BundleEvent
s are received synchronously by the BundleTracker
,
it is highly recommended that implementations of these methods do not alter
bundle states while being synchronized on any object.
The BundleTracker
class is thread-safe. It does not call a
BundleTrackerCustomizer
while holding any locks.
BundleTrackerCustomizer
implementations must also be thread-safe.
1.4
Thread-safe
The Bundle
being added to the BundleTracker
.
The bundle event which caused this customizer method to be
called or null
if there is no bundle event associated with
the call to this method.
A bundle is being added to the BundleTracker
.
This method is called before a bundle which matched the search parameters
of the BundleTracker
is added to the BundleTracker
. This
method should return the object to be tracked for the specified
Bundle
. The returned object is stored in the
BundleTracker
and is available from the
getObject method.
The object to be tracked for the specified Bundle
object
or null
if the specified Bundle
object should not
be tracked.
The Bundle
whose state has been modified.
The bundle event which caused this customizer method to be
called or null
if there is no bundle event associated with
the call to this method.
The tracked object for the specified bundle.
A bundle tracked by the BundleTracker
has been modified.
This method is called when a bundle being tracked by the
BundleTracker
has had its state modified.
The Bundle
that has been removed.
The bundle event which caused this customizer method to be
called or null
if there is no bundle event associated with
the call to this method.
The tracked object for the specified bundle.
A bundle tracked by the BundleTracker
has been removed.
This method is called after a bundle is no longer being tracked by the
BundleTracker
.
The type of the service being tracked.
The type of the tracked object.
The ServiceTracker
class simplifies using services from the
Framework's service registry.
A ServiceTracker
object is constructed with search criteria and a
ServiceTrackerCustomizer
object. A ServiceTracker
can use a
ServiceTrackerCustomizer
to customize the service objects to be
tracked. The ServiceTracker
can then be opened to begin tracking all
services in the Framework's service registry that match the specified search
criteria. The ServiceTracker
correctly handles all of the details of
listening to ServiceEvent
s and getting and ungetting services.
The getServiceReferences
method can be called to get references to
the services being tracked. The getService
and getServices
methods can be called to get the service objects for the tracked service.
The ServiceTracker
class is thread-safe. It does not call a
ServiceTrackerCustomizer
while holding any locks.
ServiceTrackerCustomizer
implementations must also be thread-safe.
Thread-safe
The Filter used by this ServiceTracker
which specifies the search
criteria for the services to track.
1.1
The BundleContext
against which the tracking is
done.
The ServiceReference
for the service to be
tracked.
The customizer object to call when services are added,
modified, or removed in this ServiceTracker
. If customizer
is null
, then this ServiceTracker
will be used as
the ServiceTrackerCustomizer
and this
ServiceTracker
will call the
ServiceTrackerCustomizer
methods on itself.
Create a ServiceTracker
on the specified ServiceReference
.
The service referenced by the specified ServiceReference
will be
tracked by this ServiceTracker
.
The BundleContext
against which the tracking is
done.
The class name of the services to be tracked.
The customizer object to call when services are added,
modified, or removed in this ServiceTracker
. If customizer
is null
, then this ServiceTracker
will be used as
the ServiceTrackerCustomizer
and this
ServiceTracker
will call the
ServiceTrackerCustomizer
methods on itself.
Create a ServiceTracker
on the specified class name.
Services registered under the specified class name will be tracked by
this ServiceTracker
.
The BundleContext
against which the tracking is
done.
The Filter
to select the services to be tracked.
The customizer object to call when services are added,
modified, or removed in this ServiceTracker
. If customizer
is null, then this ServiceTracker
will be used as the
ServiceTrackerCustomizer
and this ServiceTracker
will call the ServiceTrackerCustomizer
methods on itself.
Create a ServiceTracker
on the specified Filter
object.
Services which match the specified Filter
object will be tracked
by this ServiceTracker
.
1.1
The BundleContext
against which the tracking is
done.
The class of the services to be tracked.
The customizer object to call when services are added,
modified, or removed in this ServiceTracker
. If customizer
is null
, then this ServiceTracker
will be used as
the ServiceTrackerCustomizer
and this
ServiceTracker
will call the
ServiceTrackerCustomizer
methods on itself.
Create a ServiceTracker
on the specified class.
Services registered under the name of the specified class will be tracked
by this ServiceTracker
.
1.5
The reference to the service being added to this
ServiceTracker
.
Default implementation of the
ServiceTrackerCustomizer.addingService
method.
This method is only called when this ServiceTracker
has been
constructed with a null ServiceTrackerCustomizer
argument.
This implementation returns the result of calling getService
, on
the BundleContext
with which this ServiceTracker
was
created, passing the specified ServiceReference
.
This method can be overridden in a subclass to customize the service object to be tracked for the service being added. In that case, take care not to rely on the default implementation of removedService to unget the service.
The service object to be tracked for the service added to this
ServiceTracker
.
Close this ServiceTracker
.
This method should be called when this ServiceTracker
should end
the tracking of services.
This implementation calls getServiceReferences() to get the list of tracked services to remove.
The reference to the desired service.
Returns the service object for the specified ServiceReference
if
the specified referenced service is being tracked by this
ServiceTracker
.
A service object or null
if the service referenced by the
specified ServiceReference
is not being tracked.
Returns a service object for one of the services being tracked by this
ServiceTracker
.
If any services are being tracked, this implementation returns the result
of calling getService(getServiceReference())
.
A service object or null
if no services are being
tracked.
Returns a ServiceReference
for one of the services being tracked
by this ServiceTracker
.
If multiple services are being tracked, the service that is first in the
ranking order is returned.
This is the same algorithm used by
BundleContext.getServiceReference
.
This implementation calls getServiceReferences() to get the list of references for the tracked services.
A ServiceReference
or null
if no services are
being tracked.
1.1
Return an array of ServiceReference
s for all services being
tracked by this ServiceTracker
.
Array of ServiceReference
s or null
if no services
are being tracked.
Return an array of service objects for all services being tracked by this
ServiceTracker
.
This implementation calls getServiceReferences() to get the list of references for the tracked services and then calls getService(ServiceReference) for each reference to get the tracked service object.
An array of service objects or null
if no services are
being tracked.
An array into which the tracked service objects will be stored, if the array is large enough.
Return an array of service objects for all services being tracked by this
ServiceTracker
. The runtime type of the returned array is that of
the specified array.
This implementation calls getServiceReferences() to get the list of references for the tracked services and then calls getService(ServiceReference) for each reference to get the tracked service object.
An array of service objects being tracked. If the specified array
is large enough to hold the result, then the specified array is
returned. If the specified array is longer then necessary to hold
the result, the array element after the last service object is
set to null
. If the specified array is not large enough
to hold the result, a new array is created and returned.
1.5
Return a SortedMap
of the ServiceReference
s and service
objects for all services being tracked by this ServiceTracker
.
The map is sorted in ranking
order.
A SortedMap
with the ServiceReference
s and
service objects for all services being tracked by this
ServiceTracker
. If no services are being tracked, then
the returned map is empty.
1.5
Returns the tracking count for this ServiceTracker
.
The tracking count is initialized to 0 when this ServiceTracker
is opened. Every time a service is added, modified or removed from this
ServiceTracker
, the tracking count is incremented.
The tracking count can be used to determine if this
ServiceTracker
has added, modified or removed a service by
comparing a tracking count value previously collected with the current
tracking count value. If the value has not changed, then no service has
been added, modified or removed from this ServiceTracker
since
the previous tracking count was collected.
The tracking count for this ServiceTracker
or -1 if this
ServiceTracker
is not open.
1.2
Return if this ServiceTracker
is empty.
true
if this ServiceTracker
is not tracking any
services.
1.5
The reference to modified service.
The service object for the modified service.
Default implementation of the
ServiceTrackerCustomizer.modifiedService
method.
This method is only called when this ServiceTracker
has been
constructed with a null ServiceTrackerCustomizer
argument.
This implementation does nothing.
ServiceTrackerCustomizer.modifiedService(ServiceReference, Object)
Open this ServiceTracker
and begin tracking services.
This implementation calls open(false)
.
IllegalStateException
– If the BundleContext
with
which this ServiceTracker
was created is no longer valid.
If true
, then this ServiceTracker
will track all matching services regardless of class loader
accessibility. If false
, then this ServiceTracker
will only track matching services which are class loader
accessible to the bundle whose BundleContext
is used by
this ServiceTracker
.
Open this ServiceTracker
and begin tracking services.
Services which match the search criteria specified when this
ServiceTracker
was created are now tracked by this
ServiceTracker
.
IllegalStateException
– If the BundleContext
with
which this ServiceTracker
was created is no longer valid.
1.3
The reference to the service to be removed.
Remove a service from this ServiceTracker
.
The specified service will be removed from this ServiceTracker
.
If the specified service was being tracked then the
ServiceTrackerCustomizer.removedService
method will be called for
that service.
The reference to removed service.
The service object for the removed service.
Default implementation of the
ServiceTrackerCustomizer.removedService
method.
This method is only called when this ServiceTracker
has been
constructed with a null ServiceTrackerCustomizer
argument.
This implementation calls ungetService
, on the
BundleContext
with which this ServiceTracker
was created,
passing the specified ServiceReference
.
This method can be overridden in a subclass. If the default implementation of addingService method was used, this method must unget the service.
ServiceTrackerCustomizer.removedService(ServiceReference, Object)
Return the number of services being tracked by this
ServiceTracker
.
The number of services being tracked.
The time interval in milliseconds to wait. If zero, the method will wait indefinitely.
Wait for at least one service to be tracked by this
ServiceTracker
. This method will also return when this
ServiceTracker
is closed.
It is strongly recommended that waitForService
is not used during
the calling of the BundleActivator
methods.
BundleActivator
methods are expected to complete in a short
period of time.
This implementation calls getService() to determine if a service is being tracked.
Returns the result of getService().
InterruptedException
– If another thread has interrupted the
current thread.
IllegalArgumentException
– If the value of timeout is negative.
The type of the service being tracked.
The type of the tracked object.
The ServiceTrackerCustomizer
interface allows a
ServiceTracker
to customize the service objects that are tracked. A
ServiceTrackerCustomizer
is called when a service is being added to a
ServiceTracker
. The ServiceTrackerCustomizer
can then return
an object for the tracked service. A ServiceTrackerCustomizer
is also
called when a tracked service is modified or has been removed from a
ServiceTracker
.
The methods in this interface may be called as the result of a
ServiceEvent
being received by a ServiceTracker
. Since
ServiceEvent
s are synchronously delivered by the Framework, it is
highly recommended that implementations of these methods do not register (
BundleContext.registerService
), modify (
ServiceRegistration.setProperties
) or unregister (
ServiceRegistration.unregister
) a service while being synchronized on
any object.
The ServiceTracker
class is thread-safe. It does not call a
ServiceTrackerCustomizer
while holding any locks.
ServiceTrackerCustomizer
implementations must also be thread-safe.
Thread-safe
The reference to the service being added to the
ServiceTracker
.
A service is being added to the ServiceTracker
.
This method is called before a service which matched the search
parameters of the ServiceTracker
is added to the
ServiceTracker
. This method should return the service object to
be tracked for the specified ServiceReference
. The returned
service object is stored in the ServiceTracker
and is available
from the getService
and getServices
methods.
The service object to be tracked for the specified referenced
service or null
if the specified referenced service
should not be tracked.
The reference to the service that has been modified.
The service object for the specified referenced service.
A service tracked by the ServiceTracker
has been modified.
This method is called when a service being tracked by the
ServiceTracker
has had it properties modified.
The reference to the service that has been removed.
The service object for the specified referenced service.
A service tracked by the ServiceTracker
has been removed.
This method is called after a service is no longer being tracked by the
ServiceTracker
.