54 Bundle Hook Service Specification

54.1 Introduction

The basic framework provides complete visibility for any bundle to any other bundle. In certain use cases it can be important to provide the impression to application bundles that they are part of a limited group of bundles. Bundle Hook services allow Handlers to hide bundles from other bundles by filtering the Bundle Events and return values of methods that return bundles.

Though Bundle Hooks can effectively control bundle visibility of other bundles by filtering some of the key Bundle Context methods as well as event delivery, it does not provide proper isolation. Bundles that use other API will be able to see bundles even if they are hidden by the Bundle Hooks.

54.1.1 Essentials

  • Filtering - Remove bundles from the view of specific bundles.

54.1.2 Entities

  • Find Hook - A service used by the framework to filter methods that return bundles.

  • Event Hook - A service used by the framework to filter Bundle Events before they are delivered to their listeners.

  • Collision Hook - A service used by the framework to filter colliding bundles during an install or update operation when the org.osgi.framework.bsnversion is set to managed.

  • Collision - Two bundles collide when they have the same version and bundle symbolic name.

  • Client - The bundle that finds bundles or receives events about bundles.

  • Handler - The bundle that registers a hook service.

  • Target - The bundle performing the install or update operation.

Figure 54.1 Bundle Hooks, org.osgi.framework.hooks.bundle package

Bundle Hooks, org.osgi.framework.hooks.bundle package

54.1.3 Synopsis

A Handler registers Bundle Hook services to filter the view on the bundles stored in the framework. Whenever the framework has to deliver Bundle events to one or more bundles the Event Hook services are asked to look at the target bundles and remove any targets from the collection. Removed bundles are then not notified.

If a bundle calls a method that returns a bundle like the Bundle Context getBundles method or the getBundle method, the Find Hook is called. The Find Hook can then look at the bundles that will be returned to the caller and filter that list accordingly.

If the Framework installs or updates a bundle it is possible that the new bundle symbolic name/version pair collides with an existing bundle. The org.osgi.framework.bsnversion property controls the property in this case. The Collision Hook is used to control this policy when the property is set to managed.

There can be multiple Bundle Hook services registered by different Handlers, multiple Bundle Hook services are called in service ranking order.

54.2 About the Hooks

The Bundle hooks provide a basic mechanism to hide bundles from each other as well as control bundle collisions. The Bundle Event Hook allows a Handler to hide Bundle Events from bundles, the Bundle Find Hook allows a Handler to alter the result of framework methods that return bundles. The Collision Hook is used for providing a policy when bundles collide. A collision takes place when there is an attempt to install or update a bundle and the situation arises that there are two bundles with the same bundle symbolic name and version.

A Find Hook or an Event Hook can influence the outcome of a number of operations that retrieve a bundle or show a bundle related event by removing entries from shrinkable collections. A shrinkable collection is a collection that can only remove entries, not add to it. Any attempt to add to the collection must result in throwing an Unsupported Operation Exception. All collections in the Find Hook and Event Hook API are shrinkable collections.

The framework must call the hooks in a privileged block, see Privileged Callbacks. Hooks are always called in service ranking order, Service Ranking Order.

54.3 Bundle Event Hook

Handlers must ensure that Client bundles continue to see a consistent set of Bundle Events that strictly follow the transitions defined by the OSGi specifications because Bundle events can be used in a state machine that depends on these transitions. Such state machines can get confused if some Bundle Events are missed.

For example, if a Bundle Tracker sees a STARTED event but the corresponding STOPPED event is removed for that Client then the tracker will still assume the associated bundle is active.

A simple solution is to stop the Client bundle when the Handler decides to start filtering the Bundle Events. The Client bundle should then be started after the filter is in place. This model ensures that the Handler can assume the Client has no knowledge of any hidden bundles.

However, when the bundle that implements the bundle event hook is stopped, it will of course no longer be able to filter events and the target bundle might see bundle events for bundles it was not aware of.

