From f657f2789815bb21516c31398a9260e81c0adc63 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20L=C3=A4ubrich?= Date: Sun, 5 May 2024 08:06:30 +0200 Subject: [PATCH] Add support for including a JRE in the product PDE recently added a new flag for the product to mark it to include a jre https://github.com/eclipse-pde/eclipse.pde/pull/1075 but this currently has no effect in Tycho. This now adds support for automatically include a JustJ JRE if the option is selected. --- demo/justj/README.md | 7 ++ demo/justj/automaticInstall/pom.xml | 66 +++++++++++++++++++ .../product-with-features.product | 10 +++ demo/justj/product/pom.xml | 45 +++++++++++-- .../product/product-with-features.product | 12 +++- .../publisher/PublishProductToolImpl.java | 29 +++++++- .../publisher/facade/PublishProductTool.java | 5 +- .../p2resolver/PublishProductToolTest.java | 26 ++++---- .../java/org/eclipse/tycho/test/DemoTest.java | 9 +++ .../tycho/model/ProductConfiguration.java | 5 ++ .../p2/publisher/PublishProductMojo.java | 5 +- .../test/AbstractTychoIntegrationTest.java | 15 +++++ 12 files changed, 210 insertions(+), 24 deletions(-) create mode 100644 demo/justj/README.md create mode 100644 demo/justj/automaticInstall/pom.xml create mode 100644 demo/justj/automaticInstall/product-with-features.product diff --git a/demo/justj/README.md b/demo/justj/README.md new file mode 100644 index 0000000000..842302d94e --- /dev/null +++ b/demo/justj/README.md @@ -0,0 +1,7 @@ +Tycho JustJ Demo Projects +=================== + +Sample projects demonstrating how to use Tycho with JustJ. + +* `product`: Shows how to manually include JustJ in a product using a dedicated feature +* `automaticInstall`: Shows how to use automatic install with the `includeJRE` option in the product \ No newline at end of file diff --git a/demo/justj/automaticInstall/pom.xml b/demo/justj/automaticInstall/pom.xml new file mode 100644 index 0000000000..aa60cb03d1 --- /dev/null +++ b/demo/justj/automaticInstall/pom.xml @@ -0,0 +1,66 @@ + + + 4.0.0 + org.eclipse.tycho.demo + product-with-justj + 0.0.1-SNAPSHOT + eclipse-repository + + 5.0.0-SNAPSHOT + https://download.eclipse.org/releases/2024-03/ + + + + platform + ${target-platform} + p2 + + + + + + org.eclipse.tycho + tycho-maven-plugin + ${tycho-version} + true + + + org.eclipse.tycho + tycho-p2-director-plugin + ${tycho-version} + + + materialize-products + + materialize-products + + + + + + + org.eclipse.tycho + tycho-p2-repository-plugin + ${tycho-version} + + + default-assemble-repository + + assemble-repository + + none + + + default-archive-repository + + archive-repository + + none + + + + + + diff --git a/demo/justj/automaticInstall/product-with-features.product b/demo/justj/automaticInstall/product-with-features.product new file mode 100644 index 0000000000..aeadb4cf2f --- /dev/null +++ b/demo/justj/automaticInstall/product-with-features.product @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/demo/justj/product/pom.xml b/demo/justj/product/pom.xml index be55396a1e..68f8ae8bb2 100644 --- a/demo/justj/product/pom.xml +++ b/demo/justj/product/pom.xml @@ -1,5 +1,6 @@ - 4.0.0 org.eclipse.tycho.demo @@ -7,8 +8,8 @@ 0.0.1-SNAPSHOT eclipse-repository - 2.7.3 - https://download.eclipse.org/releases/2022-06/ + 5.0.0-SNAPSHOT + https://download.eclipse.org/releases/2024-03/ @@ -35,11 +36,47 @@ target-platform-configuration ${tycho-version} - none + + org.eclipse.tycho + tycho-p2-director-plugin + ${tycho-version} + + + materialize-products + + materialize-products + + + + + + + org.eclipse.tycho + tycho-p2-repository-plugin + ${tycho-version} + + + default-assemble-repository + + assemble-repository + + none + + + default-archive-repository + + archive-repository + + none + + + diff --git a/demo/justj/product/product-with-features.product b/demo/justj/product/product-with-features.product index 620074a8e5..81eee07088 100644 --- a/demo/justj/product/product-with-features.product +++ b/demo/justj/product/product-with-features.product @@ -1,7 +1,7 @@ - + @@ -11,11 +11,21 @@ + + + + + + + + + + diff --git a/tycho-core/src/main/java/org/eclipse/tycho/p2/tools/publisher/PublishProductToolImpl.java b/tycho-core/src/main/java/org/eclipse/tycho/p2/tools/publisher/PublishProductToolImpl.java index 4d73213b55..7c63bd4a2c 100644 --- a/tycho-core/src/main/java/org/eclipse/tycho/p2/tools/publisher/PublishProductToolImpl.java +++ b/tycho-core/src/main/java/org/eclipse/tycho/p2/tools/publisher/PublishProductToolImpl.java @@ -25,9 +25,14 @@ import org.eclipse.equinox.internal.p2.publisher.eclipse.IProductDescriptor; import org.eclipse.equinox.internal.p2.publisher.eclipse.ProductFile; import org.eclipse.equinox.p2.metadata.IInstallableUnit; +import org.eclipse.equinox.p2.metadata.IRequirement; +import org.eclipse.equinox.p2.metadata.IVersionedId; +import org.eclipse.equinox.p2.metadata.MetadataFactory; import org.eclipse.equinox.p2.metadata.Version; import org.eclipse.equinox.p2.publisher.AdviceFileAdvice; +import org.eclipse.equinox.p2.publisher.IPublisherAction; import org.eclipse.equinox.p2.publisher.IPublisherAdvice; +import org.eclipse.equinox.p2.publisher.actions.RootIUAction; import org.eclipse.equinox.p2.publisher.eclipse.ProductAction; import org.eclipse.equinox.p2.repository.artifact.IArtifactRepository; import org.eclipse.equinox.p2.repository.metadata.IMetadataRepository; @@ -68,8 +73,8 @@ public PublishProductToolImpl(PublisherActionRunner publisherRunner, PublishingR } @Override - public List publishProduct(File productFile, File launcherBinaries, String flavor) - throws IllegalArgumentException { + public List publishProduct(File productFile, File launcherBinaries, String flavor, + boolean includeJRE) throws IllegalArgumentException { IProductDescriptor originalProduct = loadProductFile(productFile); ExpandedProduct expandedProduct = new ExpandedProduct(originalProduct, buildQualifier, targetPlatform, @@ -77,7 +82,25 @@ public List publishProduct(File productFile, File launcherBinari IPublisherAdvice[] advice = getProductSpecificAdviceFileAdvice(productFile, expandedProduct); - ProductAction action = new ProductAction(null, expandedProduct, flavor, launcherBinaries); + ProductAction action = new ProductAction(null, expandedProduct, flavor, launcherBinaries) { + @Override + protected IPublisherAction createRootIUAction() { + if (includeJRE) { + return new RootIUAction(id, version, name) { + @Override + protected Collection createIURequirements( + Collection children) { + Collection requirements = new ArrayList<>( + super.createIURequirements(children)); + requirements.add(MetadataFactory.createRequirement("org.eclipse.justj", "jre", null, null, + false, false)); + return requirements; + } + }; + } + return super.createRootIUAction(); + } + }; IMetadataRepository metadataRepository = publishingRepository.getMetadataRepository(); IArtifactRepository artifactRepository = publishingRepository .getArtifactRepositoryForWriting(new ProductBinariesWriteSession(expandedProduct.getId())); diff --git a/tycho-core/src/main/java/org/eclipse/tycho/p2/tools/publisher/facade/PublishProductTool.java b/tycho-core/src/main/java/org/eclipse/tycho/p2/tools/publisher/facade/PublishProductTool.java index 297005b4b4..3d30b08bf7 100644 --- a/tycho-core/src/main/java/org/eclipse/tycho/p2/tools/publisher/facade/PublishProductTool.java +++ b/tycho-core/src/main/java/org/eclipse/tycho/p2/tools/publisher/facade/PublishProductTool.java @@ -29,7 +29,10 @@ public interface PublishProductTool { * A folder that contains the native Eclipse launcher binaries * @param flavor * The installation flavor the product shall be published for + * @param includeJRE + * controls if a requirement of a (JustJ) JRE has to be added * @return a handles to the published product IU */ - List publishProduct(File productDefinition, File launcherBinaries, String flavor); + List publishProduct(File productDefinition, File launcherBinaries, String flavor, + boolean includeJRE); } diff --git a/tycho-core/src/test/java/org/eclipse/tycho/p2resolver/PublishProductToolTest.java b/tycho-core/src/test/java/org/eclipse/tycho/p2resolver/PublishProductToolTest.java index 69be8274fd..ee7f610418 100644 --- a/tycho-core/src/test/java/org/eclipse/tycho/p2resolver/PublishProductToolTest.java +++ b/tycho-core/src/test/java/org/eclipse/tycho/p2resolver/PublishProductToolTest.java @@ -110,7 +110,7 @@ public void testProductPublishingWithLaunchers() throws Exception { File launcherBinaries = resourceFile("launchers/"); subject = initPublisher(); - Collection seeds = subject.publishProduct(productDefinition, launcherBinaries, FLAVOR); + Collection seeds = subject.publishProduct(productDefinition, launcherBinaries, FLAVOR, false); assertEquals(1, seeds.size()); DependencySeed seed = seeds.iterator().next(); @@ -132,7 +132,7 @@ public void testExpandProductVersionQualifier() { File productDefinition = resourceFile("publishers/products/test.product"); subject = initPublisher(); - IInstallableUnit unit = getUnit(subject.publishProduct(productDefinition, null, FLAVOR)); + IInstallableUnit unit = getUnit(subject.publishProduct(productDefinition, null, FLAVOR, false)); assertEquals("0.1.0." + QUALIFIER, unit.getVersion().toString()); } @@ -143,7 +143,7 @@ public void testExpandVersionsOfInclusionsWithZeros() throws Exception { subject = initPublisher(createBundleIU("test.plugin", "0.1.0.20141230"), createBundleIU("test.plugin", "1.1.0"), createFeatureIU("test.feature", "0.2.0.20141230"), createFeatureIU("test.feature", "1.2.0")); - IInstallableUnit unit = getUnit(subject.publishProduct(productDefinition, null, FLAVOR)); + IInstallableUnit unit = getUnit(subject.publishProduct(productDefinition, null, FLAVOR, false)); assertThat(unit.getRequirements(), hasItem(strictRequirement("test.plugin", "1.1.0"))); assertThat(unit.getRequirements(), hasItem(strictRequirement("test.feature.feature.group", "1.2.0"))); @@ -155,7 +155,7 @@ public void testExpandVersionsOfInclusionsWithQualifierLiterals() throws Excepti subject = initPublisher(createBundleIU("test.plugin", "0.1.0.20141230"), createBundleIU("test.plugin", "1.1.0"), createFeatureIU("test.feature", "0.2.0.20141230"), createFeatureIU("test.feature", "1.2.0")); - IInstallableUnit unit = getUnit(subject.publishProduct(productDefinition, null, FLAVOR)); + IInstallableUnit unit = getUnit(subject.publishProduct(productDefinition, null, FLAVOR, false)); assertThat(unit.getRequirements(), hasItem(strictRequirement("test.plugin", "0.1.0.20141230"))); assertThat(unit.getRequirements(), hasItem(strictRequirement("test.feature.feature.group", "0.2.0.20141230"))); @@ -167,7 +167,7 @@ public void testExpandVersionWithSyntaxError() throws Exception { subject = initPublisher(); BuildFailureException e = assertThrows(BuildFailureException.class, - () -> subject.publishProduct(productDefinition, null, FLAVOR)); + () -> subject.publishProduct(productDefinition, null, FLAVOR, false)); assertThat(e.getMessage(), both(containsString("inclusionsWithVersionSyntaxError.product")).and(containsString("nonOSGi"))); } @@ -180,7 +180,7 @@ public void testPublishingReportsAllResolutionErrorsAtOnce() throws Exception { logVerifier.expectError(containsString("test.feature1")); logVerifier.expectError(containsString("test.feature2")); assertThrows(DependencyResolutionException.class, - () -> subject.publishProduct(productDefinition, null, FLAVOR)); + () -> subject.publishProduct(productDefinition, null, FLAVOR, false)); } @Test @@ -189,7 +189,7 @@ public void testExpandVersionsIgnoresBundlesInFeatureBasedProduct() throws Excep File productDefinition = resourceFile("publishers/products/featureProductWithLeftovers.product"); subject = initPublisher(createFeatureIU("org.eclipse.rcp", "3.3.101.R34x_v20081125")); - IInstallableUnit unit = getUnit(subject.publishProduct(productDefinition, null, FLAVOR)); + IInstallableUnit unit = getUnit(subject.publishProduct(productDefinition, null, FLAVOR, false)); assertThat(unit.getRequirements(), hasItem(strictRequirement("org.eclipse.rcp.feature.group", "3.3.101.R34x_v20081125"))); @@ -200,7 +200,7 @@ public void testExpandVersionsIgnoresFeaturesInBundleBasedProduct() throws Excep File productDefinition = resourceFile("publishers/products/pluginProductWithLeftovers.product"); subject = initPublisher(createBundleIU("org.eclipse.core.runtime", "3.5.0.v20090525")); - IInstallableUnit unit = getUnit(subject.publishProduct(productDefinition, null, FLAVOR)); + IInstallableUnit unit = getUnit(subject.publishProduct(productDefinition, null, FLAVOR, false)); assertThat(unit.getRequirements(), hasItem(strictRequirement("org.eclipse.core.runtime", "3.5.0.v20090525"))); } @@ -214,7 +214,7 @@ public void testPublishingWithMissingFragments() throws Exception { logVerifier.expectError(containsString("org.eclipse.core.filesystem.hpux.ppc")); assertThrows(DependencyResolutionException.class, - () -> subject.publishProduct(productDefinition, launcherBinaries, FLAVOR)); + () -> subject.publishProduct(productDefinition, launcherBinaries, FLAVOR, false)); } @Test @@ -222,7 +222,7 @@ public void testPublishingWithP2Inf() { File productDefinition = resourceFile("publishers/products/p2Inf/test.product"); subject = initPublisher(); - subject.publishProduct(productDefinition, null, FLAVOR); + subject.publishProduct(productDefinition, null, FLAVOR, false); assertThat(unitsIn(outputRepository), hasItem(unitWithId("testproduct"))); IInstallableUnit unit = getUnique(unitWithId("testproduct"), unitsIn(outputRepository)); @@ -239,7 +239,7 @@ public void testPublishingWithProductSpecificP2Inf() { File productDefinition = resourceFile("publishers/products/p2InfPerProduct/test.product"); subject = initPublisher(); - IInstallableUnit unit = getUnit(subject.publishProduct(productDefinition, null, FLAVOR)); + IInstallableUnit unit = getUnit(subject.publishProduct(productDefinition, null, FLAVOR, false)); assertThat(unit.getRequirements(), hasItem(strictRequirement("extra.iu", "1.2.3." + QUALIFIER))); } @@ -250,7 +250,7 @@ public void testPublishingWithVariableExpansion() { subject = initPublisher(createBundleIU("org.eclipse.osgi", "3.10.1.v20140909-1633")); when(interpolatorMock.interpolate("${unqualifiedVersion}.${buildQualifier}")).thenReturn("1.0.0.20150109"); - IInstallableUnit mainUnit = getUnit(subject.publishProduct(productDefinition, null, FLAVOR)); + IInstallableUnit mainUnit = getUnit(subject.publishProduct(productDefinition, null, FLAVOR, false)); String configUnitId = "tooling" + mainUnit.getId() + ".config.testws.testos.testarch"; IInstallableUnit configUnit = getUnique(unitWithId(configUnitId), unitsIn(outputRepository)); @@ -265,7 +265,7 @@ public void testPublishingWithRootFeatures() { createFeatureIU("org.eclipse.e4.rcp", "1.0"), createFeatureIU("org.eclipse.help", "2.0.102.v20140128"), createFeatureIU("org.eclipse.egit", "2.0")); - List seeds = subject.publishProduct(productDefinition, null, FLAVOR); + List seeds = subject.publishProduct(productDefinition, null, FLAVOR, false); IInstallableUnit productUnit = getUnique(productUnit(), unitsIn(seeds)); assertThat(productUnit.getRequirements(), diff --git a/tycho-its/src/test/java/org/eclipse/tycho/test/DemoTest.java b/tycho-its/src/test/java/org/eclipse/tycho/test/DemoTest.java index dba3c902be..78edecb9ee 100644 --- a/tycho-its/src/test/java/org/eclipse/tycho/test/DemoTest.java +++ b/tycho-its/src/test/java/org/eclipse/tycho/test/DemoTest.java @@ -12,6 +12,7 @@ *******************************************************************************/ package org.eclipse.tycho.test; +import java.io.File; import java.util.List; import org.apache.maven.it.Verifier; @@ -23,6 +24,14 @@ */ public class DemoTest extends AbstractTychoIntegrationTest { + @Test + public void testTychoJustJDemo() throws Exception { + assertIncludesJustJ(new File(runDemo("justj", "-f", "product").getBasedir(), + "product/target/products/product-with-justj-features")); + assertIncludesJustJ(new File(runDemo("justj", "-f", "automaticInstall").getBasedir(), + "automaticInstall/target/products/product-with-justj-features")); + } + @Test public void testSureFireDemo() throws Exception { runDemo("testing/surefire/", "-f", "with-maven-layout"); diff --git a/tycho-metadata-model/src/main/java/org/eclipse/tycho/model/ProductConfiguration.java b/tycho-metadata-model/src/main/java/org/eclipse/tycho/model/ProductConfiguration.java index faa476d54b..268a6c07be 100644 --- a/tycho-metadata-model/src/main/java/org/eclipse/tycho/model/ProductConfiguration.java +++ b/tycho-metadata-model/src/main/java/org/eclipse/tycho/model/ProductConfiguration.java @@ -172,6 +172,11 @@ public boolean includeLaunchers() { return attribute == null || Boolean.parseBoolean(attribute); } + public boolean includeJRE() { + String attribute = dom.getAttributeValue("includeJRE"); + return attribute == null || Boolean.parseBoolean(attribute); + } + public String getVersion() { return dom.getAttributeValue("version"); } diff --git a/tycho-p2-publisher-plugin/src/main/java/org/eclipse/tycho/plugins/p2/publisher/PublishProductMojo.java b/tycho-p2-publisher-plugin/src/main/java/org/eclipse/tycho/plugins/p2/publisher/PublishProductMojo.java index 33665bacbb..33d4853345 100644 --- a/tycho-p2-publisher-plugin/src/main/java/org/eclipse/tycho/plugins/p2/publisher/PublishProductMojo.java +++ b/tycho-p2-publisher-plugin/src/main/java/org/eclipse/tycho/plugins/p2/publisher/PublishProductMojo.java @@ -125,8 +125,9 @@ protected Collection publishContent(PublisherServiceFactory publ } boolean includeLaunchers = productConfiguration.includeLaunchers(); - seeds.addAll(publisher.publishProduct(productFile, - includeLaunchers ? getExpandedLauncherBinaries() : null, FLAVOR)); + seeds.addAll( + publisher.publishProduct(productFile, includeLaunchers ? getExpandedLauncherBinaries() : null, + FLAVOR, productConfiguration.includeJRE())); hasLaunchers |= includeLaunchers; } catch (IOException e) { throw new MojoExecutionException( diff --git a/tycho-testing-harness/src/main/java/org/eclipse/tycho/test/AbstractTychoIntegrationTest.java b/tycho-testing-harness/src/main/java/org/eclipse/tycho/test/AbstractTychoIntegrationTest.java index 3e71c90c0c..ce68ac03b2 100644 --- a/tycho-testing-harness/src/main/java/org/eclipse/tycho/test/AbstractTychoIntegrationTest.java +++ b/tycho-testing-harness/src/main/java/org/eclipse/tycho/test/AbstractTychoIntegrationTest.java @@ -14,9 +14,11 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; import java.io.File; import java.io.IOException; +import java.nio.file.Files; import java.util.Arrays; import java.util.List; import java.util.regex.Pattern; @@ -293,4 +295,17 @@ protected static void verifyErrorFreeLog(Verifier verifier) throws VerificationE } } + protected void assertIncludesJustJ(File productDir) throws IOException { + File eclipseIni = assertFileExists(productDir, "**/eclipse.ini")[0]; + List lines = Files.readAllLines(eclipseIni.toPath()); + for (int i = 0; i < lines.size(); i++) { + if (lines.get(i).equals("-vm")) { + String vm = lines.get(i + 1); + assertTrue("VM (" + vm + ") is not JustJ!", vm.startsWith("plugins/org.eclipse.justj.openjdk.")); + return; + } + } + fail("No VM installed in the product!"); + } + }