Skip to content

Commit

Permalink
use maven properties for different classpath entries and paths (#26)
Browse files Browse the repository at this point in the history
Fixes: #24
Signed-off-by: Markus Rathgeb <maggu2810@gmail.com>
  • Loading branch information
maggu2810 authored and vorburger committed Nov 27, 2017
1 parent cb33a07 commit e16401d
Show file tree
Hide file tree
Showing 2 changed files with 119 additions and 37 deletions.
22 changes: 18 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,27 @@ Configures the path to Eclipse external annotations for null analysis on the Mav

1. Allows to configure Java Compiler Project Properties from maven-compiler-plugin; read either from a dependency of maven-compiler-plugin containing a org.eclipse.jdt.core.prefs file, or from configuration/compilerArguments/properties.

2. Allows to configure the path to external annotations for the Maven Dependencies and JRE classpath containers. The path is
- either taken from the &quot;m2e.jdt.annotationpath&quot; property in POM files, if it exists (this for configuring one single archive of *.eea for ALL Maven dependencies AND the JRE),
- or by individually associating archives on the projects main (not maven-compiler-plugin) dependencies with classpath entries, based on a eea-for-gav marker file in the *-eea.jar which indicates for which Maven GAV it holds external annotations.
2. Allows to configure the path to external annotations for the Maven Dependencies and JRE classpath containers.
The path is

* either taken from the `m2e.jdt.annotationpath` property in POM files, if it exists.
This is used to configure one single archive of *.eea for ALL Maven dependencies AND the JRE.

* or taken from the different properties in POM files. This is used to configure different locations for JRE and Maven dependencies.
* `m2e.eea.annotationpath.jre`: The annotation path for JRE
* `m2e.eea.annotationpath.maven`: The annotation path for Maven dependencies
* `m2e.eea.annotationpath.pde`: The annotation path for required PDE plugins

* or by individually associating archives on the projects main (not maven-compiler-plugin) dependencies with classpath entries, based on a eea-for-gav marker file in the *-eea.jar which indicates for which Maven GAV it holds external annotations.

p2 update site to install this from: `http://www.lastnpe.org/eclipse-external-annotations-m2e-plugin-p2-site/` _(The 404 is normal, just because there is no index.html; it will work in Eclipse.)_

You can also build it yourself: `git clone https://github.com/lastnpe/eclipse-external-annotations-m2e-plugin.git; ./mvnw clean package`
You can also build it yourself:

```
git clone https://github.com/lastnpe/eclipse-external-annotations-m2e-plugin.git
./mvnw clean package
```

see usage examples in [lastnpe/eclipse-null-eea-augments/examples/](https://github.com/lastnpe/eclipse-null-eea-augments/tree/master/examples/maven) (or [sylvainlaurent/null-pointer-analysis-examples](https://github.com/sylvainlaurent/null-pointer-analysis-examples/tree/master/with-external-annotations) for the older single EEA approach).

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,10 +58,23 @@
public class ClasspathConfigurator extends AbstractProjectConfigurator implements IJavaProjectConfigurator {

private static final Pattern NEWLINE_REGEXP = Pattern.compile("\\n");
private static final String JRE_CONTAINER = "org.eclipse.jdt.launching.JRE_CONTAINER";
private static final MavenGAV JAVA_GAV = MavenGAV.of("java", "java");
private static final String EEA_FOR_GAV_FILENAME = "eea-for-gav";

/*
* Classpath
*/
private static final String JRE_CONTAINER = "org.eclipse.jdt.launching.JRE_CONTAINER";
private static final String MAVEN_CLASSPATH_CONTAINER = "org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER";
private static final String PDE_REQUIRED_PLUGINS = "org.eclipse.pde.core.requiredPlugins";

/*
* Maven properties
*/
private static final String M2E_JDT_ANNOTATIONPATH = "m2e.jdt.annotationpath";
private static final String M2E_EEA_ANNOTATIONPATH_JRE = "m2e.eea.annotationpath.jre";
private static final String M2E_EEA_ANNOTATIONPATH_MVN = "m2e.eea.annotationpath.maven";
private static final String M2E_EEA_ANNOTATIONPATH_PDE = "m2e.eea.annotationpath.pde";

private final static Logger LOGGER = LoggerFactory.getLogger(ClasspathConfigurator.class);

Expand Down Expand Up @@ -142,7 +155,7 @@ private Optional<File> toFile(final IPath iPath) {

/**
* Reads content of a name file from either inside a JAR or a directory
*
*
* @param fileOrDirectory either a ZIP/JAR file, or a directory
* @param fileName file to look for in that ZIP/JAR file or directory
* @return content of file, if any
Expand Down Expand Up @@ -193,39 +206,66 @@ private List<String> readLines(final String string) {
@Override
public void configureRawClasspath(final ProjectConfigurationRequest request, final IClasspathDescriptor classpath,
final IProgressMonitor monitor) throws CoreException {
final String annotationPath = getSingleProjectWideAnnotationPath(request.getMavenProjectFacade());
if (annotationPath != null && !annotationPath.isEmpty()) {
setContainerClasspathExternalAnnotationsPath(classpath, annotationPath, false);
} else {
// Find the JRE's EEA among the dependencies to set it....
// Note that at this stage of M2E we have to use the Maven project dependencies,
// and cannot rely on the dependencies already being on the IClasspathDescriptor
// (that happens in configureClasspath() not here in configureRawClasspath())
//
final MavenProject mavenProject = request.getMavenProject();
for (final Dependency dependency : mavenProject.getDependencies()) {
// Filter by "*-eea" artifactId naming convention, just for performance
if (!dependency.getArtifactId().endsWith("-eea")) {
continue;
}
final Artifact artifact = maven.resolve(dependency.getGroupId(), dependency.getArtifactId(),
dependency.getVersion(), dependency.getType(), dependency.getClassifier(),
mavenProject.getRemoteArtifactRepositories(), monitor);
if (artifact != null && artifact.isResolved()) {
final File eeaProjectOrJarFile = artifact.getFile();
if (getExternalAnnotationMapping(eeaProjectOrJarFile).contains(JAVA_GAV)) {
final IPath iPath = getProjectPathFromAbsoluteLocationIfPossible(eeaProjectOrJarFile);
setContainerClasspathExternalAnnotationsPath(classpath, iPath.toString(), true);
return;
}
final IMavenProjectFacade mavenProjectFacade = request.getMavenProjectFacade();

/*
* First check for the property for one global path for all classpaths.
*/

if (setContainerClasspathEeaPath(classpath, mavenProjectFacade, M2E_JDT_ANNOTATIONPATH, Optional.empty())) {
return;
}

/*
* If the above has not been set, check if there are properties for specific classpaths.
*/

boolean hasProp = false;
hasProp |= setContainerClasspathEeaPath(classpath, mavenProjectFacade, M2E_EEA_ANNOTATIONPATH_JRE,
Optional.of(JRE_CONTAINER));
hasProp |= setContainerClasspathEeaPath(classpath, mavenProjectFacade, M2E_EEA_ANNOTATIONPATH_MVN,
Optional.of(MAVEN_CLASSPATH_CONTAINER));
hasProp |= setContainerClasspathEeaPath(classpath, mavenProjectFacade, M2E_EEA_ANNOTATIONPATH_PDE,
Optional.of(PDE_REQUIRED_PLUGINS));
if (hasProp) {
return;
}

/*
* If the above has not been set, check the dependencies.
*/

// Find the JRE's EEA among the dependencies to set it....
// Note that at this stage of M2E we have to use the Maven project dependencies,
// and cannot rely on the dependencies already being on the IClasspathDescriptor
// (that happens in configureClasspath() not here in configureRawClasspath())
//

final Optional<String> cpe = Optional.of(JRE_CONTAINER);

final MavenProject mavenProject = request.getMavenProject();
for (final Dependency dependency : mavenProject.getDependencies()) {
// Filter by "*-eea" artifactId naming convention, just for performance
if (!dependency.getArtifactId().endsWith("-eea")) {
continue;
}
final Artifact artifact = maven.resolve(dependency.getGroupId(), dependency.getArtifactId(),
dependency.getVersion(), dependency.getType(), dependency.getClassifier(),
mavenProject.getRemoteArtifactRepositories(), monitor);
if (artifact != null && artifact.isResolved()) {
final File eeaProjectOrJarFile = artifact.getFile();
if (getExternalAnnotationMapping(eeaProjectOrJarFile).contains(JAVA_GAV)) {
final IPath iPath = getProjectPathFromAbsoluteLocationIfPossible(eeaProjectOrJarFile);
setContainerClasspathExternalAnnotationsPath(classpath, iPath.toString(), cpe);
return;
}
}
}
}

/**
* Attempt to convert an absolute File to a workspace relative project patch.
*
*
* @param file a File pointing either to a JAR file in the Maven repo, or a project on disk
* @return IPath which will either be workspace relative if match found, else same location (absolute)
*/
Expand All @@ -249,19 +289,47 @@ private IPath getProjectPathFromAbsoluteLocationIfPossible(File file) {
return org.eclipse.core.runtime.Path.fromOSString(file.getAbsolutePath());
}

private boolean setContainerClasspathEeaPath(final IClasspathDescriptor classpath,
final IMavenProjectFacade mavenProjectFacade, final String mavenPropertyName,
final Optional<String> startsWith) {
final String annotationPath = getSingleProjectWideAnnotationPath(mavenProjectFacade, mavenPropertyName);
if (annotationPath != null && !annotationPath.isEmpty()) {
setContainerClasspathExternalAnnotationsPath(classpath, annotationPath, startsWith);
return true;
} else {
return false;
}
}

/**
* Set classpath for external annotations.
*
* @param classpath the classpath
* @param annotationPath the path of the annotation
* @param startsWith if present the annotation path if added only if the classpath entry starts with the given
* prefix, if empty it is added to every classpath entry
*/
private void setContainerClasspathExternalAnnotationsPath(final IClasspathDescriptor classpath,
final String annotationPath, final boolean onlyJRE) {
final String annotationPath, final Optional<String> startsWith) {
for (final IClasspathEntryDescriptor cpEntry : classpath.getEntryDescriptors()) {
if (cpEntry.getEntryKind() == IClasspathEntry.CPE_CONTAINER) {
if (onlyJRE && !cpEntry.getPath().toString().startsWith(JRE_CONTAINER)) {
continue;
if (startsWith.isPresent()) {
if (cpEntry.getPath().toString().startsWith(startsWith.get())) {
setExternalAnnotationsPath(cpEntry, annotationPath);
}
} else {
setExternalAnnotationsPath(cpEntry, annotationPath);
}
setExternalAnnotationsPath(cpEntry, annotationPath);
}
}
}

private String getSingleProjectWideAnnotationPath(final IMavenProjectFacade mavenProjectFacade) {
return getSingleProjectWideAnnotationPath(mavenProjectFacade, M2E_JDT_ANNOTATIONPATH);
}

private String getSingleProjectWideAnnotationPath(final IMavenProjectFacade mavenProjectFacade,
final String propertyName) {
if (mavenProjectFacade == null) {
return null;
}
Expand All @@ -273,7 +341,7 @@ private String getSingleProjectWideAnnotationPath(final IMavenProjectFacade mave
if (properties == null) {
return null;
}
final String property = properties.getProperty(M2E_JDT_ANNOTATIONPATH);
final String property = properties.getProperty(propertyName);
if (property == null) {
return null;
} else {
Expand Down

0 comments on commit e16401d

Please sign in to comment.