As a best practice a Handler should not hide a Bundle from itself. That is, its own events should always be received and if it gets the bundles from the framework its own Bundle object should be included.

A Handler must register a bundle Event Hook service to intercept and filter events before they are delivered to bundles. The framework must call the event(BundleEvent,Collection) method on all registered hooks in service ranking order to filter the events before they are delivered to any of the registered bundle listeners. The Handler can remove any BundleContext objects from the given shrinkable collection it wants shield from the event's Bundle.

The event method must be called once for each Bundle Event, this includes Bundle Events that are generated when there are no Bundle Listeners registered.

The event(BundleEvent,Collection) method must be called on the same thread that is performing the action which generated the specified event. The shrinkable collection includes BundleContext objects with all Bundle Listeners registered with them.

A Bundle Event Hook must receive all Bundle Events:

  • INSTALLED

  • RESOLVED

  • STARTING

  • STARTED

  • STOPPING

  • STOPPED

  • UNRESOLVED

  • UPDATED

  • UNINSTALLED

  • Other if new events are defined in later versions

54.3.1 System Bundle Listeners

Bundle Listeners may be registered with the system bundle's BundleContext. If at least one Bundle Listener is registered with the system bundle's BundleContext then the system bundle's BundleContext must be contained in the shrinkable collection passed to the event(BundleEvent,Collection) bundle event hook method. Just like other BundleContext objects contained in the shrinkable collection, the system bundle's BundleContext may be removed. If the system bundle's BundleContext is removed by a bundle Event Hook then the BundleContext will not be contained in the collection for the remaining bundle Event Hooks called. Unlike other BundleContext objects, if the system bundle's BundleContext is removed from the shrinkable collection then the bundle event is still delivered to the Bundle Listeners added to the system bundle's BundleContext.

54.4 Bundle Find Hook

The purpose of the Bundle Find Hook, is to limit the visibility of bundles to selected Client bundles. The Find Hook service is called with the find(BundleContext,Collection) method on all Handler Hook services in service ranking order when a Client bundle tries to get bundles from the framework. A registered Find Hook service gets a chance to inspect the candidate set of bundles and can remove any bundle that must be hidden from the receiver.

The Bundle Find Hook can filter the result of the following methods:

The Find Hook is not called for:

  • getBundle(String) - If the caller knows the name then it is not necessary to hide the bundle.

The Bundle Find Hook is also used during an install operation when the to be installed bundle is already installed at a given location. Normally, the install the returns the Bundle object of the existing bundle but this can cause confusion for the installer when this bundle is hidden by the Find Hook. Therefore, the REJECTED_BY_HOOK Bundle Exception is thrown when the find(BundleContext,Collection) method determines that the Bundle Context has no visibility of the conflicting bundle.

54.4.1 System Bundle Context

When the getBundle(long) or getBundles() methods are called using the system bundle's BundleContext then the bundle Find Hooks are called in the same way the hooks are called when a normal BundleContext is used. The system bundle's BundleContext along with the shrinkable candidate bundles collection is passed to the find(BundleContext,Collection) method. Bundle Find Hooks may remove bundles from the shrinkable collection. If a bundle is removed by a bundle Find Hook then the bundle will not be contained in the collection for the remaining bundle Find Hooks called. Unlike other BundleContext objects, if the system bundle's BundleContext is used to find bundles then the Framework ignores the bundle removals performed by the bundle Find Hooks and allows the bundles removed to remain visible in the find results.

The bundle Find Hook is also used during an install operation. When the system bundle's BundleContext is used to install a bundle then the bundle Find Hooks are called in the same way the hooks are called when a normal BundleContext is used. Unlike other BundleContext objects, if the system bundle's BundleContext is used to install bundles then the Framework ignores the bundle removals performed by the bundle Find Hooks. This implies that if the system bundle's BundleContext is used to install a bundle at a location where an existing bundle is installed then the existing bundle is always returned.

