Skip to content

Commit

Permalink
Add an OSGi property tester to check if action should apply
Browse files Browse the repository at this point in the history
Currently the UnresolvedImportFixProcessor can only work on a project if
it has the org.eclipse.pde.PluginNature but actually we can work on many
different kind of projects independent of the nature.

This now adds a new property tester that evaluates the project if it
matches a certain layout than a nature and allows to enable the
classpath container on them on demand.
  • Loading branch information
laeubi committed Jan 31, 2024
1 parent c8e935f commit 5825fb4
Show file tree
Hide file tree
Showing 5 changed files with 174 additions and 2 deletions.
3 changes: 2 additions & 1 deletion ui/org.eclipse.pde.bnd.ui/META-INF/MANIFEST.MF
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@ Require-Bundle: org.eclipse.jdt.ui,
org.eclipse.jface.text,
org.eclipse.swt,
org.eclipse.jface,
org.eclipse.ui.workbench
org.eclipse.ui.workbench,
org.eclipse.core.expressions
Automatic-Module-Name: org.eclipse.pde.bnd.ui
Bundle-Activator: org.eclipse.pde.bnd.ui.Resources
Bundle-RequiredExecutionEnvironment: JavaSE-17
Expand Down
17 changes: 17 additions & 0 deletions ui/org.eclipse.pde.bnd.ui/plugin.xml
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,21 @@
</handledMarkerTypes>
</quickFixProcessor>
</extension>
<extension
point="org.eclipse.core.expressions.propertyTesters">
<propertyTester
class="org.eclipse.pde.bnd.ui.OSGiPropertyTester"
id="org.eclipse.pde.bnd.osgitester.javaproject"
namespace="org.eclipse.pde.bnd"
properties="isOSGiClasspathProject"
type="org.eclipse.jdt.core.IJavaProject">
</propertyTester>
<propertyTester
class="org.eclipse.pde.bnd.ui.OSGiPropertyTester"
id="org.eclipse.pde.bnd.osgitester.project"
namespace="org.eclipse.pde.bnd"
properties="isOSGiClasspathProject"
type="org.eclipse.core.resources.IProject">
</propertyTester>
</extension>
</plugin>
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
/*******************************************************************************
* 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.pde.bnd.ui;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.jar.JarFile;
import java.util.jar.Manifest;

import org.eclipse.core.expressions.PropertyTester;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.jdt.core.IJavaProject;
import org.osgi.framework.Constants;

import aQute.bnd.build.Project;
import aQute.bnd.build.Workspace;

public class OSGiPropertyTester extends PropertyTester {

@Override
public boolean test(Object receiver, String property, Object[] args, Object expectedValue) {
IProject project = getProject(receiver);
if (project != null) {
if ("isOSGiClasspathProject".equals(property)) {
return isOSGiClasspathProject(project);
}
}
return false;
}

public static boolean isOSGiClasspathProject(IProject project) {
// only java projects can have a classpath...
if (isJavaNature(project)) {
// if it already has some well known nature we can assume its true
if (isPdeNature(project) || isBndToolsNature(project)) {
return true;
}
// otherwise we need to dig a bit deeper
if (isAutomaticManifest(project) || isManifestFirst(project)) {
return true;
}
if (isBndWithClasspath(project)) {
return true;
}
}
return false;
}

private static boolean isAutomaticManifest(IProject project) {
return project.getFile("pde.bnd").exists();
}

protected static boolean isBndWithClasspath(IProject project) {
IFile bndFile = project.getFile(Project.BNDFILE);
if (bndFile.exists()) {
// it might be a BND project with classpath ...
IPath location = project.getLocation();
if (location != null) {
File projectDir = location.toFile();
if (projectDir != null) {
try {
Project plainBnd = Workspace.getProject(projectDir);
if (!plainBnd.getBuildpath().isEmpty() || !plainBnd.getTestpath().isEmpty()) {
return true;
}
} catch (Exception e) {
// no way to tell...
}
}
}
}
return false;
}

protected static boolean isManifestFirst(IProject project) {
IFile manifestFile = project.getFile(JarFile.MANIFEST_NAME);
if (manifestFile.exists()) {
// This seems to be a "manifest-first" project...
try (InputStream contents = manifestFile.getContents()) {
Manifest manifest = new Manifest(contents);
return manifest.getMainAttributes().getValue(Constants.BUNDLE_MANIFESTVERSION) != null;
} catch (IOException | CoreException e) {
// we can't make further assumptions here...
}
}
return false;
}

private static boolean isBndToolsNature(IProject project) {
try {
return project.hasNature("bndtools.core.bndnature");
} catch (CoreException e) {
// we can't know then...
}
return false;
}

private static boolean isPdeNature(IProject project) {
try {
return project.hasNature("org.eclipse.pde.PluginNature");
} catch (CoreException e) {
// we can't know then...
}
return false;
}

private static boolean isJavaNature(IProject project) {
try {
return project.hasNature("org.eclipse.jdt.core.javanature");
} catch (CoreException e) {
// we can't know then...
}
return false;
}

private IProject getProject(Object receiver) {
if (receiver instanceof IProject project) {
return project;
}
if (receiver instanceof IJavaProject java) {
return java.getProject();
}
return null;
}

}
Original file line number Diff line number Diff line change
@@ -1,3 +1,16 @@
/*******************************************************************************
* 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.bnd.ui;

import org.eclipse.jface.resource.ImageDescriptor;
Expand Down
2 changes: 1 addition & 1 deletion ui/org.eclipse.pde.ui/plugin.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1684,7 +1684,7 @@
name="%classpathFixProcessor.unresolvedImport.name">
<enablement>
<with variable="project">
<test property="org.eclipse.jdt.core.isInJavaProjectWithNature" value="org.eclipse.pde.PluginNature"/>
<test property="org.eclipse.pde.bnd.isOSGiClasspathProject" />
</with>
</enablement>
<overrides id="org.eclipse.jdt.ui.text.correction.DefaultClasspathFixProcessor"/>
Expand Down

0 comments on commit 5825fb4

Please sign in to comment.