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 5d89c5edf9..4bd1b96a73 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 @@ -262,6 +262,10 @@ private List getPublisherActions(String packaging, File basedi return actions; } + public Collection getInstallableUnits(IProductDescriptor productDescriptor) throws CoreException { + return publisher.publishMetadata(List.of(new ProductDependenciesAction(productDescriptor))); + } + public Collection getInstallableUnits(Manifest manifest) { Attributes mainAttributes = manifest.getMainAttributes(); CaseInsensitiveDictionaryMap headers = new CaseInsensitiveDictionaryMap<>( diff --git a/p2-maven-plugin/src/main/java/org/eclipse/tycho/p2maven/actions/ProductFile2.java b/p2-maven-plugin/src/main/java/org/eclipse/tycho/p2maven/actions/ProductFile2.java index b2c55cfe61..a2ad68d153 100644 --- a/p2-maven-plugin/src/main/java/org/eclipse/tycho/p2maven/actions/ProductFile2.java +++ b/p2-maven-plugin/src/main/java/org/eclipse/tycho/p2maven/actions/ProductFile2.java @@ -12,6 +12,7 @@ *******************************************************************************/ package org.eclipse.tycho.p2maven.actions; +import java.io.File; import java.util.List; import org.eclipse.equinox.internal.p2.publisher.eclipse.ProductFile; @@ -26,7 +27,11 @@ public class ProductFile2 extends ProductFile { protected static final String ATTRIBUTE_ARCH = "arch"; - public ProductFile2(String location) throws Exception { + public ProductFile2(File location) throws Exception { + this(location.getAbsolutePath()); + } + + public ProductFile2(String location) throws Exception { super(location); } diff --git a/tycho-api/src/main/java/org/eclipse/tycho/IDependencyMetadata.java b/tycho-api/src/main/java/org/eclipse/tycho/IDependencyMetadata.java index ced8511a5c..6aaf61e402 100644 --- a/tycho-api/src/main/java/org/eclipse/tycho/IDependencyMetadata.java +++ b/tycho-api/src/main/java/org/eclipse/tycho/IDependencyMetadata.java @@ -20,7 +20,12 @@ public interface IDependencyMetadata { enum DependencyMetadataType { - INITIAL, SEED, RESOLVE; + INITIAL, SEED, RESOLVE, + /** + * Additional metadata describing requirements like defined in the targets platform + * dependency resolution + */ + ADDITIONAL; } Set getDependencyMetadata(DependencyMetadataType type); diff --git a/tycho-api/src/main/java/org/eclipse/tycho/UnmodifiableDependencyMetadata.java b/tycho-api/src/main/java/org/eclipse/tycho/UnmodifiableDependencyMetadata.java new file mode 100644 index 0000000000..4b2738d2a2 --- /dev/null +++ b/tycho-api/src/main/java/org/eclipse/tycho/UnmodifiableDependencyMetadata.java @@ -0,0 +1,49 @@ +/******************************************************************************* + * Copyright (c) 2024 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; + +import java.util.Collection; +import java.util.Collections; +import java.util.Set; + +import org.eclipse.equinox.p2.metadata.IInstallableUnit; + +public class UnmodifiableDependencyMetadata implements IDependencyMetadata { + + private Set units; + private DependencyMetadataType dependencyMetadataType; + + public UnmodifiableDependencyMetadata(Set units, DependencyMetadataType type) { + this.dependencyMetadataType = type; + this.units = Collections.unmodifiableSet(units); + } + + @Override + public Set getDependencyMetadata(DependencyMetadataType type) { + if (dependencyMetadataType == type) { + return getDependencyMetadata(); + } + return Set.of(); + } + + @Override + public Set getDependencyMetadata() { + return units; + } + + @Override + public void setDependencyMetadata(DependencyMetadataType type, Collection units) { + throw new UnsupportedOperationException(); + } + +} diff --git a/tycho-core/src/main/java/org/eclipse/tycho/core/bnd/BndP2MetadataProvider.java b/tycho-core/src/main/java/org/eclipse/tycho/core/bnd/BndP2MetadataProvider.java index 74b0e5324e..1a5de009b4 100644 --- a/tycho-core/src/main/java/org/eclipse/tycho/core/bnd/BndP2MetadataProvider.java +++ b/tycho-core/src/main/java/org/eclipse/tycho/core/bnd/BndP2MetadataProvider.java @@ -12,7 +12,6 @@ *******************************************************************************/ package org.eclipse.tycho.core.bnd; -import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Map; @@ -25,9 +24,11 @@ import org.eclipse.core.runtime.CoreException; import org.eclipse.equinox.p2.metadata.IInstallableUnit; import org.eclipse.tycho.IDependencyMetadata; +import org.eclipse.tycho.IDependencyMetadata.DependencyMetadataType; import org.eclipse.tycho.OptionalResolutionAction; import org.eclipse.tycho.TargetEnvironment; import org.eclipse.tycho.TychoConstants; +import org.eclipse.tycho.UnmodifiableDependencyMetadata; import org.eclipse.tycho.resolver.InstallableUnitProvider; import org.eclipse.tycho.resolver.P2MetadataProvider; @@ -49,28 +50,8 @@ public Map getDependencyMetadata(MavenSession sessi if (units.isEmpty()) { return Collections.emptyMap(); } - IDependencyMetadata metadata = new IDependencyMetadata() { - - @Override - public Set getDependencyMetadata(DependencyMetadataType type) { - if (type == DependencyMetadataType.INITIAL) { - return getDependencyMetadata(); - } - return Collections.emptySet(); - } - - @Override - public Set getDependencyMetadata() { - return units; - } - - @Override - public void setDependencyMetadata(DependencyMetadataType type, Collection units) { - throw new UnsupportedOperationException(); - } - - }; - return Map.of(TychoConstants.PDE_BND, metadata); + return Map.of(TychoConstants.PDE_BND, + new UnmodifiableDependencyMetadata(units, DependencyMetadataType.INITIAL)); } } diff --git a/tycho-core/src/main/java/org/eclipse/tycho/core/osgitools/EclipseRepositoryProject.java b/tycho-core/src/main/java/org/eclipse/tycho/core/osgitools/EclipseRepositoryProject.java index 0dd45d280d..7ace0a21f4 100644 --- a/tycho-core/src/main/java/org/eclipse/tycho/core/osgitools/EclipseRepositoryProject.java +++ b/tycho-core/src/main/java/org/eclipse/tycho/core/osgitools/EclipseRepositoryProject.java @@ -122,7 +122,7 @@ public List loadCategories(final File categoriesDirectory) { * @param project * @return */ - protected List loadProducts(final ReactorProject project) { + public static List loadProducts(final ReactorProject project) { List products = new ArrayList<>(); for (File file : getProductFiles(project)) { try { @@ -153,7 +153,7 @@ private List getCategoryFiles(final File basedir) { * the project containing the product files * @return The list of product files to parse for an eclipse-repository project */ - public List getProductFiles(final ReactorProject project) { + public static List getProductFiles(final ReactorProject project) { final File projectLocation = project.getBasedir(); return getProductFiles(projectLocation); } @@ -165,7 +165,7 @@ public List getProductFiles(final ReactorProject project) { * the directory containing the product files * @return The list of product files to parse for an eclipse-repository project */ - public List getProductFiles(final File basedir) { + public static List getProductFiles(final File basedir) { final List files = new ArrayList<>(); // noinspection ConstantConditions diff --git a/tycho-core/src/main/java/org/eclipse/tycho/p2resolver/P2DependencyResolver.java b/tycho-core/src/main/java/org/eclipse/tycho/p2resolver/P2DependencyResolver.java index 54f6d7473a..4242cf30d2 100644 --- a/tycho-core/src/main/java/org/eclipse/tycho/p2resolver/P2DependencyResolver.java +++ b/tycho-core/src/main/java/org/eclipse/tycho/p2resolver/P2DependencyResolver.java @@ -354,6 +354,13 @@ private DependencyArtifacts doResolveDependencies(MavenSession session, MavenPro for (IRequirement requirement : resolverConfiguration.getAdditionalRequirements()) { resolver.addRequirement(requirement); } + Set additionalDependencyMetadata = DefaultReactorProject.adapt(project) + .getDependencyMetadata(DependencyMetadataType.ADDITIONAL); + for (IInstallableUnit unit : additionalDependencyMetadata) { + for (IRequirement requirement : unit.getRequirements()) { + resolver.addRequirement(requirement); + } + } } BuildProperties buildProperties = buildPropertiesParser.parse(DefaultReactorProject.adapt(project)); diff --git a/tycho-maven-plugin/src/main/resources/META-INF/maven/extension.xml b/tycho-maven-plugin/src/main/resources/META-INF/maven/extension.xml index e90dd7588a..1648eaff0f 100644 --- a/tycho-maven-plugin/src/main/resources/META-INF/maven/extension.xml +++ b/tycho-maven-plugin/src/main/resources/META-INF/maven/extension.xml @@ -21,6 +21,7 @@ org.eclipse.equinox.p2.repository.artifact org.eclipse.equinox.p2.repository.metadata org.eclipse.equinox.internal.p2.metadata + org.eclipse.equinox.internal.p2.publisher.eclipse diff --git a/tycho-p2-publisher-plugin/pom.xml b/tycho-p2-publisher-plugin/pom.xml index c6c5c95e6c..62483c2782 100644 --- a/tycho-p2-publisher-plugin/pom.xml +++ b/tycho-p2-publisher-plugin/pom.xml @@ -56,4 +56,21 @@ + + + + + org.apache.maven.plugins + maven-plugin-plugin + + + tycho-p2-publisher + + + + org.codehaus.plexus + plexus-component-metadata + + + diff --git a/tycho-p2-publisher-plugin/src/main/java/org/eclipse/tycho/plugins/p2/publisher/PublishProductInstallableUnitProvider.java b/tycho-p2-publisher-plugin/src/main/java/org/eclipse/tycho/plugins/p2/publisher/PublishProductInstallableUnitProvider.java new file mode 100644 index 0000000000..b3ecfa3488 --- /dev/null +++ b/tycho-p2-publisher-plugin/src/main/java/org/eclipse/tycho/plugins/p2/publisher/PublishProductInstallableUnitProvider.java @@ -0,0 +1,83 @@ +/******************************************************************************* + * Copyright (c) 2024 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.plugins.p2.publisher; + +import java.io.File; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import org.apache.maven.execution.MavenSession; +import org.apache.maven.model.Plugin; +import org.apache.maven.project.MavenProject; +import org.codehaus.plexus.component.annotations.Component; +import org.codehaus.plexus.component.annotations.Requirement; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.equinox.p2.metadata.IInstallableUnit; +import org.eclipse.equinox.p2.metadata.IRequirement; +import org.eclipse.tycho.PackagingType; +import org.eclipse.tycho.core.osgitools.EclipseRepositoryProject; +import org.eclipse.tycho.p2maven.InstallableUnitGenerator; +import org.eclipse.tycho.p2maven.actions.ProductFile2; +import org.eclipse.tycho.resolver.InstallableUnitProvider; + +@Component(role = InstallableUnitProvider.class, hint = PublishProductInstallableUnitProvider.HINT) +public class PublishProductInstallableUnitProvider implements InstallableUnitProvider { + + static final String HINT = "publish-products"; + + @Requirement + private InstallableUnitGenerator installableUnitGenerator; + + @Override + public Collection getInstallableUnits(MavenProject project, MavenSession session) + throws CoreException { + return getProductUnits(installableUnitGenerator, project); + } + + static Set getProductUnits(InstallableUnitGenerator installableUnitGenerator, + MavenProject project) { + if (PackagingType.TYPE_ECLIPSE_REPOSITORY.equals(project.getPackaging())) { + //This is already handled there... + //TODO can we merge the both ways to determine the requirements? + return Set.of(); + } + Plugin plugin = project.getPlugin("org.eclipse.tycho:tycho-p2-publisher-plugin"); + if (plugin == null || plugin.getExecutions().isEmpty()) { + return Set.of(); + } + List productFiles = EclipseRepositoryProject.getProductFiles(project.getBasedir()); + if (productFiles.isEmpty()) { + return Set.of(); + } + List requirements = new ArrayList<>(); + for (File file : productFiles) { + try { + Collection units = installableUnitGenerator + .getInstallableUnits(new ProductFile2(file)); + for (IInstallableUnit unit : units) { + requirements.addAll(unit.getRequirements()); + } + } catch (CoreException e) { + } catch (Exception e) { + } + } + if (requirements.isEmpty()) { + return Set.of(); + } + return new HashSet<>(InstallableUnitProvider.createIU(requirements, HINT)); + } + +} diff --git a/tycho-p2-publisher-plugin/src/main/java/org/eclipse/tycho/plugins/p2/publisher/PublishProductMetadataProvider.java b/tycho-p2-publisher-plugin/src/main/java/org/eclipse/tycho/plugins/p2/publisher/PublishProductMetadataProvider.java new file mode 100644 index 0000000000..46396a34c3 --- /dev/null +++ b/tycho-p2-publisher-plugin/src/main/java/org/eclipse/tycho/plugins/p2/publisher/PublishProductMetadataProvider.java @@ -0,0 +1,39 @@ +package org.eclipse.tycho.plugins.p2.publisher; + +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.apache.maven.execution.MavenSession; +import org.apache.maven.project.MavenProject; +import org.codehaus.plexus.component.annotations.Component; +import org.codehaus.plexus.component.annotations.Requirement; +import org.eclipse.equinox.p2.metadata.IInstallableUnit; +import org.eclipse.tycho.IDependencyMetadata; +import org.eclipse.tycho.IDependencyMetadata.DependencyMetadataType; +import org.eclipse.tycho.OptionalResolutionAction; +import org.eclipse.tycho.TargetEnvironment; +import org.eclipse.tycho.UnmodifiableDependencyMetadata; +import org.eclipse.tycho.p2maven.InstallableUnitGenerator; +import org.eclipse.tycho.resolver.P2MetadataProvider; + +@Component(role = P2MetadataProvider.class, hint = PublishProductInstallableUnitProvider.HINT) +public class PublishProductMetadataProvider implements P2MetadataProvider { + + @Requirement + private InstallableUnitGenerator installableUnitGenerator; + + @Override + public Map getDependencyMetadata(MavenSession session, MavenProject project, + List environments, OptionalResolutionAction optionalAction) { + + Set productUnits = PublishProductInstallableUnitProvider + .getProductUnits(installableUnitGenerator, project); + if (productUnits.isEmpty()) { + return Map.of(); + } + return Map.of(PublishProductInstallableUnitProvider.HINT, + new UnmodifiableDependencyMetadata(productUnits, DependencyMetadataType.ADDITIONAL)); + } + +} 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 a031d19d1a..33665bacbb 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 @@ -67,8 +67,8 @@ /** *

- * Publishes all product definitions files (*.product) that are present in the root of the - * project. + * Publishes all product definitions files (*.product) that are present in the root of + * the project. *

* * @see https://wiki.eclipse.org/Equinox/p2/Publisher @@ -113,7 +113,7 @@ protected Collection publishContent(PublisherServiceFactory publ List seeds = new ArrayList<>(); boolean hasLaunchers = false; - for (final File productFile : eclipseRepositoryProject.getProductFiles(productsDirectory)) { + for (final File productFile : EclipseRepositoryProject.getProductFiles(productsDirectory)) { try { ProductConfiguration productConfiguration = ProductConfiguration.read(productFile); if (productConfiguration.getId() == null || productConfiguration.getId().isEmpty()) { diff --git a/tycho-spi/src/main/java/org/eclipse/tycho/resolver/InstallableUnitProvider.java b/tycho-spi/src/main/java/org/eclipse/tycho/resolver/InstallableUnitProvider.java index 936f4a2906..1fc3581933 100644 --- a/tycho-spi/src/main/java/org/eclipse/tycho/resolver/InstallableUnitProvider.java +++ b/tycho-spi/src/main/java/org/eclipse/tycho/resolver/InstallableUnitProvider.java @@ -36,7 +36,7 @@ static Collection createIU(Stream requirements, return createIU(requirements.toList(), idPrefix); } - static Collection createIU(List requirements, String idPrefix) { + static Collection createIU(Collection requirements, String idPrefix) { if (requirements.isEmpty()) { return Collections.emptyList(); }