From da21ce122058b79382cd30a7e5b43a3fa49a9160 Mon Sep 17 00:00:00 2001 From: Hannes Wellmann Date: Tue, 7 May 2024 10:52:49 +0200 Subject: [PATCH 1/2] Minimal reproducer test-case for #3824 Add a minimal reproducer test-case for issue https://github.com/eclipse-tycho/tycho/issues/3824 regarding the validation failure of transitive generated 'osgi.extender=osgi.component' requirements in bundles containing DS components of version 1.4. (cherry picked from commit 6394de506035a4ce291be4ffc0ce4f4dc7469f4a) --- .../tycho-ds-dependency/.mvn/extensions.xml | 8 +++ .../tycho-ds-dependency/plugin.a/.classpath | 7 +++ .../plugin.a/META-INF/MANIFEST.MF | 6 +++ .../plugin.a/build.properties | 4 ++ .../plugin.a/src/foo/bar/MyComponent.java | 12 +++++ .../tycho-ds-dependency/plugin.b/.classpath | 7 +++ .../plugin.b/META-INF/MANIFEST.MF | 6 +++ .../plugin.b/build.properties | 2 + .../projects/tycho-ds-dependency/pom.xml | 51 +++++++++++++++++++ .../compiler/CompilerClasspathEntryTest.java | 10 ++++ 10 files changed, 113 insertions(+) create mode 100644 tycho-its/projects/tycho-ds-dependency/.mvn/extensions.xml create mode 100644 tycho-its/projects/tycho-ds-dependency/plugin.a/.classpath create mode 100644 tycho-its/projects/tycho-ds-dependency/plugin.a/META-INF/MANIFEST.MF create mode 100644 tycho-its/projects/tycho-ds-dependency/plugin.a/build.properties create mode 100644 tycho-its/projects/tycho-ds-dependency/plugin.a/src/foo/bar/MyComponent.java create mode 100644 tycho-its/projects/tycho-ds-dependency/plugin.b/.classpath create mode 100644 tycho-its/projects/tycho-ds-dependency/plugin.b/META-INF/MANIFEST.MF create mode 100644 tycho-its/projects/tycho-ds-dependency/plugin.b/build.properties create mode 100644 tycho-its/projects/tycho-ds-dependency/pom.xml diff --git a/tycho-its/projects/tycho-ds-dependency/.mvn/extensions.xml b/tycho-its/projects/tycho-ds-dependency/.mvn/extensions.xml new file mode 100644 index 0000000000..ff2889110d --- /dev/null +++ b/tycho-its/projects/tycho-ds-dependency/.mvn/extensions.xml @@ -0,0 +1,8 @@ + + + + org.eclipse.tycho + tycho-build + ${tycho-version} + + diff --git a/tycho-its/projects/tycho-ds-dependency/plugin.a/.classpath b/tycho-its/projects/tycho-ds-dependency/plugin.a/.classpath new file mode 100644 index 0000000000..81fe078c20 --- /dev/null +++ b/tycho-its/projects/tycho-ds-dependency/plugin.a/.classpath @@ -0,0 +1,7 @@ + + + + + + + diff --git a/tycho-its/projects/tycho-ds-dependency/plugin.a/META-INF/MANIFEST.MF b/tycho-its/projects/tycho-ds-dependency/plugin.a/META-INF/MANIFEST.MF new file mode 100644 index 0000000000..c68de2a3f8 --- /dev/null +++ b/tycho-its/projects/tycho-ds-dependency/plugin.a/META-INF/MANIFEST.MF @@ -0,0 +1,6 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-SymbolicName: plugin.a +Bundle-Version: 1.0.0.qualifier +Bundle-RequiredExecutionEnvironment: JavaSE-17 +Import-Package: org.osgi.service.event;version="[1.4.0,2.0.0)" diff --git a/tycho-its/projects/tycho-ds-dependency/plugin.a/build.properties b/tycho-its/projects/tycho-ds-dependency/plugin.a/build.properties new file mode 100644 index 0000000000..34d2e4d2da --- /dev/null +++ b/tycho-its/projects/tycho-ds-dependency/plugin.a/build.properties @@ -0,0 +1,4 @@ +source.. = src/ +output.. = bin/ +bin.includes = META-INF/,\ + . diff --git a/tycho-its/projects/tycho-ds-dependency/plugin.a/src/foo/bar/MyComponent.java b/tycho-its/projects/tycho-ds-dependency/plugin.a/src/foo/bar/MyComponent.java new file mode 100644 index 0000000000..d7d5f90546 --- /dev/null +++ b/tycho-its/projects/tycho-ds-dependency/plugin.a/src/foo/bar/MyComponent.java @@ -0,0 +1,12 @@ +package foo.bar; + +import org.osgi.service.component.annotations.Component; +import org.osgi.service.event.EventHandler; +import org.osgi.service.event.Event; + +@Component(service = EventHandler.class) +public class MyComponent implements EventHandler { + @Override + public void handleEvent(Event event) { + } +} diff --git a/tycho-its/projects/tycho-ds-dependency/plugin.b/.classpath b/tycho-its/projects/tycho-ds-dependency/plugin.b/.classpath new file mode 100644 index 0000000000..81fe078c20 --- /dev/null +++ b/tycho-its/projects/tycho-ds-dependency/plugin.b/.classpath @@ -0,0 +1,7 @@ + + + + + + + diff --git a/tycho-its/projects/tycho-ds-dependency/plugin.b/META-INF/MANIFEST.MF b/tycho-its/projects/tycho-ds-dependency/plugin.b/META-INF/MANIFEST.MF new file mode 100644 index 0000000000..4f00fc0d85 --- /dev/null +++ b/tycho-its/projects/tycho-ds-dependency/plugin.b/META-INF/MANIFEST.MF @@ -0,0 +1,6 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-SymbolicName: plugin.b +Bundle-Version: 1.0.0.qualifier +Require-Bundle: plugin.a;bundle-version="1.0.0" +Bundle-RequiredExecutionEnvironment: JavaSE-17 diff --git a/tycho-its/projects/tycho-ds-dependency/plugin.b/build.properties b/tycho-its/projects/tycho-ds-dependency/plugin.b/build.properties new file mode 100644 index 0000000000..7594fab8d5 --- /dev/null +++ b/tycho-its/projects/tycho-ds-dependency/plugin.b/build.properties @@ -0,0 +1,2 @@ +bin.includes = META-INF/,\ + . diff --git a/tycho-its/projects/tycho-ds-dependency/pom.xml b/tycho-its/projects/tycho-ds-dependency/pom.xml new file mode 100644 index 0000000000..b93d0c8b05 --- /dev/null +++ b/tycho-its/projects/tycho-ds-dependency/pom.xml @@ -0,0 +1,51 @@ + + 4.0.0 + + foo + foo + 1.0.0-SNAPSHOT + pom + + + plugin.a + plugin.b + + + + UTF-8 + + + + + platform + ${target-platform} + p2 + + + + + + + + org.eclipse.tycho + tycho-maven-plugin + ${tycho-version} + true + + + + org.eclipse.tycho + tycho-ds-plugin + ${tycho-version} + + 1.4 + true + + + + + + + \ No newline at end of file diff --git a/tycho-its/src/test/java/org/eclipse/tycho/test/compiler/CompilerClasspathEntryTest.java b/tycho-its/src/test/java/org/eclipse/tycho/test/compiler/CompilerClasspathEntryTest.java index a0a6853694..3439b42c49 100644 --- a/tycho-its/src/test/java/org/eclipse/tycho/test/compiler/CompilerClasspathEntryTest.java +++ b/tycho-its/src/test/java/org/eclipse/tycho/test/compiler/CompilerClasspathEntryTest.java @@ -17,6 +17,7 @@ import java.io.File; import java.nio.file.Files; +import java.nio.file.Path; import java.util.List; import java.util.stream.Collectors; @@ -91,6 +92,15 @@ private void verifyDs(Verifier verifier) throws VerificationException { assertFalse(new File(generated, "tycho.ds.TestComponent2.xml").isFile()); } + @Test + public void testTransitiveDSComponents() throws Exception { + Verifier verifier = getVerifier("tycho-ds-dependency", true, true); + verifier.executeGoals(List.of("clean", "verify")); + verifier.verifyErrorFreeLog(); + Path generated = Path.of(verifier.getBasedir(), "plugin.a/target/classes/OSGI-INF"); + assertTrue(Files.isRegularFile(generated.resolve("foo.bar.MyComponent.xml"))); + } + @Test public void testOSGiAnnotations() throws Exception { Verifier verifier = getVerifier("compiler.annotations", false, true); From 57cc3979d0cb57f336dadb960fed56aa872b1146 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20L=C3=A4ubrich?= Date: Fri, 31 May 2024 10:14:26 +0200 Subject: [PATCH 2/2] Use the updated p2 metadata once the project is packed Currently Tycho always uses the INITIAL dependency metadata to compute the preliminary target platform. As this metadata can change once the project is packed (e.g. headers added / removed) this can lead to problems in plugins that depend on the changed plugin because P2 sees the updated metadata afterwards and fails. This now distinguish both cases and used the SEED metadata if the project was already packed. Fix https://github.com/eclipse-tycho/tycho/issues/3824 (cherry picked from commit fc9133220e207f7e6c2f64ce254f43ff7b3a7c46) --- .../p2maven/InstallableUnitGenerator.java | 74 ++++++++++++------- .../tycho/ReactorProjectIdentities.java | 6 ++ .../tycho/p2resolver/P2GeneratorImpl.java | 3 +- .../p2resolver/TargetPlatformFactoryImpl.java | 17 ++++- .../org.eclipse.swt.gtk.linux.x86/pom.xml | 17 ++++- .../tycho-ds-dependency/.mvn/maven.config | 1 + 6 files changed, 88 insertions(+), 30 deletions(-) create mode 100644 tycho-its/projects/tycho-ds-dependency/.mvn/maven.config diff --git a/p2-maven-plugin/src/main/java/org/eclipse/tycho/p2maven/InstallableUnitGenerator.java b/p2-maven-plugin/src/main/java/org/eclipse/tycho/p2maven/InstallableUnitGenerator.java index 4bd1b96a73..7e9508c5b2 100644 --- a/p2-maven-plugin/src/main/java/org/eclipse/tycho/p2maven/InstallableUnitGenerator.java +++ b/p2-maven-plugin/src/main/java/org/eclipse/tycho/p2maven/InstallableUnitGenerator.java @@ -86,6 +86,8 @@ public class InstallableUnitGenerator { private static final String KEY_UNITS = "InstallableUnitGenerator.units"; + private static final String KEY_ARTIFACT_FILE = "InstallableUnitGenerator.artifactFile"; + @Requirement private IProvisioningAgent provisioningAgent; @@ -165,28 +167,37 @@ public Collection getInstallableUnits(MavenProject project, Ma Objects.requireNonNull(session); log.debug("Computing installable units for " + project + ", force update = " + forceUpdate); synchronized (project) { - if (!forceUpdate) { - Object contextValue = project.getContextValue(KEY_UNITS); - if (contextValue instanceof Collection) { - Collection collection = (Collection) contextValue; - if (isCompatible(collection)) { - log.debug("Using cached value for " + project); - return collection; - } else { - log.debug("Cannot use cached value for " + project - + " because of incompatible classloaders, update is forced"); - } - } - } File basedir = project.getBasedir(); if (basedir == null || !basedir.isDirectory()) { log.warn("No valid basedir for " + project + " found"); return Collections.emptyList(); } + File projectArtifact = getProjectArtifact(project); + if (!forceUpdate) { + // first check if the packed state might has changed... + if (Objects.equals(project.getContextValue(KEY_ARTIFACT_FILE), projectArtifact)) { + Object contextValue = project.getContextValue(KEY_UNITS); + if (contextValue instanceof Collection) { + // now check if we are classlaoder compatible... + Collection collection = (Collection) contextValue; + if (isCompatible(collection)) { + log.debug("Using cached value for " + project); + return collection; + } else { + log.debug("Cannot use cached value for " + project + + " because of incompatible classloaders, update is forced"); + } + } + } else { + log.info("Cannot use cached value for " + project + + " because project artifact has changed, update is forced"); + } + } String packaging = project.getPackaging(); String version = project.getVersion(); String artifactId = project.getArtifactId(); - List actions = getPublisherActions(packaging, basedir, version, artifactId); + List actions = getPublisherActions(packaging, basedir, projectArtifact, version, + artifactId); Collection publishedUnits = publisher.publishMetadata(actions); for (InstallableUnitProvider unitProvider : getProvider(project, session)) { log.debug("Asking " + unitProvider + " for additional units for " + project); @@ -207,24 +218,38 @@ public Collection getInstallableUnits(MavenProject project, Ma log.debug("Cannot generate any InstallableUnit for packaging type '" + packaging + "' for " + project); } project.setContextValue(KEY_UNITS, result); + project.setContextValue(KEY_ARTIFACT_FILE, projectArtifact); return result; } } - private List getPublisherActions(String packaging, File basedir, String version, - String artifactId) throws CoreException { + private static File getProjectArtifact(MavenProject project) { + Artifact artifact = project.getArtifact(); + if (artifact != null) { + File file = artifact.getFile(); + if (file != null && file.exists()) { + return file; + } + } + return null; + } + + private List getPublisherActions(String packaging, File basedir, File projectArtifact, + String version, String artifactId) throws CoreException { List actions = new ArrayList<>(); switch (packaging) { case PackagingType.TYPE_ECLIPSE_TEST_PLUGIN: case PackagingType.TYPE_ECLIPSE_PLUGIN: { - actions.add(new BundlesAction(new File[] { basedir })); + File bundleFile = Objects.requireNonNullElse(projectArtifact, basedir); + actions.add(new BundlesAction(new File[] { bundleFile })); break; } case PackagingType.TYPE_ECLIPSE_FEATURE: { FeatureParser parser = new FeatureParser(); - Feature feature = parser.parse(basedir); - feature.setLocation(basedir.getAbsolutePath()); + File featureFile = Objects.requireNonNullElse(projectArtifact, basedir); + Feature feature = parser.parse(featureFile); + feature.setLocation(featureFile.getAbsolutePath()); FeatureDependenciesAction action = new FeatureDependenciesAction(feature); actions.add(action); break; @@ -353,11 +378,11 @@ public synchronized Collection getUnits(Artifact artifact) { if (PackagingType.TYPE_ECLIPSE_PLUGIN.equals(type) || PackagingType.TYPE_ECLIPSE_TEST_PLUGIN.equals(type) || "bundle".equals(type)) { List actions = getPublisherActions(PackagingType.TYPE_ECLIPSE_PLUGIN, file, - artifact.getVersion(), artifact.getArtifactId()); + file, artifact.getVersion(), artifact.getArtifactId()); return units = publisher.publishMetadata(actions); } else if (PackagingType.TYPE_ECLIPSE_FEATURE.equals(type)) { List actions = getPublisherActions(PackagingType.TYPE_ECLIPSE_FEATURE, file, - artifact.getVersion(), artifact.getArtifactId()); + file, artifact.getVersion(), artifact.getArtifactId()); return units = publisher.publishMetadata(actions); } else { boolean isBundle = false; @@ -365,20 +390,19 @@ public synchronized Collection getUnits(Artifact artifact) { try (JarFile jarFile = new JarFile(file)) { Manifest manifest = jarFile.getManifest(); isBundle = manifest != null - && manifest.getMainAttributes() - .getValue(Constants.BUNDLE_SYMBOLICNAME) != null; + && manifest.getMainAttributes().getValue(Constants.BUNDLE_SYMBOLICNAME) != null; isFeature = jarFile.getEntry("feature.xml") != null; } catch (IOException e) { // can't determine the type then... } if (isBundle) { List actions = getPublisherActions(PackagingType.TYPE_ECLIPSE_PLUGIN, - file, artifact.getVersion(), artifact.getArtifactId()); + file, file, artifact.getVersion(), artifact.getArtifactId()); return units = publisher.publishMetadata(actions); } if (isFeature) { List actions = getPublisherActions(PackagingType.TYPE_ECLIPSE_FEATURE, - file, artifact.getVersion(), artifact.getArtifactId()); + file, file, artifact.getVersion(), artifact.getArtifactId()); return units = publisher.publishMetadata(actions); } } diff --git a/tycho-api/src/main/java/org/eclipse/tycho/ReactorProjectIdentities.java b/tycho-api/src/main/java/org/eclipse/tycho/ReactorProjectIdentities.java index 6dbda78107..6d3df43a89 100644 --- a/tycho-api/src/main/java/org/eclipse/tycho/ReactorProjectIdentities.java +++ b/tycho-api/src/main/java/org/eclipse/tycho/ReactorProjectIdentities.java @@ -46,4 +46,10 @@ public final int hashCode() { return Objects.hash(getArtifactId(), getGroupId(), getVersion()); } + @Override + public String toString() { + return "ReactorProjectIdentities [GroupId=" + getGroupId() + ", ArtifactId=" + getArtifactId() + ", Version=" + + getVersion() + ", Basedir=" + getBasedir() + "]"; + } + } diff --git a/tycho-core/src/main/java/org/eclipse/tycho/p2resolver/P2GeneratorImpl.java b/tycho-core/src/main/java/org/eclipse/tycho/p2resolver/P2GeneratorImpl.java index 7ba3c924d0..23e0b706f1 100644 --- a/tycho-core/src/main/java/org/eclipse/tycho/p2resolver/P2GeneratorImpl.java +++ b/tycho-core/src/main/java/org/eclipse/tycho/p2resolver/P2GeneratorImpl.java @@ -451,8 +451,7 @@ public Map generateMetadata(MavenProject project, boolean g PublisherOptions options = new PublisherOptions(); options.setGenerateDownloadStats(generateDownloadStatsProperty); options.setGenerateChecksums(generateChecksums); - Map generatedMetadata = generateMetadata(artifacts, options, targetDir); - return generatedMetadata; + return generateMetadata(artifacts, options, targetDir); } @Override diff --git a/tycho-core/src/main/java/org/eclipse/tycho/p2resolver/TargetPlatformFactoryImpl.java b/tycho-core/src/main/java/org/eclipse/tycho/p2resolver/TargetPlatformFactoryImpl.java index 8818eb0e24..51570d6cb3 100644 --- a/tycho-core/src/main/java/org/eclipse/tycho/p2resolver/TargetPlatformFactoryImpl.java +++ b/tycho-core/src/main/java/org/eclipse/tycho/p2resolver/TargetPlatformFactoryImpl.java @@ -561,9 +561,9 @@ private Map getPreliminaryReactorPro Map> duplicateReactorUIs = new HashMap<>(); for (ReactorProject project : reactorProjects) { - Set projectIUs = project.getDependencyMetadata(DependencyMetadataType.INITIAL); - if (projectIUs == null) { + Set projectIUs = getPreliminaryReactorProjectUIs(project); + if (projectIUs == null || projectIUs.isEmpty()) { continue; } for (IInstallableUnit iu : projectIUs) { @@ -589,6 +589,19 @@ private Map getPreliminaryReactorPro return reactorUIs; } + private Set getPreliminaryReactorProjectUIs(ReactorProject project) { + String packaging = project.getPackaging(); + if (PackagingType.TYPE_ECLIPSE_PLUGIN.equals(packaging) || PackagingType.TYPE_ECLIPSE_FEATURE.equals(packaging) + || PackagingType.TYPE_ECLIPSE_TEST_PLUGIN.equals(packaging)) { + File artifact = project.getArtifact(); + if (artifact != null && artifact.isFile()) { + //the project was already build, use the seed units as they include anything maybe updated by p2-metadata mojo + return project.getDependencyMetadata(DependencyMetadataType.SEED); + } + } + return project.getDependencyMetadata(DependencyMetadataType.INITIAL); + } + private void applyFilters(TargetPlatformFilterEvaluator filter, Collection collectionToModify, Set reactorProjectUIs, ExecutionEnvironmentResolutionHints eeResolutionHints, Set shadowedIus) { diff --git a/tycho-its/projects/eeProfile.resolution.fragments/org.eclipse.swt.gtk.linux.x86/pom.xml b/tycho-its/projects/eeProfile.resolution.fragments/org.eclipse.swt.gtk.linux.x86/pom.xml index 5b8b35aec2..3bb5502a47 100644 --- a/tycho-its/projects/eeProfile.resolution.fragments/org.eclipse.swt.gtk.linux.x86/pom.xml +++ b/tycho-its/projects/eeProfile.resolution.fragments/org.eclipse.swt.gtk.linux.x86/pom.xml @@ -13,5 +13,20 @@ org.eclipse.swt.gtk.linux.x86 3.102.0-SNAPSHOT eclipse-plugin - + + + + org.eclipse.tycho + target-platform-configuration + + + ignore + + true + + + + + + diff --git a/tycho-its/projects/tycho-ds-dependency/.mvn/maven.config b/tycho-its/projects/tycho-ds-dependency/.mvn/maven.config new file mode 100644 index 0000000000..3e8679b48c --- /dev/null +++ b/tycho-its/projects/tycho-ds-dependency/.mvn/maven.config @@ -0,0 +1 @@ +-Dtycho.localArtifacts=ignore