diff options
Diffstat (limited to 'bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/ModuleResolver.java')
-rw-r--r-- | bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/container/ModuleResolver.java | 325 |
1 files changed, 104 insertions, 221 deletions
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 3a40b5bec..91eebcf11 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 @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2012, 2020 IBM Corporation and others. + * Copyright (c) 2012, 2021 IBM Corporation and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -29,7 +29,6 @@ import java.util.Iterator; import java.util.LinkedHashSet; import java.util.LinkedList; import java.util.List; -import java.util.ListIterator; import java.util.Map; import java.util.Set; import java.util.concurrent.CancellationException; @@ -40,7 +39,6 @@ import java.util.concurrent.ScheduledFuture; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicReference; -import java.util.function.Function; import org.apache.felix.resolver.Logger; import org.apache.felix.resolver.ResolutionError; import org.apache.felix.resolver.ResolverImpl; @@ -48,6 +46,7 @@ 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.container.NamespaceList; +import org.eclipse.osgi.internal.container.NamespaceList.Builder; import org.eclipse.osgi.internal.debug.Debug; import org.eclipse.osgi.internal.framework.EquinoxConfiguration; import org.eclipse.osgi.internal.framework.EquinoxContainer; @@ -183,17 +182,15 @@ final class ModuleResolver { Map<ModuleRevision, ModuleWiring> generateDelta(Map<Resource, List<Wire>> result, Map<ModuleRevision, ModuleWiring> wiringCopy) { Map<ModuleRevision, Map<ModuleCapability, List<ModuleWire>>> provided = new HashMap<>(); - Map<ModuleRevision, List<ModuleWire>> required = new HashMap<>(); + Map<ModuleRevision, NamespaceList<ModuleWire>> required = new HashMap<>(result.size() * 4 / 3 + 1); // First populate the list of provided and required wires for revision // This is done this way to share the wire object between both the provider and requirer for (Map.Entry<Resource, List<Wire>> resultEntry : result.entrySet()) { ModuleRevision revision = (ModuleRevision) resultEntry.getKey(); - List<ModuleWire> requiredWires = new ArrayList<>(resultEntry.getValue().size()); - List<String> seen = new ArrayList<>(5); + NamespaceList.Builder<ModuleWire> requiredWires = NamespaceList.Builder.create(WIRE); for (Wire wire : resultEntry.getValue()) { ModuleWire moduleWire = new ModuleWire((ModuleCapability) wire.getCapability(), (ModuleRevision) wire.getProvider(), (ModuleRequirement) wire.getRequirement(), (ModuleRevision) wire.getRequirer()); - requiredWires.add(getInsertIndex(moduleWire.getCapability().getNamespace(), requiredWires, seen, - NamespaceList.WIRE), moduleWire); + requiredWires.add(moduleWire); Map<ModuleCapability, List<ModuleWire>> providedWiresMap = provided.get(moduleWire.getProvider()); if (providedWiresMap == null) { providedWiresMap = new HashMap<>(); @@ -206,7 +203,7 @@ final class ModuleResolver { } providedWires.add(moduleWire); } - required.put(revision, requiredWires); + required.put(revision, requiredWires.build()); } Map<ModuleRevision, ModuleWiring> delta = new HashMap<>(); @@ -232,148 +229,96 @@ final class ModuleResolver { return delta; } - private ModuleWiring createNewWiring(ModuleRevision revision, Map<ModuleRevision, Map<ModuleCapability, List<ModuleWire>>> provided, Map<ModuleRevision, List<ModuleWire>> required) { - Map<ModuleCapability, List<ModuleWire>> providedWireMap = provided.get(revision); - if (providedWireMap == null) - providedWireMap = Collections.emptyMap(); - List<ModuleWire> requiredWires = required.get(revision); - if (requiredWires == null) - requiredWires = Collections.emptyList(); + private ModuleWiring createNewWiring(ModuleRevision revision, Map<ModuleRevision, Map<ModuleCapability, List<ModuleWire>>> provided, Map<ModuleRevision, NamespaceList<ModuleWire>> required) { - List<ModuleCapability> capabilities = sortByNamespaceCopy(revision.getModuleCapabilities(null), CAPABILITY); - ListIterator<ModuleCapability> iCapabilities = capabilities.listIterator(capabilities.size()); - List<ModuleRequirement> requirements = sortByNamespaceCopy(revision.getModuleRequirements(null), REQUIREMENT); - ListIterator<ModuleRequirement> iRequirements = requirements.listIterator(requirements.size()); + Map<ModuleCapability, List<ModuleWire>> providedWireMap = provided.getOrDefault(revision, Collections.emptyMap()); + NamespaceList<ModuleWire> requiredWires = required.getOrDefault(revision, NamespaceList.empty(WIRE)); + + NamespaceList.Builder<ModuleCapability> capabilities = Builder.create(CAPABILITY); + capabilities.addAll(revision.getModuleCapabilities(null)); + NamespaceList.Builder<ModuleRequirement> requirements = Builder.create(REQUIREMENT); + requirements.addAll(revision.getModuleRequirements(null)); // if revision is a fragment remove payload requirements and capabilities if ((BundleRevision.TYPE_FRAGMENT & revision.getTypes()) != 0) { - removePayloadContent(iCapabilities, iRequirements); + removePayloadContent(capabilities, requirements); } else { // add fragment capabilities and requirements List<ModuleCapability> hostCapabilities = revision.getModuleCapabilities(HostNamespace.HOST_NAMESPACE); ModuleCapability hostCapability = hostCapabilities.isEmpty() ? null : hostCapabilities.get(0); if (hostCapability != null) { - addPayloadContent(providedWireMap.get(hostCapability), iCapabilities, iRequirements); + addPayloadContent(providedWireMap.get(hostCapability), capabilities, requirements); } } - removeNonEffectiveCapabilities(iCapabilities); - removeNonEffectiveRequirements(iRequirements, requiredWires); - Collection<String> substituted = removeSubstitutedCapabilities(iCapabilities, requiredWires); + removeNonEffectiveCapabilities(capabilities); + removeNonEffectiveRequirements(requirements, requiredWires); + Collection<String> substituted = removeSubstitutedCapabilities(capabilities, requiredWires); - List<ModuleWire> providedWires = new ArrayList<>(); + NamespaceList.Builder<ModuleWire> providedWires = NamespaceList.Builder.create(WIRE); addProvidedWires(providedWireMap, providedWires, capabilities); InternalUtils.filterCapabilityPermissions(capabilities); - return new ModuleWiring(revision, new NamespaceList<>(capabilities, CAPABILITY), - new NamespaceList<>(requirements, REQUIREMENT), new NamespaceList<>(providedWires, WIRE), - new NamespaceList<>(requiredWires, WIRE), substituted); - } + return new ModuleWiring(revision, capabilities.build(), requirements.build(), providedWires.build(), + requiredWires, substituted); - private <E> List<E> sortByNamespaceCopy(List<E> elements, Function<E, String> getNamespace) { - List<E> result = new ArrayList<>(elements.size()); - List<String> seen = new ArrayList<>(); - for (E e : elements) { - String namespace = getNamespace.apply(e); - result.add(getInsertIndex(namespace, result, seen, getNamespace), e); - } - return result; } - private <E> int getInsertIndex(String namespace, List<E> elements, List<String> seen, - Function<E, String> getNamespace) { - if (seen.contains(namespace)) { - for (int i = elements.size() - 1; i > -1; i--) { - if (namespace.equals(getNamespace.apply(elements.get(i)))) { - return i + 1; - } - } - throw new IllegalStateException(); - } - seen.add(namespace); - return elements.size(); - } - - private static void removePayloadContent(ListIterator<ModuleCapability> iCapabilities, ListIterator<ModuleRequirement> iRequirements) { - rewind(iCapabilities); - while (iCapabilities.hasNext()) { - if (!NON_PAYLOAD_CAPABILITIES.contains(iCapabilities.next().getNamespace())) { - iCapabilities.remove(); - } - } + private static void removePayloadContent(NamespaceList.Builder<ModuleCapability> capabilities, + NamespaceList.Builder<ModuleRequirement> requirements) { - rewind(iRequirements); - while (iRequirements.hasNext()) { - if (!NON_PAYLOAD_REQUIREMENTS.contains(iRequirements.next().getNamespace())) { - iRequirements.remove(); - } - } + capabilities.removeNamespaceIf(namespace -> !NON_PAYLOAD_CAPABILITIES.contains(namespace)); + requirements.removeNamespaceIf(namespace -> !NON_PAYLOAD_REQUIREMENTS.contains(namespace)); } - private static Collection<String> removeSubstitutedCapabilities(ListIterator<ModuleCapability> iCapabilities, List<ModuleWire> requiredWires) { - Collection<String> substituted = null; - for (ModuleWire moduleWire : requiredWires) { - if (!PackageNamespace.PACKAGE_NAMESPACE.equals(moduleWire.getCapability().getNamespace())) - continue; + private static Collection<String> removeSubstitutedCapabilities(NamespaceList.Builder<ModuleCapability> capabilities, NamespaceList<ModuleWire> requiredWires) { + Collection<String> substituted = new ArrayList<>(); + for (ModuleWire moduleWire : requiredWires.getList(PackageNamespace.PACKAGE_NAMESPACE)) { String packageName = (String) moduleWire.getCapability().getAttributes().get(PackageNamespace.PACKAGE_NAMESPACE); - rewind(iCapabilities); - while (iCapabilities.hasNext()) { - ModuleCapability capability = iCapabilities.next(); - if (PackageNamespace.PACKAGE_NAMESPACE.equals(capability.getNamespace())) { - if (packageName.equals(capability.getAttributes().get(PackageNamespace.PACKAGE_NAMESPACE))) { - // found a package capability with the same name as a package that got imported - // this indicates a substitution - iCapabilities.remove(); - if (substituted == null) { - substituted = new ArrayList<>(); - } - if (!substituted.contains(packageName)) { - substituted.add(packageName); - } + capabilities.removeElementsOfNamespaceIf(PackageNamespace.PACKAGE_NAMESPACE, capability -> { + if (packageName.equals(capability.getAttributes().get(PackageNamespace.PACKAGE_NAMESPACE))) { + // found a package capability with the same name as a package that got imported + // this indicates a substitution + if (!substituted.contains(packageName)) { + substituted.add(packageName); } + return true; } - } + return false; + }); } - return substituted == null ? Collections.<String> emptyList() : substituted; + return substituted.isEmpty() ? Collections.emptyList() : substituted; } - private static void removeNonEffectiveRequirements(ListIterator<ModuleRequirement> iRequirements, List<ModuleWire> requiredWires) { + private static void removeNonEffectiveRequirements(NamespaceList.Builder<ModuleRequirement> requirements, NamespaceList<ModuleWire> requiredWires) { Set<ModuleRequirement> wireRequirements = new HashSet<>(); - for (ModuleWire mw : requiredWires) { + for (ModuleWire mw : requiredWires.getList(null)) { wireRequirements.add(mw.getRequirement()); } - - rewind(iRequirements); - while (iRequirements.hasNext()) { - ModuleRequirement requirement = iRequirements.next(); + requirements.removeIf(requirement -> { // check the effective directive; Object effective = requirement.getDirectives().get(Namespace.REQUIREMENT_EFFECTIVE_DIRECTIVE); if (effective != null && !Namespace.EFFECTIVE_RESOLVE.equals(effective)) { - iRequirements.remove(); - } else { - - if (!wireRequirements.contains(requirement)) { - if (!PackageNamespace.PACKAGE_NAMESPACE.equals(requirement.getNamespace())) { - iRequirements.remove(); - } else { - Object resolution = requirement.getDirectives().get(Namespace.REQUIREMENT_RESOLUTION_DIRECTIVE); - if (!PackageNamespace.RESOLUTION_DYNAMIC.equals(resolution)) { - iRequirements.remove(); - } - } + return true; + } + if (!wireRequirements.contains(requirement)) { + if (!PackageNamespace.PACKAGE_NAMESPACE.equals(requirement.getNamespace())) { + return true; + } + Object resolution = requirement.getDirectives().get(Namespace.REQUIREMENT_RESOLUTION_DIRECTIVE); + if (!PackageNamespace.RESOLUTION_DYNAMIC.equals(resolution)) { + return true; } } - } + return false; + }); } - void removeNonEffectiveCapabilities(ListIterator<ModuleCapability> iCapabilities) { - rewind(iCapabilities); - while (iCapabilities.hasNext()) { - Capability capability = iCapabilities.next(); + void removeNonEffectiveCapabilities(Collection<ModuleCapability> capabilities) { + capabilities.removeIf(capability -> { Object effective = capability.getDirectives().get(Namespace.CAPABILITY_EFFECTIVE_DIRECTIVE); if (effective != null && !Namespace.EFFECTIVE_RESOLVE.equals(effective)) { - iCapabilities.remove(); if (DEBUG_PROVIDERS) { Debug.println(new StringBuilder("RESOLVER: Capability filtered because it was not effective") //$NON-NLS-1$ .append(SEPARATOR).append(TAB) // @@ -384,16 +329,18 @@ final class ModuleResolver { .append(capability.getResource()) // .toString()); } + return true; } - } + return false; + }); } - private static void addPayloadContent(List<ModuleWire> hostWires, ListIterator<ModuleCapability> iCapabilities, ListIterator<ModuleRequirement> iRequirements) { + private static void addPayloadContent(List<ModuleWire> hostWires, NamespaceList.Builder<ModuleCapability> capabilities, NamespaceList.Builder<ModuleRequirement> requirements) { if (hostWires == null) return; for (ModuleWire hostWire : hostWires) { + // add fragment capabilities - String currentNamespace = null; List<ModuleCapability> fragmentCapabilities = hostWire.getRequirer().getModuleCapabilities(null); for (ModuleCapability fragmentCapability : fragmentCapabilities) { if (NON_PAYLOAD_CAPABILITIES.contains(fragmentCapability.getNamespace())) { @@ -403,23 +350,10 @@ final class ModuleResolver { if (effective != null && !Namespace.EFFECTIVE_RESOLVE.equals(effective)) { continue; // don't include, not effective } - if (!fragmentCapability.getNamespace().equals(currentNamespace)) { - currentNamespace = fragmentCapability.getNamespace(); - fastForward(iCapabilities); - while (iCapabilities.hasPrevious()) { - if (iCapabilities.previous().getNamespace().equals(currentNamespace)) { - iCapabilities.next(); // put position after the last one - break; - } - } - } - if (!iCapabilities.hasPrevious()) { - fastForward(iCapabilities); - } - iCapabilities.add(fragmentCapability); + capabilities.add(fragmentCapability); } + // add fragment requirements - currentNamespace = null; List<ModuleRequirement> fragmentRequriements = hostWire.getRequirer().getModuleRequirements(null); for (ModuleRequirement fragmentRequirement : fragmentRequriements) { if (NON_PAYLOAD_REQUIREMENTS.contains(fragmentRequirement.getNamespace())) { @@ -429,24 +363,12 @@ final class ModuleResolver { if (effective != null && !Namespace.EFFECTIVE_RESOLVE.equals(effective)) { continue; // don't include, not effective } - if (!fragmentRequirement.getNamespace().equals(currentNamespace)) { - currentNamespace = fragmentRequirement.getNamespace(); - boolean isDynamic = isDynamic(fragmentRequirement); - fastForward(iRequirements); - while (iRequirements.hasPrevious()) { - ModuleRequirement previous = iRequirements.previous(); - if (previous.getNamespace().equals(currentNamespace)) { - if (isDynamic || !isDynamic(previous)) { - iRequirements.next(); // put position after the last one - break; - } - } - } - } - if (!iRequirements.hasPrevious()) { - fastForward(iRequirements); + if (!PackageNamespace.PACKAGE_NAMESPACE.equals(fragmentRequirement.getNamespace()) + || isDynamic(fragmentRequirement)) { + requirements.add(fragmentRequirement); + } else { + requirements.addAfterLastMatch(fragmentRequirement, r -> !isDynamic(r)); } - iRequirements.add(fragmentRequirement); } } } @@ -455,61 +377,24 @@ final class ModuleResolver { return PackageNamespace.PACKAGE_NAMESPACE.equals(requirement.getNamespace()) && PackageNamespace.RESOLUTION_DYNAMIC.equals(requirement.getDirectives().get(Namespace.REQUIREMENT_RESOLUTION_DIRECTIVE)); } - private static void addProvidedWires(Map<ModuleCapability, List<ModuleWire>> toAdd, List<ModuleWire> existing, final List<ModuleCapability> orderedCapabilities) { + private static void addProvidedWires(Map<ModuleCapability, List<ModuleWire>> toAdd, + NamespaceList.Builder<ModuleWire> existing, NamespaceList.Builder<ModuleCapability> capabilities) { if (toAdd == null) return; - int originalSize = existing.size(); - for (ModuleCapability capability : orderedCapabilities) { + for (ModuleCapability capability : capabilities) { List<ModuleWire> newWires = toAdd.get(capability); if (newWires != null) { existing.addAll(newWires); } } - if (originalSize != 0) { - Collections.sort(existing, new Comparator<ModuleWire>() { - @Override - public int compare(ModuleWire w1, ModuleWire w2) { - int index1 = orderedCapabilities.indexOf(w1.getCapability()); - int index2 = orderedCapabilities.indexOf(w2.getCapability()); - return index1 - index2; - } - }); - } - } - - private static void addRequiredWires(List<ModuleWire> toAdd, List<ModuleWire> existing, final List<ModuleRequirement> orderedRequirements) { - if (toAdd == null) - return; - int originalSize = existing.size(); - existing.addAll(toAdd); - if (originalSize != 0) { - Collections.sort(existing, new Comparator<ModuleWire>() { - @Override - public int compare(ModuleWire w1, ModuleWire w2) { - int index1 = orderedRequirements.indexOf(w1.getRequirement()); - int index2 = orderedRequirements.indexOf(w2.getRequirement()); - return index1 - index2; - } - }); - } } - private static void fastForward(ListIterator<?> listIterator) { - while (listIterator.hasNext()) - listIterator.next(); - } - - static void rewind(ListIterator<?> listIterator) { - while (listIterator.hasPrevious()) - listIterator.previous(); - } - - private static ModuleWiring createWiringDelta(ModuleRevision revision, ModuleWiring existingWiring, Map<ModuleCapability, List<ModuleWire>> providedWireMap, List<ModuleWire> requiredWires) { + private static ModuleWiring createWiringDelta(ModuleRevision revision, ModuleWiring existingWiring, Map<ModuleCapability, List<ModuleWire>> providedWireMap, NamespaceList<ModuleWire> requiredWires) { // No null checks are done here on the wires since this is a copy. - List<ModuleWire> existingProvidedWires = existingWiring.getProvidedWires().copyList(); - List<ModuleCapability> existingCapabilities = existingWiring.getCapabilities().copyList(); - List<ModuleWire> existingRequiredWires = existingWiring.getRequiredWires().copyList(); - List<ModuleRequirement> existingRequirements = existingWiring.getRequirements().copyList(); + NamespaceList.Builder<ModuleWire> existingProvidedWires = existingWiring.getProvidedWires().createBuilder(); + NamespaceList.Builder<ModuleCapability> existingCapabilities = existingWiring.getCapabilities().createBuilder(); + NamespaceList.Builder<ModuleWire> existingRequiredWires = existingWiring.getRequiredWires().createBuilder(); + NamespaceList.Builder<ModuleRequirement> existingRequirements = existingWiring.getRequirements().createBuilder(); // First, add newly resolved fragment capabilities and requirements if (providedWireMap != null) { @@ -517,7 +402,7 @@ final class ModuleResolver { ModuleCapability hostCapability = hostCapabilities.isEmpty() ? null : hostCapabilities.get(0); List<ModuleWire> newHostWires = hostCapability == null ? null : providedWireMap.get(hostCapability); if (newHostWires != null) { - addPayloadContent(newHostWires, existingCapabilities.listIterator(), existingRequirements.listIterator()); + addPayloadContent(newHostWires, existingCapabilities, existingRequirements); } } @@ -526,11 +411,13 @@ final class ModuleResolver { // Also need to include any new required wires that may have be added for fragment hosts // Also will be needed for dynamic imports - addRequiredWires(requiredWires, existingRequiredWires, existingRequirements); + if (requiredWires != null) { + existingRequiredWires.addAll(requiredWires); + } InternalUtils.filterCapabilityPermissions(existingCapabilities); - return new ModuleWiring(revision, existingCapabilities, existingRequirements, existingProvidedWires, - existingRequiredWires, existingWiring.getSubstitutedNames()); + return new ModuleWiring(revision, existingCapabilities.build(), existingRequirements.build(), + existingProvidedWires.build(), existingRequiredWires.build(), existingWiring.getSubstitutedNames()); } static boolean isSingleton(ModuleRevision revision) { @@ -721,11 +608,10 @@ final class ModuleResolver { } List<Capability> filterProviders(Requirement requirement, List<ModuleCapability> candidates, boolean filterResolvedHosts) { - ListIterator<ModuleCapability> iCandidates = candidates.listIterator(); - filterDisabled(iCandidates); - removeNonEffectiveCapabilities(iCandidates); - removeSubstituted(iCandidates); - filterPermissions((BundleRequirement) requirement, iCandidates); + filterDisabled(candidates); + removeNonEffectiveCapabilities(candidates); + removeSubstituted(candidates); + filterPermissions((BundleRequirement) requirement, candidates); List<ModuleCapability> filteredMatches = null; if (DEBUG_PROVIDERS || DEBUG_HOOKS) { @@ -800,9 +686,8 @@ final class ModuleResolver { } } - private void filterPermissions(BundleRequirement requirement, ListIterator<ModuleCapability> iCandidates) { - rewind(iCandidates); - if (System.getSecurityManager() == null || !iCandidates.hasNext()) { + private void filterPermissions(BundleRequirement requirement, List<ModuleCapability> candidates) { + if (System.getSecurityManager() == null) { return; } @@ -811,18 +696,16 @@ final class ModuleResolver { return; } - candidates: while (iCandidates.hasNext()) { - ModuleCapability candidate = iCandidates.next(); + candidates.removeIf(candidate -> { // TODO this is a hack for when a bundle imports and exports the same package if (PackageNamespace.PACKAGE_NAMESPACE.equals(requirement.getNamespace())) { if (requirement.getRevision().equals(candidate.getRevision())) { - continue candidates; + return false; } } Permission requirePermission = InternalUtils.getRequirePermission(candidate); Permission providePermission = InternalUtils.getProvidePermission(candidate); if (!requirement.getRevision().getBundle().hasPermission(requirePermission)) { - iCandidates.remove(); if (DEBUG_PROVIDERS) { Debug.println(new StringBuilder("RESOLVER: Capability filtered because requirer did not have permission") //$NON-NLS-1$ .append(SEPARATOR).append(TAB) // @@ -833,8 +716,8 @@ final class ModuleResolver { .append(candidate.getResource()) // .toString()); } + return true; } else if (!candidate.getRevision().getBundle().hasPermission(providePermission)) { - iCandidates.remove(); if (DEBUG_PROVIDERS) { Debug.println(new StringBuilder("RESOLVER: Capability filtered because provider did not have permission") //$NON-NLS-1$ .append(SEPARATOR).append(TAB) // @@ -845,16 +728,15 @@ final class ModuleResolver { .append(candidate.getResource()) // .toString()); } + return true; } - } + return false; + }); } - private void filterDisabled(ListIterator<ModuleCapability> iCandidates) { - rewind(iCandidates); - while (iCandidates.hasNext()) { - Capability capability = iCandidates.next(); + private void filterDisabled(List<ModuleCapability> candidates) { + candidates.removeIf(capability -> { if (disabled.contains(capability.getResource())) { - iCandidates.remove(); if (DEBUG_PROVIDERS) { Debug.println(new StringBuilder("RESOLVER: Capability filtered because it was disabled") //$NON-NLS-1$ .append(SEPARATOR).append(TAB) // @@ -865,17 +747,16 @@ final class ModuleResolver { .append(capability.getResource()) // .toString()); } + return true; } - } + return false; + }); } - private void removeSubstituted(ListIterator<ModuleCapability> iCapabilities) { - rewind(iCapabilities); - while (iCapabilities.hasNext()) { - ModuleCapability capability = iCapabilities.next(); + private void removeSubstituted(List<ModuleCapability> capabilities) { + capabilities.removeIf(capability -> { ModuleWiring wiring = wirings.get(capability.getRevision()); if (wiring != null && wiring.isSubtituted(capability)) { - iCapabilities.remove(); if (DEBUG_PROVIDERS) { Debug.println(new StringBuilder("RESOLVER: Capability filtered because it was substituted") //$NON-NLS-1$ .append(SEPARATOR).append(TAB) // @@ -886,8 +767,10 @@ final class ModuleResolver { .append(capability.getResource()) // .toString()); } + return true; } - } + return false; + }); } @Override @@ -942,7 +825,7 @@ final class ModuleResolver { 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()); + filterDisabled(candidates); for (ModuleCapability candidate : candidates) { ModuleRequirement hostReq = candidate.getRevision().getModuleRequirements(HostNamespace.HOST_NAMESPACE).get(0); for (ModuleCapability hostCap : hostCaps) { |