OSGi Framework Resolver Hook instances are obtained from the OSGi {@link ResolverHookFactory Framework Resolver Hook Factory} service.
A Resolver Hook instance is called by the framework during a resolve process. A resolver hook may influence the outcome of a resolve process by removing entries from shrinkable collections that are passed to the hook during a resolve process. A shrinkable collection is a {@code Collection} thatsupports all remove operations. Any other attempts to modify a shrinkable collection will result in an {@code UnsupportedOperationException} beingthrown.
The following steps outline the way a framework uses the resolver hooks during a resolve process.
- Collect a snapshot of registered resolver hook factories that will be called during the current resolve process. Any hook factories registered after the snapshot is taken must not be called during the current resolve process. A resolver hook factory contained in the snapshot may become unregistered during the resolve process. The framework should handle this and stop calling the resolver hook instance provided by the unregistered hook factory and the current resolve process must fail. If possible, an exception must be thrown to the caller of the API which triggered the resolve process. In cases where the the caller is not available a framework event of type error should be fired.
- For each registered hook factory call the {@link ResolverHookFactory#begin(Collection)} method to inform the hooksabout a resolve process beginning and to obtain a Resolver Hook instance that will be used for the duration of the resolve process.
- Determine the collection of unresolved bundle revisions that may be considered for resolution during the current resolution process and place each of the bundle revisions in a shrinkable collection {@code Resolvable}. For each resolver hook call the {@link #filterResolvable(Collection)} methodwith the shrinkable collection {@code Resolvable}.
- The shrinkable collection {@code Resolvable} now contains all theunresolved bundle revisions that may end up as resolved at the end of the current resolve process. Any other bundle revisions that got removed from the shrinkable collection {@code Resolvable} must not end up as resolved at theend of the current resolve process.
- For each bundle revision {@code B} left in the shrinkable collection{@code Resolvable} and any bundle revision {@code B} which is currentlyresolved that represents a singleton bundle do the following:
- Determine the collection of available capabilities that have a namespace of {@link IdentityNamespace osgi.identity}, are singletons, and have the same symbolic name as the singleton bundle revision {@code B} and place each ofthe matching capabilities into a shrinkable collection {@code Collisions}.
- Remove the {@link IdentityNamespace osgi.identity} capability provided bybundle revision {@code B} from shrinkable collection {@code Collisions}. A singleton bundle cannot collide with itself.
- For each resolver hook call the {@link #filterSingletonCollisions(BundleCapability,Collection)} with the{@link IdentityNamespace osgi.identity} capability provided by bundlerevision {@code B} and the shrinkable collection {@code Collisions}
- The shrinkable collection {@code Collisions} now contains all singleton{@link IdentityNamespace osgi.identity} capabilities that can influence theability of bundle revision {@code B} to resolve.
- If the bundle revision {@code B} is already resolved then any resolvablebundle revision contained in the collection {@code Collisions} is not allowedto resolve.
- During a resolve process a framework is free to attempt to resolve any or all bundles contained in shrinkable collection {@code Resolvable}. For each bundle revision {@code B} left in the shrinkable collection{@code Resolvable} which the framework attempts to resolve the followingsteps must be followed:
- For each requirement {@code R} specified by bundle revision {@code B}determine the collection of capabilities that satisfy (or match) the requirement and place each matching capability into a shrinkable collection {@code Candidates}. A capability is considered to match a particular requirement if its attributes satisfy a specified requirement and the requirer bundle has permission to access the capability.
- For each resolver hook call the {@link #filterMatches(BundleRequirement,Collection)} with the requirement{@code R} and the shrinkable collection {@code Candidates}.
- The shrinkable collection {@code Candidates} now contains all thecapabilities that may be used to satisfy the requirement {@code R}. Any other capabilities that got removed from the shrinkable collection {@code Candidates} must not be used to satisfy requirement {@code R}.
- For each resolver hook call the {@link #end()} method to inform the hooksabout a resolve process ending.
In all cases, the order in which the resolver hooks are called is the reverse compareTo ordering of their Service References. That is, the service with the highest ranking number must be called first. In cases where a shrinkable collection becomes empty the framework is required to call the remaining registered hooks.
Resolver hooks are low level. Implementations of the resolver hook must be careful not to create an unresolvable state which is very hard for a developer or a provisioner to diagnose. Resolver hooks also must not be allowed to start another synchronous resolve process (e.g. by calling {@link Bundle#start()} or {@link FrameworkWiring#resolveBundles(Collection)}). The framework must detect this and throw an {@link IllegalStateException}.
@see ResolverHookFactory
@NotThreadSafe
@author $Id: 7b2a0a5dbec7b0e999112ae324d050fcf190fa5d $