diff --git a/tools/src/tools/ExportArtifact.java b/tools/src/tools/ExportArtifact.java new file mode 100644 index 0000000000..95f3691a52 --- /dev/null +++ b/tools/src/tools/ExportArtifact.java @@ -0,0 +1,49 @@ +/******************************************************************************* + * 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 tools; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.TreeMap; +import java.util.jar.JarFile; + +/** + * prints a list of packages from a jar that can be used inside + * tycho-maven-plugin/src/main/resources/META-INF/maven/extension.xml + */ +public class ExportArtifact { + public static void main(String[] args) throws IOException { + Map> packages = new TreeMap<>(); + try (JarFile jarFile = new JarFile(args[0])) { + jarFile.stream().forEach(entry -> { + String name = entry.getName(); + if (name.endsWith(".class")) { + int lastIndexOf = name.lastIndexOf('/'); + if (lastIndexOf > 0) { + String pkg = name.substring(0, lastIndexOf).replace('/', '.'); + packages.computeIfAbsent(pkg, x -> new ArrayList<>()).add(name); + } + } + }); + } + for (Entry> pkg : packages.entrySet()) { + if (pkg.getValue().isEmpty()) { + continue; + } + System.out.println("" + pkg.getKey() + ""); + } + } +} 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..e90dd7588a 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,149 @@ org.eclipse.core.resources --> de.pdark.decentxml + + aQute.bnd.annotation + aQute.bnd.annotation.baseline + aQute.bnd.annotation.headers + aQute.bnd.annotation.jpms + aQute.bnd.annotation.licenses + aQute.bnd.annotation.metatype + aQute.bnd.annotation.plugin + aQute.bnd.annotation.service + aQute.bnd.annotation.spi + aQute.bnd.annotation.xml + aQute.bnd.apiguardian.api + aQute.bnd.aspectj.plugin + aQute.bnd.build + aQute.bnd.build.api + aQute.bnd.build.model + aQute.bnd.build.model.clauses + aQute.bnd.build.model.conversions + aQute.bnd.buildtool + aQute.bnd.bundle.annotations + aQute.bnd.cdi + aQute.bnd.classindex + aQute.bnd.compatibility + aQute.bnd.component + aQute.bnd.component.annotations + aQute.bnd.component.error + aQute.bnd.connection.settings + aQute.bnd.differ + aQute.bnd.exporter.executable + aQute.bnd.exporter.runbundles + aQute.bnd.filerepo + aQute.bnd.header + aQute.bnd.help + aQute.bnd.help.instructions + aQute.bnd.http + aQute.bnd.make + aQute.bnd.make.calltree + aQute.bnd.make.component + aQute.bnd.make.coverage + aQute.bnd.make.metatype + aQute.bnd.maven + aQute.bnd.maven.support + aQute.bnd.metatype + aQute.bnd.metatype.annotations + aQute.bnd.obr + aQute.bnd.osgi + aQute.bnd.osgi.eclipse + aQute.bnd.osgi.repository + aQute.bnd.osgi.resource + aQute.bnd.plugin.ant + aQute.bnd.plugin.eclipse + aQute.bnd.plugin.git + aQute.bnd.plugin.gradle + aQute.bnd.plugin.jpms + aQute.bnd.plugin.maven + aQute.bnd.plugin.spi + aQute.bnd.print + aQute.bnd.properties + aQute.bnd.remoteworkspace.client + aQute.bnd.remoteworkspace.server + aQute.bnd.resource.repository + aQute.bnd.service + aQute.bnd.service.action + aQute.bnd.service.classparser + aQute.bnd.service.clipboard + aQute.bnd.service.diff + aQute.bnd.service.export + aQute.bnd.service.extension + aQute.bnd.service.externalplugin + aQute.bnd.service.generate + aQute.bnd.service.library + aQute.bnd.service.lifecycle + aQute.bnd.service.maven + aQute.bnd.service.message + aQute.bnd.service.progress + aQute.bnd.service.release + aQute.bnd.service.remotelaunch + aQute.bnd.service.remoteworkspace + aQute.bnd.service.reporter + aQute.bnd.service.repository + aQute.bnd.service.resolve.hook + aQute.bnd.service.resource + aQute.bnd.service.specifications + aQute.bnd.service.url + aQute.bnd.service.verifier + aQute.bnd.signing + aQute.bnd.url + aQute.bnd.util.dto + aQute.bnd.util.home + aQute.bnd.util.repository + aQute.bnd.version + aQute.bnd.version.maven + aQute.bnd.xmlattribute + aQute.lib.aspects + aQute.lib.base64 + aQute.lib.collections + aQute.lib.concurrent.serial + aQute.lib.concurrentinit + aQute.lib.converter + aQute.lib.date + aQute.lib.deployer + aQute.lib.fileset + aQute.lib.filter + aQute.lib.formatter + aQute.lib.hex + aQute.lib.hierarchy + aQute.lib.io + aQute.lib.json + aQute.lib.link + aQute.lib.manifest + aQute.lib.mavenpasswordobfuscator + aQute.lib.persistentmap + aQute.lib.redirect + aQute.lib.settings + aQute.lib.specinterface + aQute.lib.spring + aQute.lib.stringrover + aQute.lib.strings + aQute.lib.tag + aQute.lib.utf8properties + aQute.lib.watcher + aQute.lib.xml + aQute.lib.xpath + aQute.lib.zip + aQute.libg.command + aQute.libg.cryptography + aQute.libg.filelock + aQute.libg.generics + aQute.libg.glob + aQute.libg.gzip + aQute.libg.ints + aQute.libg.map + aQute.libg.qtokens + aQute.libg.reporter + aQute.libg.reporter.slf4j + aQute.libg.sed + aQute.libg.tuple + aQute.libg.uri + aQute.service.reporter + 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