diff options
author | Thomas Watson | 2016-06-02 19:29:32 +0000 |
---|---|---|
committer | Thomas Watson | 2017-06-16 12:38:08 +0000 |
commit | 0965ee422528b80cd11bb690f7d94559c54c0d16 (patch) | |
tree | 19240cb97a60192fb768f3254e418f52a98963ac /bundles | |
parent | 943977005bfc2a3c04daca26822418310029133f (diff) | |
download | rt.equinox.framework-0965ee422528b80cd11bb690f7d94559c54c0d16.tar.gz rt.equinox.framework-0965ee422528b80cd11bb690f7d94559c54c0d16.tar.xz rt.equinox.framework-0965ee422528b80cd11bb690f7d94559c54c0d16.zip |
Bug 492825 - [osgi R7] Resolver specification updates for version 1.1
Add onCancel support
Change-Id: I0e46d80bb47a044fa9d1087515b550fc2cf0773b
Signed-off-by: Thomas Watson <tjwatson@us.ibm.com>
Diffstat (limited to 'bundles')
10 files changed, 158 insertions, 70 deletions
diff --git a/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/container/TestModuleContainer.java b/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/container/TestModuleContainer.java index 96b67023b..884901693 100644 --- a/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/container/TestModuleContainer.java +++ b/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/container/TestModuleContainer.java @@ -1800,12 +1800,14 @@ public class TestModuleContainer extends AbstractTest { } }; ExecutorService executor = new ThreadPoolExecutor(coreThreads, maxThreads, idleTimeout, TimeUnit.SECONDS, queue, threadFactory, rejectHandler); + ScheduledExecutorService timeoutExecutor = new ScheduledThreadPoolExecutor(1); Map<String, String> configuration = new HashMap<String, String>(); configuration.put(EquinoxConfiguration.PROP_RESOLVER_BATCH_TIMEOUT, "5000"); Map<String, String> debugOpts = Collections.emptyMap(); DummyContainerAdaptor adaptor = new DummyContainerAdaptor(new DummyCollisionHook(false), configuration, new DummyResolverHookFactory(), new DummyDebugOptions(debugOpts)); adaptor.setResolverExecutor(executor); + adaptor.setTimeoutExecutor(timeoutExecutor); ModuleContainer container = adaptor.getContainer(); for (int i = 1; i <= 1000; i++) { for (Map<String, String> manifest : getUsesTimeoutManifests("test" + i)) { @@ -1818,6 +1820,7 @@ public class TestModuleContainer extends AbstractTest { Assert.assertEquals("Wrong state of module: " + module, State.RESOLVED, module.getState()); } executor.shutdown(); + timeoutExecutor.shutdown(); System.gc(); System.gc(); System.gc(); diff --git a/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/container/dummys/DummyContainerAdaptor.java b/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/container/dummys/DummyContainerAdaptor.java index 630b2f43e..4bf96b573 100644 --- a/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/container/dummys/DummyContainerAdaptor.java +++ b/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/container/dummys/DummyContainerAdaptor.java @@ -13,6 +13,7 @@ package org.eclipse.osgi.tests.container.dummys; import java.util.EnumSet; import java.util.Map; import java.util.concurrent.Executor; +import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.atomic.AtomicBoolean; import org.eclipse.osgi.container.*; import org.eclipse.osgi.container.Module.Settings; @@ -31,6 +32,7 @@ public class DummyContainerAdaptor extends ModuleContainerAdaptor { private final ResolverHookFactory resolverHookFactory; private final DebugOptions debugOptions; private volatile Executor resolverExecutor; + private volatile ScheduledExecutorService timeoutExecutor; public DummyContainerAdaptor(ModuleCollisionHook collisionHook, Map<String, String> configuration) { this(collisionHook, configuration, new DummyResolverHookFactory()); @@ -123,4 +125,13 @@ public class DummyContainerAdaptor extends ModuleContainerAdaptor { return super.getResolverExecutor(); } + public void setTimeoutExecutor(ScheduledExecutorService timeoutExecutor) { + this.timeoutExecutor = timeoutExecutor; + } + + @Override + public ScheduledExecutorService getScheduledExecutor() { + return this.timeoutExecutor; + } + } diff --git a/bundles/org.eclipse.osgi/META-INF/MANIFEST.MF b/bundles/org.eclipse.osgi/META-INF/MANIFEST.MF index 872adf90a..91c3be476 100644 --- a/bundles/org.eclipse.osgi/META-INF/MANIFEST.MF +++ b/bundles/org.eclipse.osgi/META-INF/MANIFEST.MF @@ -105,7 +105,7 @@ Bundle-Activator: org.eclipse.osgi.internal.framework.SystemBundleActivator Bundle-Description: %systemBundle Bundle-Copyright: %copyright Bundle-Vendor: %eclipse.org -Bundle-Version: 3.12.0.qualifier +Bundle-Version: 3.13.0.qualifier Bundle-Localization: systembundle Bundle-DocUrl: http://www.eclipse.org Eclipse-ExtensibleAPI: true diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/ModuleContainerAdaptor.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/ModuleContainerAdaptor.java index 31cce058c..117473a79 100644 --- a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/ModuleContainerAdaptor.java +++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/ModuleContainerAdaptor.java @@ -13,6 +13,7 @@ package org.eclipse.osgi.container; import java.io.DataInputStream; import java.util.EnumSet; import java.util.concurrent.Executor; +import java.util.concurrent.ScheduledExecutorService; import org.eclipse.osgi.container.Module.Settings; import org.eclipse.osgi.service.debug.DebugOptions; import org.osgi.framework.Constants; @@ -317,4 +318,14 @@ public abstract class ModuleContainerAdaptor { // do nothing by default return null; } + + /** + * Returns the scheduled executor that may be used by the + * container to schedule background tasks. + * @return the scheduled executor, or null if background tasks are not supported + * @since 3.13 + */ + public ScheduledExecutorService getScheduledExecutor() { + return null; + } } 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 d58c142e6..9d0b7872f 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,8 +12,8 @@ package org.eclipse.osgi.container; import java.security.Permission; import java.util.*; -import java.util.concurrent.Executor; -import java.util.concurrent.TimeUnit; +import java.util.concurrent.*; +import java.util.concurrent.atomic.AtomicBoolean; import org.apache.felix.resolver.*; import org.eclipse.osgi.container.ModuleRequirement.DynamicModuleRequirement; import org.eclipse.osgi.container.namespaces.EquinoxFragmentNamespace; @@ -472,11 +472,6 @@ final class ModuleResolver { return version instanceof Version ? (Version) version : Version.emptyVersion; } - static class ResolutionTimeout extends RuntimeException { - private static final long serialVersionUID = 1L; - // Just a marker exception to break out of extra long resolution - } - class ResolveProcess extends ResolveContext implements Comparator<Capability>, FelixResolveContext, Executor { class ResolveLogger extends Logger { @@ -512,7 +507,6 @@ final class ModuleResolver { @Override public boolean isDebugEnabled() { - checkTimeout(); return DEBUG_USES; } @@ -553,8 +547,7 @@ final class ModuleResolver { private volatile boolean currentlyResolvingMandatory = false; private final Set<Resource> transitivelyResolveFailures = new LinkedHashSet<>(); private final Set<Resource> failedToResolve = new HashSet<>(); - private final long resolveTimeout = System.currentTimeMillis() + resolverBatchTimeout; - private volatile boolean checkTimeout = true; + private AtomicBoolean scheduleTimeout = new AtomicBoolean(true); /* * Used to generate the UNRESOLVED_PROVIDER resolution report entries. * @@ -849,12 +842,13 @@ final class ModuleResolver { @Override public Collection<Resource> findRelatedResources(Resource host) { + // for the container we only care about fragments for related resources List<ModuleCapability> hostCaps = ((ModuleRevision) host).getModuleCapabilities(HostNamespace.HOST_NAMESPACE); if (hostCaps.isEmpty()) { return Collections.emptyList(); } - Collection<Resource> ondemandFragments = new ArrayList<>(); + Collection<Resource> relatedFragments = new ArrayList<>(); for (String hostBSN : getHostBSNs(hostCaps)) { 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()); @@ -866,14 +860,14 @@ final class ModuleResolver { ModuleRequirement hostReq = candidate.getRevision().getModuleRequirements(HostNamespace.HOST_NAMESPACE).get(0); for (ModuleCapability hostCap : hostCaps) { if (hostReq.matches(hostCap)) { - ondemandFragments.add(candidate.getResource()); + relatedFragments.add(candidate.getResource()); break; } } } } - return ondemandFragments; + return relatedFragments; } private Collection<String> getHostBSNs(List<ModuleCapability> hostCaps) { @@ -1037,9 +1031,13 @@ final class ModuleResolver { } maxUsedMemory = Math.max(maxUsedMemory, Runtime.getRuntime().freeMemory() - initialFreeMemory); } - } catch (ResolutionTimeout timeoutException) { + } catch (ResolutionException resolutionException) { + if (resolutionException.getCause() instanceof CancellationException) { // revert back to single bundle resolves resolveRevisionsIndividually(isMandatory, logger, result, toResolve, revisions); + } else { + throw resolutionException; + } } catch (OutOfMemoryError memoryError) { // revert back to single bundle resolves resolveRevisionsIndividually(isMandatory, logger, result, toResolve, revisions); @@ -1053,7 +1051,7 @@ final class ModuleResolver { } private void resolveRevisionsIndividually(boolean isMandatory, ResolveLogger logger, Map<Resource, List<Wire>> result, Collection<Resource> toResolve, Collection<ModuleRevision> revisions) throws ResolutionException { - checkTimeout = false; + scheduleTimeout.set(false); for (Resource resource : toResolve) { if (!wirings.containsKey(resource) && !failedToResolve.contains(resource)) { resolveRevisions(Collections.singletonList(resource), isMandatory, logger, result); @@ -1091,9 +1089,11 @@ final class ModuleResolver { result.put(interimResultEntry.getKey(), interimResultEntry.getValue()); } } - } catch (ResolutionTimeout timeoutException) { + } catch (ResolutionException resolutionException) { + if (resolutionException.getCause() instanceof CancellationException) { applyTransitiveFailures = false; - throw timeoutException; + } + throw resolutionException; } catch (OutOfMemoryError memoryError) { applyTransitiveFailures = false; throw memoryError; @@ -1588,14 +1588,21 @@ final class ModuleResolver { @Override public void execute(Runnable command) { - checkTimeout(); adaptor.getResolverExecutor().execute(command); } - void checkTimeout() { - if (checkTimeout && resolveTimeout < System.currentTimeMillis()) { - checkTimeout = false; - throw new ResolutionTimeout(); + @Override + public void onCancel(Runnable callback) { + // Note that for each resolve Process we only want timeout the initial batch resolve + if (scheduleTimeout.compareAndSet(true, false)) { + ScheduledExecutorService scheduledExecutor = adaptor.getScheduledExecutor(); + if (scheduledExecutor != null) { + try { + scheduledExecutor.schedule(callback, resolverBatchTimeout, TimeUnit.MILLISECONDS); + } catch (RejectedExecutionException e) { + // ignore may have been shutdown, it is ok we will not be able to timeout + } + } } } diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/EquinoxContainerAdaptor.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/EquinoxContainerAdaptor.java index f02e02d30..4c3e6539a 100644 --- a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/EquinoxContainerAdaptor.java +++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/EquinoxContainerAdaptor.java @@ -339,6 +339,11 @@ public class EquinoxContainerAdaptor extends ModuleContainerAdaptor { return executor.getInitialized(lazyExecutorCreator); } + @Override + public ScheduledExecutorService getScheduledExecutor() { + return container.getScheduledExecutor(); + } + public void shutdownResolverExecutor() { Executor current = executor.getAndClear(); if (current instanceof ExecutorService) { diff --git a/bundles/org.eclipse.osgi/felix/src/org/apache/felix/resolver/Candidates.java b/bundles/org.eclipse.osgi/felix/src/org/apache/felix/resolver/Candidates.java index af597d487..f2ef54f52 100755 --- a/bundles/org.eclipse.osgi/felix/src/org/apache/felix/resolver/Candidates.java +++ b/bundles/org.eclipse.osgi/felix/src/org/apache/felix/resolver/Candidates.java @@ -184,17 +184,15 @@ class Candidates addCandidates(result.candidates); result.candidates = null; result.remaining = null; - if (!Util.isFragment(resource)) + Collection<Resource> relatedResources = rc.findRelatedResources(resource); + m_session.setRelatedResources(resource, relatedResources); + for (Resource relatedResource : relatedResources) { - Collection<Resource> ondemandFragments = rc.findRelatedResources(resource); - for (Resource fragment : ondemandFragments) + if (m_session.isValidRelatedResource(relatedResource)) { - if (m_session.isValidOnDemandResource(fragment)) - { - // This resource is a valid on demand resource; - // populate it now, consider it optional - toPopulate.addFirst(fragment); - } + // This resource is a valid related resource; + // populate it now, consider it optional + toPopulate.addFirst(relatedResource); } } continue; 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; } diff --git a/bundles/org.eclipse.osgi/osgi/src/org/osgi/service/resolver/packageinfo b/bundles/org.eclipse.osgi/osgi/src/org/osgi/service/resolver/packageinfo deleted file mode 100644 index 3987f9c4e..000000000 --- a/bundles/org.eclipse.osgi/osgi/src/org/osgi/service/resolver/packageinfo +++ /dev/null @@ -1 +0,0 @@ -version 1.1 diff --git a/bundles/org.eclipse.osgi/pom.xml b/bundles/org.eclipse.osgi/pom.xml index 793b913e4..3fefdbb72 100644 --- a/bundles/org.eclipse.osgi/pom.xml +++ b/bundles/org.eclipse.osgi/pom.xml @@ -19,7 +19,7 @@ </parent> <groupId>org.eclipse.osgi</groupId> <artifactId>org.eclipse.osgi</artifactId> - <version>3.12.0-SNAPSHOT</version> + <version>3.13.0-SNAPSHOT</version> <packaging>eclipse-plugin</packaging> <build> |