Skip to content

Commit

Permalink
Synchronize values changed in the Overview with the instructions file
Browse files Browse the repository at this point in the history
Currently one can edit the instructions file and after safe the manifest
is updated (and thus also the editor), but the other way does not work,
if one for example edit the name in the overview page the changes are
just overwritten on the next compile.

This installs listeners and implements a very basic model for the
instructions so changes are mirrored to the instructions file as it
already happens for the MANIFEST.MF source tab.
  • Loading branch information
laeubi committed Apr 4, 2023
1 parent 71e89bb commit 9cddd29
Show file tree
Hide file tree
Showing 19 changed files with 416 additions and 107 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -33,15 +33,23 @@
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.core.runtime.jobs.JobChangeAdapter;
import org.eclipse.osgi.util.NLS;
import org.eclipse.pde.internal.core.ICoreConstants;
import org.eclipse.pde.internal.core.PDECore;
import org.eclipse.pde.internal.core.PDECoreMessages;
import org.eclipse.pde.internal.core.natures.BndProject;
import org.eclipse.pde.internal.core.project.PDEProject;

public class BndBuilder extends IncrementalProjectBuilder {

private static final String CLASS_EXTENSION = ".class"; //$NON-NLS-1$

private static final Predicate<IResource> classFilter = resource -> {
// This is currently disabled as it sometimes lead to jar not generated as
// JDT is clearing the outputfolder while the build is running, need to
// investigate if we can avoid this and it actually has benefits to build
// everything async.
private static final boolean USE_JOB = false;

private static final Predicate<IResource> CLASS_FILTER = resource -> {
if (resource instanceof IFile) {
return resource.getName().endsWith(CLASS_EXTENSION);
}
Expand All @@ -55,19 +63,23 @@ public class BndBuilder extends IncrementalProjectBuilder {
@Override
protected IProject[] build(int kind, Map<String, String> args, IProgressMonitor monitor) throws CoreException {
IProject project = getProject();
if (BndProject.isBndProject(project) && hasRelevantDelta(getDelta(project))) {
Job buildJob = buildJobMap.compute(project, (p, oldJob) -> {
Job job = Job.create(NLS.bind(PDECoreMessages.BundleBuilder_building, project.getName()),
new BndBuild(p, oldJob));
job.addJobChangeListener(new JobChangeAdapter() {
@Override
public void done(IJobChangeEvent event) {
buildJobMap.remove(p, job);
}
if (BndProject.isBndProject(project) && (requireBuild(project) || hasRelevantDelta(getDelta(project)))) {
if (USE_JOB) {
Job buildJob = buildJobMap.compute(project, (p, oldJob) -> {
Job job = Job.create(NLS.bind(PDECoreMessages.BundleBuilder_building, project.getName()),
new BndBuild(p, oldJob));
job.addJobChangeListener(new JobChangeAdapter() {
@Override
public void done(IJobChangeEvent event) {
buildJobMap.remove(p, job);
}
});
return job;
});
return job;
});
buildJob.schedule();
buildJob.schedule();
} else {
buildProjectJar(project, monitor);
}
}
return new IProject[] { project };
}
Expand All @@ -94,29 +106,39 @@ public void run(IProgressMonitor monitor) {
return;
}
}
try {
Optional<Project> bndProject = BndProjectManager.getBndProject(project);
if (bndProject.isEmpty()) {
return;
}
if (monitor.isCanceled()) {
return;
}
try (Project bnd = bndProject.get(); ProjectBuilder builder = new ProjectBuilder(bnd)) {
builder.setBase(bnd.getBase());
ProjectJar jar = new ProjectJar(project, classFilter);
builder.setJar(jar);
builder.build();
}
if (monitor.isCanceled()) {
return;
}
} catch (Exception e) {
PDECore.log(e);
buildProjectJar(project, monitor);
}

}

private static void buildProjectJar(IProject project, IProgressMonitor monitor) {
try {
Optional<Project> bndProject = BndProjectManager.getBndProject(project);
if (bndProject.isEmpty()) {
return;
}
if (monitor.isCanceled()) {
return;
}
try (Project bnd = bndProject.get(); ProjectBuilder builder = new ProjectBuilder(bnd)) {
builder.setBase(bnd.getBase());
ProjectJar jar = new ProjectJar(project, CLASS_FILTER);
builder.setJar(jar);
builder.build();
}
if (monitor.isCanceled()) {
return;
}
} catch (Exception e) {
PDECore.log(e);
}
}

private static boolean requireBuild(IProject project) {
// If there is no manifest file yet, always generate one
return !PDEProject.getManifest(project).exists();
}

private static boolean hasRelevantDelta(IResourceDelta delta) throws CoreException {
if (delta != null) {
AtomicBoolean result = new AtomicBoolean();
Expand All @@ -128,7 +150,8 @@ public boolean visit(IResourceDelta delta) throws CoreException {
if (resource instanceof IFile) {
IFile file = (IFile) resource;
String name = file.getName();
if (name.endsWith(CLASS_EXTENSION) || file.getName().equals(BndProject.INSTRUCTIONS_FILE)) {
if (name.endsWith(CLASS_EXTENSION) || file.getName().equals(BndProject.INSTRUCTIONS_FILE)
|| name.equals(ICoreConstants.MANIFEST_FILENAME)) {
result.set(true);
return false;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,18 +66,20 @@ public static Optional<Project> getBndProject(IProject project) throws Exception

private static void setupProject(Project bnd, IProject project) throws CoreException {
IPath base = project.getFullPath();
IJavaProject javaProject = JavaCore.create(project);
IClasspathEntry[] classpath = javaProject.getRawClasspath();
List<String> src = new ArrayList<>(1);
for (IClasspathEntry cpe : classpath) {
if (cpe.getEntryKind() == IClasspathEntry.CPE_SOURCE) {
src.add(cpe.getPath().makeRelativeTo(base).toString());
if (project.hasNature(JavaCore.NATURE_ID)) {
IJavaProject javaProject = JavaCore.create(project);
IClasspathEntry[] classpath = javaProject.getRawClasspath();
List<String> src = new ArrayList<>(1);
for (IClasspathEntry cpe : classpath) {
if (cpe.getEntryKind() == IClasspathEntry.CPE_SOURCE) {
src.add(cpe.getPath().makeRelativeTo(base).toString());
}
}
String outputLocation = javaProject.getOutputLocation().makeRelativeTo(base).toString();
bnd.setProperty(Constants.DEFAULT_PROP_SRC_DIR, src.stream().collect(Collectors.joining(DELIMITER)));
bnd.setProperty(Constants.DEFAULT_PROP_BIN_DIR, outputLocation);
bnd.setProperty(Constants.DEFAULT_PROP_TARGET_DIR, outputLocation);
}
String outputLocation = javaProject.getOutputLocation().makeRelativeTo(base).toString();
bnd.setProperty(Constants.DEFAULT_PROP_SRC_DIR, src.stream().collect(Collectors.joining(DELIMITER)));
bnd.setProperty(Constants.DEFAULT_PROP_BIN_DIR, outputLocation);
bnd.setProperty(Constants.DEFAULT_PROP_TARGET_DIR, outputLocation);
String buildPath = bnd.getProperty(Constants.BUILDPATH);
Stream<String> enhnacedBuildPath = OSGiAnnotationsClasspathContributor.annotations()
.map(p -> p.getPluginBase().getId());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,29 +20,31 @@
import java.util.function.Predicate;
import java.util.jar.JarFile;
import java.util.jar.Manifest;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.eclipse.jdt.core.IClasspathEntry;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.pde.internal.core.project.PDEProject;

public class ProjectJar extends Jar {

private IFolder outputFolder;
private final IContainer outputFolder;

public ProjectJar(IProject project, Predicate<IResource> filter) throws CoreException {
super(project.getName());
outputFolder = PDEProject.getBundleRoot(project);
FileResource.addResources(this, outputFolder, filter);
if (project.hasNature(JavaCore.NATURE_ID)) {
IJavaProject javaProject = JavaCore.create(project);
IPath outputLocation = javaProject.getOutputLocation();
IWorkspaceRoot workspaceRoot = project.getWorkspace().getRoot();
outputFolder = workspaceRoot.getFolder(outputLocation);
FileResource.addResources(this, outputFolder, filter);
IClasspathEntry[] classpath = javaProject.getResolvedClasspath(true);
for (IClasspathEntry cp : classpath) {
if (cp.getEntryKind() == IClasspathEntry.CPE_SOURCE && !cp.isTest()) {
Expand All @@ -67,7 +69,7 @@ public boolean putResource(String path, Resource resource, boolean overwrite) {
if (resource instanceof FileResource) {
return super.putResource(path, resource, overwrite);
}
IFile file = outputFolder.getFile(path);
IFile file = outputFolder.getFile(new Path(path));
try {
if (file.exists()) {
if (overwrite) {
Expand Down Expand Up @@ -101,8 +103,4 @@ private void mkdirs(IResource resource) throws CoreException {
}
}

public IFolder getOutputFolder() {
return outputFolder;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@

import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.pde.internal.core.bnd.BndBuilder;

public class BndProject extends BaseProject {
Expand Down Expand Up @@ -45,7 +44,7 @@ public static boolean isBndProject(IProject project) {

private static boolean hasRequiredNatures(IProject project) {
try {
return project.hasNature(BndProject.NATURE_ID) && project.hasNature(JavaCore.NATURE_ID);
return project.hasNature(BndProject.NATURE_ID);
} catch (CoreException e) {
return false;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@
import org.eclipse.core.runtime.preferences.IEclipsePreferences;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.pde.core.plugin.IPluginModelBase;
import org.eclipse.pde.core.plugin.PluginRegistry;
import org.eclipse.pde.internal.core.ICoreConstants;
Expand Down Expand Up @@ -67,15 +66,17 @@ public static IContainer getBundleRoot(IProject project) {
}
}
if (BndProject.isBndProject(project)) {
IJavaProject javaProject = JavaCore.create(project);
IPath outputLocation;

try {
outputLocation = javaProject.getOutputLocation();
IWorkspaceRoot workspaceRoot = project.getWorkspace().getRoot();
IFolder outputFolder = workspaceRoot.getFolder(outputLocation);
return outputFolder;
} catch (JavaModelException e) {
// can't get output folder... fall through as last resort.
if (project.hasNature(JavaCore.NATURE_ID)) {
IJavaProject javaProject = JavaCore.create(project);
IPath outputLocation = javaProject.getOutputLocation();
IWorkspaceRoot workspaceRoot = project.getWorkspace().getRoot();
return workspaceRoot.getFolder(outputLocation);
}
} catch (CoreException e) {
// can't determine the bundle root then from java settings!
// fall through as last resort
}
}
return project;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,9 @@ public static HashSet<String> getExistingImports(IPluginModelBase model, boolean
}

private static void addSelfAndDirectImports(HashSet<String> set, IPluginModelBase model) {
if (model == null) {
return;
}
set.add(model.getPluginBase().getId());
IPluginImport[] imports = model.getPluginBase().getImports();
for (IPluginImport pImport : imports) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -888,7 +888,7 @@ public IAnnotationModel getAnnotationModel(Match match) {

@Override
protected final void addPages() {
fError = getAggregateModel() == null;
fError = hasMissingResources();
if (fError) {
try {
addPage(new MissingResourcePage(this));
Expand All @@ -899,6 +899,10 @@ protected final void addPages() {
addEditorPages();
}

protected boolean hasMissingResources() {
return getAggregateModel() == null;
}

protected abstract void addEditorPages();

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*******************************************************************************
* 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.pde.internal.ui.editor.bnd;

import org.eclipse.jface.text.BadLocationException;

/**
* this wraps the jface-text BadLocationException into a bnd-document one
*/
final class BndBadLocationException extends aQute.bnd.properties.BadLocationException {

private static final long serialVersionUID = 1L;

public BndBadLocationException(BadLocationException wrapped) {
super(wrapped.getMessage());
initCause(wrapped);
}

}

0 comments on commit 9cddd29

Please sign in to comment.