Skip to content

Commit

Permalink
Support setting the bundleroot for manifest generated projects
Browse files Browse the repository at this point in the history
Currently we have only the option to set the bundleroot to a different
folder (what the will become the outputfolder). In some cases one might
want to set the bundle root also to the project root.

This now adds special handling for the case where bundle root != output
folder.

Fix #803
  • Loading branch information
laeubi committed Oct 19, 2023
1 parent 27cf508 commit b7460d0
Show file tree
Hide file tree
Showing 3 changed files with 90 additions and 13 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
package org.eclipse.pde.internal.core.bnd;

import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicBoolean;
Expand Down Expand Up @@ -131,7 +132,25 @@ private static void buildProjectJar(IProject project, IProgressMonitor monitor)
if (monitor.isCanceled()) {
return;
}
try (Project bnd = bndProject.get(); ProjectBuilder builder = new ProjectBuilder(bnd)) {
try (Project bnd = bndProject.get(); ProjectBuilder builder = new ProjectBuilder(bnd) {
@Override
public void addClasspath(aQute.bnd.osgi.Jar jar) {
try {
// If the output exits, the ProjectBuilder adds the
// output as a classpath jar, this on the other hand
// later confuses BND because it thinks there is a
// splitpackage and tries to copy the class into the jar
// again...
if (Objects.equals(jar.getSource(), bnd.getOutput())) {
jar.close();
return;
}
} catch (Exception e) {
// can't do anything useful...
}
super.addClasspath(jar);
}
}) {
builder.setBase(bnd.getBase());
ProjectJar jar = new ProjectJar(project, CLASS_FILTER);
builder.setJar(jar);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.jdt.core.IClasspathEntry;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.JavaCore;
Expand All @@ -38,10 +39,11 @@
public class ProjectJar extends Jar {

private final IContainer outputFolder;
private IFile manifestFile;

public ProjectJar(IProject project, Predicate<IResource> filter) throws CoreException {
super(project.getName());
outputFolder = PDEProject.getBundleRoot(project);
outputFolder = PDEProject.getJavaOutputFolder(project);
FileResource.addResources(this, outputFolder, filter);
if (project.hasNature(JavaCore.NATURE_ID)) {
IJavaProject javaProject = JavaCore.create(project);
Expand All @@ -57,12 +59,53 @@ public ProjectJar(IProject project, Predicate<IResource> filter) throws CoreExce
}
}
}
manifestFile = PDEProject.getManifest(project);
}

@Override
public void setManifest(Manifest manifest) {
super.setManifest(manifest);
putResource(JarFile.MANIFEST_NAME, new ManifestResource(manifest));
ManifestResource resource = new ManifestResource(manifest);
// We must handle this with a little care here, first we put it as a
// resource, what will make other parts of BND find it and copy it to
// the output location(so it can be found when using the output as a
// classpath)
putResource(JarFile.MANIFEST_NAME, resource);
// but we also need to make sure if BUNDLE_ROOT != output location
// another copy for PDE and other things that expect it at the bundle
// root...
IFile file = outputFolder.getFile(IPath.fromOSString(JarFile.MANIFEST_NAME));
if (!file.getFullPath().equals(manifestFile.getFullPath())) {
// bundle root is currently not where we store it...
if (manifestFile.exists()) {
try (InputStream stream = resource.openInputStream()) {
manifestFile.setContents(stream, true, false, null);
} catch (RuntimeException e) {
throw e;
} catch (Exception e) {
throw new RuntimeException(e);
}
} else {
try {
mkdirs(manifestFile);
} catch (CoreException e) {
throw new RuntimeException(e);
}
try (InputStream stream = resource.openInputStream()) {
manifestFile.create(stream, true, null);
} catch (RuntimeException e) {
throw e;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
try {
manifestFile.setDerived(true, new NullProgressMonitor());
} catch (CoreException e) {
// if only that don't work just go on...
}
}

}

@Override
Expand Down Expand Up @@ -104,4 +147,9 @@ private void mkdirs(IResource resource) throws CoreException {
}
}

@Override
public String toString() {
return "Project" + super.toString(); //$NON-NLS-1$
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -60,18 +60,18 @@ public static IContainer getBundleRoot(IProject project) {
if (node != null) {
String string = node.get(BUNDLE_ROOT_PATH, null);
if (string != null) {
if (string.isBlank()) {
return project;
}
IPath path = IPath.fromPortableString(string);
return project.getFolder(path);
}
}
if (BndProject.isBndProject(project)) {

try {
if (project.hasNature(JavaCore.NATURE_ID)) {
IJavaProject javaProject = JavaCore.create(project);
IPath outputLocation = javaProject.getOutputLocation();
IWorkspaceRoot workspaceRoot = project.getWorkspace().getRoot();
return workspaceRoot.getFolder(outputLocation);
IFolder outputFolder = getJavaOutputFolder(project);
if (outputFolder != null) {
return outputFolder;
}
} catch (CoreException e) {
// can't determine the bundle root then from java settings!
Expand All @@ -81,6 +81,16 @@ public static IContainer getBundleRoot(IProject project) {
return project;
}

public static IFolder getJavaOutputFolder(IProject project) throws CoreException {
if (project.hasNature(JavaCore.NATURE_ID)) {
IJavaProject javaProject = JavaCore.create(project);
IPath outputLocation = javaProject.getOutputLocation();
IWorkspaceRoot workspaceRoot = project.getWorkspace().getRoot();
return workspaceRoot.getFolder(outputLocation);
}
return null;
}

/**
* Returns the launch shortcuts configured for this project
* or <code>null</code> if default launchers should be used.
Expand Down Expand Up @@ -117,10 +127,10 @@ public static String getExportWizard(IProject project) {
}

/**
* Sets the root of the bundle related artifacts in the specified project
* to the specified container. When <code>null</code> is specified, the
* bundle root will be the project itself. The container must be within
* the specified project.
* Sets the root of the bundle related artifacts in the specified project to
* the specified container. When <code>null</code> is specified, the bundle
* root will be the project itself. The container must be within the
* specified project.
*
* @param project project
* @param root project relative bundle root path, or <code>null</code> (or an empty path)
Expand Down

0 comments on commit b7460d0

Please sign in to comment.