diff --git a/demo/osgi-repository/repository/pom.xml b/demo/osgi-repository/repository/pom.xml
index 9e8154b58a..34b014d41b 100644
--- a/demo/osgi-repository/repository/pom.xml
+++ b/demo/osgi-repository/repository/pom.xml
@@ -17,10 +17,24 @@
${tycho-version}
true
-
-
- maven
-
+
+
+
+
+
+ local
+ package
+
+ package-repository
+
+
+ local
+
+ deploy
+
+
+
+
diff --git a/tycho-repository-plugin/pom.xml b/tycho-repository-plugin/pom.xml
index 5f41df677a..d740ca38cc 100644
--- a/tycho-repository-plugin/pom.xml
+++ b/tycho-repository-plugin/pom.xml
@@ -57,6 +57,11 @@
org.codehaus.plexus
plexus-archiver
+
+ org.eclipse.tycho
+ tycho-spi
+ ${project.version}
+
diff --git a/tycho-repository-plugin/src/main/java/org/eclipse/tycho/repository/plugin/OSGiRepositoryGenerator.java b/tycho-repository-plugin/src/main/java/org/eclipse/tycho/repository/plugin/OSGiRepositoryGenerator.java
new file mode 100644
index 0000000000..557403dc90
--- /dev/null
+++ b/tycho-repository-plugin/src/main/java/org/eclipse/tycho/repository/plugin/OSGiRepositoryGenerator.java
@@ -0,0 +1,99 @@
+/*******************************************************************************
+ * 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.repository.plugin;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.URI;
+import java.util.List;
+
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.io.FilenameUtils;
+import org.apache.maven.plugin.MojoExecutionException;
+import org.apache.maven.plugin.MojoFailureException;
+import org.apache.maven.plugin.logging.Log;
+import org.apache.maven.project.MavenProject;
+import org.codehaus.plexus.component.annotations.Component;
+import org.codehaus.plexus.configuration.PlexusConfiguration;
+import org.eclipse.tycho.MavenArtifactNamespace;
+import org.eclipse.tycho.packaging.RepositoryGenerator;
+
+import aQute.bnd.osgi.repository.XMLResourceGenerator;
+import aQute.bnd.osgi.resource.CapReqBuilder;
+import aQute.bnd.osgi.resource.ResourceBuilder;
+
+@Component(role = RepositoryGenerator.class, hint = OSGiRepositoryGenerator.HINT)
+public class OSGiRepositoryGenerator implements RepositoryGenerator {
+
+ static final String HINT = "osgi";
+
+ @Override
+ public File createRepository(List projects, RepositoryConfiguration repoConfig)
+ throws IOException, MojoExecutionException, MojoFailureException {
+ XMLResourceGenerator resourceGenerator = new XMLResourceGenerator();
+ resourceGenerator.name(repoConfig.getRepositoryName());
+ File folder;
+ PlexusConfiguration generatorConfig = repoConfig.getConfiguration();
+ String repositoryFileName = generatorConfig.getChild("repositoryFileName")
+ .getValue("repository.xml");
+ if (repoConfig.getLayout() == RepositoryLayout.local) {
+ String folderName = generatorConfig.getChild("repositoryFolderName")
+ .getValue(FilenameUtils.getBaseName(repositoryFileName));
+ folder = new File(repoConfig.getDestination(), folderName);
+ folder.mkdirs();
+ resourceGenerator.base(folder.toURI());
+ } else {
+ folder = null;
+ }
+ Log log = repoConfig.getLog();
+ for (MavenProject project : projects) {
+ ResourceBuilder rb = new ResourceBuilder();
+ try {
+ URI uri;
+ File file = project.getArtifact().getFile();
+ if (folder == null) {
+ uri = new URI(
+ "mvn:" + project.getGroupId() + ":" + project.getArtifactId() + ":" + project.getVersion());
+ } else {
+ uri = new File(folder, file.getName()).toURI();
+ }
+ if (rb.addFile(project.getArtifact().getFile(), uri)) {
+ CapReqBuilder identity = new CapReqBuilder(MavenArtifactNamespace.MAVEN_ARTIFACT_NAMESPACE)
+ .addAttribute(MavenArtifactNamespace.CAPABILITY_GROUP_ATTRIBUTE, project.getGroupId())
+ .addAttribute(MavenArtifactNamespace.MAVEN_ARTIFACT_NAMESPACE, project.getArtifactId())
+ .addAttribute(MavenArtifactNamespace.CAPABILITY_VERSION_ATTRIBUTE, project.getVersion());
+ rb.addCapability(identity);
+ resourceGenerator.resource(rb.build());
+ log.info("Adding " + project.getId());
+ if (folder != null) {
+ FileUtils.copyFileToDirectory(file, folder);
+ }
+ } else {
+ log.info("Skip " + project.getId() + ": Not a bundle");
+ }
+ } catch (Exception e) {
+ log.warn("Ignoring " + project.getId() + ": " + e, log.isDebugEnabled() ? e : null);
+ }
+ }
+ if (folder != null) {
+ File location = new File(folder, repositoryFileName);
+ resourceGenerator.save(location);
+ return folder;
+ } else {
+ File location = new File(repoConfig.getDestination(), repositoryFileName);
+ resourceGenerator.save(location);
+ return location;
+ }
+ }
+
+}
diff --git a/tycho-repository-plugin/src/main/java/org/eclipse/tycho/repository/plugin/PackageRepositoryMojo.java b/tycho-repository-plugin/src/main/java/org/eclipse/tycho/repository/plugin/PackageRepositoryMojo.java
index 1865f6cc33..e80894f8ef 100644
--- a/tycho-repository-plugin/src/main/java/org/eclipse/tycho/repository/plugin/PackageRepositoryMojo.java
+++ b/tycho-repository-plugin/src/main/java/org/eclipse/tycho/repository/plugin/PackageRepositoryMojo.java
@@ -14,14 +14,16 @@
import java.io.File;
import java.io.IOException;
-import java.net.URI;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
-import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
import org.apache.maven.artifact.Artifact;
import org.apache.maven.artifact.handler.DefaultArtifactHandler;
import org.apache.maven.execution.MavenSession;
import org.apache.maven.plugin.AbstractMojo;
+import org.apache.maven.plugin.MojoExecution;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugin.logging.Log;
@@ -29,21 +31,27 @@
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.project.MavenProject;
+import org.apache.maven.project.MavenProjectHelper;
import org.codehaus.plexus.archiver.Archiver;
import org.codehaus.plexus.archiver.zip.ZipArchiver;
-import org.eclipse.tycho.ArtifactType;
-import org.eclipse.tycho.MavenArtifactNamespace;
-
-import aQute.bnd.osgi.repository.XMLResourceGenerator;
-import aQute.bnd.osgi.resource.CapReqBuilder;
-import aQute.bnd.osgi.resource.ResourceBuilder;
+import org.codehaus.plexus.configuration.PlexusConfiguration;
+import org.codehaus.plexus.configuration.xml.XmlPlexusConfiguration;
+import org.eclipse.tycho.packaging.RepositoryGenerator;
+import org.eclipse.tycho.packaging.RepositoryGenerator.RepositoryConfiguration;
+import org.eclipse.tycho.packaging.RepositoryGenerator.RepositoryLayout;
/**
* Generates an OSGi repository from the current reactor projects
*
*/
@Mojo(name = "package-repository")
-public class PackageRepositoryMojo extends AbstractMojo {
+public class PackageRepositoryMojo extends AbstractMojo implements RepositoryConfiguration {
+
+ private static final XmlPlexusConfiguration NO_SETTINGS = new XmlPlexusConfiguration("settings");
+
+ static final String DEFAULT_REPOSITORY_TYPE = OSGiRepositoryGenerator.HINT;
+
+ static final String PARAMETER_REPOSITORY_TYPE = "repositoryType";
@Parameter(property = "session", readonly = true)
protected MavenSession session;
@@ -56,13 +64,6 @@ public class PackageRepositoryMojo extends AbstractMojo {
@Parameter(defaultValue = "${project.name}")
private String repositoryName;
- /**
- * Specify the filename of the additionally generated OSGi Repository (if
- * enabled)
- */
- @Parameter(defaultValue = "repository.xml")
- private String repositoryFileName;
-
@Parameter(defaultValue = "${project.build.directory}")
private File destination;
@@ -82,82 +83,95 @@ public class PackageRepositoryMojo extends AbstractMojo {
@Parameter(defaultValue = "maven")
private RepositoryLayout repositoryLayout;
+ /**
+ * Configures the used repository type
+ */
+ @Parameter(defaultValue = DEFAULT_REPOSITORY_TYPE, name = PARAMETER_REPOSITORY_TYPE)
+ private String repositoryType;
+
+ @Parameter(property = "mojoExecution", readonly = true)
+ MojoExecution execution;
+
+ /**
+ * Configures the repository type specific settings.
+ */
+ @Parameter
+ private PlexusConfiguration settings;
+
@Component(role = Archiver.class, hint = "zip")
private ZipArchiver zipArchiver;
+ @Component(role = RepositoryGenerator.class)
+ private Map generators;
+
+ @Component
+ private MavenProjectHelper mavenProjectHelper;
+
@Override
public void execute() throws MojoExecutionException, MojoFailureException {
- XMLResourceGenerator resourceGenerator = new XMLResourceGenerator();
- resourceGenerator.name(repositoryName);
- File folder;
- if (repositoryLayout == RepositoryLayout.local) {
- folder = new File(destination, FilenameUtils.getBaseName(repositoryFileName));
- folder.mkdirs();
- resourceGenerator.base(folder.toURI());
- } else {
- folder = null;
- }
- for (MavenProject project : session.getProjects()) {
- if (isInteresting(project)) {
- ResourceBuilder rb = new ResourceBuilder();
- try {
- URI uri;
- File file = project.getArtifact().getFile();
- if (folder == null) {
- uri = new URI("mvn:" + project.getGroupId() + ":" + project.getArtifactId() + ":"
- + project.getVersion());
- } else {
- uri = new File(folder, file.getName()).toURI();
- }
- if (rb.addFile(project.getArtifact().getFile(), uri)) {
- CapReqBuilder identity = new CapReqBuilder(MavenArtifactNamespace.MAVEN_ARTIFACT_NAMESPACE)
- .addAttribute(MavenArtifactNamespace.CAPABILITY_GROUP_ATTRIBUTE, project.getGroupId())
- .addAttribute(MavenArtifactNamespace.MAVEN_ARTIFACT_NAMESPACE, project.getArtifactId())
- .addAttribute(MavenArtifactNamespace.CAPABILITY_VERSION_ATTRIBUTE,
- project.getVersion());
- rb.addCapability(identity);
- resourceGenerator.resource(rb.build());
- getLog().info("Adding " + project.getId());
- if (folder != null) {
- FileUtils.copyFileToDirectory(file, folder);
- }
- } else {
- getLog().info("Skip " + project.getId() + ": Not a bundle");
- }
- } catch (Exception e) {
- Log log = getLog();
- log.warn("Ignoring " + project.getId() + ": " + e, log.isDebugEnabled() ? e : null);
- }
- }
+ RepositoryGenerator generator = generators.get(repositoryType);
+ if (generator == null) {
+ throw new MojoFailureException(
+ "No repository implementation of type " + repositoryType + " found, available ones are "
+ + generators.keySet().stream().sorted().collect(Collectors.joining(", ")));
}
+ List projects = session.getProjects().stream().filter(generator::isInteresting).toList();
try {
- Artifact artifact = project.getArtifact();
- if (folder != null) {
- File location = new File(folder, repositoryFileName);
- resourceGenerator.save(location);
- File destFile = new File(destination, project.getArtifactId() + "-" + folder.getName() + ".zip");
- zipArchiver.addDirectory(folder);
+ File repository = generator.createRepository(projects, this);
+ String executionId = execution.getExecutionId();
+ if (repository.isDirectory()) {
+ File destFile = new File(destination, project.getArtifactId() + "-" + repository.getName() + ".zip");
+ zipArchiver.addDirectory(repository);
zipArchiver.setDestFile(destFile);
zipArchiver.createArchive();
- artifact.setFile(destFile);
- artifact.setArtifactHandler(new DefaultArtifactHandler("zip"));
+ if (executionId.startsWith("default-")) {
+ Artifact artifact = project.getArtifact();
+ artifact.setFile(destFile);
+ artifact.setArtifactHandler(new DefaultArtifactHandler("zip"));
+ } else {
+ mavenProjectHelper.attachArtifact(project, "zip", executionId, destFile);
+ }
} else {
- File location = new File(destination, repositoryFileName);
- resourceGenerator.save(location);
- artifact.setArtifactHandler(new DefaultArtifactHandler("xml"));
- artifact.setFile(location);
+ String extension = FilenameUtils.getExtension(repository.getName());
+ if (executionId.startsWith("default-")) {
+ Artifact artifact = project.getArtifact();
+ artifact.setArtifactHandler(new DefaultArtifactHandler(extension));
+ artifact.setFile(repository);
+ } else {
+ mavenProjectHelper.attachArtifact(project, extension, executionId, repository);
+ }
}
} catch (IOException e) {
- throw new MojoExecutionException("Could not write OSGi Repository!", e);
+ throw new MojoExecutionException("Could not write repository!", e);
}
}
- public static boolean isInteresting(MavenProject other) {
- String packaging = other.getPackaging();
- return "jar".equalsIgnoreCase(packaging) || "bundle".equalsIgnoreCase(packaging)
- || ArtifactType.TYPE_ECLIPSE_PLUGIN.equals(packaging)
- || ArtifactType.TYPE_BUNDLE_FRAGMENT.equals(packaging)
- || ArtifactType.TYPE_ECLIPSE_TEST_PLUGIN.equals(packaging);
+ @Override
+ public File getDestination() {
+ return destination;
+ }
+
+ @Override
+ public RepositoryLayout getLayout() {
+ return repositoryLayout;
+ }
+
+ @Override
+ public String getRepositoryName() {
+ return repositoryName;
+ }
+
+ @Override
+ public Log getLog() {
+ return super.getLog();
+ }
+
+ @Override
+ public PlexusConfiguration getConfiguration() {
+ if (settings == null) {
+ return NO_SETTINGS;
+ }
+ return settings;
}
}
diff --git a/tycho-repository-plugin/src/main/java/org/eclipse/tycho/repository/plugin/RepositoryLayout.java b/tycho-repository-plugin/src/main/java/org/eclipse/tycho/repository/plugin/RepositoryLayout.java
deleted file mode 100644
index fe678ce47b..0000000000
--- a/tycho-repository-plugin/src/main/java/org/eclipse/tycho/repository/plugin/RepositoryLayout.java
+++ /dev/null
@@ -1,24 +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.repository.plugin;
-
-public enum RepositoryLayout {
- /**
- * reference artifacts using mvn: protocol
- */
- maven,
- /**
- * references artifacts as local files and copy them into a folder
- */
- local;
-}
\ No newline at end of file
diff --git a/tycho-repository-plugin/src/main/java/org/eclipse/tycho/repository/plugin/TychoRepositoryPluginMavenLifecycleParticipant.java b/tycho-repository-plugin/src/main/java/org/eclipse/tycho/repository/plugin/TychoRepositoryPluginMavenLifecycleParticipant.java
index b3088291be..82c275a639 100644
--- a/tycho-repository-plugin/src/main/java/org/eclipse/tycho/repository/plugin/TychoRepositoryPluginMavenLifecycleParticipant.java
+++ b/tycho-repository-plugin/src/main/java/org/eclipse/tycho/repository/plugin/TychoRepositoryPluginMavenLifecycleParticipant.java
@@ -12,42 +12,85 @@
*******************************************************************************/
package org.eclipse.tycho.repository.plugin;
+import java.util.HashSet;
import java.util.List;
+import java.util.Map;
+import java.util.Set;
import org.apache.maven.AbstractMavenLifecycleParticipant;
import org.apache.maven.MavenExecutionException;
import org.apache.maven.execution.MavenSession;
import org.apache.maven.model.Dependency;
import org.apache.maven.model.Plugin;
+import org.apache.maven.model.PluginExecution;
import org.apache.maven.project.MavenProject;
import org.codehaus.plexus.component.annotations.Component;
+import org.codehaus.plexus.component.annotations.Requirement;
+import org.codehaus.plexus.logging.Logger;
+import org.codehaus.plexus.util.xml.Xpp3Dom;
+import org.eclipse.tycho.helper.PluginConfigurationHelper;
+import org.eclipse.tycho.helper.ProjectHelper;
+import org.eclipse.tycho.packaging.RepositoryGenerator;
@Component(role = AbstractMavenLifecycleParticipant.class)
public class TychoRepositoryPluginMavenLifecycleParticipant extends AbstractMavenLifecycleParticipant {
+ @Requirement
+ Map generators;
+
+ @Requirement
+ PluginConfigurationHelper configurationHelper;
+
+ @Requirement
+ ProjectHelper projectHelper;
+
+ @Requirement
+ Logger logger;
+
@Override
public void afterProjectsRead(MavenSession session) throws MavenExecutionException {
List projects = session.getProjects();
for (MavenProject project : projects) {
- if ("repository".equals(project.getPackaging()) && project.getPlugin("org.eclipse.tycho:tycho-repository-plugin") != null) {
- addInterestingProjects(project, projects);
+ Plugin plugin = project.getPlugin("org.eclipse.tycho:tycho-repository-plugin");
+ if ("repository".equals(project.getPackaging()) && plugin != null) {
+ Set added = new HashSet();
+ for (PluginExecution execution : plugin.getExecutions()) {
+ for (String goal : execution.getGoals()) {
+ addInterestingProjects(project, projects, session, goal, added);
+ }
+ }
}
}
}
- private void addInterestingProjects(MavenProject project, List projects) {
+ private void addInterestingProjects(MavenProject project, List projects, MavenSession session,
+ String goal, Set added) {
+ Xpp3Dom configuration = projectHelper.getPluginConfiguration("org.eclipse.tycho", "tycho-repository-plugin",
+ goal, project, session);
+ String repoType = configurationHelper.getConfiguration(configuration)
+ .getString(PackageRepositoryMojo.PARAMETER_REPOSITORY_TYPE)
+ .orElse(PackageRepositoryMojo.DEFAULT_REPOSITORY_TYPE);
+ RepositoryGenerator generator = generators.get(repoType);
+ if (generator == null) {
+ logger.warn(
+ "Can't determine projects that should be declared as automatic discovered dependencies because RepositoryGenerator of type '"
+ + repoType + "' was not found!");
+ return;
+ }
for (MavenProject other : projects) {
- if (other == project) {
+ if (other == project || added.contains(other)) {
continue;
}
- if (PackageRepositoryMojo.isInteresting(other)) {
+ if (generator.isInteresting(other)) {
Dependency dependency = new Dependency();
dependency.setGroupId(other.getGroupId());
dependency.setArtifactId(other.getArtifactId());
dependency.setVersion(other.getVersion());
project.getModel().addDependency(dependency);
+ added.add(other);
}
}
+
}
}
diff --git a/tycho-spi/src/main/java/org/eclipse/tycho/packaging/RepositoryGenerator.java b/tycho-spi/src/main/java/org/eclipse/tycho/packaging/RepositoryGenerator.java
new file mode 100644
index 0000000000..8f675f3fd3
--- /dev/null
+++ b/tycho-spi/src/main/java/org/eclipse/tycho/packaging/RepositoryGenerator.java
@@ -0,0 +1,107 @@
+/*******************************************************************************
+ * 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.packaging;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.List;
+
+import org.apache.maven.plugin.MojoExecutionException;
+import org.apache.maven.plugin.MojoFailureException;
+import org.apache.maven.plugin.logging.Log;
+import org.apache.maven.project.MavenProject;
+import org.codehaus.plexus.configuration.PlexusConfiguration;
+import org.eclipse.tycho.ArtifactType;
+
+/**
+ * A {@link RepositoryGenerator} is responsible for generate a specific repository format from a set
+ * of items.
+ *
+ */
+public interface RepositoryGenerator {
+
+ /**
+ * Creates a repository from the supplied list of maven projects
+ *
+ * @param projects
+ * the list of projects to use
+ * @param configuration
+ * the configuration for the resulting repository
+ * @return the generated repository
+ * @throws IOException
+ * @throws MojoExecutionException
+ * if an internal error occurs while generating the repository
+ * @throws MojoFailureException
+ * if a user configuration error occurs
+ */
+ File createRepository(List projects, RepositoryConfiguration configuration)
+ throws IOException, MojoExecutionException, MojoFailureException;
+
+ /**
+ * Determines if a given project is interesting for this generator, a generator might be capable
+ * of processing specific things and should probably be able to generate some content from such
+ * a project, the default implementation includes "jar"
, "bundle"
,
+ * {@value ArtifactType#TYPE_ECLIPSE_PLUGIN} and {@value ArtifactType#TYPE_ECLIPSE_TEST_PLUGIN}
+ * packaged projects as potentially interesting.
+ *
+ * @param mavenProject
+ * @return true
if the project is interesting or false
otherwise.
+ */
+ default boolean isInteresting(MavenProject mavenProject) {
+ String packaging = mavenProject.getPackaging();
+ return "jar".equalsIgnoreCase(packaging) || "bundle".equalsIgnoreCase(packaging)
+ || ArtifactType.TYPE_ECLIPSE_PLUGIN.equals(packaging)
+ || ArtifactType.TYPE_ECLIPSE_TEST_PLUGIN.equals(packaging);
+ }
+
+ static enum RepositoryLayout {
+ /**
+ * reference artifacts using mvn: protocol
+ */
+ maven,
+ /**
+ * references artifacts as local files and copy them into a folder
+ */
+ local;
+ }
+
+ static interface RepositoryConfiguration {
+
+ /**
+ * @return he base folder where the repository should be generated
+ */
+ File getDestination();
+
+ /**
+ * @return the desired repository layout, if the generator do not understand the layout it
+ * should throw a {@link MojoFailureException}
+ */
+ RepositoryLayout getLayout();
+
+ /**
+ * @return the user visible name of the repository. This is a hint, if the provider does not
+ * support such thing it could ignore this
+ */
+ String getRepositoryName();
+
+ /**
+ * @return the additional respository configuration.
+ */
+ PlexusConfiguration getConfiguration();
+
+ /**
+ * @return the logger to issue logging messages
+ */
+ Log getLog();
+ }
+}