diff --git a/tycho-bundles/org.eclipse.tycho.p2.resolver.impl.test/src/test/java/org/eclipse/tycho/p2/target/TestResolverFactory.java b/tycho-bundles/org.eclipse.tycho.p2.resolver.impl.test/src/test/java/org/eclipse/tycho/p2/target/TestResolverFactory.java index 9f3a62bf37..de173901bd 100644 --- a/tycho-bundles/org.eclipse.tycho.p2.resolver.impl.test/src/test/java/org/eclipse/tycho/p2/target/TestResolverFactory.java +++ b/tycho-bundles/org.eclipse.tycho.p2.resolver.impl.test/src/test/java/org/eclipse/tycho/p2/target/TestResolverFactory.java @@ -151,7 +151,7 @@ public TargetPlatformFactoryImpl getTargetPlatformFactoryImpl() { @Override public P2Resolver createResolver(MavenLogger logger) { - return new P2ResolverImpl(getTargetPlatformFactoryImpl(), mavenContext.getLogger()); + return new P2ResolverImpl(getTargetPlatformFactoryImpl(), null, mavenContext.getLogger()); } @Override diff --git a/tycho-bundles/org.eclipse.tycho.p2.resolver.impl/src/main/java/org/eclipse/tycho/p2/resolver/P2ResolverFactoryImpl.java b/tycho-bundles/org.eclipse.tycho.p2.resolver.impl/src/main/java/org/eclipse/tycho/p2/resolver/P2ResolverFactoryImpl.java index 23b66805fc..1b5741fa51 100644 --- a/tycho-bundles/org.eclipse.tycho.p2.resolver.impl/src/main/java/org/eclipse/tycho/p2/resolver/P2ResolverFactoryImpl.java +++ b/tycho-bundles/org.eclipse.tycho.p2.resolver.impl/src/main/java/org/eclipse/tycho/p2/resolver/P2ResolverFactoryImpl.java @@ -15,11 +15,28 @@ package org.eclipse.tycho.p2.resolver; import java.io.File; +import java.util.AbstractMap.SimpleEntry; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; import java.util.Map; +import java.util.Map.Entry; import java.util.Objects; +import java.util.Optional; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import java.util.stream.Collectors; +import org.eclipse.equinox.internal.p2.metadata.IRequiredCapability; import org.eclipse.equinox.p2.core.ProvisionException; import org.eclipse.equinox.p2.metadata.IInstallableUnit; +import org.eclipse.equinox.p2.metadata.IProvidedCapability; +import org.eclipse.equinox.p2.metadata.IRequirement; +import org.eclipse.equinox.p2.publisher.eclipse.BundlesAction; import org.eclipse.tycho.ArtifactDescriptor; import org.eclipse.tycho.MavenDependencyDescriptor; import org.eclipse.tycho.ReactorProject; @@ -35,9 +52,11 @@ import org.eclipse.tycho.p2.target.TargetDefinitionResolverService; import org.eclipse.tycho.p2.target.TargetPlatformFactoryImpl; import org.eclipse.tycho.p2.target.facade.PomDependencyCollector; +import org.eclipse.tycho.p2.util.resolution.ResolutionData; import org.eclipse.tycho.repository.local.LocalArtifactRepository; import org.eclipse.tycho.repository.local.LocalMetadataRepository; +@SuppressWarnings("restriction") public class P2ResolverFactoryImpl implements P2ResolverFactory { // TODO cache these instances in an p2 agent, and not here @@ -48,6 +67,7 @@ public class P2ResolverFactoryImpl implements P2ResolverFactory { private LocalRepositoryP2Indices localRepoIndices; private RemoteAgentManager remoteAgentManager; private TargetDefinitionResolverService targetDefinitionResolverService; + private ConcurrentMap>> hostRequirementMap = new ConcurrentHashMap<>(); private static synchronized LocalMetadataRepository getLocalMetadataRepository(MavenContext context, LocalRepositoryP2Indices localRepoIndices) { @@ -90,7 +110,62 @@ public TargetPlatformFactoryImpl getTargetPlatformFactory() { @Override public P2ResolverImpl createResolver(MavenLogger logger) { - return new P2ResolverImpl(getTargetPlatformFactory(), logger); + return new P2ResolverImpl(getTargetPlatformFactory(), this, logger); + } + + public Set calculateDependencyFragments(ResolutionData data, + Collection resolvedUnits) { + Collection availableIUs = data.getAvailableIUs(); + List> fragmentsList = availableIUs.stream()// + .map(iu -> hostRequirementMap.computeIfAbsent(iu, key -> { + for (IProvidedCapability capability : iu.getProvidedCapabilities()) { + String nameSpace = capability.getNamespace(); + if (BundlesAction.CAPABILITY_NS_OSGI_FRAGMENT.equals(nameSpace)) { + String fragmentName = capability.getName(); + return findFragmentHostRequirement(iu, fragmentName); + } + } + return Optional.empty(); + + }))// + .filter(Optional::isPresent)// + .map(Optional::get)// + .collect(Collectors.toCollection(ArrayList::new)); + if (fragmentsList.isEmpty()) { + return Collections.emptySet(); + } + Set dependencyFragments = new HashSet<>(); + for (Iterator iterator = resolvedUnits.iterator(); iterator.hasNext() + && !fragmentsList.isEmpty();) { + IInstallableUnit resolvedUnit = iterator.next(); + addMatchingFragments(fragmentsList, dependencyFragments, resolvedUnit); + } + return dependencyFragments; + } + + private static void addMatchingFragments(List> fragmentsList, + Set dependencyFragments, IInstallableUnit unitToMatch) { + Iterator> iterator = fragmentsList.iterator(); + while (iterator.hasNext()) { + Entry fragment = iterator.next(); + if (fragment.getValue().isMatch(unitToMatch)) { + dependencyFragments.add(fragment.getKey()); + iterator.remove(); + } + } + } + + private static Optional> findFragmentHostRequirement( + IInstallableUnit unit, String fragmentName) { + for (IRequirement requirement : unit.getRequirements()) { + if (requirement instanceof IRequiredCapability) { + IRequiredCapability requiredCapability = (IRequiredCapability) requirement; + if (fragmentName.equals(requiredCapability.getName())) { + return Optional.of(new SimpleEntry<>(unit, requiredCapability)); + } + } + } + return Optional.empty(); } // setters for DS diff --git a/tycho-bundles/org.eclipse.tycho.p2.resolver.impl/src/main/java/org/eclipse/tycho/p2/resolver/P2ResolverImpl.java b/tycho-bundles/org.eclipse.tycho.p2.resolver.impl/src/main/java/org/eclipse/tycho/p2/resolver/P2ResolverImpl.java index 4c73b2c19a..ccc7edde6f 100644 --- a/tycho-bundles/org.eclipse.tycho.p2.resolver.impl/src/main/java/org/eclipse/tycho/p2/resolver/P2ResolverImpl.java +++ b/tycho-bundles/org.eclipse.tycho.p2.resolver.impl/src/main/java/org/eclipse/tycho/p2/resolver/P2ResolverImpl.java @@ -35,7 +35,6 @@ import java.util.function.Consumer; import org.eclipse.core.runtime.IProgressMonitor; -import org.eclipse.equinox.internal.p2.metadata.IRequiredCapability; import org.eclipse.equinox.internal.p2.metadata.InstallableUnit; import org.eclipse.equinox.p2.metadata.IArtifactKey; import org.eclipse.equinox.p2.metadata.IInstallableUnit; @@ -98,8 +97,12 @@ public class P2ResolverImpl implements P2Resolver { private PomDependencies pomDependencies = PomDependencies.ignore; - public P2ResolverImpl(TargetPlatformFactoryImpl targetPlatformFactory, MavenLogger logger) { + private P2ResolverFactoryImpl p2ResolverFactoryImpl; + + public P2ResolverImpl(TargetPlatformFactoryImpl targetPlatformFactory, P2ResolverFactoryImpl p2ResolverFactoryImpl, + MavenLogger logger) { this.targetPlatformFactory = targetPlatformFactory; + this.p2ResolverFactoryImpl = p2ResolverFactoryImpl; this.logger = logger; this.monitor = new LoggingProgressMonitor(logger); this.environments = Collections.singletonList(TargetEnvironment.getRunningEnvironment()); @@ -255,40 +258,11 @@ protected P2ResolutionResult resolveDependencies(Collection ro if (usedTargetPlatformUnits != null) { usedTargetPlatformUnits.addAll(newState); } - Set dependencyFragments = new HashSet<>(); - for (IInstallableUnit iu : availableUnits) { - for (IProvidedCapability capability : iu.getProvidedCapabilities()) { - String nameSpace = capability.getNamespace(); - if (BundlesAction.CAPABILITY_NS_OSGI_FRAGMENT.equals(nameSpace)) { - String fragmentName = capability.getName(); - IRequiredCapability fragmentHost = findFragmentHostRequirement(iu, fragmentName); - if (fragmentHost != null) { - for (IInstallableUnit resolved : newState) { - if (fragmentHost.isMatch(resolved)) { - dependencyFragments.add(iu); - break; - } - } - } - } - } - - } + Set dependencyFragments = p2ResolverFactoryImpl == null ? Collections.emptySet() + : p2ResolverFactoryImpl.calculateDependencyFragments(data, newState); return toResolutionResult(newState, dependencyFragments, project, targetPlatform); } - private static IRequiredCapability findFragmentHostRequirement(IInstallableUnit unit, String fragmentName) { - for (IRequirement requirement : unit.getRequirements()) { - if (requirement instanceof IRequiredCapability) { - IRequiredCapability requiredCapability = (IRequiredCapability) requirement; - if (fragmentName.equals(requiredCapability.getName())) { - return requiredCapability; - } - } - } - return null; - } - private P2ResolutionResult toResolutionResult(Collection resolvedUnits, Collection dependencyFragments, ReactorProject project, P2TargetPlatform targetPlatform) { Set currentProjectUnits = getProjectUnits(project);