Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'bundles/org.eclipse.osgi/felix/src/org/apache/felix/resolver/ResolverImpl.java')
-rwxr-xr-xbundles/org.eclipse.osgi/felix/src/org/apache/felix/resolver/ResolverImpl.java126
1 files changed, 90 insertions, 36 deletions
diff --git a/bundles/org.eclipse.osgi/felix/src/org/apache/felix/resolver/ResolverImpl.java b/bundles/org.eclipse.osgi/felix/src/org/apache/felix/resolver/ResolverImpl.java
index 7735df71f..09f9ec56a 100755
--- a/bundles/org.eclipse.osgi/felix/src/org/apache/felix/resolver/ResolverImpl.java
+++ b/bundles/org.eclipse.osgi/felix/src/org/apache/felix/resolver/ResolverImpl.java
@@ -53,7 +53,7 @@ public class ResolverImpl implements Resolver
// Note this class is not thread safe.
// Only use in the context of a single thread.
- static class ResolveSession
+ static class ResolveSession implements Runnable
{
// Holds the resolve context for this session
private final ResolveContext m_resolveContext;
@@ -62,9 +62,11 @@ public class ResolverImpl implements Resolver
private final Resource m_dynamicHost;
private final Requirement m_dynamicReq;
private final List<Capability> m_dynamicCandidates;
- // keeps track of valid on demand fragments that we have seen.
+ // keeps track of valid related resources that we have seen.
// a null value or TRUE indicate it is valid
- Map<Resource, Boolean> m_validOnDemandResources = new HashMap<Resource, Boolean>(0);
+ private Map<Resource, Boolean> m_validRelatedResources = new HashMap<Resource, Boolean>(0);
+ // keeps track of related resources for each resource
+ private Map<Resource, Collection<Resource>> m_relatedResources = new HashMap<Resource, Collection<Resource>>(0);
// Holds candidate permutations based on permutating "uses" chains.
// These permutations are given higher priority.
private final List<Candidates> m_usesPermutations = new LinkedList<Candidates>();
@@ -88,8 +90,19 @@ public class ResolverImpl implements Resolver
private final Set<Requirement> m_sub_mutated = new HashSet<Requirement>();
private final ConcurrentMap<String, List<String>> m_usesCache = new ConcurrentHashMap<String, List<String>>();
private ResolutionError m_currentError;
+ volatile private CancellationException m_isCancelled = null;
- ResolveSession(ResolveContext resolveContext, Executor executor, Resource dynamicHost, Requirement dynamicReq, List<Capability> dynamicCandidates)
+ static ResolveSession createSession(ResolveContext resolveContext, Executor executor, Resource dynamicHost, Requirement dynamicReq, List<Capability> dynamicCandidates)
+ {
+ ResolveSession session = new ResolveSession(resolveContext, executor, dynamicHost, dynamicReq, dynamicCandidates);
+ // call onCancel first
+ session.getContext().onCancel(session);
+ // now gather the mandatory and optional resources
+ session.initMandatoryAndOptionalResources();
+ return session;
+ }
+
+ private ResolveSession(ResolveContext resolveContext, Executor executor, Resource dynamicHost, Requirement dynamicReq, List<Capability> dynamicCandidates)
{
m_resolveContext = resolveContext;
m_executor = executor;
@@ -100,12 +113,18 @@ public class ResolverImpl implements Resolver
m_mandatoryResources = Collections.singletonList(dynamicHost);
m_optionalResources = Collections.emptyList();
} else {
- // Make copies of arguments in case we want to modify them.
- m_mandatoryResources = new ArrayList<Resource>(resolveContext.getMandatoryResources());
- m_optionalResources = new ArrayList<Resource>(resolveContext.getOptionalResources());
+ // Do not call resolve context yet, onCancel must be called first
+ m_mandatoryResources = new ArrayList<Resource>();
+ m_optionalResources = new ArrayList<Resource>();
}
}
+ private void initMandatoryAndOptionalResources() {
+ if (!isDynamic()) {
+ m_mandatoryResources.addAll(getContext().getMandatoryResources());
+ m_optionalResources.addAll(getContext().getOptionalResources());
+ }
+ }
Candidates getMultipleCardCandidates()
{
return m_multipleCardCandidates;
@@ -281,28 +300,52 @@ public class ResolverImpl implements Resolver
return m_dynamicCandidates;
}
- public boolean isValidOnDemandResource(Resource fragment) {
- Boolean valid = m_validOnDemandResources.get(fragment);
+ public boolean isValidRelatedResource(Resource resource) {
+ Boolean valid = m_validRelatedResources.get(resource);
if (valid == null)
{
- // Mark this resource as a valid on demand resource
- m_validOnDemandResources.put(fragment, Boolean.TRUE);
+ // Mark this resource as a valid related resource
+ m_validRelatedResources.put(resource, Boolean.TRUE);
valid = Boolean.TRUE;
}
return valid;
}
- public boolean invalidateOnDemandResource(Resource faultyResource) {
- Boolean valid = m_validOnDemandResources.get(faultyResource);
+ public boolean invalidateRelatedResource(Resource faultyResource) {
+ Boolean valid = m_validRelatedResources.get(faultyResource);
if (valid != null && valid)
{
- // This was an ondemand resource.
+ // This was related resource.
// Invalidate it and try again.
- m_validOnDemandResources.put(faultyResource, Boolean.FALSE);
+ m_validRelatedResources.put(faultyResource, Boolean.FALSE);
return true;
}
return false;
}
+
+ public Collection<Resource> getRelatedResources(Resource resource) {
+ Collection<Resource> related = m_relatedResources.get(resource);
+ return related == null ? Collections.<Resource> emptyList() : related;
+ }
+
+ public void setRelatedResources(Resource resource, Collection<Resource> related) {
+ m_relatedResources.put(resource, related);
+ }
+
+ @Override
+ public void run() {
+ m_isCancelled = new CancellationException();
+ }
+
+ boolean isCancelled() {
+ return m_isCancelled != null;
+ }
+
+ void checkForCancel() throws ResolutionException {
+ if (isCancelled()) {
+ throw new ResolutionException("Resolver operation has been cancelled.", m_isCancelled, null);
+ }
+ }
}
public ResolverImpl(Logger logger)
@@ -373,13 +416,12 @@ public class ResolverImpl implements Resolver
public Map<Resource, List<Wire>> resolve(ResolveContext rc, Executor executor) throws ResolutionException
{
- ResolveSession session = new ResolveSession(rc, executor, null, null, null);
+ ResolveSession session = ResolveSession.createSession(rc, executor, null, null, null);
return doResolve(session);
}
private Map<Resource, List<Wire>> doResolve(ResolveSession session) throws ResolutionException {
Map<Resource, List<Wire>> wireMap = new HashMap<Resource, List<Wire>>();
-
boolean retry;
do
{
@@ -393,6 +435,7 @@ public class ResolverImpl implements Resolver
Map<Resource, ResolutionError> faultyResources = new HashMap<Resource, ResolutionError>();
Candidates allCandidates = findValidCandidates(session, faultyResources);
+ session.checkForCancel();
// If there is a resolve exception, then determine if an
// optionally resolved resource is to blame (typically a fragment).
@@ -404,7 +447,7 @@ public class ResolverImpl implements Resolver
retry = (session.getOptionalResources().removeAll(resourceKeys));
for (Resource faultyResource : resourceKeys)
{
- if (session.invalidateOnDemandResource(faultyResource))
+ if (session.invalidateRelatedResource(faultyResource))
{
retry = true;
}
@@ -432,8 +475,7 @@ public class ResolverImpl implements Resolver
}
if (session.isDynamic() )
{
- wireMap = populateDynamicWireMap(session.getContext(),
- session.getDynamicHost(), session.getDynamicRequirement(),
+ wireMap = populateDynamicWireMap(session,
wireMap, allCandidates);
}
else
@@ -444,7 +486,7 @@ public class ResolverImpl implements Resolver
{
wireMap =
populateWireMap(
- session.getContext(), allCandidates.getWrappedHost(resource),
+ session, allCandidates.getWrappedHost(resource),
wireMap, allCandidates);
}
}
@@ -551,7 +593,7 @@ public class ResolverImpl implements Resolver
}
}
}
- while (session.getCurrentError() != null);
+ while (!session.isCancelled() && session.getCurrentError() != null);
return allCandidates;
}
@@ -579,6 +621,9 @@ public class ResolverImpl implements Resolver
rethrow = checkPackageSpaceConsistency(
session, entry.getValue(),
allCandidates, session.isDynamic(), resourcePkgMap, resultCache);
+ if (session.isCancelled()) {
+ return null;
+ }
if (rethrow != null)
{
Resource faultyResource = entry.getKey();
@@ -622,7 +667,7 @@ public class ResolverImpl implements Resolver
"Matching candidate does not provide a package name.");
}
}
- ResolveSession session = new ResolveSession(context, new DumbExecutor(), host, dynamicRequirement, matches);
+ ResolveSession session = ResolveSession.createSession(context, new DumbExecutor(), host, dynamicRequirement, matches);
return doResolve(session);
}
@@ -1456,6 +1501,9 @@ public class ResolverImpl implements Resolver
rethrow = checkPackageSpaceConsistency(
session, cap.getResource(),
allCandidates, false, resourcePkgMap, resultCache);
+ if (session.isCancelled()) {
+ return null;
+ }
if (rethrow != null)
{
// If the lower level check didn't create any permutations,
@@ -1855,11 +1903,11 @@ public class ResolverImpl implements Resolver
}
private static Map<Resource, List<Wire>> populateWireMap(
- ResolveContext rc, Resource resource,
+ ResolveSession session, Resource resource,
Map<Resource, List<Wire>> wireMap, Candidates allCandidates)
{
Resource unwrappedResource = getDeclaredResource(resource);
- if (!rc.getWirings().containsKey(unwrappedResource)
+ if (!session.getContext().getWirings().containsKey(unwrappedResource)
&& !wireMap.containsKey(unwrappedResource))
{
wireMap.put(unwrappedResource, Collections.<Wire>emptyList());
@@ -1882,7 +1930,7 @@ public class ResolverImpl implements Resolver
|| !resource.equals(cand.getResource()))
{
// Populate wires for the candidate
- populateWireMap(rc, cand.getResource(),
+ populateWireMap(session, cand.getResource(),
wireMap, allCandidates);
Resource provider;
@@ -1962,7 +2010,7 @@ public class ResolverImpl implements Resolver
// Otherwise, if the fragment isn't already resolved and
// this is the first time we are seeing it, then create
// a wire for the non-payload requirement.
- else if (!rc.getWirings().containsKey(fragment)
+ else if (!session.getContext().getWirings().containsKey(fragment)
&& !wireMap.containsKey(fragment))
{
Wire wire = createWire(req, allCandidates);
@@ -1978,6 +2026,12 @@ public class ResolverImpl implements Resolver
wireMap.put(fragment, fragmentWires);
}
}
+ // now make sure any related resources are populated
+ for (Resource related : session.getRelatedResources(unwrappedResource)) {
+ if (allCandidates.isPopulated(related)) {
+ populateWireMap(session, related, wireMap, allCandidates);
+ }
+ }
}
return wireMap;
@@ -2012,31 +2066,31 @@ public class ResolverImpl implements Resolver
}
private static Map<Resource, List<Wire>> populateDynamicWireMap(
- ResolveContext rc, Resource resource, Requirement dynReq,
- Map<Resource, List<Wire>> wireMap, Candidates allCandidates)
+ ResolveSession session, Map<Resource,
+ List<Wire>> wireMap, Candidates allCandidates)
{
- wireMap.put(resource, Collections.<Wire>emptyList());
+ wireMap.put(session.getDynamicHost(), Collections.<Wire>emptyList());
List<Wire> packageWires = new ArrayList<Wire>();
// Get the candidates for the current dynamic requirement.
// Record the dynamic candidate.
- Capability dynCand = allCandidates.getFirstCandidate(dynReq);
+ Capability dynCand = allCandidates.getFirstCandidate(session.getDynamicRequirement());
- if (!rc.getWirings().containsKey(dynCand.getResource()))
+ if (!session.getContext().getWirings().containsKey(dynCand.getResource()))
{
- populateWireMap(rc, dynCand.getResource(),
+ populateWireMap(session, dynCand.getResource(),
wireMap, allCandidates);
}
packageWires.add(
new WireImpl(
- resource,
- dynReq,
+ session.getDynamicHost(),
+ session.getDynamicRequirement(),
getDeclaredResource(dynCand.getResource()),
getDeclaredCapability(dynCand)));
- wireMap.put(resource, packageWires);
+ wireMap.put(session.getDynamicHost(), packageWires);
return wireMap;
}

Back to the top