701 Tracker Specification

701.1 Introduction

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.

701.1.1 Essentials

  • 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.

701.1.2 Operation

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.

701.1.3 Entities

Figure 701.1 Class diagram of org.osgi.util.tracker

Class diagram of org.osgi.util.tracker

701.2 Tracking

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.

701.2.1 Usage

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.

701.2.2 General API

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.

701.2.3 Tracking Count

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.

701.2.4 Multi Threading

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.

701.2.5 Synchronous

Trackers use synchronous listeners; the callbacks are called on the same thread as that of the initiating event. Care should be taken to not linger in the callback and perform non-trivial work. Callbacks should return immediately and move substantial work to other threads.

701.3 Service Tracker

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:

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 is false, the Service Tracker must only track compatible versions.

701.3.1 Using a Service Tracker

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 the ServiceTracker object's getService() 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 the ServiceTracker object's getService(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 the BundleActivator 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, causing removedService to be called for that service.

  • close() - This method must remove all services being tracked by the ServiceTracker object, causing removedService 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.

701.3.2 Customizing the Service Tracker class

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:

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.

701.3.3 Customizing Example

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.

701.4 Bundle Tracker

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.

701.4.1 Bundle States

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.

701.4.2 Constructor

The BundleTracker interface defines the following constructors to create BundleTracker objects:

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.

701.4.3 Using a Bundle Tracker

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.

701.4.4 Customizing the Bundle Tracker class

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 the Bundle object itself. If null 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 the addingBundle 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.

701.4.5 Extender Model

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);
    }
}

701.5 Security

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.

701.5.1 Synchronous Bundle Listener

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.

701.6 org.osgi.util.tracker

Version 1.5

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)"

701.6.1 Summary

  • BundleTracker - The BundleTracker class simplifies tracking bundles much like the ServiceTracker simplifies tracking services.

  • BundleTrackerCustomizer - The BundleTrackerCustomizer interface allows a BundleTracker to customize the Bundles that are tracked.

  • ServiceTracker - The ServiceTracker class simplifies using services from the Framework's service registry.

  • ServiceTrackerCustomizer - The ServiceTrackerCustomizer interface allows a ServiceTracker to customize the service objects that are tracked.

701.6.2 public class BundleTracker<T>
implements BundleTrackerCustomizer<T>

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

701.6.2.1 protected final BundleContext context

The Bundle Context used by this BundleTracker.

701.6.2.2 public BundleTracker(BundleContext context, int stateMask, BundleTrackerCustomizer<T> customizer)

The BundleContext against which the tracking is done.

The bit mask of the ORing 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.

Bundle.getState()

701.6.2.3 public T addingBundle(Bundle bundle, BundleEvent event)

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.

BundleTrackerCustomizer.addingBundle(Bundle, BundleEvent)

701.6.2.4 public void close()

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.

701.6.2.5 public Bundle[] getBundles()

Return an array of Bundles for all bundles being tracked by this BundleTracker.

An array of Bundles or null if no bundles are being tracked.

701.6.2.6 public T getObject(Bundle bundle)

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.

701.6.2.7 public Map<Bundle, T> getTracked()

Return a Map with the Bundles and customized objects for all bundles being tracked by this BundleTracker.

A Map with the Bundles 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

701.6.2.8 public int getTrackingCount()

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.

701.6.2.9 public boolean isEmpty()

Return if this BundleTracker is empty.

true if this BundleTracker is not tracking any bundles.

1.5

701.6.2.10 public void modifiedBundle(Bundle bundle, BundleEvent event, T object)

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)

701.6.2.11 public void open()

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.

701.6.2.12 public void remove(Bundle bundle)

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.

701.6.2.13 public void removedBundle(Bundle bundle, BundleEvent event, T object)

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)

701.6.2.14 public int size()

Return the number of bundles being tracked by this BundleTracker.

The number of bundles being tracked.

701.6.3 public interface BundleTrackerCustomizer<T>

The type of the tracked object.

The BundleTrackerCustomizer interface allows a BundleTracker to customize the Bundles 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 BundleEvents 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

701.6.3.1 public T addingBundle(Bundle bundle, BundleEvent event)

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.

701.6.3.2 public void modifiedBundle(Bundle bundle, BundleEvent event, T object)

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.

701.6.3.3 public void removedBundle(Bundle bundle, BundleEvent event, T object)

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.

701.6.4 public class ServiceTracker<S, T>
implements ServiceTrackerCustomizer<S, T>

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 ServiceEvents 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

701.6.4.1 protected final BundleContext context

The Bundle Context used by this ServiceTracker.

701.6.4.2 protected final Filter filter

The Filter used by this ServiceTracker which specifies the search criteria for the services to track.

1.1

701.6.4.3 public ServiceTracker(BundleContext context, ServiceReference<S> reference, ServiceTrackerCustomizer<S, T> customizer)

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.

701.6.4.4 public ServiceTracker(BundleContext context, String clazz, ServiceTrackerCustomizer<S, T> customizer)

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.

701.6.4.5 public ServiceTracker(BundleContext context, Filter filter, ServiceTrackerCustomizer<S, T> customizer)

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

701.6.4.6 public ServiceTracker(BundleContext context, Class<S> clazz, ServiceTrackerCustomizer<S, T> customizer)

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

701.6.4.7 public T addingService(ServiceReference<S> reference)

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.

ServiceTrackerCustomizer.addingService(ServiceReference)

701.6.4.8 public void close()

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.

701.6.4.9 public T getService(ServiceReference<S> reference)

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.

701.6.4.10 public T getService()

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.

701.6.4.11 public ServiceReference<S> getServiceReference()

Returns a ServiceReference for one of the services being tracked by this ServiceTracker.

If multiple services are being tracked, the service with the highest ranking (as specified in its service.ranking property) is returned. If there is a tie in ranking, the service with the lowest service id (as specified in its service.id property); that is, the service that was registered first 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

701.6.4.12 public ServiceReference<S>[] getServiceReferences()

Return an array of ServiceReferences for all services being tracked by this ServiceTracker.

Array of ServiceReferences or null if no services are being tracked.

701.6.4.13 public Object[] getServices()

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.

701.6.4.14 public T[] getServices(T[] array)

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

701.6.4.15 public SortedMap<ServiceReference<S>, T> getTracked()

Return a SortedMap of the ServiceReferences and service objects for all services being tracked by this ServiceTracker. The map is sorted in reverse natural order of ServiceReference. That is, the first entry is the service with the highest ranking and the lowest service id.

A SortedMap with the ServiceReferences 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

701.6.4.16 public int getTrackingCount()

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

701.6.4.17 public boolean isEmpty()

Return if this ServiceTracker is empty.

true if this ServiceTracker is not tracking any services.

1.5

701.6.4.18 public void modifiedService(ServiceReference<S> reference, T service)

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)

701.6.4.19 public void open()

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.

open(boolean)

701.6.4.20 public void open(boolean trackAllServices)

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

701.6.4.21 public void remove(ServiceReference<S> reference)

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.

701.6.4.22 public void removedService(ServiceReference<S> reference, T 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)

701.6.4.23 public int size()

Return the number of services being tracked by this ServiceTracker.

The number of services being tracked.

701.6.4.24 public T waitForService(long timeout) throws InterruptedException

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.

701.6.5 public interface ServiceTrackerCustomizer<S, T>

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 ServiceEvents 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

701.6.5.1 public T addingService(ServiceReference<S> reference)

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.

701.6.5.2 public void modifiedService(ServiceReference<S> reference, T service)

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.

701.6.5.3 public void removedService(ServiceReference<S> reference, T service)

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.