org.osgi.framework.hooks.resolver.ResolverHook Maven / Gradle / Ivy
/*
* Copyright (c) OSGi Alliance (2010, 2011). All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.osgi.framework.hooks.resolver;
import java.util.Collection;
import org.osgi.framework.Bundle;
import org.osgi.framework.wiring.BundleCapability;
import org.osgi.framework.wiring.BundleRequirement;
import org.osgi.framework.wiring.BundleRevision;
import org.osgi.framework.wiring.FrameworkWiring;
/**
* 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} that
* supports all remove operations. Any other attempts to modify a shrinkable
* collection will result in an {@code UnsupportedOperationException} being
* thrown.
*
*
* 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 hooks
* about 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 R}. For each
* resolver hook call the {@link #filterResolvable(Collection)} method with the
* shrinkable collection {@code R}.
* - The shrinkable collection {@code R} now contains all the unresolved
* 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 R} must not end up as resolved at the end of the
* current resolve process.
* - For each bundle revision {@code B} left in the shrinkable collection
* {@code R} that represents a singleton bundle do the following:
* Determine the collection of available capabilities that have a name space of
* {@link BundleRevision#BUNDLE_NAMESPACE osgi.wiring.bundle}, are singletons,
* and have the same symbolic name as the singleton bundle revision {@code B}
* and place each of the matching capabilities into a shrinkable collection
* {@code S}.
*
* Remove the {@link BundleRevision#BUNDLE_NAMESPACE osgi.wiring.bundle}
* capability provided by bundle revision {@code B} from shrinkable collection
* {@code S}. A singleton bundle cannot collide with itself.
*
* For each resolver hook call the
* {@link #filterSingletonCollisions(BundleCapability, Collection)} with the
* {@link BundleRevision#BUNDLE_NAMESPACE osgi.wiring.bundle} capability
* provided by bundle revision {@code B} and the shrinkable collection {@code S}
*
* The shrinkable collection {@code S} now contains all singleton
* {@link BundleRevision#BUNDLE_NAMESPACE osgi.wiring.bundle} capabilities that
* can influence the ability of bundle revision {@code B} to resolve.
* - During a resolve process a framework is free to attempt to resolve any or
* all bundles contained in shrinkable collection {@code R}. For each bundle
* revision {@code B} left in the shrinkable collection {@code R} which the
* framework attempts to resolve the following steps must be followed:
*
* For each requirement {@code T} 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 C}. 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 T} and the shrinkable collection {@code C}.
*
*
* The shrinkable collection {@code C} now contains all the capabilities that
* may be used to satisfy the requirement {@code T}. Any other capabilities that
* got removed from the shrinkable collection {@code C} must not be used to
* satisfy requirement {@code T}.
* - For each resolver hook call the {@link #end()} method to inform the hooks
* about 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
* @version $Id: ea23400257d780706250f8825ec886aaebb0e5d8 $
*/
public interface ResolverHook {
/**
* Filter resolvable candidates hook method. This method may be called
* multiple times during a single resolve process.
* This method can filter the collection of candidates by removing
* potential candidates. Removing a candidate will prevent the candidate
* from resolving during the current resolve process.
*
* @param candidates the collection of resolvable candidates available during
* a resolve process.
*/
void filterResolvable(Collection candidates);
/**
* Filter singleton collisions hook method. This method is called during the
* resolve process for the specified singleton. The specified singleton
* represents a singleton capability and the specified collection represent
* a collection of singleton capabilities which are considered collision
* candidates. The singleton capability and the collection of collision
* candidates must all use the same name space.
*
* Currently only capabilities with the name space of
* {@link BundleRevision#BUNDLE_NAMESPACE osgi.wiring.bundle} can be
* singletons. In that case all the collision candidates have the name space
* of {@link BundleRevision#BUNDLE_NAMESPACE osgi.wiring.bundle}, are
* singletons, and have the same symbolic name as the specified singleton
* capability.
*
* In the future, capabilities in other name spaces may support the
* singleton concept. Hook implementations should be prepared to receive
* calls to this method for capabilities in name spaces other than
* {@link BundleRevision#BUNDLE_NAMESPACE osgi.wiring.bundle}.
*
* This method can filter the list of collision candidates by removing
* potential collisions. Removing a collision candidate will allow the
* specified singleton to resolve regardless of the resolution state of the
* removed collision candidate.
*
* @param singleton the singleton involved in a resolve process
* @param collisionCandidates a collection of singleton collision candidates
*/
void filterSingletonCollisions(BundleCapability singleton, Collection collisionCandidates);
/**
* Filter matches hook method. This method is called during the resolve process for the
* specified requirement. The collection of candidates match the specified requirement.
* This method can filter the collection of matching candidates by removing candidates from
* the collection. Removing a candidate will prevent the resolve process from choosing the
* removed candidate to satisfy the requirement.
*
* All of the candidates will have the same name space and will
* match the specified requirement.
*
* If the Java Runtime Environment supports permissions then the collection of
* candidates will only contain candidates for which the requirer has permission to
* access.
* @param requirement the requirement to filter candidates for
* @param candidates a collection of candidates that match the requirement
*/
void filterMatches(BundleRequirement requirement, Collection candidates);
/**
* This method is called once at the end of the resolve process.
* After the end method is called the resolve process has ended.
* The framework must not hold onto this resolver hook instance
* after end has been called.
*/
void end();
}