54.5 Bundle Collision Hook

Two bundles collide when they have the same bundle symbolic name and version, although there location must always be different. The org.osgi.framework.bsnversion launching property (see Launching Properties ) defines the policy when a collision is about to take place during install or update operations. The launching property can have the following values:

  • single - Collisions are not allowed, attempting to install/update a bundle that will cause a collision is rejected and all bundles can assume there are no collisions between installed bundles.

  • multiple - Collisions are allowed and bundles must assume that there are collisions in the set of installed bundles.

  • managed - Collisions are managed via a Collision Hook service, specified in the remainder of this section.

There are two types of operation that can create a new bundle revision: Install and Update. During this creation the framework has to consider its bsnversion policy as defined by the launching property. For each creation, there are a number of candidates to collide with. In single mode, any candidate that exists will fail the creation. In multiple mode, any number of candidates are allowed. In managed mode, no candidates are allowed, like the single mode, but the Collision Hook services can prune the list of candidates before the framework makes the decision. If the Collision Hook services have emptied the list of candidates then the installation will succeed, if any bundle remains in this list then the operation fails. In managed mode, creations are treated as in single mode but bundles must assume as if the system operates in multiple mode.

The purpose of the Collision Hook is to delegate the decision of bundle collisions to a management agent. For example, using this and other hooks a management agent can create regions of bundles that have limited visibility of each other. Since these bundles do not have visibility of all other bundles a global collision does not necessarily translate into a collision inside a region. Using the Collision Hook the management agent can allow these collisions globally but restrict their impact locally.

In managed mode the framework must call all registered Collision Hook services for each bundle install and update operation. The calling order of the hooks is defined by ranking order, see Service Ranking Order. The Collision Hook service is only called in managed mode and there exists one or more candidates during the creation phase of an install/update operation.

The CollisionHook interface has a single method:

  • filterCollisions(int,Bundle,Collection) - An install or update operation is in progress that will result in a possible bundle collision. The implementer of this method can optionally shrink the given collection of any collision candidates if it can decide that a collision cannot harm.

The filterCollisions(int,Bundle,Collection) method takes a type of operation value that must be one of the following two values that indicate the operation that caused the Collision Hook to be called:

54.5.1 System Bundle Context

When the system bundle's BundleContext is used to install a bundle then the Collision Hooks are called in the same way the hooks are called when a normal BundleContext is used. The system bundle along with the shrinkable candidate bundles collection is passed to the filterCollisions(int,Bundle,Collection) method. Bundle Collision Hooks may remove bundles from the shrinkable collection. If a bundle is removed by a bundle Collision Hook then the bundle will not be contained in the collection for the remaining bundle Collision Hooks called. Unlike the other bundle and service hooks, if the system bundle's BundleContext is used to install a bundle then the Framework must not ignore the bundle removals performed by the bundle Collision Hooks. This implies that the system bundle's BundleContext can be used to install the same bundle multiple times when the org.osgi.framework.bsnversion launching property is set to managed.

54.6 Security

All hooks described in this specification are highly complex facilities that require great care in their implementation to maintain the Framework invariants. It is therefore important that in a secure system the permission to register these hooks is only given to privileged bundles.

In this case, the user of the hook services is the framework. Therefore, there is never a need to provide:

  • ServicePermission[..EventHook,GET], or

  • ServicePermission[..FindHook,GET], or

  • ServicePermission[..CollisionHook,GET]

Implementers of these hooks must have:

  • ServicePermission[..EventHook,REGISTER] for Event Hook services.

  • ServicePermission[..FindHook,REGISTER] for Find Hook services

  • ServicePermission[..CollisionHook,REGISTER] for Collision Hook services

54.7 org.osgi.framework.hooks.bundle

Version 1.1

Framework Bundle Hooks Package Version 1.1.

Bundles wishing to use this package must list the package in the Import-Package header of the bundle's manifest.

