Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Watson2013-11-19 21:21:33 +0000
committerThomas Watson2013-11-21 15:52:38 +0000
commit5a122e8088f7db503d94c46fac507cee86aee578 (patch)
tree99f78ccecbf1c9b876335ef409a28317fa64687f
parent56378517e2131c04a5e5804fb27db5fd80b54dc3 (diff)
downloadrt.equinox.framework-5a122e8088f7db503d94c46fac507cee86aee578.tar.gz
rt.equinox.framework-5a122e8088f7db503d94c46fac507cee86aee578.tar.xz
rt.equinox.framework-5a122e8088f7db503d94c46fac507cee86aee578.zip
Bug 421706 - Can't start Eclipse M3 after installing "everything"I20131203-0800I20131126-0800
- Do single bundle resolves to reduce the uses constraint problem set.
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/ModuleContainer.java2
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/ModuleDatabase.java21
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/ModuleResolver.java169
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/builders/OSGiManifestBuilderFactory.java3
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/legacy/PackageAdminImpl.java6
5 files changed, 141 insertions, 60 deletions
diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/ModuleContainer.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/ModuleContainer.java
index 02c487162..c4164886b 100644
--- a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/ModuleContainer.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/ModuleContainer.java
@@ -144,7 +144,7 @@ public final class ModuleContainer {
* @param attributes the requirement attributes
* @return a synthetic requirement
*/
- public Requirement createRequirement(String namespace, Map<String, String> directives, Map<String, ?> attributes) {
+ public static Requirement createRequirement(String namespace, Map<String, String> directives, Map<String, ?> attributes) {
return new ModuleRequirement(namespace, directives, attributes, null);
}
diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/ModuleDatabase.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/ModuleDatabase.java
index 5b371ed65..5482159f5 100644
--- a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/ModuleDatabase.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/ModuleDatabase.java
@@ -180,27 +180,6 @@ public class ModuleDatabase {
}
/**
- * Returns a snapshot collection of current revisions which are fragments
-
- * @return a snapshot collection of current revisions which are fragments
- */
- final Collection<ModuleRevision> getFragmentRevisions() {
- Collection<ModuleRevision> fragments = new ArrayList<ModuleRevision>();
- readLock();
- try {
- for (Module module : modulesById.values()) {
- ModuleRevision revision = module.getCurrentRevision();
- if (revision != null && ((revision.getTypes() & BundleRevision.TYPE_FRAGMENT) != 0)) {
- fragments.add(revision);
- }
- }
- return fragments;
- } finally {
- readUnlock();
- }
- }
-
- /**
* Installs a new revision using the specified builder, location and module.
* <p>
* A write operation protected by the {@link #writeLock() write} lock.
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 de9cc6929..e3e9bd11e 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
@@ -12,9 +12,9 @@ package org.eclipse.osgi.container;
import java.security.Permission;
import java.util.*;
-import org.apache.felix.resolver.Logger;
-import org.apache.felix.resolver.ResolverImpl;
+import org.apache.felix.resolver.*;
import org.eclipse.osgi.container.ModuleRequirement.DynamicModuleRequirement;
+import org.eclipse.osgi.container.namespaces.EquinoxFragmentNamespace;
import org.eclipse.osgi.internal.container.InternalUtils;
import org.eclipse.osgi.internal.messages.Msg;
import org.eclipse.osgi.report.resolution.*;
@@ -402,7 +402,7 @@ final class ModuleResolver {
return version instanceof Version ? (Version) version : Version.emptyVersion;
}
- class ResolveProcess extends ResolveContext implements Comparator<Capability> {
+ class ResolveProcess extends ResolveContext implements Comparator<Capability>, FelixResolveContext {
class ResolveLogger extends Logger {
private Map<Resource, ResolutionException> errors = null;
@@ -445,9 +445,14 @@ final class ModuleResolver {
private final boolean triggersMandatory;
private final ModuleDatabase moduleDatabase;
private final Map<ModuleRevision, ModuleWiring> wirings;
+ private final Set<ModuleRevision> previouslyResolved;
private final DynamicModuleRequirement dynamicReq;
private volatile ResolverHook hook = null;
private volatile Map<String, Collection<ModuleRevision>> byName = null;
+ private volatile ModuleRevision currentlyResolving = null;
+ private volatile boolean currentlyResolvingMandatory = false;
+ private final Set<Resource> transitivelyResolveFailures = new LinkedHashSet<Resource>();
+ private final Set<Resource> failedToResolve = new HashSet<Resource>();
/*
* Used to generate the UNRESOLVED_PROVIDER resolution report entries.
*
@@ -469,6 +474,7 @@ final class ModuleResolver {
this.optionals.removeAll(triggers);
}
this.wirings = new HashMap<ModuleRevision, ModuleWiring>(wirings);
+ this.previouslyResolved = new HashSet<ModuleRevision>(wirings.keySet());
this.moduleDatabase = moduleDatabase;
this.dynamicReq = null;
}
@@ -482,6 +488,7 @@ final class ModuleResolver {
this.triggersMandatory = false;
this.optionals = new ArrayList<ModuleRevision>(unresolved);
this.wirings = wirings;
+ this.previouslyResolved = new HashSet<ModuleRevision>(wirings.keySet());
this.moduleDatabase = moduleDatabase;
this.dynamicReq = dynamicReq;
}
@@ -489,13 +496,7 @@ final class ModuleResolver {
@Override
public List<Capability> findProviders(Requirement requirement) {
List<ModuleCapability> candidates = moduleDatabase.findCapabilities(requirement);
- // 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);
- if (result.isEmpty())
- reportBuilder.addEntry(requirement.getResource(), Entry.Type.MISSING_CAPABILITY, requirement);
- else
- computeUnresolvedProviders(requirement, result);
return result;
}
@@ -510,16 +511,43 @@ final class ModuleResolver {
removeSubstituted(iCandidates);
filterPermissions((BundleRequirement) requirement, iCandidates);
hook.filterMatches((BundleRequirement) requirement, InternalUtils.asListBundleCapability(candidates));
+
// filter resolved hosts after calling hooks to allow hooks to see the host capability
filterResolvedHosts(requirement, candidates, filterResolvedHosts);
+
+ if (requirement instanceof DynamicModuleRequirement) {
+ requirement = ((DynamicModuleRequirement) requirement).getOriginal();
+ }
+ if (candidates.isEmpty()) {
+ if (!wirings.containsKey(requirement.getResource())) {
+ reportBuilder.addEntry(requirement.getResource(), Entry.Type.MISSING_CAPABILITY, requirement);
+ String resolution = requirement.getDirectives().get(Namespace.REQUIREMENT_RESOLUTION_DIRECTIVE);
+ if ((resolution == null || Namespace.RESOLUTION_MANDATORY.equals(resolution))) {
+ transitivelyResolveFailures.add(requirement.getResource());
+ }
+ }
+ } else {
+ computeUnresolvedProviders(requirement, candidates);
+ }
+
+ filterFailedToResolve(candidates);
+
Collections.sort(candidates, this);
return InternalUtils.asListCapability(candidates);
}
+ private void filterFailedToResolve(List<ModuleCapability> candidates) {
+ for (Iterator<ModuleCapability> iCandidates = candidates.iterator(); iCandidates.hasNext();) {
+ if (failedToResolve.contains(iCandidates.next().getRevision())) {
+ iCandidates.remove();
+ }
+ }
+ }
+
private void filterResolvedHosts(Requirement requirement, List<ModuleCapability> candidates, boolean filterResolvedHosts) {
if (filterResolvedHosts && HostNamespace.HOST_NAMESPACE.equals(requirement.getNamespace())) {
for (Iterator<ModuleCapability> iCandidates = candidates.iterator(); iCandidates.hasNext();) {
- if (wirings.containsKey(iCandidates.next().getRevision())) {
+ if (previouslyResolved.contains(iCandidates.next().getRevision())) {
iCandidates.remove();
}
}
@@ -596,15 +624,45 @@ final class ModuleResolver {
@Override
public Collection<Resource> getMandatoryResources() {
- if (triggersMandatory) {
- return InternalUtils.asCollectionResource(triggers);
+ if (currentlyResolvingMandatory) {
+ return Collections.<Resource> singleton(currentlyResolving);
}
- return super.getMandatoryResources();
+ return Collections.emptyList();
}
@Override
public Collection<Resource> getOptionalResources() {
- return InternalUtils.asCollectionResource(optionals);
+ if (!currentlyResolvingMandatory) {
+ return Collections.<Resource> singleton(currentlyResolving);
+ }
+ return Collections.emptyList();
+ }
+
+ @Override
+ public Collection<Resource> getOndemandResources(Resource host) {
+ String hostBSN = ((ModuleRevision) host).getSymbolicName();
+ if (hostBSN == null) {
+ return Collections.emptyList();
+ }
+ List<ModuleCapability> hostCaps = ((ModuleRevision) host).getModuleCapabilities(HostNamespace.HOST_NAMESPACE);
+ if (hostCaps.isEmpty()) {
+ return Collections.emptyList();
+ }
+ ModuleCapability hostCap = hostCaps.get(0);
+ String matchFilter = "(" + EquinoxFragmentNamespace.FRAGMENT_NAMESPACE + "=" + hostBSN + ")"; //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$
+ Requirement fragmentRequirement = ModuleContainer.createRequirement(EquinoxFragmentNamespace.FRAGMENT_NAMESPACE, Collections.<String, String> singletonMap(Namespace.REQUIREMENT_FILTER_DIRECTIVE, matchFilter), Collections.<String, Object> emptyMap());
+ List<ModuleCapability> candidates = moduleDatabase.findCapabilities(fragmentRequirement);
+ // filter out disabled fragments and singletons
+ filterDisabled(candidates.listIterator());
+ Collection<Resource> ondemandFragments = new ArrayList<Resource>(candidates.size());
+ for (Iterator<ModuleCapability> iCandidates = candidates.iterator(); iCandidates.hasNext();) {
+ ModuleCapability candidate = iCandidates.next();
+ ModuleRequirement hostReq = candidate.getRevision().getModuleRequirements(HostNamespace.HOST_NAMESPACE).get(0);
+ if (hostReq.matches(hostCap)) {
+ ondemandFragments.add(candidate.getResource());
+ }
+ }
+ return ondemandFragments;
}
ModuleResolutionReport resolve() {
@@ -641,16 +699,26 @@ final class ModuleResolver {
if (dynamicReq != null) {
result = resolveDynamic();
} else {
+ result = new HashMap<Resource, List<Wire>>();
Map<Resource, List<Wire>> dynamicAttachWirings = resolveNonPayLoadFragments();
+ applyInterimResultToWiringCopy(dynamicAttachWirings);
if (!dynamicAttachWirings.isEmpty()) {
- // update the copy of wirings to include the new attachments
- Map<ModuleRevision, ModuleWiring> updatedWirings = generateDelta(dynamicAttachWirings, wirings);
- for (Map.Entry<ModuleRevision, ModuleWiring> updatedWiring : updatedWirings.entrySet()) {
- wirings.put(updatedWiring.getKey(), updatedWiring.getValue());
+ // be sure to remove the revisions from the optional and triggers
+ // so they no longer attempt to be resolved
+ Set<Resource> fragmentResources = dynamicAttachWirings.keySet();
+ triggers.removeAll(fragmentResources);
+ optionals.removeAll(fragmentResources);
+
+ result.putAll(dynamicAttachWirings);
+ }
+ if (triggersMandatory) {
+ for (ModuleRevision mandatory : triggers) {
+ resolveSingleRevision(mandatory, true, logger, result);
}
}
- result = new ResolverImpl(logger).resolve(this);
- result.putAll(dynamicAttachWirings);
+ for (ModuleRevision optional : optionals) {
+ resolveSingleRevision(optional, false, logger, result);
+ }
}
} catch (ResolutionException e) {
re = e;
@@ -668,6 +736,49 @@ final class ModuleResolver {
}
}
+ private void resolveSingleRevision(ModuleRevision single, boolean isMandatory, ResolveLogger logger, Map<Resource, List<Wire>> result) throws ResolutionException {
+ if (wirings.containsKey(single) || failedToResolve.contains(single)) {
+ return;
+ }
+ currentlyResolving = single;
+ currentlyResolvingMandatory = isMandatory;
+ transitivelyResolveFailures.clear();
+ Map<Resource, List<Wire>> interimResults = null;
+ try {
+ transitivelyResolveFailures.add(single);
+ interimResults = new ResolverImpl(logger).resolve(this);
+ applyInterimResultToWiringCopy(interimResults);
+ // now apply the simple wires to the results
+ for (Map.Entry<Resource, List<Wire>> interimResultEntry : interimResults.entrySet()) {
+ List<Wire> existingWires = result.get(interimResultEntry.getKey());
+ if (existingWires != null) {
+ existingWires.addAll(interimResultEntry.getValue());
+ } else {
+ result.put(interimResultEntry.getKey(), interimResultEntry.getValue());
+ }
+ }
+ } finally {
+ transitivelyResolveFailures.addAll(logger.getUsesConstraintViolations().keySet());
+ if (interimResults != null) {
+ transitivelyResolveFailures.removeAll(interimResults.keySet());
+ }
+ // what is left did not resolve
+ failedToResolve.addAll(transitivelyResolveFailures);
+ currentlyResolving = null;
+ currentlyResolvingMandatory = false;
+ }
+ }
+
+ private void applyInterimResultToWiringCopy(Map<Resource, List<Wire>> interimResult) {
+ if (!interimResult.isEmpty()) {
+ // update the copy of wirings to include interim results
+ Map<ModuleRevision, ModuleWiring> updatedWirings = generateDelta(interimResult, wirings);
+ for (Map.Entry<ModuleRevision, ModuleWiring> updatedWiring : updatedWirings.entrySet()) {
+ wirings.put(updatedWiring.getKey(), updatedWiring.getValue());
+ }
+ }
+ }
+
private void computeUsesConstraintViolations(Map<Resource, ResolutionException> usesConstraintViolations) {
for (Map.Entry<Resource, ResolutionException> usesConstraintViolation : usesConstraintViolations.entrySet()) {
reportBuilder.addEntry(usesConstraintViolation.getKey(), Type.USES_CONSTRAINT_VIOLATION, usesConstraintViolation.getValue());
@@ -798,10 +909,6 @@ final class ModuleResolver {
}
}
if (resolvedReqs) {
- // be sure to remove the revision from the optional and triggers
- // so they no longer attempt to be resolved
- triggers.remove(nonPayLoad);
- optionals.remove(nonPayLoad);
dynamicAttachment.put(nonPayLoad, nonPayloadWires);
}
}
@@ -824,13 +931,7 @@ final class ModuleResolver {
private Map<Resource, List<Wire>> resolveDynamic() throws ResolutionException {
List<Capability> dynamicMatches = filterProviders(dynamicReq.getOriginal(), moduleDatabase.findCapabilities(dynamicReq));
- if (dynamicMatches.isEmpty())
- reportBuilder.addEntry(dynamicReq.getResource(), Entry.Type.MISSING_CAPABILITY, dynamicReq.getOriginal());
- else
- computeUnresolvedProviders(dynamicReq.getOriginal(), dynamicMatches);
- Collection<Resource> ondemandFragments = InternalUtils.asCollectionResource(moduleDatabase.getFragmentRevisions());
-
- return new ResolverImpl(new Logger(0)).resolve(this, dynamicReq.getRevision(), dynamicReq.getOriginal(), dynamicMatches, ondemandFragments);
+ return new ResolverImpl(new Logger(0)).resolve(this, dynamicReq.getRevision(), dynamicReq.getOriginal(), dynamicMatches);
}
private void filterResolvable() {
@@ -913,7 +1014,7 @@ final class ModuleResolver {
// this is to avoid interacting with the module database
Set<ModuleRevision> revisions = new HashSet<ModuleRevision>();
revisions.addAll(unresolved);
- revisions.addAll(wirings.keySet());
+ revisions.addAll(previouslyResolved);
current = new HashMap<String, Collection<ModuleRevision>>();
for (ModuleRevision revision : revisions) {
Collection<ModuleRevision> sameName = current.get(revision.getSymbolicName());
@@ -982,8 +1083,8 @@ final class ModuleResolver {
// TODO Ideally this policy should be handled by the ModuleDatabase.
// To do that the wirings would have to be provided since the wirings may
// be a subset of the current wirings provided by the ModuleDatabase
- boolean resolved1 = wirings.get(c1.getResource()) != null;
- boolean resolved2 = wirings.get(c2.getResource()) != null;
+ boolean resolved1 = previouslyResolved.contains(c1.getResource());
+ boolean resolved2 = previouslyResolved.contains(c2.getResource());
if (resolved1 != resolved2)
return resolved1 ? -1 : 1;
diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/builders/OSGiManifestBuilderFactory.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/builders/OSGiManifestBuilderFactory.java
index 8c29f87d6..2f3a39c04 100644
--- a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/builders/OSGiManifestBuilderFactory.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/builders/OSGiManifestBuilderFactory.java
@@ -439,7 +439,8 @@ public final class OSGiManifestBuilderFactory {
directives.put(BundleNamespace.REQUIREMENT_FILTER_DIRECTIVE, filter.toString());
builder.addRequirement(HostNamespace.HOST_NAMESPACE, directives, new HashMap<String, Object>(0));
// Add a fragment capability to advertise what host this resource is providing a fragment for
- builder.addCapability(EquinoxFragmentNamespace.FRAGMENT_NAMESPACE, Collections.<String, String> emptyMap(), Collections.<String, Object> singletonMap(EquinoxFragmentNamespace.FRAGMENT_NAMESPACE, hostName));
+ directives = Collections.singletonMap(EquinoxModuleDataNamespace.CAPABILITY_EFFECTIVE_DIRECTIVE, EquinoxModuleDataNamespace.EFFECTIVE_INFORMATION);
+ builder.addCapability(EquinoxFragmentNamespace.FRAGMENT_NAMESPACE, directives, Collections.<String, Object> singletonMap(EquinoxFragmentNamespace.FRAGMENT_NAMESPACE, hostName));
}
private static void getProvideCapabilities(ModuleRevisionBuilder builder, ManifestElement[] provideElements, boolean chechSystemCapabilities) throws BundleException {
diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/legacy/PackageAdminImpl.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/legacy/PackageAdminImpl.java
index 1547c69cb..92b1857bc 100644
--- a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/legacy/PackageAdminImpl.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/legacy/PackageAdminImpl.java
@@ -108,7 +108,7 @@ public class PackageAdminImpl implements PackageAdmin {
String filter = "(" + PackageNamespace.PACKAGE_NAMESPACE + "=" + (name == null ? "*" : name) + ")"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$//$NON-NLS-4$
Map<String, String> directives = Collections.<String, String> singletonMap(Namespace.REQUIREMENT_FILTER_DIRECTIVE, filter);
Map<String, Boolean> attributes = Collections.singletonMap(Capabilities.SYNTHETIC_REQUIREMENT, Boolean.TRUE);
- Requirement packageReq = container.createRequirement(PackageNamespace.PACKAGE_NAMESPACE, directives, attributes);
+ Requirement packageReq = ModuleContainer.createRequirement(PackageNamespace.PACKAGE_NAMESPACE, directives, attributes);
Collection<BundleCapability> packageCaps = container.getFrameworkWiring().findProviders(packageReq);
InternalUtils.filterCapabilityPermissions(packageCaps);
List<ExportedPackage> result = new ArrayList<ExportedPackage>();
@@ -135,7 +135,7 @@ public class PackageAdminImpl implements PackageAdmin {
String filter = "(" + BundleNamespace.BUNDLE_NAMESPACE + "=" + (symbolicName == null ? "*" : symbolicName) + ")"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$//$NON-NLS-4$
Map<String, String> directives = Collections.<String, String> singletonMap(Namespace.REQUIREMENT_FILTER_DIRECTIVE, filter);
Map<String, Boolean> attributes = Collections.singletonMap(Capabilities.SYNTHETIC_REQUIREMENT, Boolean.TRUE);
- Requirement bundleReq = container.createRequirement(BundleNamespace.BUNDLE_NAMESPACE, directives, attributes);
+ Requirement bundleReq = ModuleContainer.createRequirement(BundleNamespace.BUNDLE_NAMESPACE, directives, attributes);
Collection<BundleCapability> bundleCaps = container.getFrameworkWiring().findProviders(bundleReq);
InternalUtils.filterCapabilityPermissions(bundleCaps);
Collection<RequiredBundle> result = new ArrayList<RequiredBundle>();
@@ -158,7 +158,7 @@ public class PackageAdminImpl implements PackageAdmin {
}
VersionRange range = versionRange == null ? null : new VersionRange(versionRange);
String filter = (range != null ? "(&" : "") + "(" + IdentityNamespace.IDENTITY_NAMESPACE + "=" + symbolicName + ")" + (range != null ? range.toFilterString(IdentityNamespace.CAPABILITY_VERSION_ATTRIBUTE) + ")" : ""); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$
- Requirement identityReq = container.createRequirement(IdentityNamespace.IDENTITY_NAMESPACE, Collections.<String, String> singletonMap(Namespace.REQUIREMENT_FILTER_DIRECTIVE, filter), Collections.<String, Object> emptyMap());
+ Requirement identityReq = ModuleContainer.createRequirement(IdentityNamespace.IDENTITY_NAMESPACE, Collections.<String, String> singletonMap(Namespace.REQUIREMENT_FILTER_DIRECTIVE, filter), Collections.<String, Object> emptyMap());
Collection<BundleCapability> identityCaps = container.getFrameworkWiring().findProviders(identityReq);
if (identityCaps.isEmpty()) {

Back to the top