diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md
index 0d2cb2c38e..0e0d7dbf48 100644
--- a/RELEASE_NOTES.md
+++ b/RELEASE_NOTES.md
@@ -6,6 +6,32 @@ If you are reading this in the browser, then you can quickly jump to specific ve
## 5.0.0 (under development)
+### new `tycho-eclipse-plugin`
+
+Tycho now contains a new `tycho-eclipse-plugin` that is dedicated to executing "tasks like eclipse", this currently includes
+- the former tycho-extras `tycho-eclipserun-plugin` and its mojos
+- a new `eclipse-build` mojo that allows to take a literal eclipse project and execute the build on it
+
+#### new `eclipse-build` mojo
+
+The `eclipse-build` mojo can be used like this
+
+```xml
+
+ org.eclipse.tycho
+ tycho-eclipse-plugin
+ ${tycho-version}
+
+
+ eclipse-build
+
+ eclipse-build
+
+
+
+
+```
+
### support for PDE Api Tools Annotations
Tycho now supports PDE Api Tools Annotations to be added to the project automatically.
diff --git a/pom.xml b/pom.xml
index 405a9bb328..fcbdccc557 100644
--- a/pom.xml
+++ b/pom.xml
@@ -557,6 +557,7 @@
tycho-targetplatform
tycho-bnd-plugin
tycho-repository-plugin
+ tycho-eclipse-plugin
diff --git a/tycho-core/src/main/java/org/eclipse/tycho/core/resolver/AdditionalBundleRequirementsInstallableUnitProvider.java b/tycho-core/src/main/java/org/eclipse/tycho/core/resolver/AdditionalBundleRequirementsInstallableUnitProvider.java
index f066bedd81..187d8991ac 100644
--- a/tycho-core/src/main/java/org/eclipse/tycho/core/resolver/AdditionalBundleRequirementsInstallableUnitProvider.java
+++ b/tycho-core/src/main/java/org/eclipse/tycho/core/resolver/AdditionalBundleRequirementsInstallableUnitProvider.java
@@ -18,7 +18,6 @@
import java.util.Collections;
import java.util.List;
import java.util.Optional;
-import java.util.UUID;
import org.apache.maven.execution.MavenSession;
import org.apache.maven.project.MavenProject;
@@ -29,8 +28,6 @@
import org.eclipse.equinox.p2.metadata.IInstallableUnit;
import org.eclipse.equinox.p2.metadata.IRequirement;
import org.eclipse.equinox.p2.metadata.MetadataFactory;
-import org.eclipse.equinox.p2.metadata.MetadataFactory.InstallableUnitDescription;
-import org.eclipse.equinox.p2.metadata.Version;
import org.eclipse.equinox.p2.metadata.VersionRange;
import org.eclipse.equinox.p2.publisher.eclipse.BundlesAction;
import org.eclipse.tycho.BuildProperties;
@@ -67,7 +64,7 @@ public Collection getInstallableUnits(MavenProject project, Ma
try (Processor processor = bndTychoProject.get()) {
List requirements = getBndClasspathRequirements(processor);
if (!requirements.isEmpty()) {
- return createIU(requirements);
+ return InstallableUnitProvider.createIU(requirements, "bnd-classpath-requirements");
}
} catch (IOException e) {
logger.warn("Can't determine classpath requirements from " + project.getId(), e);
@@ -80,7 +77,7 @@ public Collection getInstallableUnits(MavenProject project, Ma
.map(bundleName -> MetadataFactory.createRequirement(BundlesAction.CAPABILITY_NS_OSGI_BUNDLE,
bundleName, VersionRange.emptyRange, null, true, true))
.toList();
- return createIU(additionalBundleRequirements);
+ return InstallableUnitProvider.createIU(additionalBundleRequirements, "additional-bundle-requirements");
}
return Collections.emptyList();
}
@@ -97,15 +94,4 @@ public static List getBndClasspathRequirements(Processor processor
return Collections.emptyList();
}
- private Collection createIU(List additionalBundleRequirements) {
- if (additionalBundleRequirements.isEmpty()) {
- return Collections.emptyList();
- }
- InstallableUnitDescription result = new MetadataFactory.InstallableUnitDescription();
- result.setId("additional-bundle-requirements-" + UUID.randomUUID());
- result.setVersion(Version.createOSGi(0, 0, 0, String.valueOf(System.currentTimeMillis())));
- result.addRequirements(additionalBundleRequirements);
- return List.of(MetadataFactory.createInstallableUnit(result));
- }
-
}
diff --git a/tycho-core/src/main/java/org/eclipse/tycho/osgi/framework/EclipseApplication.java b/tycho-core/src/main/java/org/eclipse/tycho/osgi/framework/EclipseApplication.java
index 236e66f6e0..6bca6000d9 100644
--- a/tycho-core/src/main/java/org/eclipse/tycho/osgi/framework/EclipseApplication.java
+++ b/tycho-core/src/main/java/org/eclipse/tycho/osgi/framework/EclipseApplication.java
@@ -12,6 +12,7 @@
*******************************************************************************/
package org.eclipse.tycho.osgi.framework;
+import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
@@ -27,6 +28,7 @@
import java.util.Set;
import java.util.function.Predicate;
+import org.apache.maven.project.MavenProject;
import org.codehaus.plexus.logging.Logger;
import org.eclipse.equinox.p2.metadata.IInstallableUnit;
import org.eclipse.equinox.p2.metadata.IRequirement;
@@ -61,8 +63,8 @@ public class EclipseApplication {
public static final String ARG_APPLICATION = "-application";
- private static final Set ALWAYS_START_BUNDLES = Set.of(Bundles.BUNDLE_CORE,
- Bundles.BUNDLE_SCR, Bundles.BUNDLE_APP);
+ private static final Set ALWAYS_START_BUNDLES = Set.of(Bundles.BUNDLE_CORE, Bundles.BUNDLE_SCR,
+ Bundles.BUNDLE_APP);
private P2Resolver resolver;
private TargetPlatform targetPlatform;
private Logger logger;
@@ -72,12 +74,15 @@ public class EclipseApplication {
private Map frameworkProperties = new LinkedHashMap<>();
private Predicate loggingFilter = always -> true;
private Set startBundles = new HashSet<>(ALWAYS_START_BUNDLES);
+ private Map baseDirMap;
- EclipseApplication(String name, P2Resolver resolver, TargetPlatform targetPlatform, Logger logger) {
+ EclipseApplication(String name, P2Resolver resolver, TargetPlatform targetPlatform, Logger logger,
+ Map baseDirMap) {
this.name = name;
this.resolver = resolver;
this.targetPlatform = targetPlatform;
this.logger = logger;
+ this.baseDirMap = baseDirMap;
}
public synchronized Collection getApplicationBundles() {
@@ -100,7 +105,18 @@ private List resolveBundles(P2Resolver resolver) {
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());
+ File location = entry.getLocation(true);
+ Path path = location.toPath();
+ if (location.isDirectory()) {
+ MavenProject mavenProject = baseDirMap.get(location);
+ if (mavenProject != null) {
+ File artifactFile = mavenProject.getArtifact().getFile();
+ if (artifactFile != null && artifactFile.exists()) {
+ path = artifactFile.toPath();
+ }
+ }
+ }
+ resolvedBundles.add(path);
}
}
}
@@ -187,10 +203,14 @@ public EclipseFramework startFramework(EclipseWorkspace workspace, List
+ 4.0.0
+
+ org.eclipse.tycho
+ tycho
+ 5.0.0-SNAPSHOT
+
+ tycho-eclipse-plugin
+ Tycho Eclipse Plugin
+ maven-plugin
+
+ ${minimal-maven-version}
+
+ Maven Plugins for working with Eclipse
+
+
+ org.apache.maven
+ maven-core
+
+
+ org.apache.maven
+ maven-plugin-api
+
+
+ org.apache.maven.plugin-tools
+ maven-plugin-annotations
+
+
+ org.codehaus.plexus
+ plexus-utils
+
+
+ org.eclipse.tycho
+ tycho-core
+ ${project.version}
+
+
+ org.eclipse.pde
+ org.eclipse.pde.core
+ 3.17.100
+ jar
+
+
+ *
+ *
+
+
+
+
+ org.eclipse.tycho
+ sisu-equinox-launching
+ ${project.version}
+
+
+ org.eclipse.tycho
+ tycho-testing-harness
+ test
+
+
+ org.mockito
+ mockito-core
+ test
+
+
+ org.apache.maven
+ maven-compat
+ test
+
+
+
+
+
+ org.codehaus.plexus
+ plexus-component-metadata
+
+
+
+
\ No newline at end of file
diff --git a/tycho-eclipse-plugin/src/main/java/org/eclipse/tycho/eclipsebuild/BundleListTargetLocation.java b/tycho-eclipse-plugin/src/main/java/org/eclipse/tycho/eclipsebuild/BundleListTargetLocation.java
new file mode 100644
index 0000000000..cdb3c4735c
--- /dev/null
+++ b/tycho-eclipse-plugin/src/main/java/org/eclipse/tycho/eclipsebuild/BundleListTargetLocation.java
@@ -0,0 +1,83 @@
+/*******************************************************************************
+ * Copyright (c) 2019 Red Hat Inc. 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:
+ * - Mickael Istria (Red Hat Inc.)
+ *******************************************************************************/
+package org.eclipse.tycho.eclipsebuild;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.pde.core.target.ITargetDefinition;
+import org.eclipse.pde.core.target.ITargetLocation;
+import org.eclipse.pde.core.target.TargetBundle;
+import org.eclipse.pde.core.target.TargetFeature;
+
+class BundleListTargetLocation implements ITargetLocation {
+
+ private TargetBundle[] bundles;
+
+ public BundleListTargetLocation(TargetBundle[] bundles) {
+ this.bundles = bundles;
+ }
+
+ @Override
+ public T getAdapter(Class adapter) {
+ return null;
+ }
+
+ @Override
+ public IStatus resolve(ITargetDefinition definition, IProgressMonitor monitor) {
+ return Status.OK_STATUS;
+ }
+
+ @Override
+ public boolean isResolved() {
+ return true;
+ }
+
+ @Override
+ public IStatus getStatus() {
+ return Status.OK_STATUS;
+ }
+
+ @Override
+ public String getType() {
+ return "BundleList"; //$NON-NLS-1$
+ }
+
+ @Override
+ public String getLocation(boolean resolve) throws CoreException {
+ return null;
+ }
+
+ @Override
+ public TargetBundle[] getBundles() {
+ return this.bundles;
+ }
+
+ @Override
+ public TargetFeature[] getFeatures() {
+ return null;
+ }
+
+ @Override
+ public String[] getVMArguments() {
+ return null;
+ }
+
+ @Override
+ public String serialize() {
+ return null;
+ }
+
+}
diff --git a/tycho-eclipse-plugin/src/main/java/org/eclipse/tycho/eclipsebuild/EclipseBuild.java b/tycho-eclipse-plugin/src/main/java/org/eclipse/tycho/eclipsebuild/EclipseBuild.java
new file mode 100644
index 0000000000..58a210cf56
--- /dev/null
+++ b/tycho-eclipse-plugin/src/main/java/org/eclipse/tycho/eclipsebuild/EclipseBuild.java
@@ -0,0 +1,142 @@
+/*******************************************************************************
+ * 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.io.IOException;
+import java.io.Serializable;
+import java.nio.file.Path;
+import java.util.concurrent.Callable;
+
+import org.eclipse.core.resources.IMarker;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IProjectDescription;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IWorkspace;
+import org.eclipse.core.resources.IWorkspaceDescription;
+import org.eclipse.core.resources.IncrementalProjectBuilder;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.core.runtime.Platform;
+
+public class EclipseBuild implements Callable, Serializable {
+
+ private boolean debug;
+ private String baseDir;
+
+ EclipseBuild(Path projectDir, boolean debug) {
+ this.debug = debug;
+ this.baseDir = pathAsString(projectDir);
+ }
+
+ @Override
+ public EclipseBuildResult call() throws Exception {
+ EclipseBuildResult result = new EclipseBuildResult();
+ Platform.addLogListener((status, plugin) -> debug(status.toString()));
+ disableAutoBuild();
+ deleteAllProjects();
+ IProject project = importProject();
+ IProgressMonitor debugMonitor = new IProgressMonitor() {
+
+ @Override
+ public void worked(int work) {
+
+ }
+
+ @Override
+ public void subTask(String name) {
+ debug("SubTask: " + name);
+ }
+
+ @Override
+ public void setTaskName(String name) {
+ debug("Task: " + name);
+ }
+
+ @Override
+ public void setCanceled(boolean value) {
+
+ }
+
+ @Override
+ public boolean isCanceled() {
+ return false;
+ }
+
+ @Override
+ public void internalWorked(double work) {
+
+ }
+
+ @Override
+ public void done() {
+
+ }
+
+ @Override
+ public void beginTask(String name, int totalWork) {
+ setTaskName(name);
+ }
+ };
+ project.build(IncrementalProjectBuilder.CLEAN_BUILD, debugMonitor);
+ project.build(IncrementalProjectBuilder.FULL_BUILD, debugMonitor);
+ for (IMarker marker : project.findMarkers(IMarker.PROBLEM, true, IResource.DEPTH_INFINITE)) {
+ result.addMarker(marker);
+ debug(marker.toString());
+ }
+ ResourcesPlugin.getWorkspace().save(true, new NullProgressMonitor());
+ return result;
+ }
+
+ static void disableAutoBuild() throws CoreException {
+ IWorkspace workspace = ResourcesPlugin.getWorkspace();
+ IWorkspaceDescription desc = workspace.getDescription();
+ desc.setAutoBuilding(false);
+ workspace.setDescription(desc);
+ }
+
+ private void deleteAllProjects() throws CoreException {
+ for (IProject project : ResourcesPlugin.getWorkspace().getRoot().getProjects()) {
+ project.delete(IResource.NEVER_DELETE_PROJECT_CONTENT | IResource.FORCE, new NullProgressMonitor());
+ }
+ }
+
+ private IProject importProject() throws CoreException, IOException {
+ IPath projectPath = IPath.fromOSString(baseDir);
+ IPath projectDescriptionFile = projectPath.append(IProjectDescription.DESCRIPTION_FILE_NAME);
+ IProjectDescription projectDescription = ResourcesPlugin.getWorkspace()
+ .loadProjectDescription(projectDescriptionFile);
+ projectDescription.setLocation(projectPath);
+// projectDescription.setBuildSpec(new ICommand[0]);
+ IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject(projectDescription.getName());
+ project.create(projectDescription, new NullProgressMonitor());
+ project.open(new NullProgressMonitor());
+ return project;
+ }
+
+ private void debug(String string) {
+ if (debug) {
+ System.out.println(string);
+ }
+ }
+
+ static String pathAsString(Path path) {
+ if (path != null) {
+ return path.toAbsolutePath().toString();
+ }
+ return null;
+ }
+
+}
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
new file mode 100644
index 0000000000..f904e5aeec
--- /dev/null
+++ b/tycho-eclipse-plugin/src/main/java/org/eclipse/tycho/eclipsebuild/EclipseBuildInstallableUnitProvider.java
@@ -0,0 +1,55 @@
+/*******************************************************************************
+ * 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.Collection;
+import java.util.List;
+import java.util.Optional;
+
+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.core.runtime.CoreException;
+import org.eclipse.equinox.p2.metadata.IInstallableUnit;
+import org.eclipse.equinox.p2.metadata.MetadataFactory;
+import org.eclipse.equinox.p2.metadata.VersionRange;
+import org.eclipse.equinox.p2.publisher.eclipse.BundlesAction;
+import org.eclipse.tycho.helper.PluginConfigurationHelper;
+import org.eclipse.tycho.helper.PluginConfigurationHelper.Configuration;
+import org.eclipse.tycho.resolver.InstallableUnitProvider;
+
+@Component(role = InstallableUnitProvider.class, hint = "eclipse-build")
+public class EclipseBuildInstallableUnitProvider implements InstallableUnitProvider {
+
+ @Requirement
+ PluginConfigurationHelper configurationHelper;
+
+ @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);
+ if (local.isPresent() && local.get()) {
+ // for local target resolution the bundles become requirements...
+ Optional> list = configuration.getStringList("bundles");
+ return InstallableUnitProvider.createIU(list.stream().flatMap(Collection::stream)
+ .map(bundleName -> MetadataFactory.createRequirement(BundlesAction.CAPABILITY_NS_OSGI_BUNDLE,
+ bundleName,
+ VersionRange.emptyRange, null, false, true)),
+ "eclipse-build-bundles");
+ }
+ return List.of();
+ }
+
+}
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
new file mode 100644
index 0000000000..fa90c29f4c
--- /dev/null
+++ b/tycho-eclipse-plugin/src/main/java/org/eclipse/tycho/eclipsebuild/EclipseBuildMojo.java
@@ -0,0 +1,189 @@
+/*******************************************************************************
+ * 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.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
+ private List bundles;
+
+ @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(Set.of());
+ 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));
+ result.markers().filter(marker -> marker.getAttribute(IMarker.SEVERITY, -1) == IMarker.SEVERITY_INFO)
+ .forEach(info -> printMarker(info, result, getLog()::info));
+ result.markers().filter(marker -> marker.getAttribute(IMarker.SEVERITY, -1) == IMarker.SEVERITY_WARNING)
+ .forEach(warn -> printMarker(warn, result, getLog()::warn));
+ List errors = result.markers()
+ .filter(marker -> marker.getAttribute(IMarker.SEVERITY, -1) == IMarker.SEVERITY_ERROR).toList();
+ errors.forEach(error -> printMarker(error, result, getLog()::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 getBundles() {
+ HashSet 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/EclipseBuildResult.java b/tycho-eclipse-plugin/src/main/java/org/eclipse/tycho/eclipsebuild/EclipseBuildResult.java
new file mode 100644
index 0000000000..3ec70742d8
--- /dev/null
+++ b/tycho-eclipse-plugin/src/main/java/org/eclipse/tycho/eclipsebuild/EclipseBuildResult.java
@@ -0,0 +1,47 @@
+/*******************************************************************************
+ * 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.io.Serializable;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Stream;
+
+import org.eclipse.core.resources.IMarker;
+import org.eclipse.core.resources.IResource;
+
+public class EclipseBuildResult implements Serializable {
+
+ private List markers = new ArrayList();
+ private Map resourceMap = new HashMap();
+
+ public void addMarker(IMarker marker) {
+
+ MarkerDTO wrapper = new MarkerDTO(marker);
+ markers.add(wrapper);
+ IResource resource = marker.getResource();
+ if (resource != null) {
+ resourceMap.put(wrapper, resource.getProjectRelativePath().toString());
+ }
+ }
+
+ public Stream markers() {
+ return markers.stream();
+ }
+
+ public String getMarkerPath(IMarker marker) {
+ return resourceMap.get(marker);
+ }
+}
diff --git a/tycho-eclipse-plugin/src/main/java/org/eclipse/tycho/eclipsebuild/MarkerDTO.java b/tycho-eclipse-plugin/src/main/java/org/eclipse/tycho/eclipsebuild/MarkerDTO.java
new file mode 100644
index 0000000000..411b86f83e
--- /dev/null
+++ b/tycho-eclipse-plugin/src/main/java/org/eclipse/tycho/eclipsebuild/MarkerDTO.java
@@ -0,0 +1,174 @@
+/*******************************************************************************
+ * 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.io.Serializable;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.eclipse.core.resources.IMarker;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.Status;
+
+class MarkerDTO implements IMarker, Serializable {
+
+ private long id;
+ private long creationTime;
+ private String type;
+ private String string;
+ private HashMap attributes;
+ private boolean exits;
+
+ MarkerDTO(IMarker marker) {
+ id = marker.getId();
+ string = marker.toString();
+ attributes = new HashMap();
+ exits = marker.exists();
+ try {
+ creationTime = marker.getCreationTime();
+ } catch (CoreException e) {
+ }
+ try {
+ type = marker.getType();
+ } catch (CoreException e) {
+ }
+ try {
+ Map map = marker.getAttributes();
+ if (map != null) {
+ map.forEach((k, v) -> {
+ if (v == null) {
+ return;
+ }
+ attributes.put(k, v.toString());
+ });
+ }
+ } catch (CoreException e) {
+ }
+ }
+
+ @Override
+ public Object getAttribute(String attributeName) throws CoreException {
+ return getAttribute(attributeName, null);
+ }
+
+ @Override
+ public int getAttribute(String attributeName, int defaultValue) {
+ try {
+ return Integer.parseInt(getAttribute(attributeName, String.valueOf(defaultValue)));
+ } catch (NumberFormatException e) {
+ return defaultValue;
+ }
+ }
+
+ @Override
+ public String getAttribute(String attributeName, String defaultValue) {
+ return (String) attributes.getOrDefault(attributeName, defaultValue);
+ }
+
+ @Override
+ public boolean getAttribute(String attributeName, boolean defaultValue) {
+ return Boolean.parseBoolean(getAttribute(attributeName, String.valueOf(defaultValue)));
+ }
+
+ @Override
+ public Map getAttributes() throws CoreException {
+ checkExsits();
+ return attributes;
+ }
+
+ @Override
+ public Object[] getAttributes(String[] attributeNames) throws CoreException {
+ throw new CoreException(Status.error("Not implemented"));
+ }
+
+ @Override
+ public long getCreationTime() throws CoreException {
+ checkExsits();
+ return creationTime;
+ }
+
+ @Override
+ public long getId() {
+ return id;
+ }
+
+ @Override
+ public String getType() throws CoreException {
+ checkExsits();
+ return type;
+ }
+
+ @Override
+ public IResource getResource() {
+ return null;
+ }
+
+ @Override
+ public T getAdapter(Class adapter) {
+ return null;
+ }
+
+ @Override
+ public void delete() throws CoreException {
+ throw new CoreException(Status.error("Not implemented"));
+ }
+
+ @Override
+ public boolean exists() {
+ return exits;
+ }
+
+ @Override
+ public boolean isSubtypeOf(String superType) throws CoreException {
+ throw new CoreException(Status.error("Not implemented"));
+ }
+
+ @Override
+ public void setAttribute(String attributeName, int value) throws CoreException {
+ throw new CoreException(Status.error("Not implemented"));
+
+ }
+
+ @Override
+ public void setAttribute(String attributeName, Object value) throws CoreException {
+ throw new CoreException(Status.error("Not implemented"));
+ }
+
+ @Override
+ public void setAttribute(String attributeName, boolean value) throws CoreException {
+ throw new CoreException(Status.error("Not implemented"));
+ }
+
+ @Override
+ public void setAttributes(String[] attributeNames, Object[] values) throws CoreException {
+ throw new CoreException(Status.error("Not implemented"));
+ }
+
+ @Override
+ public void setAttributes(Map attributes) throws CoreException {
+ throw new CoreException(Status.error("Not implemented"));
+ }
+
+ private void checkExsits() throws CoreException {
+ if (!exits) {
+ throw new CoreException(Status.error("DO not exits"));
+ }
+
+ }
+
+ @Override
+ public String toString() {
+ return string;
+ }
+}
diff --git a/tycho-eclipse-plugin/src/main/java/org/eclipse/tycho/eclipsebuild/SetTargetPlatform.java b/tycho-eclipse-plugin/src/main/java/org/eclipse/tycho/eclipsebuild/SetTargetPlatform.java
new file mode 100644
index 0000000000..616326345a
--- /dev/null
+++ b/tycho-eclipse-plugin/src/main/java/org/eclipse/tycho/eclipsebuild/SetTargetPlatform.java
@@ -0,0 +1,76 @@
+/*******************************************************************************
+ * 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.io.File;
+import java.io.Serializable;
+import java.nio.file.Path;
+import java.util.Collection;
+import java.util.List;
+import java.util.Objects;
+import java.util.concurrent.Callable;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.ILogListener;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.pde.core.target.ITargetDefinition;
+import org.eclipse.pde.core.target.ITargetLocation;
+import org.eclipse.pde.core.target.ITargetPlatformService;
+import org.eclipse.pde.core.target.LoadTargetDefinitionJob;
+import org.eclipse.pde.core.target.TargetBundle;
+import org.eclipse.pde.internal.core.target.TargetPlatformService;
+
+public class SetTargetPlatform implements Callable, Serializable {
+
+ private boolean debug;
+ private List targetBundles;
+
+ SetTargetPlatform(Collection dependencyBundles, boolean debug) {
+ this.debug = debug;
+ this.targetBundles = dependencyBundles.stream().map(EclipseBuild::pathAsString).toList();
+ }
+
+ @Override
+ public Serializable call() throws Exception {
+ ILogListener listener = (status, plugin) -> debug(status.toString());
+ Platform.addLogListener(listener);
+ EclipseBuild.disableAutoBuild();
+ ITargetPlatformService service = TargetPlatformService.getDefault();
+ ITargetDefinition target = service.newTarget();
+ target.setName("buildpath");
+ debug("== Target Platform Bundles ==");
+ TargetBundle[] bundles = targetBundles.stream().peek(this::debug).map(absoluteFile -> {
+ try {
+ return new TargetBundle(new File(absoluteFile));
+ } catch (CoreException e) {
+ debug(e.toString());
+ return null;
+ }
+ }).filter(Objects::nonNull)//
+ .toArray(TargetBundle[]::new);
+ target.setTargetLocations(new ITargetLocation[] { new BundleListTargetLocation(bundles) });
+ service.saveTargetDefinition(target);
+ Job job = new LoadTargetDefinitionJob(target);
+ job.schedule();
+ job.join();
+ return null;
+ }
+
+ private void debug(String string) {
+ if (debug) {
+ System.out.println(string);
+ }
+ }
+
+}
diff --git a/tycho-extras/tycho-eclipserun-plugin/src/main/java/org/eclipse/tycho/extras/eclipserun/EclipseRunMojo.java b/tycho-eclipse-plugin/src/main/java/org/eclipse/tycho/eclipserun/EclipseRunMojo.java
similarity index 98%
rename from tycho-extras/tycho-eclipserun-plugin/src/main/java/org/eclipse/tycho/extras/eclipserun/EclipseRunMojo.java
rename to tycho-eclipse-plugin/src/main/java/org/eclipse/tycho/eclipserun/EclipseRunMojo.java
index ac3d619b63..323a857298 100644
--- a/tycho-extras/tycho-eclipserun-plugin/src/main/java/org/eclipse/tycho/extras/eclipserun/EclipseRunMojo.java
+++ b/tycho-eclipse-plugin/src/main/java/org/eclipse/tycho/eclipserun/EclipseRunMojo.java
@@ -11,7 +11,7 @@
* Sonatype Inc. - initial API and implementation
* Marc-Andre Laperle - EclipseRunMojo inspired by TestMojo
*******************************************************************************/
-package org.eclipse.tycho.extras.eclipserun;
+package org.eclipse.tycho.eclipserun;
import java.io.File;
import java.util.ArrayList;
@@ -57,7 +57,6 @@
import org.eclipse.tycho.core.resolver.P2Resolver;
import org.eclipse.tycho.core.resolver.P2ResolverFactory;
import org.eclipse.tycho.p2.target.facade.TargetPlatformConfigurationStub;
-import org.eclipse.tycho.plugins.p2.extras.Repository;
/**
* Launch an eclipse process with arbitrary commandline arguments. The eclipse
@@ -371,7 +370,7 @@ private EquinoxInstallation createEclipseInstallation() throws MojoFailureExcept
return installationFactory.createInstallation(installationDesc, work);
}
- void runEclipse(EquinoxInstallation runtime) throws MojoExecutionException {
+ public void runEclipse(EquinoxInstallation runtime) throws MojoExecutionException {
try {
File workspace = new File(work, "data").getAbsoluteFile();
synchronized (WORKSPACE_LOCKS.computeIfAbsent(workspace.getAbsolutePath(), k -> new Object())) {
@@ -392,7 +391,7 @@ void runEclipse(EquinoxInstallation runtime) throws MojoExecutionException {
}
}
- LaunchConfiguration createCommandLine(EquinoxInstallation runtime) throws MojoExecutionException {
+ public LaunchConfiguration createCommandLine(EquinoxInstallation runtime) throws MojoExecutionException {
EquinoxLaunchConfiguration cli = new EquinoxLaunchConfiguration(runtime);
String executable = null;
diff --git a/tycho-eclipse-plugin/src/main/java/org/eclipse/tycho/eclipserun/Repository.java b/tycho-eclipse-plugin/src/main/java/org/eclipse/tycho/eclipserun/Repository.java
new file mode 100644
index 0000000000..b7f6579ae8
--- /dev/null
+++ b/tycho-eclipse-plugin/src/main/java/org/eclipse/tycho/eclipserun/Repository.java
@@ -0,0 +1,96 @@
+/*******************************************************************************
+ * Copyright (c) 2011 SAP AG 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:
+ * Tobias Oberlies - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.tycho.eclipserun;
+
+import java.net.URI;
+import java.util.Arrays;
+import java.util.stream.Collectors;
+
+public final class Repository {
+
+ public enum Layout {
+ BOTH("p2"), METADATA("p2-metadata"), ARTIFACTS("p2-artifacts");
+
+ private String literal;
+
+ private Layout(String literal) {
+ this.literal = literal;
+ }
+
+ boolean matches(String value) {
+ return literal.equals(value);
+ }
+
+ public boolean hasMetadata() {
+ return this != ARTIFACTS;
+ }
+
+ public boolean hasArtifacts() {
+ return this != METADATA;
+ }
+
+ @Override
+ public String toString() {
+ return literal;
+ }
+ }
+
+ private String id;
+
+ private URI url;
+
+ private Layout layout = Layout.BOTH;
+
+ public Repository() {
+ }
+
+ public Repository(URI location) {
+ this.url = location;
+ }
+
+ /**
+ * @return never null
+ */
+ public URI getLocation() {
+ if (url == null)
+ throw new IllegalStateException("Attribute 'url' is required for source repositories");
+ return url;
+ }
+
+ /**
+ * @return never null
+ */
+ public Layout getLayout() {
+ return layout;
+ }
+
+ /**
+ * @return may be null
+ */
+ public String getId() {
+ return id;
+ }
+
+ public void setLayout(String value) {
+ for (Layout layout : Layout.values()) {
+ if (layout.matches(value)) {
+ this.layout = layout;
+ return;
+ }
+ }
+ String values = Arrays.stream(Layout.values()).map(Object::toString).collect(Collectors.joining(", "));
+ throw new IllegalArgumentException(
+ "Unrecognized value for attribute 'layout': \"" + value + "\". Valid values are: " + values);
+ }
+
+}
diff --git a/tycho-extras/tycho-eclipserun-plugin/src/main/resources/META-INF/m2e/lifecycle-mapping-metadata.xml b/tycho-eclipse-plugin/src/main/resources/META-INF/m2e/lifecycle-mapping-metadata.xml
similarity index 100%
rename from tycho-extras/tycho-eclipserun-plugin/src/main/resources/META-INF/m2e/lifecycle-mapping-metadata.xml
rename to tycho-eclipse-plugin/src/main/resources/META-INF/m2e/lifecycle-mapping-metadata.xml
diff --git a/tycho-extras/tycho-eclipserun-plugin/src/test/java/org/eclipse/tycho/extras/eclipserun/EclipseRunMojoTest.java b/tycho-eclipse-plugin/src/test/java/org/eclipse/tycho/extras/eclipserun/EclipseRunMojoTest.java
similarity index 98%
rename from tycho-extras/tycho-eclipserun-plugin/src/test/java/org/eclipse/tycho/extras/eclipserun/EclipseRunMojoTest.java
rename to tycho-eclipse-plugin/src/test/java/org/eclipse/tycho/extras/eclipserun/EclipseRunMojoTest.java
index 76b8f0fca1..8460d243a1 100644
--- a/tycho-extras/tycho-eclipserun-plugin/src/test/java/org/eclipse/tycho/extras/eclipserun/EclipseRunMojoTest.java
+++ b/tycho-eclipse-plugin/src/test/java/org/eclipse/tycho/extras/eclipserun/EclipseRunMojoTest.java
@@ -36,6 +36,7 @@
import org.eclipse.tycho.core.maven.ToolchainProvider;
import org.eclipse.tycho.core.resolver.P2Resolver;
import org.eclipse.tycho.core.resolver.P2ResolverFactory;
+import org.eclipse.tycho.eclipserun.EclipseRunMojo;
import org.eclipse.tycho.p2.target.facade.TargetPlatformFactory;
import org.eclipse.tycho.testing.AbstractTychoMojoTestCase;
import org.eclipse.tycho.version.TychoVersion;
@@ -53,7 +54,7 @@ public class EclipseRunMojoTest extends AbstractTychoMojoTestCase {
public void setUp() throws Exception {
super.setUp();
- runMojo = (EclipseRunMojo) lookupMojo("org.eclipse.tycho.extras", "tycho-eclipserun-plugin",
+ runMojo = (EclipseRunMojo) lookupMojo("org.eclipse.tycho", "tycho-eclipse-plugin",
TychoVersion.getTychoVersion(), "eclipse-run", null);
runMojo.setLog(new SilentLog());
MavenSession mavenSession = newMavenSession(mock(MavenProject.class));
diff --git a/tycho-extras/tycho-eclipserun-plugin/pom.xml b/tycho-extras/tycho-eclipserun-plugin/pom.xml
index dfa7727018..c7a33be4a2 100644
--- a/tycho-extras/tycho-eclipserun-plugin/pom.xml
+++ b/tycho-extras/tycho-eclipserun-plugin/pom.xml
@@ -23,6 +23,13 @@
${minimal-maven-version}
+
+
+ org.eclipse.tycho
+ tycho-eclipse-plugin
+ The eclipse-run mojo is now part of the tycho-eclipse-plugin
+
+
Tycho Eclipserun Plugin
@@ -57,15 +64,10 @@
org.eclipse.tycho
- tycho-testing-harness
- test
-
-
- org.mockito
- mockito-core
- test
+ tycho-eclipse-plugin
+ ${project.version}
-
+
its
diff --git a/tycho-spi/src/main/java/org/eclipse/tycho/helper/PluginConfigurationHelper.java b/tycho-spi/src/main/java/org/eclipse/tycho/helper/PluginConfigurationHelper.java
index e8dce66a84..1ffeafa52d 100644
--- a/tycho-spi/src/main/java/org/eclipse/tycho/helper/PluginConfigurationHelper.java
+++ b/tycho-spi/src/main/java/org/eclipse/tycho/helper/PluginConfigurationHelper.java
@@ -15,6 +15,8 @@
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.URL;
+import java.util.Arrays;
+import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
@@ -129,11 +131,7 @@ public Optional getChild(String name) {
public Optional getString(String name) {
return getChild(name).map(child -> {
- String value = child.configuration.getValue();
- if (value == null) {
- return child.configuration.getAttribute("default-value");
- }
- return value;
+ return getValue(child.configuration);
});
}
@@ -158,6 +156,22 @@ public String toString() {
return configuration == null ? "-empty configuration-" : String.valueOf(configuration);
}
+ public Optional> getStringList(String name) {
+ return getChild(name).map(child -> {
+ return Arrays.stream(child.configuration.getChildren()).map(PluginConfigurationHelper::getValue)
+ .toList();
+ });
+
+ }
+
+ }
+
+ private static String getValue(Xpp3Dom dom) {
+ String value = dom.getValue();
+ if (value == null) {
+ return dom.getAttribute("default-value");
+ }
+ return value;
}
}
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 4813bde1b2..936f4a2906 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
@@ -1,26 +1,49 @@
package org.eclipse.tycho.resolver;
import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.UUID;
+import java.util.stream.Stream;
import org.apache.maven.execution.MavenSession;
import org.apache.maven.project.MavenProject;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.equinox.p2.metadata.IInstallableUnit;
+import org.eclipse.equinox.p2.metadata.IRequirement;
+import org.eclipse.equinox.p2.metadata.MetadataFactory;
+import org.eclipse.equinox.p2.metadata.MetadataFactory.InstallableUnitDescription;
+import org.eclipse.equinox.p2.metadata.Version;
/**
- * Components implementing this interface can provide additional project units,
- * for example source features/bundles.
+ * Components implementing this interface can provide additional project units, for example source
+ * features/bundles.
*/
public interface InstallableUnitProvider {
- /**
- * Computes the {@link IInstallableUnit}s for the given maven project
- *
- * @param project
- * @param session
- * @return the collection of units, probably empty but never null
- * @throws CoreException if anything goes wrong
- */
- Collection getInstallableUnits(MavenProject project, MavenSession session) throws CoreException;
+ /**
+ * Computes the {@link IInstallableUnit}s for the given maven project
+ *
+ * @param project
+ * @param session
+ * @return the collection of units, probably empty but never null
+ * @throws CoreException
+ * if anything goes wrong
+ */
+ Collection getInstallableUnits(MavenProject project, MavenSession session) throws CoreException;
+ static Collection createIU(Stream requirements, String idPrefix) {
+ return createIU(requirements.toList(), idPrefix);
+ }
+
+ static Collection createIU(List requirements, String idPrefix) {
+ if (requirements.isEmpty()) {
+ return Collections.emptyList();
+ }
+ InstallableUnitDescription result = new MetadataFactory.InstallableUnitDescription();
+ result.setId(idPrefix + "-" + UUID.randomUUID());
+ result.setVersion(Version.createOSGi(0, 0, 0, String.valueOf(System.currentTimeMillis())));
+ result.addRequirements(requirements);
+ return List.of(MetadataFactory.createInstallableUnit(result));
+ }
}