Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--bundles/org.eclipse.osgi.container.tests/src/org/eclipse/osgi/container/tests/ResolutionReportTest.java28
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/ModuleResolver.java86
2 files changed, 66 insertions, 48 deletions
diff --git a/bundles/org.eclipse.osgi.container.tests/src/org/eclipse/osgi/container/tests/ResolutionReportTest.java b/bundles/org.eclipse.osgi.container.tests/src/org/eclipse/osgi/container/tests/ResolutionReportTest.java
index 7fe18503d..3e76bcaf9 100644
--- a/bundles/org.eclipse.osgi.container.tests/src/org/eclipse/osgi/container/tests/ResolutionReportTest.java
+++ b/bundles/org.eclipse.osgi.container.tests/src/org/eclipse/osgi/container/tests/ResolutionReportTest.java
@@ -22,7 +22,6 @@ import org.eclipse.osgi.container.tests.dummys.*;
import org.eclipse.osgi.report.resolution.ResolutionReport;
import org.junit.Test;
import org.osgi.framework.Constants;
-import org.osgi.framework.namespace.IdentityNamespace;
import org.osgi.framework.wiring.BundleRevision;
import org.osgi.framework.wiring.FrameworkWiring;
import org.osgi.resource.*;
@@ -171,7 +170,7 @@ public class ResolutionReportTest extends AbstractTest {
assertResolutionReportEntriesSize(entries, 1);
ResolutionReport.Entry entry = entries.get(0);
assertResolutionReportEntryTypeUnresolvedProvider(entry.getType());
- assertResolutionReportEntryDataUnresolvedProvider(entry.getData(), "resolution.report.d");
+ assertResolutionReportEntryDataUnresolvedProvider(entry.getData(), Arrays.asList("resolution.report.d"));
entries = resourceToEntries.get(resolutionReportD.getCurrentRevision());
assertResolutionReportEntriesSize(entries, 1);
@@ -197,7 +196,7 @@ public class ResolutionReportTest extends AbstractTest {
assertResolutionReportEntriesSize(entries, 1);
ResolutionReport.Entry entry = entries.get(0);
assertResolutionReportEntryTypeUnresolvedProvider(entry.getType());
- assertResolutionReportEntryDataUnresolvedProvider(entry.getData(), "resolution.report.f");
+ assertResolutionReportEntryDataUnresolvedProvider(entry.getData(), Arrays.asList("osgi.wiring.package"));
entries = resourceToEntries.get(resolutionReportF.getCurrentRevision());
assertResolutionReportEntriesSize(entries, 1);
@@ -210,6 +209,8 @@ public class ResolutionReportTest extends AbstractTest {
hook.getResolutionReports().clear();
}
+ // TODO Need to test both mandatory and optional triggers.
+
private void assertResolutionDoesNotSucceed(ModuleContainer container, Collection<Module> modules) {
try {
container.resolve(modules, true);
@@ -276,12 +277,23 @@ public class ResolutionReportTest extends AbstractTest {
assertTrue("Wrong requirement namespace value", requirement.getDirectives().get(Namespace.REQUIREMENT_FILTER_DIRECTIVE).contains(namespace + "=" + namespaceValue));
}
- private void assertResolutionReportEntryDataUnresolvedProvider(Object data, String osgiIdentity) {
+ @SuppressWarnings("unchecked")
+ private void assertResolutionReportEntryDataUnresolvedProvider(Object data, Collection<String> namespaces) {
assertResolutionReportEntryDataNotNull(data);
- assertTrue("Wrong resolution report entry data type", data instanceof Resource);
- Resource resource = (Resource) data;
- Capability capability = resource.getCapabilities(IdentityNamespace.IDENTITY_NAMESPACE).get(0);
- assertEquals("Wrong unresolved provider", osgiIdentity, capability.getAttributes().get(IdentityNamespace.IDENTITY_NAMESPACE));
+ assertTrue("Wrong resolution report entry data type", data instanceof Map);
+ Map<Requirement, Set<Capability>> unresolvedProviders = (Map<Requirement, Set<Capability>>) data;
+ assertEquals("Wrong number of unresolved providers", namespaces.size(), unresolvedProviders.size());
+ for (String namespace : namespaces) {
+ boolean found = false;
+ for (Map.Entry<Requirement, Set<Capability>> entry : unresolvedProviders.entrySet()) {
+ if (entry.getKey().getNamespace().equals(namespace)) {
+ found = true;
+ break;
+ }
+ }
+ if (!found)
+ fail("Unresolved provider not found: " + namespace);
+ }
}
private void assertResolutionReportEntryTypeMissingCapability(ResolutionReport.Entry.Type type) {
diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/ModuleResolver.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/ModuleResolver.java
index f8b7090e6..cee96ca50 100644
--- a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/ModuleResolver.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/ModuleResolver.java
@@ -476,11 +476,15 @@ final class ModuleResolver {
private volatile ResolverHook hook = null;
private volatile Map<String, Collection<ModuleRevision>> byName = null;
/*
- * Maps a resource requested to be resolved to all unresolved providers
- * having one or more capabilities matching a requirement necessary for
- * successful resolution.
+ * Used to generate the UNRESOLVED_PROVIDER resolution report entries.
+ *
+ * The inner map associates a requirement to the set of all matching
+ * capabilities that were found. The outer map associates the requiring
+ * resource to the inner map so that its contents may easily be looked
+ * up from the set of unresolved resources, if any, after the resolution
+ * has occurred.
*/
- private final Map<Resource, Set<Resource>> unresolvedProviders = new HashMap<Resource, Set<Resource>>();
+ private final Map<Resource, Map<Requirement, Set<Capability>>> unresolvedProviders = new HashMap<Resource, Map<Requirement, Set<Capability>>>();
ResolveProcess(Collection<ModuleRevision> unresolved, Collection<ModuleRevision> triggers, boolean triggersMandatory, Map<ModuleRevision, ModuleWiring> wirings, ModuleDatabase moduleDatabase) {
this.unresolved = unresolved;
@@ -515,9 +519,10 @@ final class ModuleResolver {
// TODO Record missing capability here if empty? Then record other
// entry types later if an existing capability was filtered?
List<Capability> result = filterProviders(requirement, candidates);
- computeUnresolvedProviders(requirement, result);
if (result.isEmpty())
reportBuilder.addEntry(requirement.getResource(), Entry.Type.MISSING_CAPABILITY, requirement);
+ else
+ computeUnresolvedProviders(requirement, result);
return result;
}
@@ -677,52 +682,53 @@ final class ModuleResolver {
// For each resource, add report entries for any unresolved
// providers.
for (Resource shouldHaveResolvedResource : shouldHaveResolvedResources) {
- if (unresolvedProviders.get(shouldHaveResolvedResource) == null)
+ Map<Requirement, Set<Capability>> requirementToCapabilities = unresolvedProviders.get(shouldHaveResolvedResource);
+ if (requirementToCapabilities == null)
continue;
- for (Resource unresolvedProvider : unresolvedProviders.get(shouldHaveResolvedResource)) {
- if (resolution == null || !resolution.containsKey(unresolvedProvider)) {
- reportBuilder.addEntry(shouldHaveResolvedResource, Entry.Type.UNRESOLVED_PROVIDER, unresolvedProvider);
+ // If nothing resolved then there are no resolved resources to
+ // filter out.
+ if (resolution != null) {
+ // Filter out capability providers that resolved.
+ for (Iterator<Set<Capability>> values = requirementToCapabilities.values().iterator(); values.hasNext();) {
+ Set<Capability> value = values.next();
+ for (Iterator<Capability> capabilities = value.iterator(); capabilities.hasNext();)
+ if (resolution.containsKey(capabilities.next().getResource()))
+ // Remove the resolved capability provider.
+ capabilities.remove();
+ if (value.isEmpty())
+ // Remove the requirement that has no unresolved
+ // capability providers.
+ values.remove();
}
}
+ // Add a report entry if there are any remaining requirements
+ // pointing to unresolved capability providers.
+ if (!requirementToCapabilities.isEmpty())
+ reportBuilder.addEntry(shouldHaveResolvedResource, Entry.Type.UNRESOLVED_PROVIDER, requirementToCapabilities);
}
}
/*
* Given a requirement and its matching capabilities, map the
- * requirement's resource to capability resources that are unresolved.
+ * requirement's resource to the requirement and matching capabilities.
+ * This data is used to compute report entries for resources that did
+ * not resolve because a provider did not resolve.
*/
private void computeUnresolvedProviders(Requirement requirement, Collection<? extends Capability> capabilities) {
- if (capabilities.isEmpty())
- // There were no capabilities matching the requirement.
- return;
- Set<Resource> toAdd = new HashSet<Resource>(capabilities.size());
- for (Capability capability : capabilities) {
- Resource resource = capability.getResource();
- if (!isResolved(resource))
- // Add the capability provider because it is not resolved.
- toAdd.add(resource);
- }
- if (toAdd.isEmpty())
- // There were no unresolved capability providers.
- return;
Resource requirer = requirement.getResource();
- Set<Resource> toAddTo = unresolvedProviders.get(requirer);
- if (toAddTo == null)
- // The requiring resource was not already mapped to any
- // unresolved providers.
- unresolvedProviders.put(requirer, toAdd);
- else
- // The requiring resource was already mapped to unresolved
- // providers. Add the new ones.
- toAddTo.addAll(toAdd);
- }
-
- /*
- * Determine if the specified resource is already resolved within the
- * context of this resolve process.
- */
- private boolean isResolved(Resource resource) {
- return wirings.containsKey(resource);
+ Map<Requirement, Set<Capability>> requirementToCapabilities = unresolvedProviders.get(requirer);
+ if (requirementToCapabilities == null) {
+ requirementToCapabilities = new HashMap<Requirement, Set<Capability>>();
+ unresolvedProviders.put(requirer, requirementToCapabilities);
+ }
+ Set<Capability> value = requirementToCapabilities.get(requirement);
+ if (value == null) {
+ value = new HashSet<Capability>(capabilities.size());
+ requirementToCapabilities.put(requirement, value);
+ }
+ for (Capability capability : capabilities)
+ if (!wirings.containsKey(capability.getResource()))
+ value.add(capability);
}
private Map<Resource, List<Wire>> resolveFrameworkExtensions() {

Back to the top