From acb71db9045f1a50cad99d0d61f06b8e8f5d9bda Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20L=C3=A4ubrich?= Date: Tue, 16 Jan 2024 10:42:23 +0100 Subject: [PATCH] Add support for platform URLs in automatic manifest generation plugins PDE allows the definition of extraClassPathJars what is very similar to bnd -classpath, one usually uses a platform://. Currently there are two issues: 1) the tycho-compile does not understand these 2) bnd tries to resolve them with httpclient This adds the code to correctly resolve them in a similar way as Tycho does for extraClassPathJars. --- .../maven/BndMavenLifecycleParticipant.java | 9 ++-- .../tycho/bnd/mojos/GenerateManifestMojo.java | 41 +++++++++++++++---- .../core/bnd/BndClasspathContributor.java | 38 +++++++++++++++-- .../tycho/core/bnd/BndPluginManager.java | 35 ++++++++++++++++ .../resources/META-INF/maven/extension.xml | 7 ++++ 5 files changed, 112 insertions(+), 18 deletions(-) create mode 100644 tycho-core/src/main/java/org/eclipse/tycho/core/bnd/BndPluginManager.java diff --git a/tycho-bnd-plugin/src/main/java/org/eclipse/tycho/bnd/maven/BndMavenLifecycleParticipant.java b/tycho-bnd-plugin/src/main/java/org/eclipse/tycho/bnd/maven/BndMavenLifecycleParticipant.java index 7bb401fe07..3e197b0b95 100644 --- a/tycho-bnd-plugin/src/main/java/org/eclipse/tycho/bnd/maven/BndMavenLifecycleParticipant.java +++ b/tycho-bnd-plugin/src/main/java/org/eclipse/tycho/bnd/maven/BndMavenLifecycleParticipant.java @@ -33,11 +33,11 @@ import org.codehaus.plexus.component.annotations.Component; import org.codehaus.plexus.component.annotations.Requirement; import org.codehaus.plexus.logging.Logger; +import org.eclipse.tycho.core.bnd.BndPluginManager; import aQute.bnd.build.Project; import aQute.bnd.build.Workspace; import aQute.bnd.osgi.Constants; -import aQute.bnd.service.RepositoryPlugin; /** * This component injects information from the BND model into the maven model, @@ -64,7 +64,7 @@ public class BndMavenLifecycleParticipant extends AbstractMavenLifecycleParticip private Logger logger; @Requirement - private Map repositoryPlugins; + private BndPluginManager bndPluginManager; @Override public void afterProjectsRead(MavenSession session) throws MavenExecutionException { @@ -174,10 +174,7 @@ private Map getProjects(MavenSession session) { File basedir = mavenProject.getBasedir(); Workspace ws = Workspace.findWorkspace(basedir.getParentFile()); if (workspaces.add(ws)) { - for (RepositoryPlugin repositoryPlugin : repositoryPlugins.values()) { - ws.addBasicPlugin(repositoryPlugin); - } - ws.refresh(); + bndPluginManager.setupWorkspace(ws); } Project project = ws.getProject(basedir.getName()); mavenProject.setContextValue(Project.class.getName(), project); diff --git a/tycho-bnd-plugin/src/main/java/org/eclipse/tycho/bnd/mojos/GenerateManifestMojo.java b/tycho-bnd-plugin/src/main/java/org/eclipse/tycho/bnd/mojos/GenerateManifestMojo.java index d42b0f5ffd..ff410b5ee8 100644 --- a/tycho-bnd-plugin/src/main/java/org/eclipse/tycho/bnd/mojos/GenerateManifestMojo.java +++ b/tycho-bnd-plugin/src/main/java/org/eclipse/tycho/bnd/mojos/GenerateManifestMojo.java @@ -17,8 +17,8 @@ import java.nio.file.Files; import java.nio.file.Path; import java.util.List; -import java.util.Map; import java.util.function.Predicate; +import java.util.regex.Matcher; import java.util.stream.Collectors; import org.apache.maven.artifact.Artifact; @@ -32,12 +32,16 @@ import org.apache.maven.plugins.annotations.Parameter; import org.apache.maven.plugins.annotations.ResolutionScope; import org.apache.maven.project.MavenProject; +import org.eclipse.tycho.ArtifactKey; +import org.eclipse.tycho.ArtifactType; import org.eclipse.tycho.ClasspathEntry; +import org.eclipse.tycho.TargetPlatform; import org.eclipse.tycho.TychoConstants; import org.eclipse.tycho.bnd.MavenProjectJar; import org.eclipse.tycho.classpath.ClasspathContributor; import org.eclipse.tycho.core.TychoProject; import org.eclipse.tycho.core.TychoProjectManager; +import org.eclipse.tycho.core.bnd.BndPluginManager; import org.eclipse.tycho.core.osgitools.BundleClassPath; import org.eclipse.tycho.core.osgitools.DefaultReactorProject; import org.eclipse.tycho.core.osgitools.OsgiBundleProject; @@ -49,7 +53,6 @@ import aQute.bnd.osgi.Constants; import aQute.bnd.osgi.Jar; import aQute.bnd.osgi.Processor; -import aQute.bnd.service.RepositoryPlugin; /** * The mojos support generation of the manifest file like it is done in PDE if @@ -66,7 +69,7 @@ public class GenerateManifestMojo extends AbstractMojo { }; @Component - private Map repositoryPlugins; + private BndPluginManager bndPluginManager; @Parameter(property = "project", readonly = true) protected MavenProject mavenProject; @@ -87,7 +90,32 @@ public void execute() throws MojoExecutionException, MojoFailureException { File instructionsFile = new File(basedir, TychoConstants.PDE_BND); if (instructionsFile.isFile()) { try (Project project = new Project(getWorkspace(), basedir, instructionsFile); - ProjectBuilder builder = new ProjectBuilder(project); + ProjectBuilder builder = new ProjectBuilder(project) { + @Override + public Jar getJarFromName(String name, String from) { + Matcher m = TychoConstants.PLATFORM_URL_PATTERN.matcher(name); + if (m.matches()) { + TargetPlatform targetPlatform = projectManager.getTargetPlatform(mavenProject) + .orElse(null); + if (targetPlatform == null) { + return null; + } + String pluginId = m.group(2); + try { + ArtifactKey artifact = targetPlatform + .resolveArtifact(ArtifactType.TYPE_ECLIPSE_PLUGIN, pluginId, null); + File artifactLocation = targetPlatform.getArtifactLocation(artifact); + if (artifactLocation == null) { + return null; + } + return new Jar(artifactLocation); + } catch (Exception e) { + return null; + } + } + return super.getJarFromName(name, from); + } + }; Jar jar = new MavenProjectJar(mavenProject, CLASS_FILTER)) { setupProject(project); BundleClassPath bundleClassPath = osgi @@ -138,10 +166,7 @@ Workspace getWorkspace() throws Exception { run.setProperty(Constants.STANDALONE, "true"); Workspace workspace = Workspace.createStandaloneWorkspace(run, new File(mavenProject.getBuild().getDirectory(), Project.BNDCNF).toURI()); - for (RepositoryPlugin repositoryPlugin : repositoryPlugins.values()) { - workspace.addBasicPlugin(repositoryPlugin); - } - workspace.refresh(); + bndPluginManager.setupWorkspace(workspace); return workspace; } diff --git a/tycho-core/src/main/java/org/eclipse/tycho/core/bnd/BndClasspathContributor.java b/tycho-core/src/main/java/org/eclipse/tycho/core/bnd/BndClasspathContributor.java index 9542803d79..0145d6bc41 100644 --- a/tycho-core/src/main/java/org/eclipse/tycho/core/bnd/BndClasspathContributor.java +++ b/tycho-core/src/main/java/org/eclipse/tycho/core/bnd/BndClasspathContributor.java @@ -19,6 +19,7 @@ import java.util.Collections; import java.util.List; import java.util.Optional; +import java.util.regex.Matcher; import org.apache.maven.project.MavenProject; import org.codehaus.plexus.component.annotations.Component; @@ -27,7 +28,10 @@ import org.eclipse.tycho.ArtifactKey; import org.eclipse.tycho.ArtifactType; import org.eclipse.tycho.ClasspathEntry; +import org.eclipse.tycho.DependencyResolutionException; +import org.eclipse.tycho.IllegalArtifactReferenceException; import org.eclipse.tycho.ReactorProject; +import org.eclipse.tycho.TargetPlatform; import org.eclipse.tycho.TychoConstants; import org.eclipse.tycho.classpath.ClasspathContributor; import org.eclipse.tycho.core.TychoProjectManager; @@ -54,7 +58,21 @@ public List getAdditionalClasspathEntries(MavenProject project, if (classpath != null && !classpath.isBlank()) { List additional = new ArrayList<>(); for (String file : classpath.split(",")) { - additional.add(new BndClasspathEntry(new File(project.getBasedir(), file.trim()))); + Matcher m = TychoConstants.PLATFORM_URL_PATTERN.matcher(file); + if (m.matches()) { + TargetPlatform targetPlatform = projectManager.getTargetPlatform(project) + .orElseThrow(() -> new IllegalStateException("Project has no target platform")); + try { + ArtifactKey artifactKey = targetPlatform + .resolveArtifact(ArtifactType.TYPE_ECLIPSE_PLUGIN, m.group(2), null); + File location = targetPlatform.getArtifactLocation(artifactKey); + additional.add(new BndClasspathEntry(location, artifactKey)); + } catch (DependencyResolutionException | IllegalArtifactReferenceException e) { + throw new RuntimeException("can't resolve classpath entry " + file, e); + } + } else { + additional.add(new BndClasspathEntry(new File(project.getBasedir(), file.trim()), null)); + } } return additional; } @@ -66,17 +84,19 @@ public List getAdditionalClasspathEntries(MavenProject project, return Collections.emptyList(); } - private static final class BndClasspathEntry implements ClasspathEntry, ArtifactKey { + private static final class BndClasspathEntry implements ClasspathEntry { private File file; + private ArtifactKey artifactKey; - public BndClasspathEntry(File file) { + public BndClasspathEntry(File file, ArtifactKey artifactKey) { this.file = file; + this.artifactKey = artifactKey == null ? new FileBasedKey(file) : artifactKey; } @Override public ArtifactKey getArtifactKey() { - return this; + return artifactKey; } @Override @@ -94,6 +114,16 @@ public Collection getAccessRules() { return null; } + } + + private static final class FileBasedKey implements ArtifactKey { + + private File file; + + public FileBasedKey(File file) { + this.file = file; + } + @Override public String getType() { return ArtifactType.TYPE_ECLIPSE_PLUGIN; diff --git a/tycho-core/src/main/java/org/eclipse/tycho/core/bnd/BndPluginManager.java b/tycho-core/src/main/java/org/eclipse/tycho/core/bnd/BndPluginManager.java new file mode 100644 index 0000000000..ced593065c --- /dev/null +++ b/tycho-core/src/main/java/org/eclipse/tycho/core/bnd/BndPluginManager.java @@ -0,0 +1,35 @@ +/******************************************************************************* + * Copyright (c) 2024 Christoph Läubrich and others. + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Christoph Läubrich - initial API and implementation + *******************************************************************************/ +package org.eclipse.tycho.core.bnd; + +import java.util.Map; + +import org.codehaus.plexus.component.annotations.Component; +import org.codehaus.plexus.component.annotations.Requirement; + +import aQute.bnd.build.Workspace; +import aQute.bnd.service.RepositoryPlugin; + +/** + * Manager that collects BndPlugins in the plexus domain and installs them into a workspace + */ +@Component(role = BndPluginManager.class) +public class BndPluginManager { + @Requirement + private Map repositoryPlugins; + + public void setupWorkspace(Workspace ws) { + repositoryPlugins.values().forEach(ws::addBasicPlugin); + ws.refresh(); + } +} diff --git a/tycho-maven-plugin/src/main/resources/META-INF/maven/extension.xml b/tycho-maven-plugin/src/main/resources/META-INF/maven/extension.xml index c6840c91a4..203516af73 100644 --- a/tycho-maven-plugin/src/main/resources/META-INF/maven/extension.xml +++ b/tycho-maven-plugin/src/main/resources/META-INF/maven/extension.xml @@ -25,9 +25,16 @@ org.eclipse.core.resources --> de.pdark.decentxml + + aQute.bnd.build + aQute.bnd.osgi + aQute.bnd.header + aQute.service.reporter + aQute.bnd.component + biz.aQute.bnd:biz.aQute.bndlib org.eclipse.tycho:org.eclipse.tycho.embedder.shared org.eclipse.platform:org.eclipse.equinox.p2.core org.eclipse.tycho:tycho-embedder-api