diff --git a/tycho-eclipse-plugin/src/main/java/org/eclipse/tycho/eclipsebuild/AbstractEclipseBuildMojo.java b/tycho-eclipse-plugin/src/main/java/org/eclipse/tycho/eclipsebuild/AbstractEclipseBuildMojo.java new file mode 100644 index 0000000000..b22dfe9193 --- /dev/null +++ b/tycho-eclipse-plugin/src/main/java/org/eclipse/tycho/eclipsebuild/AbstractEclipseBuildMojo.java @@ -0,0 +1,198 @@ +/******************************************************************************* + * Copyright (c) 2025 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.eclipsebuild; + +import java.io.Serializable; +import java.lang.reflect.InvocationTargetException; +import java.nio.file.Path; +import java.util.Collection; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.concurrent.Callable; +import java.util.function.Consumer; + +import org.apache.maven.model.Repository; +import org.apache.maven.plugin.AbstractMojo; +import org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.plugin.MojoFailureException; +import org.apache.maven.plugin.logging.Log; +import org.apache.maven.plugins.annotations.Component; +import org.apache.maven.plugins.annotations.Parameter; +import org.apache.maven.project.MavenProject; +import org.eclipse.core.resources.IMarker; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.tycho.TargetPlatform; +import org.eclipse.tycho.core.TychoProjectManager; +import org.eclipse.tycho.osgi.framework.Bundles; +import org.eclipse.tycho.osgi.framework.EclipseApplication; +import org.eclipse.tycho.osgi.framework.EclipseApplicationManager; +import org.eclipse.tycho.osgi.framework.EclipseFramework; +import org.eclipse.tycho.osgi.framework.EclipseWorkspaceManager; +import org.eclipse.tycho.osgi.framework.Features; +import org.osgi.framework.BundleException; + +/** + * An abstract mojo baseclass that can be used to perform actions on an eclipse + * project that requires the build infrastructure. + * + * @param the rsult type + */ +public abstract class AbstractEclipseBuildMojo extends AbstractMojo { + + static final String PARAMETER_LOCAL = "local"; + + @Parameter() + private Repository eclipseRepository; + + @Parameter(defaultValue = "false", property = "tycho.eclipsebuild.skip") + private boolean skip; + + @Parameter(defaultValue = "false", property = "tycho.eclipsebuild.debug") + protected boolean debug; + + /** + * Controls if the local target platform of the project should be used to + * resolve the eclipse application + */ + @Parameter(defaultValue = "false", property = "tycho.eclipsebuild.local", name = PARAMETER_LOCAL) + private boolean local; + + @Parameter(defaultValue = "true", property = "tycho.eclipsebuild.printMarker") + private boolean printMarker; + + @Parameter + private List bundles; + + @Parameter + private List features; + + @Parameter(property = "project", readonly = true) + protected MavenProject project; + + @Component + private EclipseWorkspaceManager workspaceManager; + + @Component + private EclipseApplicationManager eclipseApplicationManager; + + @Component + private TychoProjectManager projectManager; + + @Override + public final void execute() throws MojoExecutionException, MojoFailureException { + + Collection projectDependencies; + try { + projectDependencies = projectManager.getProjectDependencies(project); + } catch (Exception e) { + throw new MojoFailureException("Can't resolve project dependencies", e); + } + EclipseApplication application; + Bundles bundles = new Bundles(getBundles()); + Features features = new Features(getFeatures()); + if (local) { + TargetPlatform targetPlatform = projectManager.getTargetPlatform(project).orElseThrow( + () -> new MojoFailureException("Can't get target platform for project " + project.getId())); + application = eclipseApplicationManager.getApplication(targetPlatform, bundles, features, getName()); + } else { + application = eclipseApplicationManager.getApplication(eclipseRepository, bundles, features, getName()); + } + try (EclipseFramework framework = application.startFramework(workspaceManager + .getWorkspace(EclipseApplicationManager.getRepository(eclipseRepository).getURL(), this), List.of())) { + 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..."); + } + Result result = framework.execute(createExecutable()); + if (printMarker) { + Log log = getLog(); + result.markers().filter(marker -> marker.getAttribute(IMarker.SEVERITY, -1) == IMarker.SEVERITY_INFO) + .forEach(info -> printMarker(info, result, log::info)); + result.markers().filter(marker -> marker.getAttribute(IMarker.SEVERITY, -1) == IMarker.SEVERITY_WARNING) + .forEach(warn -> printMarker(warn, result, log::warn)); + result.markers().filter(marker -> marker.getAttribute(IMarker.SEVERITY, -1) == IMarker.SEVERITY_ERROR) + .forEach(error -> printMarker(error, result, log::error)); + } + handleResult(result); + } catch (BundleException e) { + throw new MojoFailureException("Can't start framework!", e); + } catch (InvocationTargetException e) { + Throwable cause = e.getCause(); + if (cause.getClass().getName().equals(CoreException.class.getName())) { + throw new MojoFailureException(cause.getMessage(), cause); + } + throw new MojoExecutionException(cause); + } + } + + protected abstract void handleResult(Result result) throws MojoFailureException; + + protected abstract & Serializable, R extends Serializable> R createExecutable(); + + protected Set getFeatures() { + Set set = new HashSet<>(); + if (features != null) { + set.addAll(features); + } + return set; + } + + protected Set getBundles() { + Set set = new HashSet<>(); + set.add("org.eclipse.core.resources"); + set.add("org.eclipse.core.runtime"); + set.add("org.eclipse.core.jobs"); + if (bundles != null) { + set.addAll(bundles); + } + return set; + } + + private static void printMarker(IMarker marker, EclipseBuildResult result, Consumer consumer) { + consumer.accept(asString(marker, result).toString().trim()); + } + + protected static StringBuilder asString(IMarker marker, EclipseBuildResult result) { + StringBuilder sb = new StringBuilder(); + String path = result.getMarkerPath(marker); + if (path != null) { + sb.append(path); + int line = marker.getAttribute("lineNumber", -1); + if (line > -1) { + sb.append(":"); + sb.append(line); + } + sb.append(" "); + } + String message = marker.getAttribute("message", ""); + if (!message.isBlank()) { + sb.append(message); + sb.append(" "); + } + String sourceId = marker.getAttribute("sourceId", ""); + if (!sourceId.isBlank()) { + sb.append(sourceId); + sb.append(" "); + } + return sb; + } + + protected abstract String getName(); + +} diff --git a/tycho-eclipse-plugin/src/main/java/org/eclipse/tycho/eclipsebuild/EclipseBuildInstallableUnitProvider.java b/tycho-eclipse-plugin/src/main/java/org/eclipse/tycho/eclipsebuild/EclipseBuildInstallableUnitProvider.java index 037eedc360..5299163281 100644 --- a/tycho-eclipse-plugin/src/main/java/org/eclipse/tycho/eclipsebuild/EclipseBuildInstallableUnitProvider.java +++ b/tycho-eclipse-plugin/src/main/java/org/eclipse/tycho/eclipsebuild/EclipseBuildInstallableUnitProvider.java @@ -38,8 +38,8 @@ public class EclipseBuildInstallableUnitProvider implements InstallableUnitProvi @Override public Collection getInstallableUnits(MavenProject project, MavenSession session) throws CoreException { - Configuration configuration = configurationHelper.getConfiguration(EclipseBuildMojo.class, project, session); - Optional local = configuration.getBoolean(EclipseBuildMojo.PARAMETER_LOCAL); + Configuration configuration = configurationHelper.getConfiguration(EclipseBuildProjectMojo.class, project, session); + Optional local = configuration.getBoolean(EclipseBuildProjectMojo.PARAMETER_LOCAL); if (local.isPresent() && local.get()) { // for local target resolution the bundles become requirements... Optional> list = configuration.getStringList("bundles"); diff --git a/tycho-eclipse-plugin/src/main/java/org/eclipse/tycho/eclipsebuild/EclipseBuildMojo.java b/tycho-eclipse-plugin/src/main/java/org/eclipse/tycho/eclipsebuild/EclipseBuildMojo.java deleted file mode 100644 index 883e196016..0000000000 --- a/tycho-eclipse-plugin/src/main/java/org/eclipse/tycho/eclipsebuild/EclipseBuildMojo.java +++ /dev/null @@ -1,207 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2023 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.eclipsebuild; - -import java.lang.reflect.InvocationTargetException; -import java.nio.file.Path; -import java.util.Collection; -import java.util.HashSet; -import java.util.List; -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; -import org.apache.maven.plugin.MojoExecutionException; -import org.apache.maven.plugin.MojoFailureException; -import org.apache.maven.plugin.logging.Log; -import org.apache.maven.plugins.annotations.Component; -import org.apache.maven.plugins.annotations.LifecyclePhase; -import org.apache.maven.plugins.annotations.Mojo; -import org.apache.maven.plugins.annotations.Parameter; -import org.apache.maven.plugins.annotations.ResolutionScope; -import org.apache.maven.project.MavenProject; -import org.eclipse.core.resources.IMarker; -import org.eclipse.core.runtime.CoreException; -import org.eclipse.tycho.TargetPlatform; -import org.eclipse.tycho.core.TychoProjectManager; -import org.eclipse.tycho.osgi.framework.Bundles; -import org.eclipse.tycho.osgi.framework.EclipseApplication; -import org.eclipse.tycho.osgi.framework.EclipseApplicationManager; -import org.eclipse.tycho.osgi.framework.EclipseFramework; -import org.eclipse.tycho.osgi.framework.EclipseWorkspaceManager; -import org.eclipse.tycho.osgi.framework.Features; -import org.osgi.framework.BundleException; - -/** - * This mojo allows to perform an eclipse-build on a project like it would be performed inside the - * IDE, this can be useful in cases where there are very special builders that are not part of - * Tycho. - */ -@Mojo(name = "eclipse-build", defaultPhase = LifecyclePhase.COMPILE, threadSafe = true, requiresDependencyCollection = ResolutionScope.COMPILE_PLUS_RUNTIME) -public class EclipseBuildMojo extends AbstractMojo { - - static final String PARAMETER_LOCAL = "local"; - - private static final String NAME = "Eclipse Build Project"; - - @Parameter() - private Repository eclipseRepository; - - @Parameter(defaultValue = "false", property = "tycho.eclipsebuild.skip") - private boolean skip; - - @Parameter(defaultValue = "false", property = "tycho.eclipsebuild.debug") - private boolean debug; - - /** - * Controls if the local target platform of the project should be used to resolve the eclipse - * application - */ - @Parameter(defaultValue = "false", property = "tycho.eclipsebuild.local", name = PARAMETER_LOCAL) - private boolean local; - - @Parameter(defaultValue = "true", property = "tycho.eclipsebuild.failOnError") - private boolean failOnError; - - @Parameter(defaultValue = "true", property = "tycho.eclipsebuild.printMarker") - private boolean printMarker; - - @Parameter - private List bundles; - - @Parameter - private List features; - - @Parameter(property = "project", readonly = true) - private MavenProject project; - - @Component - private EclipseWorkspaceManager workspaceManager; - - @Component - private EclipseApplicationManager eclipseApplicationManager; - - @Component - private TychoProjectManager projectManager; - - @Override - public void execute() throws MojoExecutionException, MojoFailureException { - - Collection projectDependencies; - try { - projectDependencies = projectManager.getProjectDependencies(project); - } catch (Exception e) { - throw new MojoFailureException("Can't resolve project dependencies", e); - } - EclipseApplication application; - //TODO configureable by parameters! - Bundles bundles = new Bundles(getBundles()); - Features features = new Features(getFeatures()); - if (local) { - TargetPlatform targetPlatform = projectManager.getTargetPlatform(project).orElseThrow( - () -> new MojoFailureException("Can't get target platform for project " + project.getId())); - application = eclipseApplicationManager.getApplication(targetPlatform, bundles, features, NAME); - } else { - application = eclipseApplicationManager.getApplication(eclipseRepository, bundles, features, NAME); - } - try (EclipseFramework framework = application.startFramework(workspaceManager - .getWorkspace(EclipseApplicationManager.getRepository(eclipseRepository).getURL(), this), List.of())) { - 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..."); - } - EclipseBuildResult result = framework - .execute(new EclipseBuild(project.getBasedir().toPath(), debug)); - List errors = result.markers() - .filter(marker -> marker.getAttribute(IMarker.SEVERITY, -1) == IMarker.SEVERITY_ERROR).toList(); - if (printMarker) { - Log log = getLog(); - result.markers().filter(marker -> marker.getAttribute(IMarker.SEVERITY, -1) == IMarker.SEVERITY_INFO) - .forEach(info -> printMarker(info, result, log::info)); - result.markers().filter(marker -> marker.getAttribute(IMarker.SEVERITY, -1) == IMarker.SEVERITY_WARNING) - .forEach(warn -> printMarker(warn, result, log::warn)); - errors.forEach(error -> printMarker(error, result, log::error)); - } - if (failOnError && errors.size() > 0) { - String msg = errors.stream().map(problem -> asString(problem, result)) - .collect(Collectors.joining(System.lineSeparator())); - throw new MojoFailureException("There are Build errors:" + System.lineSeparator() + msg); - } - } catch (BundleException e) { - throw new MojoFailureException("Can't start framework!", e); - } catch (InvocationTargetException e) { - Throwable cause = e.getCause(); - if (cause.getClass().getName().equals(CoreException.class.getName())) { - throw new MojoFailureException(cause.getMessage(), cause); - } - throw new MojoExecutionException(cause); - } - } - - private Set getFeatures() { - Set set = new HashSet<>(); - if (features != null) { - set.addAll(features); - } - return set; - } - - private Set getBundles() { - Set set = new HashSet<>(); - set.add("org.eclipse.core.resources"); - set.add("org.eclipse.core.runtime"); - set.add("org.eclipse.core.jobs"); - if (bundles != null) { - set.addAll(bundles); - } - return set; - } - - private void printMarker(IMarker marker, EclipseBuildResult result, Consumer consumer) { - StringBuilder sb = asString(marker, result); - consumer.accept(sb.toString().trim()); - } - - private StringBuilder asString(IMarker marker, EclipseBuildResult result) { - StringBuilder sb = new StringBuilder(); - String path = result.getMarkerPath(marker); - if (path != null) { - sb.append(path); - int line = marker.getAttribute("lineNumber", -1); - if (line > -1) { - sb.append(":"); - sb.append(line); - } - sb.append(" "); - } - String message = marker.getAttribute("message", ""); - if (!message.isBlank()) { - sb.append(message); - sb.append(" "); - } - String sourceId = marker.getAttribute("sourceId", ""); - if (!sourceId.isBlank()) { - sb.append(sourceId); - sb.append(" "); - } - return sb; - } - -} diff --git a/tycho-eclipse-plugin/src/main/java/org/eclipse/tycho/eclipsebuild/EclipseBuildProjectMojo.java b/tycho-eclipse-plugin/src/main/java/org/eclipse/tycho/eclipsebuild/EclipseBuildProjectMojo.java new file mode 100644 index 0000000000..b57242572c --- /dev/null +++ b/tycho-eclipse-plugin/src/main/java/org/eclipse/tycho/eclipsebuild/EclipseBuildProjectMojo.java @@ -0,0 +1,59 @@ +/******************************************************************************* + * Copyright (c) 2023 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.eclipsebuild; + +import java.util.List; +import java.util.stream.Collectors; + +import org.apache.maven.plugin.MojoFailureException; +import org.apache.maven.plugins.annotations.LifecyclePhase; +import org.apache.maven.plugins.annotations.Mojo; +import org.apache.maven.plugins.annotations.Parameter; +import org.apache.maven.plugins.annotations.ResolutionScope; +import org.eclipse.core.resources.IMarker; + +/** + * This mojo allows to perform an eclipse-build on a project like it would be + * performed inside the IDE, this can be useful in cases where there are very + * special builders that are not part of Tycho. + */ +@Mojo(name = "eclipse-build", defaultPhase = LifecyclePhase.COMPILE, threadSafe = true, requiresDependencyCollection = ResolutionScope.COMPILE_PLUS_RUNTIME) +public class EclipseBuildProjectMojo extends AbstractEclipseBuildMojo { + + @Parameter(defaultValue = "true", property = "tycho.eclipsebuild.failOnError") + private boolean failOnError; + + @Override + protected String getName() { + return "Eclipse Project Build"; + } + + @SuppressWarnings("unchecked") + @Override + protected EclipseBuild createExecutable() { + return new EclipseBuild(project.getBasedir().toPath(), debug); + } + + @Override + protected void handleResult(EclipseBuildResult result) throws MojoFailureException { + if (failOnError) { + List errorMarkers = result.markers() + .filter(marker -> marker.getAttribute(IMarker.SEVERITY, -1) == IMarker.SEVERITY_ERROR).toList(); + if (errorMarkers.size() > 0) { + String msg = errorMarkers.stream().map(problem -> asString(problem, result)) + .collect(Collectors.joining(System.lineSeparator())); + throw new MojoFailureException("There are Build errors:" + System.lineSeparator() + msg); + } + } + } +}