Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/apache/felix/resolver/Candidates.java323
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/apache/felix/resolver/FelixResolveContext.java43
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/apache/felix/resolver/Logger.java31
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/apache/felix/resolver/ResolverImpl.java253
4 files changed, 349 insertions, 301 deletions
diff --git a/bundles/org.eclipse.osgi/container/src/org/apache/felix/resolver/Candidates.java b/bundles/org.eclipse.osgi/container/src/org/apache/felix/resolver/Candidates.java
index b5429eb3a..d22ffc413 100644
--- a/bundles/org.eclipse.osgi/container/src/org/apache/felix/resolver/Candidates.java
+++ b/bundles/org.eclipse.osgi/container/src/org/apache/felix/resolver/Candidates.java
@@ -67,12 +67,13 @@ class Candidates
/**
* Private copy constructor used by the copy() method.
+ *
* @param dependentMap the capability dependency map.
* @param candidateMap the requirement candidate map.
* @param hostFragments the fragment map.
* @param wrappedHosts the wrapped hosts map.
- * @param substitutableMap
- **/
+ * @param substitutableMap
+ */
private Candidates(
Set<Resource> mandatoryResources,
Map<Capability, Set<Requirement>> dependentMap,
@@ -94,7 +95,7 @@ class Candidates
/**
* Constructs an empty Candidates object.
- **/
+ */
public Candidates(Map<Resource, Boolean> validOnDemandResources)
{
m_mandatoryResources = new HashSet<Resource>();
@@ -110,14 +111,15 @@ class Candidates
* Populates candidates for the specified revision. How a revision is
* resolved depends on its resolution type as follows:
* <ul>
- * <li><tt>MANDATORY</tt> - must resolve and failure to do so throws
- * an exception.</li>
- * <li><tt>OPTIONAL</tt> - attempt to resolve, but no exception is thrown
- * if the resolve fails.</li>
- * <li><tt>ON_DEMAND</tt> - only resolve on demand; this only applies to
- * fragments and will only resolve a fragment if its host is already
- * selected as a candidate.</li>
+ * <li><tt>MANDATORY</tt> - must resolve and failure to do so throws an
+ * exception.</li>
+ * <li><tt>OPTIONAL</tt> - attempt to resolve, but no exception is thrown if
+ * the resolve fails.</li>
+ * <li><tt>ON_DEMAND</tt> - only resolve on demand; this only applies to
+ * fragments and will only resolve a fragment if its host is already
+ * selected as a candidate.</li>
* </ul>
+ *
* @param rc the resolve context used for populating the candidates.
* @param resource the resource whose candidates should be populated.
* @param resolution indicates the resolution type.
@@ -149,7 +151,6 @@ class Candidates
return;
}
-
if (resolution == MANDATORY)
{
m_mandatoryResources.add(resource);
@@ -171,6 +172,7 @@ class Candidates
/**
* Populates candidates for the specified revision.
+ *
* @param state the resolver state used for populating the candidates.
* @param revision the revision whose candidates should be populated.
*/
@@ -220,9 +222,8 @@ class Candidates
else if (cacheValue != null)
{
// Increment and get the cycle count.
- cycleCount = (Integer)
- (((Object[]) cacheValue)[0]
- = new Integer(((Integer) ((Object[]) cacheValue)[0]).intValue() + 1));
+ cycleCount = (Integer) (((Object[]) cacheValue)[0] =
+ new Integer(((Integer) ((Object[]) cacheValue)[0]).intValue() + 1));
// Get the already populated candidates.
localCandidateMap = (Map) ((Object[]) cacheValue)[1];
// Get the remaining requirements.
@@ -261,7 +262,7 @@ class Candidates
.get(PackageNamespace.REQUIREMENT_RESOLUTION_DIRECTIVE);
if (!rc.isEffective(req)
|| ((resolution != null)
- && resolution.equals(PackageNamespace.RESOLUTION_DYNAMIC)))
+ && resolution.equals(PackageNamespace.RESOLUTION_DYNAMIC)))
{
continue;
}
@@ -285,9 +286,9 @@ class Candidates
if (Util.isFragment(resource) && rc.getWirings().containsKey(resource))
{
// This is a fragment that is already resolved and there is no unresolved hosts to attach it to.
- m_populateResultCache.put(resource, Boolean.TRUE);
- return;
- }
+ m_populateResultCache.put(resource, Boolean.TRUE);
+ return;
+ }
String msg = "Unable to resolve " + resource
+ ": missing requirement " + req;
if (rethrow != null)
@@ -321,26 +322,31 @@ class Candidates
{
add(localCandidateMap);
}
- if ((rc instanceof FelixResolveContext) && !Util.isFragment(resource)) {
- Collection<Resource> ondemandFragments = ((FelixResolveContext) rc).getOndemandResources(resource);
- for (Resource fragment : ondemandFragments) {
- Boolean valid = m_validOnDemandResources.get(fragment);
- if (valid == null) {
- // Mark this resource as a valid on demand resource
- m_validOnDemandResources.put(fragment, Boolean.TRUE);
- valid = Boolean.TRUE;
- }
- if (valid) {
- // This resource is a valid on demand resource;
- // populate it now, consider it optional
- populate(rc, fragment, OPTIONAL);
- }
- }
+ if ((rc instanceof FelixResolveContext) && !Util.isFragment(resource))
+ {
+ Collection<Resource> ondemandFragments = ((FelixResolveContext) rc).getOndemandResources(resource);
+ for (Resource fragment : ondemandFragments)
+ {
+ Boolean valid = m_validOnDemandResources.get(fragment);
+ if (valid == null)
+ {
+ // Mark this resource as a valid on demand resource
+ m_validOnDemandResources.put(fragment, Boolean.TRUE);
+ valid = Boolean.TRUE;
+ }
+ if (valid)
+ {
+ // This resource is a valid on demand resource;
+ // populate it now, consider it optional
+ populate(rc, fragment, OPTIONAL);
+ }
+ }
}
}
}
- private void populateSubstitutables() {
+ private void populateSubstitutables()
+ {
for (Map.Entry<Resource, Object> populated : m_populateResultCache.entrySet())
{
if (populated.getValue() instanceof Boolean)
@@ -366,14 +372,14 @@ class Candidates
Map<String, Collection<Capability>> exportNames = new HashMap<String, Collection<Capability>>();
for (Capability packageExport : packageExports)
{
- String packageName = (String) packageExport.getAttributes().get(PackageNamespace.PACKAGE_NAMESPACE);
- Collection<Capability> caps = exportNames.get(packageName);
- if (caps == null)
- {
- caps = new ArrayList<Capability>(1);
- exportNames.put(packageName, caps);
- }
- caps.add(packageExport);
+ String packageName = (String) packageExport.getAttributes().get(PackageNamespace.PACKAGE_NAMESPACE);
+ Collection<Capability> caps = exportNames.get(packageName);
+ if (caps == null)
+ {
+ caps = new ArrayList<Capability>(1);
+ exportNames.put(packageName, caps);
+ }
+ caps.add(packageExport);
}
// Check if any requirements substitute one of the exported packages
for (Requirement req : packageImports)
@@ -383,15 +389,17 @@ class Candidates
{
String packageName = (String) substitutes.iterator().next().getAttributes().get(PackageNamespace.PACKAGE_NAMESPACE);
Collection<Capability> exportedPackages = exportNames.get(packageName);
- if (exportedPackages != null) {
+ if (exportedPackages != null)
+ {
// The package is exported;
- // Check if the requirement only has the bundle's own export as candidates
- substitutes = new ArrayList<Capability>(substitutes);
+ // Check if the requirement only has the bundle's own export as candidates
+ substitutes = new ArrayList<Capability>(substitutes);
for (Capability exportedPackage : exportedPackages)
{
substitutes.remove(exportedPackage);
}
- if (!substitutes.isEmpty()) {
+ if (!substitutes.isEmpty())
+ {
for (Capability exportedPackage : exportedPackages)
{
m_subtitutableMap.put(exportedPackage, req);
@@ -400,26 +408,30 @@ class Candidates
}
}
}
- }
+ }
private static final int UNPROCESSED = 0;
private static final int PROCESSING = 1;
private static final int SUBSTITUTED = 2;
private static final int EXPORTED = 3;
+
void checkSubstitutes(List<Candidates> importPermutations) throws ResolutionException
{
Map<Capability, Integer> substituteStatuses = new HashMap<Capability, Integer>(m_subtitutableMap.size());
- for (Capability substitutable : m_subtitutableMap.keySet()) {
+ for (Capability substitutable : m_subtitutableMap.keySet())
+ {
// initialize with unprocessed
substituteStatuses.put(substitutable, UNPROCESSED);
}
// note we are iterating over the original unmodified map by design
- for (Capability substitutable : m_subtitutableMap.keySet()) {
+ for (Capability substitutable : m_subtitutableMap.keySet())
+ {
isSubstituted(substitutable, substituteStatuses);
}
// Remove any substituted exports from candidates
- for (Map.Entry<Capability, Integer> substituteStatus : substituteStatuses.entrySet()) {
+ for (Map.Entry<Capability, Integer> substituteStatus : substituteStatuses.entrySet())
+ {
if (substituteStatus.getValue() == SUBSTITUTED)
{
if (m_dependentMap.isEmpty())
@@ -437,10 +449,13 @@ class Candidates
Set<Requirement> dependents = m_dependentMap.get(substituteStatus.getKey());
if (dependents != null)
{
- for (Requirement dependent : dependents) {
+ for (Requirement dependent : dependents)
+ {
List<Capability> candidates = m_candidateMap.get(dependent);
- if (candidates != null) {
- candidates: for (Iterator<Capability> iCandidates = candidates.iterator(); iCandidates.hasNext();)
+ if (candidates != null)
+ {
+ candidates:
+ for (Iterator<Capability> iCandidates = candidates.iterator(); iCandidates.hasNext();)
{
Capability candidate = iCandidates.next();
Integer candidateStatus = substituteStatuses.get(candidate);
@@ -448,44 +463,46 @@ class Candidates
{
candidateStatus = EXPORTED;
}
- switch (candidateStatus) {
- case EXPORTED :
- // non-substituted candidate hit before the substituted one; do not continue
- break candidates;
- case SUBSTITUTED :
- default :
- // Need to remove any substituted that comes before an exported candidate
- iCandidates.remove();
- // continue to next candidate
- break;
- }
+ switch (candidateStatus)
+ {
+ case EXPORTED:
+ // non-substituted candidate hit before the substituted one; do not continue
+ break candidates;
+ case SUBSTITUTED:
+ default:
+ // Need to remove any substituted that comes before an exported candidate
+ iCandidates.remove();
+ // continue to next candidate
+ break;
+ }
}
}
- }
+ }
}
}
}
- private boolean isSubstituted(Capability substitutableCap, Map<Capability, Integer> substituteStatuses) throws ResolutionException
+ private boolean isSubstituted(Capability substitutableCap, Map<Capability, Integer> substituteStatuses) throws ResolutionException
{
Integer substituteState = substituteStatuses.get(substitutableCap);
- if (substituteState == null)
- {
- return false;
- }
-
- switch (substituteState.intValue()) {
- case PROCESSING :
- // found a cycle mark the initiator as not substituted
- substituteStatuses.put(substitutableCap, EXPORTED);
- return false;
- case SUBSTITUTED :
- return true;
- case EXPORTED :
- return false;
- default :
- break;
- }
+ if (substituteState == null)
+ {
+ return false;
+ }
+
+ switch (substituteState.intValue())
+ {
+ case PROCESSING:
+ // found a cycle mark the initiator as not substituted
+ substituteStatuses.put(substitutableCap, EXPORTED);
+ return false;
+ case SUBSTITUTED:
+ return true;
+ case EXPORTED:
+ return false;
+ default:
+ break;
+ }
Requirement substitutableReq = m_subtitutableMap.get(substitutableCap);
if (substitutableReq == null)
@@ -511,16 +528,16 @@ class Candidates
{
// The resource's exported package is substituted for this permutation.
substituteStatuses.put(substitutableCap, SUBSTITUTED);
- return true;
+ return true;
}
- }
+ }
}
// if we get here then the export is not substituted
substituteStatuses.put(substitutableCap, EXPORTED);
return false;
}
- public void populateDynamic(
+ public void populateDynamic(
ResolveContext rc, Resource resource,
Requirement req, List<Capability> candidates) throws ResolutionException
{
@@ -554,6 +571,7 @@ class Candidates
* synthesizes candidates for any candidates coming from any attached
* fragments, since fragment capabilities only appear once, but technically
* each host represents a unique capability.
+ *
* @param state the resolver state.
* @param revision the revision being resolved.
* @param candidates the candidates to process.
@@ -568,7 +586,7 @@ class Candidates
ResolutionException rethrow = null;
Set<Capability> fragmentCands = null;
for (Iterator<Capability> itCandCap = candidates.iterator();
- itCandCap.hasNext(); )
+ itCandCap.hasNext();)
{
Capability candCap = itCandCap.next();
@@ -626,11 +644,12 @@ class Candidates
{
for (Capability fragCand : fragmentCands)
{
- String fragCandName = fragCand.getNamespace();
- if (IdentityNamespace.IDENTITY_NAMESPACE.equals(fragCandName)) {
- // no need to wrap identity namespace ever
- continue;
- }
+ String fragCandName = fragCand.getNamespace();
+ if (IdentityNamespace.IDENTITY_NAMESPACE.equals(fragCandName))
+ {
+ // no need to wrap identity namespace ever
+ continue;
+ }
// Only necessary for resolved fragments.
Wiring wiring = rc.getWirings().get(fragCand.getResource());
if (wiring != null)
@@ -644,7 +663,7 @@ class Candidates
// since it may be a substitutable export.
if (!fragCandName.equals(PackageNamespace.PACKAGE_NAMESPACE)
|| rc.getWirings().get(wire.getProvider())
- .getResourceCapabilities(null).contains(fragCand))
+ .getResourceCapabilities(null).contains(fragCand))
{
// Note that we can just add this as a candidate
// directly, since we know it is already resolved.
@@ -691,13 +710,14 @@ class Candidates
/**
* Adds a requirement and its matching candidates to the internal data
- * structure. This method assumes it owns the data being passed in and
- * does not make a copy. It takes the data and processes, such as calculating
- * which requirements depend on which capabilities and recording any fragments
- * it finds for future merging.
+ * structure. This method assumes it owns the data being passed in and does
+ * not make a copy. It takes the data and processes, such as calculating
+ * which requirements depend on which capabilities and recording any
+ * fragments it finds for future merging.
+ *
* @param req the requirement to add.
* @param candidates the candidates matching the requirement.
- **/
+ */
private void add(Requirement req, List<Capability> candidates)
{
if (req.getNamespace().equals(HostNamespace.HOST_NAMESPACE))
@@ -711,10 +731,11 @@ class Candidates
/**
* Adds requirements and candidates in bulk. The outer map is not retained
- * by this method, but the inner data structures are, so they should not
- * be further modified by the caller.
+ * by this method, but the inner data structures are, so they should not be
+ * further modified by the caller.
+ *
* @param candidates the bulk requirements and candidates to add.
- **/
+ */
private void add(Map<Requirement, List<Capability>> candidates)
{
for (Entry<Requirement, List<Capability>> entry : candidates.entrySet())
@@ -724,12 +745,15 @@ class Candidates
}
/**
- * Returns the wrapped resource associated with the given resource. If the resource
- * was not wrapped, then the resource itself is returned. This is really only
- * needed to determine if the root resources of the resolve have been wrapped.
+ * Returns the wrapped resource associated with the given resource. If the
+ * resource was not wrapped, then the resource itself is returned. This is
+ * really only needed to determine if the root resources of the resolve have
+ * been wrapped.
+ *
* @param r the resource whose wrapper is desired.
- * @return the wrapper resource or the resource itself if it was not wrapped.
- **/
+ * @return the wrapper resource or the resource itself if it was not
+ * wrapped.
+ */
public Resource getWrappedHost(Resource r)
{
Resource wrapped = m_allWrappedHosts.get(r);
@@ -738,9 +762,10 @@ class Candidates
/**
* Gets the candidates associated with a given requirement.
+ *
* @param req the requirement whose candidates are desired.
* @return the matching candidates or null.
- **/
+ */
public List<Capability> getCandidates(Requirement req)
{
return m_candidateMap.get(req);
@@ -756,24 +781,25 @@ class Candidates
* modules and attaching their selected fragments, removing all unselected
* fragment modules, and replacing all occurrences of the original fragments
* in the internal data structures with the wrapped host modules instead.
- * Thus, fragment capabilities and requirements are merged into the appropriate
- * host and the candidates for the fragment now become candidates for the host.
- * Likewise, any module depending on a fragment now depend on the host. Note
- * that this process is sort of like multiplication, since one fragment that
- * can attach to two hosts effectively gets multiplied across the two hosts.
- * So, any modules being satisfied by the fragment will end up having the
- * two hosts as potential candidates, rather than the single fragment.
- * @throws ResolutionException if the removal of any unselected fragments result
- * in the root module being unable to resolve.
- **/
+ * Thus, fragment capabilities and requirements are merged into the
+ * appropriate host and the candidates for the fragment now become
+ * candidates for the host. Likewise, any module depending on a fragment now
+ * depend on the host. Note that this process is sort of like
+ * multiplication, since one fragment that can attach to two hosts
+ * effectively gets multiplied across the two hosts. So, any modules being
+ * satisfied by the fragment will end up having the two hosts as potential
+ * candidates, rather than the single fragment.
+ *
+ * @throws ResolutionException if the removal of any unselected fragments
+ * result in the root module being unable to resolve.
+ */
public void prepare(ResolveContext rc) throws ResolutionException
{
// Maps a host capability to a map containing its potential fragments;
// the fragment map maps a fragment symbolic name to a map that maps
// a version to a list of fragments requirements matching that symbolic
// name and version.
- Map<Capability, Map<String, Map<Version, List<Requirement>>>>
- hostFragments = Collections.EMPTY_MAP;
+ Map<Capability, Map<String, Map<Version, List<Requirement>>>> hostFragments = Collections.EMPTY_MAP;
if (m_fragmentsPresent)
{
hostFragments = populateDependents();
@@ -792,17 +818,15 @@ class Candidates
// * This includes setting candidates for attached fragment
// requirements as well as replacing fragment capabilities
// with host's attached fragment capabilities.
-
// Steps 1 and 2
List<WrappedResource> hostResources = new ArrayList<WrappedResource>();
List<Resource> unselectedFragments = new ArrayList<Resource>();
- for (Entry<Capability, Map<String, Map<Version, List<Requirement>>>>
- hostEntry : hostFragments.entrySet())
+ for (Entry<Capability, Map<String, Map<Version, List<Requirement>>>> hostEntry : hostFragments.entrySet())
{
// Step 1
Capability hostCap = hostEntry.getKey();
- Map<String, Map<Version, List<Requirement>>> fragments
- = hostEntry.getValue();
+ Map<String, Map<Version, List<Requirement>>> fragments =
+ hostEntry.getValue();
List<Resource> selectedFragments = new ArrayList<Resource>();
for (Entry<String, Map<Version, List<Requirement>>> fragEntry
: fragments.entrySet())
@@ -981,12 +1005,10 @@ class Candidates
// the fragment map maps a fragment symbolic name to a map that maps
// a version to a list of fragments requirements matching that symbolic
// name and version.
- private Map<Capability,
- Map<String, Map<Version, List<Requirement>>>> populateDependents()
+ private Map<Capability, Map<String, Map<Version, List<Requirement>>>> populateDependents()
{
- Map<Capability, Map<String, Map<Version, List<Requirement>>>>
- hostFragments = new HashMap<Capability,
- Map<String, Map<Version, List<Requirement>>>>();
+ Map<Capability, Map<String, Map<Version, List<Requirement>>>> hostFragments =
+ new HashMap<Capability, Map<String, Map<Version, List<Requirement>>>>();
for (Entry<Requirement, List<Capability>> entry : m_candidateMap.entrySet())
{
Requirement req = entry.getKey();
@@ -1008,8 +1030,7 @@ class Candidates
String resSymName = Util.getSymbolicName(req.getResource());
Version resVersion = Util.getVersion(req.getResource());
- Map<String, Map<Version, List<Requirement>>>
- fragments = hostFragments.get(cap);
+ Map<String, Map<Version, List<Requirement>>> fragments = hostFragments.get(cap);
if (fragments == null)
{
fragments = new HashMap<String, Map<Version, List<Requirement>>>();
@@ -1041,9 +1062,11 @@ class Candidates
* as a fragment or a singleton. This process may cause other modules to
* become unresolved if they depended on the module's capabilities and there
* is no other candidate.
+ *
* @param revision the module to remove.
- * @throws ResolveException if removing the module caused the resolve to fail.
- **/
+ * @throws ResolveException if removing the module caused the resolve to
+ * fail.
+ */
private void removeResource(Resource resource, ResolutionException ex)
throws ResolutionException
{
@@ -1066,12 +1089,14 @@ class Candidates
* Removes the specified module from the internal data structures, which
* involves removing its requirements and its capabilities. This may cause
* other modules to become unresolved as a result.
+ *
* @param br the module to remove.
- * @param unresolvedRevisions a list to containing any additional modules that
- * that became unresolved as a result of removing this module and will
- * also need to be removed.
- * @throws ResolveException if removing the module caused the resolve to fail.
- **/
+ * @param unresolvedRevisions a list to containing any additional modules
+ * that that became unresolved as a result of removing this module and will
+ * also need to be removed.
+ * @throws ResolveException if removing the module caused the resolve to
+ * fail.
+ */
private void remove(Resource resource, Set<Resource> unresolvedResources)
throws ResolutionException
{
@@ -1088,8 +1113,9 @@ class Candidates
/**
* Removes a requirement from the internal data structures.
+ *
* @param req the requirement to remove.
- **/
+ */
private void remove(Requirement req)
{
boolean isFragment = req.getNamespace().equals(HostNamespace.HOST_NAMESPACE);
@@ -1111,12 +1137,14 @@ class Candidates
/**
* Removes a capability from the internal data structures. This may cause
* other modules to become unresolved as a result.
+ *
* @param c the capability to remove.
- * @param unresolvedRevisions a list to containing any additional modules that
- * that became unresolved as a result of removing this module and will
- * also need to be removed.
- * @throws ResolveException if removing the module caused the resolve to fail.
- **/
+ * @param unresolvedRevisions a list to containing any additional modules
+ * that that became unresolved as a result of removing this module and will
+ * also need to be removed.
+ * @throws ResolveException if removing the module caused the resolve to
+ * fail.
+ */
private void remove(Capability c, Set<Resource> unresolvedResources)
throws ResolutionException
{
@@ -1147,8 +1175,9 @@ class Candidates
/**
* Creates a copy of the Candidates object. This is used for creating
* permutations when package space conflicts are discovered.
+ *
* @return copy of this Candidates object.
- **/
+ */
public Candidates copy()
{
Map<Capability, Set<Requirement>> dependentMap =
@@ -1190,7 +1219,7 @@ class Candidates
{
Wiring wiring = rc.getWirings().get(resource);
System.out.println(" " + resource
- + " (" + ((wiring != null) ? "RESOLVED)" : "UNRESOLVED)"));
+ + " (" + ((wiring != null) ? "RESOLVED)" : "UNRESOLVED)"));
List<Requirement> reqs = (wiring != null)
? wiring.getResourceRequirements(null)
: resource.getRequirements(null);
@@ -1216,4 +1245,4 @@ class Candidates
}
System.out.println("=== END CANDIDATE MAP ===");
}
-} \ No newline at end of file
+}
diff --git a/bundles/org.eclipse.osgi/container/src/org/apache/felix/resolver/FelixResolveContext.java b/bundles/org.eclipse.osgi/container/src/org/apache/felix/resolver/FelixResolveContext.java
index 7dbaadc24..502a7e459 100644
--- a/bundles/org.eclipse.osgi/container/src/org/apache/felix/resolver/FelixResolveContext.java
+++ b/bundles/org.eclipse.osgi/container/src/org/apache/felix/resolver/FelixResolveContext.java
@@ -20,26 +20,25 @@
import java.util.Collection;
import org.osgi.resource.Resource;
-public interface FelixResolveContext {
-
- /**
- * Return the resources that the resolver should attempt to resolve on
- * demand for specified resource which is being resolved. Inability to
- * resolve one of the on demand resources will not result in a
- * resolution exception.
- *
- * <p>
- * The resolver will ask for on demand resources for each resource that
- * is getting pulled into a resolve operation.
- * An example of an on demand resource is a fragment. When a host
- * is being resolved the resolve context will be asked if any additional
- * resources should be added to the resolve operation. The resolve context
- * may decide that the potential fragments of the host should be resolved
- * along with the host.
- *
- * @return A collection of the resources that the resolver should attempt to
- * resolve for this resolve context. May be empty if there are no
- * on demand resources. The returned collection may be unmodifiable.
- */
- public Collection<Resource> getOndemandResources(Resource host);
+public interface FelixResolveContext
+{
+ /**
+ * Return the resources that the resolver should attempt to resolve on
+ * demand for specified resource which is being resolved. Inability to
+ * resolve one of the on demand resources will not result in a resolution
+ * exception.
+ *
+ * <p>
+ * The resolver will ask for on demand resources for each resource that is
+ * getting pulled into a resolve operation. An example of an on demand
+ * resource is a fragment. When a host is being resolved the resolve context
+ * will be asked if any additional resources should be added to the resolve
+ * operation. The resolve context may decide that the potential fragments of
+ * the host should be resolved along with the host.
+ *
+ * @return A collection of the resources that the resolver should attempt to
+ * resolve for this resolve context. May be empty if there are no on demand
+ * resources. The returned collection may be unmodifiable.
+ */
+ public Collection<Resource> getOndemandResources(Resource host);
}
diff --git a/bundles/org.eclipse.osgi/container/src/org/apache/felix/resolver/Logger.java b/bundles/org.eclipse.osgi/container/src/org/apache/felix/resolver/Logger.java
index b652051f7..fd3a8a751 100644
--- a/bundles/org.eclipse.osgi/container/src/org/apache/felix/resolver/Logger.java
+++ b/bundles/org.eclipse.osgi/container/src/org/apache/felix/resolver/Logger.java
@@ -26,21 +26,21 @@ import org.osgi.service.resolver.ResolutionException;
* <p>
* This class mimics the standard OSGi <tt>LogService</tt> interface. An
* instance of this class is used by the framework for all logging. By default
- * this class logs messages to standard out. The log level can be set to
- * control the amount of logging performed, where a higher number results in
- * more logging. A log level of zero turns off logging completely.
+ * this class logs messages to standard out. The log level can be set to control
+ * the amount of logging performed, where a higher number results in more
+ * logging. A log level of zero turns off logging completely.
* </p>
* <p>
- * The log levels match those specified in the OSGi Log Service (i.e., 1 = error,
- * 2 = warning, 3 = information, and 4 = debug). The default value is 1.
+ * The log levels match those specified in the OSGi Log Service (i.e., 1 =
+ * error, 2 = warning, 3 = information, and 4 = debug). The default value is 1.
* </p>
* <p>
- * This class also uses the System Bundle's context to track log services
- * and will use the highest ranking log service, if present, as a back end
- * instead of printing to standard out. The class uses reflection to invoking
- * the log service's method to avoid a dependency on the log interface.
+ * This class also uses the System Bundle's context to track log services and
+ * will use the highest ranking log service, if present, as a back end instead
+ * of printing to standard out. The class uses reflection to invoking the log
+ * service's method to avoid a dependency on the log interface.
* </p>
-**/
+ */
public class Logger
{
public static final int LOG_ERROR = 1;
@@ -77,10 +77,10 @@ public class Logger
protected void doLog(int level, String msg, Throwable throwable)
{
- if (level > m_logLevel)
- {
- return;
- }
+ if (level > m_logLevel)
+ {
+ return;
+ }
String s = "";
s = s + msg;
if (throwable != null)
@@ -120,7 +120,8 @@ public class Logger
}
}
- public void logUsesConstraintViolation(Resource resource, ResolutionException error) {
+ public void logUsesConstraintViolation(Resource resource, ResolutionException error)
+ {
// do nothing by default
}
}
diff --git a/bundles/org.eclipse.osgi/container/src/org/apache/felix/resolver/ResolverImpl.java b/bundles/org.eclipse.osgi/container/src/org/apache/felix/resolver/ResolverImpl.java
index d6d3910fe..6ada758b0 100644
--- a/bundles/org.eclipse.osgi/container/src/org/apache/felix/resolver/ResolverImpl.java
+++ b/bundles/org.eclipse.osgi/container/src/org/apache/felix/resolver/ResolverImpl.java
@@ -264,30 +264,36 @@ public class ResolverImpl implements Resolver
catch (ResolutionException ex)
{
rethrow = ex;
- if (currentFaultyResources == null) {
- currentFaultyResources = new HashMap<Resource, ResolutionException>();
+ if (currentFaultyResources == null)
+ {
+ currentFaultyResources = new HashMap<Resource, ResolutionException>();
}
Resource faultyResource = resource;
// check that the faulty requirement is not from a fragment
- for (Requirement faultyReq : ex.getUnresolvedRequirements()) {
- if (faultyReq instanceof WrappedRequirement)
+ for (Requirement faultyReq : ex.getUnresolvedRequirements())
+ {
+ if (faultyReq instanceof WrappedRequirement)
{
faultyResource =
((WrappedRequirement) faultyReq)
.getDeclaredRequirement().getResource();
break;
- }
+ }
}
currentFaultyResources.put(faultyResource, ex);
}
}
- if (currentFaultyResources != null) {
- if (faultyResources == null) {
- faultyResources = currentFaultyResources;
- } else if (faultyResources.size() > currentFaultyResources.size()) {
- // save the optimal faultyResources which has less
- faultyResources = currentFaultyResources;
- }
+ if (currentFaultyResources != null)
+ {
+ if (faultyResources == null)
+ {
+ faultyResources = currentFaultyResources;
+ }
+ else if (faultyResources.size() > currentFaultyResources.size())
+ {
+ // save the optimal faultyResources which has less
+ faultyResources = currentFaultyResources;
+ }
}
}
while ((rethrow != null)
@@ -299,24 +305,29 @@ public class ResolverImpl implements Resolver
// again; otherwise, rethrow the resolve exception.
if (rethrow != null)
{
- if (faultyResources != null) {
- Set<Resource> resourceKeys = faultyResources.keySet();
+ if (faultyResources != null)
+ {
+ Set<Resource> resourceKeys = faultyResources.keySet();
retry = (optionalResources.removeAll(resourceKeys));
- for (Resource faultyResource : resourceKeys) {
- Boolean valid = validOnDemandResources.get(faultyResource);
- if (valid != null && valid.booleanValue()) {
- // This was an ondemand resource.
- // Invalidate it and try again.
- validOnDemandResources.put(faultyResource, Boolean.FALSE);
- retry = true;
- }
- }
+ for (Resource faultyResource : resourceKeys)
+ {
+ Boolean valid = validOnDemandResources.get(faultyResource);
+ if (valid != null && valid.booleanValue())
+ {
+ // This was an ondemand resource.
+ // Invalidate it and try again.
+ validOnDemandResources.put(faultyResource, Boolean.FALSE);
+ retry = true;
+ }
+ }
// log all the resolution exceptions for the uses constraint violations
- for (Map.Entry<Resource, ResolutionException> usesError : faultyResources.entrySet()) {
- m_logger.logUsesConstraintViolation(usesError.getKey(), usesError.getValue());
- }
+ for (Map.Entry<Resource, ResolutionException> usesError : faultyResources.entrySet())
+ {
+ m_logger.logUsesConstraintViolation(usesError.getKey(), usesError.getValue());
+ }
}
- if (!retry) {
+ if (!retry)
+ {
throw rethrow;
}
}
@@ -348,8 +359,8 @@ public class ResolverImpl implements Resolver
{
wireMap =
populateWireMap(
- rc, allCandidates.getWrappedHost(target),
- resourcePkgMap, wireMap, allCandidates);
+ rc, allCandidates.getWrappedHost(target),
+ resourcePkgMap, wireMap, allCandidates);
}
}
}
@@ -376,12 +387,13 @@ public class ResolverImpl implements Resolver
* are used to resolve the requirement and the resolve context is not asked
* to find providers for the dynamic requirement. The host resource is
* expected to not be a fragment, to already be resolved and have an
- * existing wiring provided by the resolve context. <p> This operation may
- * resolve additional resources in order to resolve the dynamic requirement.
- * The returned map will contain entries for each resource that got resolved
- * in addition to the specified host resource. The wire list for the host
- * resource will only contain a single wire which is for the dynamic
- * requirement.
+ * existing wiring provided by the resolve context.
+ * <p>
+ * This operation may resolve additional resources in order to resolve the
+ * dynamic requirement. The returned map will contain entries for each
+ * resource that got resolved in addition to the specified host resource.
+ * The wire list for the host resource will only contain a single wire which
+ * is for the dynamic requirement.
*
* @param rc the resolve context
* @param host the hosting resource
@@ -419,9 +431,6 @@ public class ResolverImpl implements Resolver
}
}
-
-
-
Map<Resource, Packages> resourcePkgMap = new HashMap<Resource, Packages>();
Map<Resource, Boolean> onDemandResources = new HashMap<Resource, Boolean>();
@@ -514,13 +523,16 @@ public class ResolverImpl implements Resolver
((WrappedRequirement) faultyReq)
.getDeclaredRequirement().getResource();
}
- Boolean valid = onDemandResources.get(faultyResource);
- if (valid != null && valid.booleanValue()) {
- onDemandResources.put(faultyResource, Boolean.FALSE);
- retry = true;
- } else {
+ Boolean valid = onDemandResources.get(faultyResource);
+ if (valid != null && valid.booleanValue())
+ {
+ onDemandResources.put(faultyResource, Boolean.FALSE);
+ retry = true;
+ }
+ else
+ {
throw rethrow;
- }
+ }
}
// If there is no exception to rethrow, then this was a clean
// resolve, so populate the wire map.
@@ -1200,18 +1212,18 @@ public class ResolverImpl implements Resolver
rethrow = (rethrow != null)
? rethrow
: new ResolutionException(
- "Uses constraint violation. Unable to resolve resource "
- + Util.getSymbolicName(resource)
- + " [" + resource
- + "] because it exports package '"
- + pkgName
- + "' and is also exposed to it from resource "
- + Util.getSymbolicName(usedBlame.m_cap.getResource())
- + " [" + usedBlame.m_cap.getResource()
- + "] via the following dependency chain:\n\n"
- + toStringBlame(session.getContext(), allCandidates, usedBlame),
- null,
- null);
+ "Uses constraint violation. Unable to resolve resource "
+ + Util.getSymbolicName(resource)
+ + " [" + resource
+ + "] because it exports package '"
+ + pkgName
+ + "' and is also exposed to it from resource "
+ + Util.getSymbolicName(usedBlame.m_cap.getResource())
+ + " [" + usedBlame.m_cap.getResource()
+ + "] via the following dependency chain:\n\n"
+ + toStringBlame(session.getContext(), allCandidates, usedBlame),
+ null,
+ null);
mutated = (mutated != null)
? mutated
@@ -1280,7 +1292,7 @@ public class ResolverImpl implements Resolver
for (Entry<String, List<Blame>> requirementBlames : allImportRequirePkgs.entrySet())
{
String pkgName = requirementBlames.getKey();
- if (!pkgs.m_usedPkgs.containsKey(pkgName))
+ if (!pkgs.m_usedPkgs.containsKey(pkgName))
{
continue;
}
@@ -1289,9 +1301,9 @@ public class ResolverImpl implements Resolver
{
if (!isCompatible(session, requirementBlames.getValue(), usedBlames.m_cap, resourcePkgMap))
{
- // Split packages, need to think how to get a good message for split packages (sigh)
- // For now we just use the first requirement that brings in the package that conflicts
- Blame requirementBlame = requirementBlames.getValue().get(0);
+ // Split packages, need to think how to get a good message for split packages (sigh)
+ // For now we just use the first requirement that brings in the package that conflicts
+ Blame requirementBlame = requirementBlames.getValue().get(0);
for (Blame usedBlame : usedBlames.m_blames)
{
if (checkMultiple(session, usedBlames, usedBlame, allCandidates))
@@ -1308,23 +1320,23 @@ public class ResolverImpl implements Resolver
rethrow = (rethrow != null)
? rethrow
: new ResolutionException(
- "Uses constraint violation. Unable to resolve resource "
- + Util.getSymbolicName(resource)
- + " [" + resource
- + "] because it is exposed to package '"
- + pkgName
- + "' from resources "
- + Util.getSymbolicName(requirementBlame.m_cap.getResource())
- + " [" + requirementBlame.m_cap.getResource()
- + "] and "
- + Util.getSymbolicName(usedBlame.m_cap.getResource())
- + " [" + usedBlame.m_cap.getResource()
- + "] via two dependency chains.\n\nChain 1:\n"
- + toStringBlame(session.getContext(), allCandidates, requirementBlame)
- + "\n\nChain 2:\n"
- + toStringBlame(session.getContext(), allCandidates, usedBlame),
- null,
- null);
+ "Uses constraint violation. Unable to resolve resource "
+ + Util.getSymbolicName(resource)
+ + " [" + resource
+ + "] because it is exposed to package '"
+ + pkgName
+ + "' from resources "
+ + Util.getSymbolicName(requirementBlame.m_cap.getResource())
+ + " [" + requirementBlame.m_cap.getResource()
+ + "] and "
+ + Util.getSymbolicName(usedBlame.m_cap.getResource())
+ + " [" + usedBlame.m_cap.getResource()
+ + "] via two dependency chains.\n\nChain 1:\n"
+ + toStringBlame(session.getContext(), allCandidates, requirementBlame)
+ + "\n\nChain 2:\n"
+ + toStringBlame(session.getContext(), allCandidates, usedBlame),
+ null,
+ null);
mutated = (mutated != null)
? mutated
@@ -1383,7 +1395,8 @@ public class ResolverImpl implements Resolver
// Try to permutate the candidate for the original
// import requirement; only permutate it if we haven't
// done so already.
- for (Blame requirementBlame : requirementBlames.getValue()) {
+ for (Blame requirementBlame : requirementBlames.getValue())
+ {
Requirement req = requirementBlame.m_reqs.get(0);
if (!mutated.contains(req))
{
@@ -1393,8 +1406,7 @@ public class ResolverImpl implements Resolver
// try to check if that the case and only permutate it once.
permutateIfNeeded(allCandidates, req, importPermutations);
}
- }
-
+ }
m_logger.log(
Logger.LOG_DEBUG,
@@ -1596,39 +1608,45 @@ public class ResolverImpl implements Resolver
if ((!currentBlames.isEmpty()) && (candCap != null))
{
List<Capability> currentSources;
- // quick check for single source package
+ // quick check for single source package
if (currentBlames.size() == 1)
{
Capability currentCap = currentBlames.get(0).m_cap;
- if (currentCap.equals(candCap)) {
+ if (currentCap.equals(candCap))
+ {
return true;
}
- currentSources =
+ currentSources =
getPackageSources(
- session,
- currentCap,
- resourcePkgMap);
- } else {
+ session,
+ currentCap,
+ resourcePkgMap);
+ }
+ else
+ {
currentSources = new ArrayList<Capability>(currentBlames.size());
- for (Blame currentBlame : currentBlames) {
- List<Capability> blameSources =
- getPackageSources(
- session,
- currentBlame.m_cap,
- resourcePkgMap);
- for (Capability blameSource : blameSources) {
- if (!currentSources.contains(blameSource)) {
- currentSources.add(blameSource);
- }
- }
- }
+ for (Blame currentBlame : currentBlames)
+ {
+ List<Capability> blameSources =
+ getPackageSources(
+ session,
+ currentBlame.m_cap,
+ resourcePkgMap);
+ for (Capability blameSource : blameSources)
+ {
+ if (!currentSources.contains(blameSource))
+ {
+ currentSources.add(blameSource);
+ }
+ }
+ }
}
List<Capability> candSources =
getPackageSources(
- session,
- candCap,
- resourcePkgMap);
+ session,
+ candCap,
+ resourcePkgMap);
return currentSources.containsAll(candSources)
|| candSources.containsAll(currentSources);
@@ -1698,7 +1716,8 @@ public class ResolverImpl implements Resolver
{
sourceCap = new WrappedCapability(cap.getResource(), sourceCap);
}
- if (!sources.contains(sourceCap)) {
+ if (!sources.contains(sourceCap))
+ {
sources.add(sourceCap);
}
}
@@ -1787,7 +1806,7 @@ public class ResolverImpl implements Resolver
{
targetCand = allCandidates.getCandidates(
targetCand.getRequirements(HostNamespace.HOST_NAMESPACE).get(0))
- .iterator().next().getResource();
+ .iterator().next().getResource();
targetCand = allCandidates.getWrappedHost(targetCand);
}
@@ -1857,11 +1876,11 @@ public class ResolverImpl implements Resolver
{
fragmentWires.add(
new WireImpl(
- getDeclaredResource(fragment),
- req,
- unwrappedResource,
- unwrappedResource.getCapabilities(
- HostNamespace.HOST_NAMESPACE).get(0)));
+ getDeclaredResource(fragment),
+ req,
+ unwrappedResource,
+ unwrappedResource.getCapabilities(
+ HostNamespace.HOST_NAMESPACE).get(0)));
}
// Otherwise, if the fragment isn't already resolved and
// this is the first time we are seeing it, then create
@@ -1939,10 +1958,10 @@ public class ResolverImpl implements Resolver
packageWires.add(
new WireImpl(
- resource,
- dynReq,
- getDeclaredResource(dynCand.getResource()),
- getDeclaredCapability(dynCand)));
+ resource,
+ dynReq,
+ getDeclaredResource(dynCand.getResource()),
+ getDeclaredCapability(dynCand)));
wireMap.put(resource, packageWires);
@@ -2033,9 +2052,9 @@ public class ResolverImpl implements Resolver
.get(PackageNamespace.PACKAGE_NAMESPACE).toString());
Capability usedCap =
getSatisfyingCapability(
- rc,
- allCandidates,
- blame.m_reqs.get(i + 1));
+ rc,
+ allCandidates,
+ blame.m_reqs.get(i + 1));
sb.append("; uses:=");
sb.append(usedCap.getAttributes()
.get(PackageNamespace.PACKAGE_NAMESPACE));
@@ -2070,7 +2089,7 @@ public class ResolverImpl implements Resolver
if (export.getNamespace().equals(PackageNamespace.PACKAGE_NAMESPACE)
&& !export.getAttributes().get(PackageNamespace.PACKAGE_NAMESPACE)
.equals(blame.m_cap.getAttributes().get(
- PackageNamespace.PACKAGE_NAMESPACE)))
+ PackageNamespace.PACKAGE_NAMESPACE)))
{
sb.append("; uses:=");
sb.append(blame.m_cap.getAttributes().get(PackageNamespace.PACKAGE_NAMESPACE));

Back to the top