From 774e135844b20b46ef71b6de4463126aa0f6da9b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20L=C3=A4ubrich?= Date: Thu, 3 Feb 2022 12:33:14 +0100 Subject: [PATCH] Fix #626 - Classpath computation must take fragments into account - pass fragments of selected dependencies to the classpath computation - add an integration test to proof the problem is fixed --- .../tycho/artifacts/DependencyArtifacts.java | 9 ++- .../java/org/eclipse/tycho/ArtifactType.java | 1 + .../resolver/DefaultP2ResolutionResult.java | 42 ++++++++++- .../MetadataOnlyP2ResolutionResult.java | 5 ++ .../tycho/p2/resolver/P2ResolverImpl.java | 69 +++++++++++++------ .../tycho/p2/target/ArtifactTypeHelper.java | 7 +- .../resolver/facade/P2ResolutionResult.java | 6 ++ .../core/osgitools/OsgiBundleProject.java | 12 +++- .../DefaultDependencyArtifacts.java | 20 +++++- .../MultiEnvironmentDependencyArtifacts.java | 12 +++- .../compiler.fragments/META-INF/MANIFEST.MF | 10 +++ .../compiler.fragments/build.properties | 4 ++ .../projects/compiler.fragments/jgit.target | 16 +++++ tycho-its/projects/compiler.fragments/pom.xml | 37 ++++++++++ .../src/compiler/fragments/TestMe.java | 67 ++++++++++++++++++ .../tycho/test/compiler/FragmentsTest.java | 26 +++++++ .../p2/resolver/P2DependencyResolver.java | 5 ++ 17 files changed, 317 insertions(+), 31 deletions(-) create mode 100644 tycho-its/projects/compiler.fragments/META-INF/MANIFEST.MF create mode 100644 tycho-its/projects/compiler.fragments/build.properties create mode 100644 tycho-its/projects/compiler.fragments/jgit.target create mode 100644 tycho-its/projects/compiler.fragments/pom.xml create mode 100644 tycho-its/projects/compiler.fragments/src/compiler/fragments/TestMe.java create mode 100644 tycho-its/src/test/java/org/eclipse/tycho/test/compiler/FragmentsTest.java diff --git a/tycho-bundles/org.eclipse.tycho.core.shared/src/main/java/org/eclipse/tycho/artifacts/DependencyArtifacts.java b/tycho-bundles/org.eclipse.tycho.core.shared/src/main/java/org/eclipse/tycho/artifacts/DependencyArtifacts.java index 58d2697be7..1901075ac2 100644 --- a/tycho-bundles/org.eclipse.tycho.core.shared/src/main/java/org/eclipse/tycho/artifacts/DependencyArtifacts.java +++ b/tycho-bundles/org.eclipse.tycho.core.shared/src/main/java/org/eclipse/tycho/artifacts/DependencyArtifacts.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2008, 2011 Sonatype Inc. and others. + * Copyright (c) 2008, 2022 Sonatype Inc. and others. * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 * which accompanies this distribution, and is available at @@ -9,6 +9,7 @@ * * Contributors: * Sonatype Inc. - initial API and implementation + * Christoph Läubrich - Issue #626 - Classpath computation must take fragments into account *******************************************************************************/ package org.eclipse.tycho.artifacts; @@ -44,6 +45,12 @@ public interface DependencyArtifacts { */ public List getArtifacts(); + /** + * + * @return additional fragments that might be attached to the artifacts + */ + Collection getFragments(); + /** * Returns all artifacts of the given type. */ diff --git a/tycho-bundles/org.eclipse.tycho.embedder.shared/src/main/java/org/eclipse/tycho/ArtifactType.java b/tycho-bundles/org.eclipse.tycho.embedder.shared/src/main/java/org/eclipse/tycho/ArtifactType.java index 582e272678..a6d567e0bf 100644 --- a/tycho-bundles/org.eclipse.tycho.embedder.shared/src/main/java/org/eclipse/tycho/ArtifactType.java +++ b/tycho-bundles/org.eclipse.tycho.embedder.shared/src/main/java/org/eclipse/tycho/ArtifactType.java @@ -20,6 +20,7 @@ public final class ArtifactType { public static final String TYPE_ECLIPSE_PLUGIN = "eclipse-plugin"; + public static final String TYPE_BUNDLE_FRAGMENT = "bundle-fragment"; public static final String TYPE_ECLIPSE_TEST_PLUGIN = "eclipse-test-plugin"; public static final String TYPE_ECLIPSE_FEATURE = "eclipse-feature"; public static final String TYPE_ECLIPSE_PRODUCT = "eclipse-product"; diff --git a/tycho-bundles/org.eclipse.tycho.p2.resolver.impl/src/main/java/org/eclipse/tycho/p2/resolver/DefaultP2ResolutionResult.java b/tycho-bundles/org.eclipse.tycho.p2.resolver.impl/src/main/java/org/eclipse/tycho/p2/resolver/DefaultP2ResolutionResult.java index 131f6fb6b4..05459991c6 100644 --- a/tycho-bundles/org.eclipse.tycho.p2.resolver.impl/src/main/java/org/eclipse/tycho/p2/resolver/DefaultP2ResolutionResult.java +++ b/tycho-bundles/org.eclipse.tycho.p2.resolver.impl/src/main/java/org/eclipse/tycho/p2/resolver/DefaultP2ResolutionResult.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2011, 2014 Sonatype Inc. and others. + * Copyright (c) 2011, 2022 Sonatype Inc. and others. * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 * which accompanies this distribution, and is available at @@ -9,6 +9,7 @@ * * Contributors: * Sonatype Inc. - initial API and implementation + * Christoph Läubrich - Issue #626 - Classpath computation must take fragments into account *******************************************************************************/ package org.eclipse.tycho.p2.resolver; @@ -16,15 +17,19 @@ import java.util.Collection; import java.util.LinkedHashMap; import java.util.LinkedHashSet; +import java.util.List; import java.util.Map; import java.util.Optional; import java.util.Set; +import java.util.stream.Collectors; import org.eclipse.equinox.p2.metadata.IArtifactKey; import org.eclipse.equinox.p2.metadata.IInstallableUnit; import org.eclipse.tycho.ArtifactKey; import org.eclipse.tycho.ArtifactType; +import org.eclipse.tycho.DefaultArtifactKey; import org.eclipse.tycho.p2.resolver.facade.P2ResolutionResult; +import org.eclipse.tycho.p2.target.ArtifactTypeHelper; import org.eclipse.tycho.p2.target.P2TargetPlatform; public class DefaultP2ResolutionResult implements P2ResolutionResult { @@ -36,7 +41,33 @@ public class DefaultP2ResolutionResult implements P2ResolutionResult { * Set of installable unit in the target platform of the module that do not come from the local * reactor. */ - private final Set nonReactorUnits = new LinkedHashSet<>(); + private final Set nonReactorUnits = new LinkedHashSet<>(); + private P2TargetPlatform resolutionContext; + private List fragments; + + public DefaultP2ResolutionResult(Collection dependencyFragments, + P2TargetPlatform resolutionContext) { + this.resolutionContext = resolutionContext; + fragments = dependencyFragments.stream().map(iu -> { + DefaultArtifactKey artifactKey = new DefaultArtifactKey(ArtifactType.TYPE_BUNDLE_FRAGMENT, iu.getId(), + iu.getVersion().toString()); + final DefaultP2ResolutionResultEntry entry; + if (resolutionContext.isFileAlreadyAvailable(artifactKey)) { + entry = new DefaultP2ResolutionResultEntry(artifactKey.getType(), artifactKey.getId(), + artifactKey.getVersion(), null, resolutionContext.getArtifactLocation(artifactKey)); + } else { + entry = new DefaultP2ResolutionResultEntry(artifactKey.getType(), artifactKey.getId(), + artifactKey.getVersion(), null, () -> { + File res = resolutionContext + .getLocalArtifactFile(ArtifactTypeHelper.toP2ArtifactKey(artifactKey)); + resolutionContext.saveLocalMavenRepository(); // store just downloaded artifacts in local Maven repo index + return res; + }); + } + entry.addInstallableUnit(iu); + return entry; + }).collect(Collectors.toList()); + } @Override public Collection getArtifacts() { @@ -44,7 +75,7 @@ public Collection getArtifacts() { } public void addArtifact(ArtifactKey artifactKey, String classifier, IInstallableUnit installableUnit, - IArtifactKey p2ArtifactKey, P2TargetPlatform resolutionContext) { + IArtifactKey p2ArtifactKey) { if (resolutionContext.isFileAlreadyAvailable(artifactKey)) { addResolvedArtifact(Optional.of(artifactKey), classifier, installableUnit, resolutionContext.getArtifactLocation(artifactKey)); @@ -141,4 +172,9 @@ public void addNonReactorUnits(Set installableUnits) { public Set getNonReactorUnits() { return nonReactorUnits; } + + @Override + public Collection getDependencyFragments() { + return fragments; + } } diff --git a/tycho-bundles/org.eclipse.tycho.p2.resolver.impl/src/main/java/org/eclipse/tycho/p2/resolver/MetadataOnlyP2ResolutionResult.java b/tycho-bundles/org.eclipse.tycho.p2.resolver.impl/src/main/java/org/eclipse/tycho/p2/resolver/MetadataOnlyP2ResolutionResult.java index 3bff37ba9c..f2efeba0e9 100644 --- a/tycho-bundles/org.eclipse.tycho.p2.resolver.impl/src/main/java/org/eclipse/tycho/p2/resolver/MetadataOnlyP2ResolutionResult.java +++ b/tycho-bundles/org.eclipse.tycho.p2.resolver.impl/src/main/java/org/eclipse/tycho/p2/resolver/MetadataOnlyP2ResolutionResult.java @@ -72,4 +72,9 @@ public Collection getArtifacts() { public Set getNonReactorUnits() { return Collections.emptySet(); } + + @Override + public Collection getDependencyFragments() { + return Collections.emptyList(); + } } 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 bc9aeece3f..4c73b2c19a 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 @@ -13,6 +13,7 @@ * Christoph Läubrich - Bug 572481 - Tycho does not understand "additional.bundles" directive in build.properties * - Issue #82 - Support resolving of non-project IUs in P2Resolver * - Issue #462 - Delay Pom considered items to the final Target Platform calculation + * - Issue #626 - Classpath computation must take fragments into account *******************************************************************************/ package org.eclipse.tycho.p2.resolver; @@ -34,6 +35,7 @@ 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; @@ -94,8 +96,6 @@ public class P2ResolverImpl implements P2Resolver { private TargetPlatformFactoryImpl targetPlatformFactory; - private Set usedTargetPlatformUnits; - private PomDependencies pomDependencies = PomDependencies.ignore; public P2ResolverImpl(TargetPlatformFactoryImpl targetPlatformFactory, MavenLogger logger) { @@ -118,24 +118,22 @@ public Map resolveTargetDependencies(Targ // we need a linked hashmap to maintain iteration-order, some of the code relies on it! Map results = new LinkedHashMap<>(); - usedTargetPlatformUnits = new LinkedHashSet<>(); + Set usedTargetPlatformUnits = new LinkedHashSet<>(); Set metadata = project != null ? project.getDependencyMetadata(DependencyMetadataType.SEED) : Collections.emptySet(); for (TargetEnvironment environment : environments) { if (isMatchingEnv(metadata, environment, logger::debug)) { results.put(environment, resolveDependencies(Collections. emptySet(), project, - new ProjectorResolutionStrategy(logger), environment, targetPlatform)); + new ProjectorResolutionStrategy(logger), environment, targetPlatform, usedTargetPlatformUnits)); } else { logger.info(MessageFormat.format( - "Project {0}:{1}:{2} does not match environment {3} skipp dependecy resolution", + "Project {0}:{1}:{2} does not match environment {3} skip dependency resolution", project.getGroupId(), project.getArtifactId(), project.getVersion(), environment.toFilterExpression())); } } targetPlatform.reportUsedLocalIUs(usedTargetPlatformUnits); - usedTargetPlatformUnits = null; - return results; } @@ -157,7 +155,7 @@ public Map resolveArtifactDependencies(Ta Map results = new LinkedHashMap<>(); for (TargetEnvironment environment : environments) { results.put(environment, resolveDependencies(roots, null, new ProjectorResolutionStrategy(logger), - environment, targetPlatform)); + environment, targetPlatform, null)); } return results; } @@ -165,7 +163,7 @@ public Map resolveArtifactDependencies(Ta @Override public P2ResolutionResult collectProjectDependencies(TargetPlatform context, ReactorProject project) { return resolveDependencies(Collections. emptySet(), project, new DependencyCollector(logger), - new TargetEnvironment(null, null, null), getTargetFromContext(context)); + new TargetEnvironment(null, null, null), getTargetFromContext(context), null); } @Override @@ -210,7 +208,8 @@ public P2ResolutionResult getTargetPlatformAsResolutionResult(TargetPlatformConf @SuppressWarnings("unchecked") protected P2ResolutionResult resolveDependencies(Collection rootUIs, ReactorProject project, - AbstractResolutionStrategy strategy, TargetEnvironment environment, P2TargetPlatform targetPlatform) { + AbstractResolutionStrategy strategy, TargetEnvironment environment, P2TargetPlatform targetPlatform, + Set usedTargetPlatformUnits) { ResolutionDataImpl data = new ResolutionDataImpl(targetPlatform.getEEResolutionHints()); Set availableUnits = targetPlatform.getInstallableUnits(); @@ -256,16 +255,46 @@ 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; + } + } + } + } + } + + } + return toResolutionResult(newState, dependencyFragments, project, targetPlatform); + } - return toResolutionResult(newState, 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 newState, ReactorProject project, - P2TargetPlatform targetPlatform) { + private P2ResolutionResult toResolutionResult(Collection resolvedUnits, + Collection dependencyFragments, ReactorProject project, P2TargetPlatform targetPlatform) { Set currentProjectUnits = getProjectUnits(project); - DefaultP2ResolutionResult result = new DefaultP2ResolutionResult(); + DefaultP2ResolutionResult result = new DefaultP2ResolutionResult(dependencyFragments, targetPlatform); - for (IInstallableUnit iu : newState) { + for (IInstallableUnit iu : resolvedUnits) { addUnit(result, iu, project, targetPlatform, currentProjectUnits); } // remove entries for which there were only "additional" IUs, but none with a recognized type @@ -275,7 +304,7 @@ private P2ResolutionResult toResolutionResult(Collection newSt targetPlatform.saveLocalMavenRepository(); // TODO 372780 remove; no longer needed when aggregation uses frozen target platform as source - collectNonReactorIUs(result, newState, targetPlatform, currentProjectUnits); + collectNonReactorIUs(result, resolvedUnits, targetPlatform, currentProjectUnits); return result; } @@ -355,7 +384,7 @@ public P2ResolutionResult resolveInstallableUnit(TargetPlatform context, String Set newState = result.toUnmodifiableSet(); - return toResolutionResult(newState, null, targetPlatform); + return toResolutionResult(newState, Collections.emptyList(), null, targetPlatform); } private static P2TargetPlatform getTargetFromContext(TargetPlatform context) { @@ -481,16 +510,16 @@ private static void addArtifactFile(DefaultP2ResolutionResult result, IInstallab if (PublisherHelper.OSGI_BUNDLE_CLASSIFIER.equals(p2ArtifactKey.getClassifier())) { ArtifactKey artifactKey = new DefaultArtifactKey(ArtifactType.TYPE_ECLIPSE_PLUGIN, id, version); - result.addArtifact(artifactKey, mavenClassifier, iu, p2ArtifactKey, context); + result.addArtifact(artifactKey, mavenClassifier, iu, p2ArtifactKey); } else if (PublisherHelper.ECLIPSE_FEATURE_CLASSIFIER.equals(p2ArtifactKey.getClassifier())) { String featureId = getFeatureId(iu); if (featureId != null) { ArtifactKey artifactKey = new DefaultArtifactKey(ArtifactType.TYPE_ECLIPSE_FEATURE, featureId, version); - result.addArtifact(artifactKey, mavenClassifier, iu, p2ArtifactKey, context); + result.addArtifact(artifactKey, mavenClassifier, iu, p2ArtifactKey); } } else { ArtifactKey key = new DefaultArtifactKey(ArtifactType.TYPE_INSTALLABLE_UNIT, id, version); - result.addArtifact(key, mavenClassifier, iu, p2ArtifactKey, context); + result.addArtifact(key, mavenClassifier, iu, p2ArtifactKey); } // ignore other/unknown artifacts, like binary blobs for now. diff --git a/tycho-bundles/org.eclipse.tycho.p2.resolver.impl/src/main/java/org/eclipse/tycho/p2/target/ArtifactTypeHelper.java b/tycho-bundles/org.eclipse.tycho.p2.resolver.impl/src/main/java/org/eclipse/tycho/p2/target/ArtifactTypeHelper.java index 3cc31ca9e7..94979130c9 100644 --- a/tycho-bundles/org.eclipse.tycho.p2.resolver.impl/src/main/java/org/eclipse/tycho/p2/target/ArtifactTypeHelper.java +++ b/tycho-bundles/org.eclipse.tycho.p2.resolver.impl/src/main/java/org/eclipse/tycho/p2/target/ArtifactTypeHelper.java @@ -12,6 +12,7 @@ *******************************************************************************/ package org.eclipse.tycho.p2.target; +import static org.eclipse.tycho.ArtifactType.TYPE_BUNDLE_FRAGMENT; import static org.eclipse.tycho.ArtifactType.TYPE_ECLIPSE_FEATURE; import static org.eclipse.tycho.ArtifactType.TYPE_ECLIPSE_PLUGIN; @@ -86,8 +87,8 @@ public static IRequirement createRequirementFor(String type, String id, VersionR } private static IRequirement createBundleRequirement(String id, VersionRange versionRange) { - return MetadataFactory.createRequirement(BundlesAction.CAPABILITY_NS_OSGI_BUNDLE, id, versionRange, null, - false, true); // optional=false, multiple=true + return MetadataFactory.createRequirement(BundlesAction.CAPABILITY_NS_OSGI_BUNDLE, id, versionRange, null, false, + true); // optional=false, multiple=true } private static IRequirement createFeatureRequirement(String id, VersionRange versionRange) { @@ -119,7 +120,7 @@ public static org.eclipse.tycho.ArtifactKey toTychoArtifact(IInstallableUnit uni // p2 artifacts public static IArtifactKey toP2ArtifactKey(org.eclipse.tycho.ArtifactKey artifact) { - if (TYPE_ECLIPSE_PLUGIN.equals(artifact.getType())) { + if (TYPE_ECLIPSE_PLUGIN.equals(artifact.getType()) || TYPE_BUNDLE_FRAGMENT.equals(artifact.getType())) { return createP2ArtifactKey(PublisherHelper.OSGI_BUNDLE_CLASSIFIER, artifact); } else if (TYPE_ECLIPSE_FEATURE.equals(artifact.getType())) { diff --git a/tycho-bundles/org.eclipse.tycho.p2.resolver.shared/src/main/java/org/eclipse/tycho/p2/resolver/facade/P2ResolutionResult.java b/tycho-bundles/org.eclipse.tycho.p2.resolver.shared/src/main/java/org/eclipse/tycho/p2/resolver/facade/P2ResolutionResult.java index d2c60fbe92..7ec9db46b8 100644 --- a/tycho-bundles/org.eclipse.tycho.p2.resolver.shared/src/main/java/org/eclipse/tycho/p2/resolver/facade/P2ResolutionResult.java +++ b/tycho-bundles/org.eclipse.tycho.p2.resolver.shared/src/main/java/org/eclipse/tycho/p2/resolver/facade/P2ResolutionResult.java @@ -40,4 +40,10 @@ public static interface Entry extends ArtifactKey { public Collection getArtifacts(); public Set getNonReactorUnits(); + + /** + * + * @return a list of fragments that belong to the resolved state of this result + */ + Collection getDependencyFragments(); } diff --git a/tycho-core/src/main/java/org/eclipse/tycho/core/osgitools/OsgiBundleProject.java b/tycho-core/src/main/java/org/eclipse/tycho/core/osgitools/OsgiBundleProject.java index 170d52b6e2..882309fd83 100644 --- a/tycho-core/src/main/java/org/eclipse/tycho/core/osgitools/OsgiBundleProject.java +++ b/tycho-core/src/main/java/org/eclipse/tycho/core/osgitools/OsgiBundleProject.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2008, 2021 Sonatype Inc. and others. + * Copyright (c) 2008, 2022 Sonatype Inc. and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -10,6 +10,7 @@ * Christoph Läubrich - [Bug 572416] Tycho does not understand "additional.bundles" directive in build.properties * [Bug 572416] Compile all source folders contained in .classpath * [Issue #460] Delay classpath resolution to the compile phase + * [Issue #626] Classpath computation must take fragments into account *******************************************************************************/ package org.eclipse.tycho.core.osgitools; @@ -498,6 +499,15 @@ private void addExtraClasspathEntries(List classpath, ReactorPro Collections.singletonList(libraryClasspathEntry.getLibraryPath()), null)); } } + //Fragments are like embedded depdnecies... + for (ArtifactDescriptor fragment : artifacts.getFragments()) { + ArtifactKey projectKey = getArtifactKey(project); + File location = fragment.getLocation(true); + if (location != null) { + classpath + .add(new DefaultClasspathEntry(project, projectKey, Collections.singletonList(location), null)); + } + } } protected DefaultClasspathEntry addBundleToClasspath(ArtifactDescriptor matchingBundle, String path) { diff --git a/tycho-core/src/main/java/org/eclipse/tycho/core/osgitools/targetplatform/DefaultDependencyArtifacts.java b/tycho-core/src/main/java/org/eclipse/tycho/core/osgitools/targetplatform/DefaultDependencyArtifacts.java index 0616377155..45b76c73aa 100644 --- a/tycho-core/src/main/java/org/eclipse/tycho/core/osgitools/targetplatform/DefaultDependencyArtifacts.java +++ b/tycho-core/src/main/java/org/eclipse/tycho/core/osgitools/targetplatform/DefaultDependencyArtifacts.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2008, 2011 Sonatype Inc. and others. + * Copyright (c) 2008, 2022 Sonatype Inc. and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -7,19 +7,26 @@ * * Contributors: * Sonatype Inc. - initial API and implementation + * Christoph Läubrich - Issue #626 - Classpath computation must take fragments into account *******************************************************************************/ package org.eclipse.tycho.core.osgitools.targetplatform; +import java.io.File; +import java.util.ArrayList; +import java.util.Collection; import java.util.Collections; import java.util.LinkedHashSet; +import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; +import java.util.function.Supplier; import org.eclipse.tycho.ArtifactDescriptor; import org.eclipse.tycho.ArtifactKey; import org.eclipse.tycho.ReactorProject; import org.eclipse.tycho.artifacts.DependencyArtifacts; +import org.eclipse.tycho.core.osgitools.DefaultArtifactDescriptor; public class DefaultDependencyArtifacts extends ArtifactCollection implements DependencyArtifacts { @@ -33,6 +40,8 @@ public class DefaultDependencyArtifacts extends ArtifactCollection implements De */ private static final Map ARTIFACT_CACHE = new ConcurrentHashMap<>(); + protected final List fragments = new ArrayList(); + /** * 'this' project, i.e. the project the dependencies were resolved for. can be null. */ @@ -85,4 +94,13 @@ public void addNonReactorUnits(Set installableUnits) { this.nonReactorUnits.addAll(installableUnits); } + public void addFragment(ArtifactKey key, Supplier location, Set installableUnits) { + fragments.add(new DefaultArtifactDescriptor(key, whatever -> location.get(), null, null, installableUnits)); + } + + @Override + public Collection getFragments() { + return Collections.unmodifiableCollection(fragments); + } + } diff --git a/tycho-core/src/main/java/org/eclipse/tycho/core/osgitools/targetplatform/MultiEnvironmentDependencyArtifacts.java b/tycho-core/src/main/java/org/eclipse/tycho/core/osgitools/targetplatform/MultiEnvironmentDependencyArtifacts.java index cf01c32171..f0d1952c79 100644 --- a/tycho-core/src/main/java/org/eclipse/tycho/core/osgitools/targetplatform/MultiEnvironmentDependencyArtifacts.java +++ b/tycho-core/src/main/java/org/eclipse/tycho/core/osgitools/targetplatform/MultiEnvironmentDependencyArtifacts.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2008, 2020 Sonatype Inc. and others. + * Copyright (c) 2008, 2022 Sonatype Inc. and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -7,7 +7,8 @@ * * Contributors: * Sonatype Inc. - initial API and implementation - * Christoph Läubrich - Bug 567782 - Platform specific fragment not support in Multi-Platform POMless build + * Christoph Läubrich - Bug 567782 - Platform specific fragment not support in Multi-Platform POMless build + * - Issue #626 - Classpath computation must take fragments into account *******************************************************************************/ package org.eclipse.tycho.core.osgitools.targetplatform; @@ -15,6 +16,7 @@ import java.util.Collections; import java.util.LinkedHashMap; import java.util.Map; +import java.util.stream.Collectors; import org.eclipse.tycho.ArtifactDescriptor; import org.eclipse.tycho.ReactorProject; @@ -58,4 +60,10 @@ public void toDebugString(StringBuilder sb, String linePrefix) { public Collection getPlatforms() { return Collections.unmodifiableCollection(platforms.keySet()); } + + @Override + public Collection getFragments() { + return platforms.values().stream().map(DependencyArtifacts::getFragments).flatMap(Collection::stream).distinct() + .collect(Collectors.toList()); + } } diff --git a/tycho-its/projects/compiler.fragments/META-INF/MANIFEST.MF b/tycho-its/projects/compiler.fragments/META-INF/MANIFEST.MF new file mode 100644 index 0000000000..394bc184f9 --- /dev/null +++ b/tycho-its/projects/compiler.fragments/META-INF/MANIFEST.MF @@ -0,0 +1,10 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: JGit with Fragment +Bundle-SymbolicName: compiler.fragments +Bundle-Version: 1.0.0 +Require-Bundle: org.eclipse.core.runtime, + org.eclipse.jgit;bundle-version="5.13.0", + com.jcraft.jsch;bundle-version="0.1.55" +Bundle-RequiredExecutionEnvironment: JavaSE-11 +Bundle-ActivationPolicy: lazy diff --git a/tycho-its/projects/compiler.fragments/build.properties b/tycho-its/projects/compiler.fragments/build.properties new file mode 100644 index 0000000000..f250f9906e --- /dev/null +++ b/tycho-its/projects/compiler.fragments/build.properties @@ -0,0 +1,4 @@ +output.. = bin/ +bin.includes = META-INF/,\ + . +source.. = src/ diff --git a/tycho-its/projects/compiler.fragments/jgit.target b/tycho-its/projects/compiler.fragments/jgit.target new file mode 100644 index 0000000000..6317fe96bf --- /dev/null +++ b/tycho-its/projects/compiler.fragments/jgit.target @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + +> + \ No newline at end of file diff --git a/tycho-its/projects/compiler.fragments/pom.xml b/tycho-its/projects/compiler.fragments/pom.xml new file mode 100644 index 0000000000..b6812348ee --- /dev/null +++ b/tycho-its/projects/compiler.fragments/pom.xml @@ -0,0 +1,37 @@ + + + 4.0.0 + tycho.its + compiler.fragments + 1.0.0 + eclipse-plugin + + + 2.7.0-SNAPSHOT + + + + + + org.eclipse.tycho + tycho-maven-plugin + ${tycho.version} + true + + + org.eclipse.tycho + target-platform-configuration + ${tycho.version} + + + jgit.target + + + + + + + + diff --git a/tycho-its/projects/compiler.fragments/src/compiler/fragments/TestMe.java b/tycho-its/projects/compiler.fragments/src/compiler/fragments/TestMe.java new file mode 100644 index 0000000000..1236b2d54c --- /dev/null +++ b/tycho-its/projects/compiler.fragments/src/compiler/fragments/TestMe.java @@ -0,0 +1,67 @@ +/******************************************************************************* + * Copyright (c) 2022 Christoph Läubrich and others. + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Christoph Läubrich - initial API and implementation + *******************************************************************************/ +package compiler.fragments; + +import java.io.File; + +import org.eclipse.jgit.api.CloneCommand; +import org.eclipse.jgit.api.Git; +import org.eclipse.jgit.api.TransportConfigCallback; +import org.eclipse.jgit.api.errors.GitAPIException; +import org.eclipse.jgit.api.errors.InvalidRemoteException; +import org.eclipse.jgit.api.errors.TransportException; +import org.eclipse.jgit.transport.JschConfigSessionFactory; +import org.eclipse.jgit.transport.OpenSshConfig; +import org.eclipse.jgit.transport.SshSessionFactory; +import org.eclipse.jgit.transport.SshTransport; +import org.eclipse.jgit.transport.Transport; +import org.eclipse.jgit.util.FS; + +import com.jcraft.jsch.JSch; +import com.jcraft.jsch.JSchException; +import com.jcraft.jsch.Session; + +public class TestMe { + public static void main(String[] args) throws InvalidRemoteException, TransportException, GitAPIException { + CloneCommand cloneCommand = Git.cloneRepository().setURI(args[0]).setDirectory(new File(args[1])); + cloneCommand.setTransportConfigCallback(new TransportConfigCallback() { + + @Override + public void configure(Transport transport) { + + if (transport instanceof SshTransport) { + SshTransport sshTransport = (SshTransport) transport; + final SshSessionFactory sshSessionFactory = new JschConfigSessionFactory() { + + @Override + protected void configure(OpenSshConfig.Host host, Session session) { + + } + + @Override + protected JSch createDefaultJSch(FS fs) throws JSchException { + + JSch defaultJSch = super.createDefaultJSch(fs); + defaultJSch.addIdentity("~/.ssh/id_rsa"); + return defaultJSch; + } + }; + sshTransport.setSshSessionFactory(sshSessionFactory); + } + } + }); + try (Git git = cloneCommand.call()) { + System.out.println(git.getRepository().getWorkTree()); + } + } +} diff --git a/tycho-its/src/test/java/org/eclipse/tycho/test/compiler/FragmentsTest.java b/tycho-its/src/test/java/org/eclipse/tycho/test/compiler/FragmentsTest.java new file mode 100644 index 0000000000..ff6acbbdce --- /dev/null +++ b/tycho-its/src/test/java/org/eclipse/tycho/test/compiler/FragmentsTest.java @@ -0,0 +1,26 @@ +/******************************************************************************* + * Copyright (c) 2022 Christoph Läubrich and others. + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Christoph Läubrich - initial API and implementation + *******************************************************************************/ +package org.eclipse.tycho.test.compiler; + +import org.apache.maven.it.Verifier; +import org.eclipse.tycho.test.AbstractTychoIntegrationTest; +import org.junit.Test; + +public class FragmentsTest extends AbstractTychoIntegrationTest { + @Test + public void testFragment() throws Exception { + Verifier verifier = getVerifier("compiler.fragments", false); + verifier.executeGoal("compile"); + verifier.verifyErrorFreeLog(); + } +} diff --git a/tycho-p2/tycho-p2-facade/src/main/java/org/eclipse/tycho/p2/resolver/P2DependencyResolver.java b/tycho-p2/tycho-p2-facade/src/main/java/org/eclipse/tycho/p2/resolver/P2DependencyResolver.java index 457f186e08..9ce663dfa1 100644 --- a/tycho-p2/tycho-p2-facade/src/main/java/org/eclipse/tycho/p2/resolver/P2DependencyResolver.java +++ b/tycho-p2/tycho-p2-facade/src/main/java/org/eclipse/tycho/p2/resolver/P2DependencyResolver.java @@ -13,6 +13,7 @@ * - [Bug 567098] pomDependencies=consider should wrap non-osgi jars * - [Bug 572481] Tycho does not understand "additional.bundles" directive in build.properties * - [Issue #462] Delay Pom considered items to the final Target Platform calculation + * - [Issue #626] Classpath computation must take fragments into account *******************************************************************************/ package org.eclipse.tycho.p2.resolver; @@ -480,6 +481,10 @@ protected DefaultDependencyArtifacts newDefaultTargetPlatform(ReactorProject pro platform.addArtifactFile(key, () -> entry.getLocation(true), entry.getInstallableUnits()); } } + for (P2ResolutionResult.Entry entry : result.getDependencyFragments()) { + ArtifactKey key = new DefaultArtifactKey(entry.getType(), entry.getId(), entry.getVersion()); + platform.addFragment(key, () -> entry.getLocation(true), entry.getInstallableUnits()); + } return platform; }