Example import for consumers using the API in this package:

Import-Package: org.osgi.framework.hooks.bundle; version="[1.1,2.0)"

54.7.1 Summary

54.7.2 public interface CollisionHook

OSGi Framework Bundle Collision Hook Service.

If the framework was launched with the org.osgi.framework.bsnversion framework launching property set to managed, then all registered collision hook services will be called during framework bundle install and update operations to determine if an install or update operation will result in a bundle symbolic name and version collision.

Thread-safe

54.7.2.1 public static final int INSTALLING = 1

Specifies a bundle install operation is being performed.

54.7.2.2 public static final int UPDATING = 2

Specifies a bundle update operation is being performed.

54.7.2.3 public void filterCollisions(int operationType, Bundle target, Collection<Bundle> collisionCandidates)

The operation type. Must be the value of installing or updating.

The target bundle used to determine what collision candidates to filter.

The collection of collision candidates. The collection supports all the optional Collection operations except add and addAll. Attempting to add to the collection will result in an UnsupportedOperationException . The collection is not synchronized.

Filter bundle collisions hook method. This method is called during the install or update operation. The operation type will be installing or updating. Depending on the operation type the target bundle and the collision candidate collection are the following:

  • installing - The target is the bundle associated with the BundleContext used to call one of the install methods. The collision candidate collection contains the existing bundles installed which have the same symbolic name and version as the bundle being installed.

  • updating - The target is the bundle used to call one of the update methods. The collision candidate collection contains the existing bundles installed which have the same symbolic name and version as the content the target bundle is being updated to.

This method can filter the collection of collision candidates by removing potential collisions. For the specified operation to succeed, the collection of collision candidates must be empty after all registered collision hook services have been called.

54.7.3 public interface EventHook

OSGi Framework Bundle Event Hook Service.

Bundles registering this service will be called during framework lifecycle (install, start, stop, update, and uninstall bundle) operations.

Thread-safe

54.7.3.1 public void event(BundleEvent event, Collection<BundleContext> contexts)

The bundle event to be delivered

A collection of Bundle Contexts for bundles which have listeners to which the specified event will be delivered. The implementation of this method may remove bundle contexts from the collection to prevent the event from being delivered to the associated bundles. The collection supports all the optional Collection operations except add and addAll. Attempting to add to the collection will result in an UnsupportedOperationException. The collection is not synchronized.

Bundle event hook method. This method is called prior to bundle event delivery when a bundle is installed, resolved, started, stopped, unresolved, or uninstalled. This method can filter the bundles which receive the event.

This method must be called by the framework one and only one time for each bundle event generated, this included bundle events which are generated when there are no bundle listeners registered. This method must be called on the same thread that is performing the action which generated the specified event. The specified collection includes bundle contexts with synchronous and asynchronous bundle listeners registered with them.

54.7.4 public interface FindHook

OSGi Framework Bundle Context Hook Service.

Bundles registering this service will be called during framework bundle find (get bundles) operations.

Thread-safe

54.7.4.1 public void find(BundleContext context, Collection<Bundle> bundles)

The bundle context of the bundle performing the find operation.

A collection of Bundles to be returned as a result of the find operation. The implementation of this method may remove bundles from the collection to prevent the bundles from being returned to the bundle performing the find operation. The collection supports all the optional Collection operations except add and addAll. Attempting to add to the collection will result in an UnsupportedOperationException . The collection is not synchronized.

Find hook method. This method is called for the following:

  • Bundle find operations using BundleContext.getBundle(long) and BundleContext.getBundles() methods. The find method can filter the result of the find operation. Note that a find operation using the BundleContext.getBundle(String) method does not cause the find method to be called.

  • Bundle install operations when an existing bundle is already installed at a given location. In this case, the find method is called to determine if the context performing the install operation is able to find the bundle. If the context cannot find the existing bundle then the install operation must fail with a BundleException.REJECTED_BY_HOOK exception.