Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for setting an API baseline in EclipseBuildMojos #4635

Merged
merged 1 commit into from
Jan 23, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -403,7 +403,7 @@ private MavenRepositoryLocation getRepository() {
private Collection<Path> getBaselineBundles() throws MojoFailureException {
long start = System.currentTimeMillis();
try {
Collection<TargetEnvironment> targetEnvironments = getBaselineEnvironments();
Collection<TargetEnvironment> targetEnvironments = projectManager.getBaselineEnvironments(project);
Optional<ArtifactKey> artifactKey = projectManager.getArtifactKey(project);
getLog().info("Resolve API baseline for " + project.getId() + " with "
+ targetEnvironments.stream().map(String::valueOf).collect(Collectors.joining(", ")));
Expand All @@ -427,25 +427,6 @@ private Collection<Path> getBaselineBundles() throws MojoFailureException {
}
}

/**
* This method selected the a target environment best suited for the current
* baseline, if it is a valid choice the running target is used (e.g. linux on
* linux host, windows on windows hosts and so on), if such environment is not
* available it is using the configured ones form the project as is.
*
* @return the chosen {@link TargetEnvironment}s
*/
private Collection<TargetEnvironment> getBaselineEnvironments() {
Collection<TargetEnvironment> targetEnvironments = projectManager.getTargetEnvironments(project);
TargetEnvironment runningEnvironment = TargetEnvironment.getRunningEnvironment();
for (TargetEnvironment targetEnvironment : targetEnvironments) {
if (targetEnvironment.equals(runningEnvironment)) {
return List.of(targetEnvironment);
}
}
return targetEnvironments;
}

private String time(long start) {
long ms = System.currentTimeMillis() - start;
if (ms < 1000) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,23 +13,16 @@
package org.eclipse.tycho.apitools;

import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Set;

import org.codehaus.plexus.component.annotations.Component;
import org.codehaus.plexus.component.annotations.Requirement;
import org.codehaus.plexus.logging.Logger;
import org.eclipse.tycho.ArtifactKey;
import org.eclipse.tycho.ArtifactType;
import org.eclipse.tycho.IllegalArtifactReferenceException;
import org.eclipse.tycho.MavenRepositoryLocation;
import org.eclipse.tycho.TargetEnvironment;
import org.eclipse.tycho.TargetPlatform;
import org.eclipse.tycho.core.resolver.P2ResolutionResult;
import org.eclipse.tycho.core.resolver.P2ResolutionResult.Entry;
import org.eclipse.tycho.core.resolver.P2Resolver;
import org.eclipse.tycho.osgi.framework.Bundles;
import org.eclipse.tycho.osgi.framework.EclipseApplication;
import org.eclipse.tycho.osgi.framework.EclipseApplicationFactory;
Expand All @@ -56,19 +49,7 @@ public class ApiApplicationResolver {
public Collection<Path> getApiBaselineBundles(Collection<MavenRepositoryLocation> baselineRepoLocations,
ArtifactKey artifactKey, Collection<TargetEnvironment> environment)
throws IllegalArtifactReferenceException {
P2Resolver resolver = applicationFactory.createResolver(environment);
resolver.addDependency(ArtifactType.TYPE_INSTALLABLE_UNIT, artifactKey.getId(), "0.0.0");
List<Path> resolvedBundles = new ArrayList<>();
TargetPlatform targetPlatform = applicationFactory.createTargetPlatform(baselineRepoLocations);
for (P2ResolutionResult result : resolver.resolveTargetDependencies(targetPlatform, null).values()) {
for (Entry entry : result.getArtifacts()) {
if (ArtifactType.TYPE_ECLIPSE_PLUGIN.equals(entry.getType())
&& !"org.eclipse.osgi".equals(entry.getId())) {
resolvedBundles.add(entry.getLocation(true).toPath());
}
}
}
return resolvedBundles;
return applicationFactory.getApiBaselineBundles(baselineRepoLocations, artifactKey, environment);
}

public EclipseApplication getApiApplication(MavenRepositoryLocation apiToolsRepo) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -379,4 +379,25 @@ public Stream<ExecutionEnvironment> getExecutionEnvironments(MavenProject projec
return Arrays.stream(manifestBREEs);
}

/**
* This method selected the a target environment best suited for the current baseline, if it is
* a valid choice the running target is used (e.g. linux on linux host, windows on windows hosts
* and so on), if such environment is not available it is using the configured ones form the
* project as is.
*
* @param project
*
* @return the chosen {@link TargetEnvironment}s
*/
public Collection<TargetEnvironment> getBaselineEnvironments(MavenProject project) {
Collection<TargetEnvironment> targetEnvironments = getTargetEnvironments(project);
TargetEnvironment runningEnvironment = TargetEnvironment.getRunningEnvironment();
for (TargetEnvironment targetEnvironment : targetEnvironments) {
if (targetEnvironment.equals(runningEnvironment)) {
return List.of(targetEnvironment);
}
}
return targetEnvironments;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
*******************************************************************************/
package org.eclipse.tycho.osgi.framework;

import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.function.Function;
Expand All @@ -26,11 +28,16 @@
import org.codehaus.plexus.component.annotations.Component;
import org.codehaus.plexus.component.annotations.Requirement;
import org.codehaus.plexus.logging.Logger;
import org.eclipse.tycho.ArtifactKey;
import org.eclipse.tycho.ArtifactType;
import org.eclipse.tycho.ExecutionEnvironmentConfiguration;
import org.eclipse.tycho.IllegalArtifactReferenceException;
import org.eclipse.tycho.MavenRepositoryLocation;
import org.eclipse.tycho.TargetEnvironment;
import org.eclipse.tycho.TargetPlatform;
import org.eclipse.tycho.core.ee.ExecutionEnvironmentConfigurationImpl;
import org.eclipse.tycho.core.resolver.P2ResolutionResult;
import org.eclipse.tycho.core.resolver.P2ResolutionResult.Entry;
import org.eclipse.tycho.core.resolver.P2Resolver;
import org.eclipse.tycho.core.resolver.P2ResolverFactory;
import org.eclipse.tycho.core.resolver.shared.IncludeSourceMode;
Expand Down Expand Up @@ -95,6 +102,24 @@ public TargetPlatform createTargetPlatform(Collection<MavenRepositoryLocation> l
return targetPlatform;
}

public Collection<Path> getApiBaselineBundles(Collection<MavenRepositoryLocation> baselineRepoLocations,
ArtifactKey artifactKey, Collection<TargetEnvironment> environment)
throws IllegalArtifactReferenceException {
P2Resolver resolver = createResolver(environment);
resolver.addDependency(ArtifactType.TYPE_INSTALLABLE_UNIT, artifactKey.getId(), "0.0.0");
List<Path> resolvedBundles = new ArrayList<>();
TargetPlatform targetPlatform = createTargetPlatform(baselineRepoLocations);
for (P2ResolutionResult result : resolver.resolveTargetDependencies(targetPlatform, null).values()) {
for (Entry entry : result.getArtifacts()) {
if (ArtifactType.TYPE_ECLIPSE_PLUGIN.equals(entry.getType())
&& !"org.eclipse.osgi".equals(entry.getId())) {
resolvedBundles.add(entry.getLocation(true).toPath());
}
}
}
return resolvedBundles;
}

public P2Resolver createResolver() {
return createResolver(List.of(TargetEnvironment.getRunningEnvironment()));
}
Expand Down
12 changes: 12 additions & 0 deletions tycho-eclipse-plugin/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,18 @@
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.eclipse.pde</groupId>
<artifactId>org.eclipse.pde.api.tools</artifactId>
<version>1.3.600</version>
<type>jar</type>
<exclusions>
<exclusion>
<groupId>*</groupId>
<artifactId>*</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.eclipse.tycho</groupId>
<artifactId>sisu-equinox-launching</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,16 @@
package org.eclipse.tycho.eclipsebuild;

import java.lang.reflect.InvocationTargetException;
import java.net.URI;
import java.nio.file.Path;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.function.Consumer;
import java.util.stream.Collectors;

import org.apache.maven.model.Repository;
import org.apache.maven.plugin.AbstractMojo;
Expand All @@ -31,11 +34,17 @@
import org.apache.maven.project.MavenProject;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.tycho.ArtifactKey;
import org.eclipse.tycho.DependencyResolutionException;
import org.eclipse.tycho.IllegalArtifactReferenceException;
import org.eclipse.tycho.MavenRepositoryLocation;
import org.eclipse.tycho.TargetEnvironment;
import org.eclipse.tycho.TargetPlatform;
import org.eclipse.tycho.core.TychoProjectManager;
import org.eclipse.tycho.model.project.EclipseProject;
import org.eclipse.tycho.osgi.framework.Bundles;
import org.eclipse.tycho.osgi.framework.EclipseApplication;
import org.eclipse.tycho.osgi.framework.EclipseApplicationFactory;
import org.eclipse.tycho.osgi.framework.EclipseApplicationManager;
import org.eclipse.tycho.osgi.framework.EclipseFramework;
import org.eclipse.tycho.osgi.framework.EclipseWorkspaceManager;
Expand All @@ -55,12 +64,22 @@ public abstract class AbstractEclipseBuildMojo<Result extends EclipseBuildResult
@Parameter()
private Repository eclipseRepository;

/**
* If configured, automatically sets a baseline for this project if api tools
* nature is enabled
*/
@Parameter(property = "baselines", name = "baselines")
private List<Repository> baselines;

@Parameter(defaultValue = "false", property = "tycho.eclipsebuild.skip")
private boolean skip;

@Parameter(defaultValue = "false", property = "tycho.eclipsebuild.debug")
protected boolean debug;

@Parameter(defaultValue = "false")
private boolean failOnResolutionError;

/**
* Controls if the local target platform of the project should be used to
* resolve the eclipse application
Expand All @@ -86,6 +105,9 @@ public abstract class AbstractEclipseBuildMojo<Result extends EclipseBuildResult
@Component
private EclipseApplicationManager eclipseApplicationManager;

@Component
private EclipseApplicationFactory applicationFactory;

@Component
private TychoProjectManager projectManager;

Expand Down Expand Up @@ -120,11 +142,25 @@ public final void execute() throws MojoExecutionException, MojoFailureException
if (debug) {
framework.printState();
}
if (framework.hasBundle(Bundles.BUNDLE_PDE_CORE)) {
framework.execute(new SetTargetPlatform(projectDependencies, debug));
} else {
getLog().info("Skip set Target Platform because " + Bundles.BUNDLE_PDE_CORE
+ " is not part of the framework...");
if (hasPDENature(eclipseProject)) {
if (framework.hasBundle(Bundles.BUNDLE_PDE_CORE)) {
framework.execute(new SetTargetPlatform(projectDependencies, debug));
} else {
getLog().info("Skip set Target Platform because " + Bundles.BUNDLE_PDE_CORE
+ " is not part of the framework...");
}
}
if (hasAPIToolsNature(eclipseProject)) {
if (framework.hasBundle(Bundles.BUNDLE_API_TOOLS)) {
if (hasBaselinesSet()) {
framework.execute(new SetApiBaseline(project.getId(), getBaselineBundles(), debug));
} else {
getLog().info("Skip set ApiBasline because no baselines set...");
}
} else {
getLog().info("Skip set ApiBasline because " + Bundles.BUNDLE_API_TOOLS
+ " is not part of the framework...");
}
}
Result result = framework.execute(createExecutable(), getRequireBundles());
if (printMarker) {
Expand Down Expand Up @@ -179,18 +215,57 @@ protected Set<String> getBundles(EclipseProject eclipseProject) {
for (String requiredBundle : getRequireBundles()) {
set.add(requiredBundle);
}
if (eclipseProject.hasNature("org.eclipse.pde.PluginNature")) {
if (hasPDENature(eclipseProject)) {
set.add(Bundles.BUNDLE_PDE_CORE);
}
if (eclipseProject.hasNature("org.eclipse.jdt.core.javanature")) {
if (hasJDTNature(eclipseProject)) {
set.add(Bundles.BUNDLE_JDT_CORE);
}
// TODO if project has org.eclipse.pde.api.tools.apiAnalysisNature and we have a
// baseline parameter then
// set.add(Bundles.BUNDLE_API_TOOLS);
if (hasAPIToolsNature(eclipseProject)) {
set.add(Bundles.BUNDLE_API_TOOLS);
}
return set;
}

private Collection<Path> getBaselineBundles() throws MojoFailureException {
try {
Collection<TargetEnvironment> targetEnvironments = projectManager.getBaselineEnvironments(project);
Optional<ArtifactKey> artifactKey = projectManager.getArtifactKey(project);
getLog().info("Resolve API baseline for " + project.getId() + " with "
+ targetEnvironments.stream().map(String::valueOf).collect(Collectors.joining(", ")));
return applicationFactory.getApiBaselineBundles(
baselines.stream().filter(repo -> repo.getUrl() != null)
.map(repo -> new MavenRepositoryLocation(repo.getId(), URI.create(repo.getUrl()))).toList(),
artifactKey.get(), targetEnvironments);
} catch (IllegalArtifactReferenceException e) {
throw new MojoFailureException("Project specify an invalid artifact key", e);
} catch (DependencyResolutionException e) {
if (failOnResolutionError) {
throw new MojoFailureException("Can't resolve API baseline!", e);
} else {
getLog().warn(
"Can't resolve API baseline: " + Objects.requireNonNullElse(e.getMessage(), e.toString()));
return List.of();
}
}
}

private boolean hasJDTNature(EclipseProject eclipseProject) {
return eclipseProject.hasNature("org.eclipse.jdt.core.javanature");
}

private boolean hasAPIToolsNature(EclipseProject eclipseProject) {
return eclipseProject.hasNature("org.eclipse.pde.api.tools.apiAnalysisNature");
}

private boolean hasPDENature(EclipseProject eclipseProject) {
return eclipseProject.hasNature("org.eclipse.pde.PluginNature");
}

private boolean hasBaselinesSet() {
return baselines != null && baselines.size() > 0;
}

private static void printMarker(IMarker marker, EclipseBuildResult result, Consumer<CharSequence> consumer) {
consumer.accept(asString(marker, result).toString().trim());
}
Expand Down
Loading
Loading