Skip to content

Commit

Permalink
Add support for platform URLs in automatic manifest generation plugins
Browse files Browse the repository at this point in the history
PDE allows the definition of extraClassPathJars what is very similar to
bnd -classpath, one usually uses a platform:/<reference to
project>/<somejar>. 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.
  • Loading branch information
laeubi committed Jan 16, 2024
1 parent 1f99d2d commit efe4ce1
Show file tree
Hide file tree
Showing 6 changed files with 294 additions and 18 deletions.
49 changes: 49 additions & 0 deletions tools/src/tools/ExportArtifact.java
Original file line number Diff line number Diff line change
@@ -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<String, List<String>> 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<String, List<String>> pkg : packages.entrySet()) {
if (pkg.getValue().isEmpty()) {
continue;
}
System.out.println("<exportedPackage>" + pkg.getKey() + "</exportedPackage>");
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -64,7 +64,7 @@ public class BndMavenLifecycleParticipant extends AbstractMavenLifecycleParticip
private Logger logger;

@Requirement
private Map<String, RepositoryPlugin> repositoryPlugins;
private BndPluginManager bndPluginManager;

@Override
public void afterProjectsRead(MavenSession session) throws MavenExecutionException {
Expand Down Expand Up @@ -174,10 +174,7 @@ private Map<MavenProject, Project> 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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand All @@ -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
Expand All @@ -66,7 +69,7 @@ public class GenerateManifestMojo extends AbstractMojo {
};

@Component
private Map<String, RepositoryPlugin> repositoryPlugins;
private BndPluginManager bndPluginManager;

@Parameter(property = "project", readonly = true)
protected MavenProject mavenProject;
Expand All @@ -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
Expand Down Expand Up @@ -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;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand All @@ -54,7 +58,21 @@ public List<ClasspathEntry> getAdditionalClasspathEntries(MavenProject project,
if (classpath != null && !classpath.isBlank()) {
List<ClasspathEntry> 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;
}
Expand All @@ -66,17 +84,19 @@ public List<ClasspathEntry> 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
Expand All @@ -94,6 +114,16 @@ public Collection<AccessRule> 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;
Expand Down
Original file line number Diff line number Diff line change
@@ -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<String, RepositoryPlugin> repositoryPlugins;

public void setupWorkspace(Workspace ws) {
repositoryPlugins.values().forEach(ws::addBasicPlugin);
ws.refresh();
}
}

0 comments on commit efe4ce1

Please sign in to comment.