Skip to content

Commit ea4c3b9

Browse files
committed
Index annotations even when running tests in Maven
There is an unfortunate interaction between Eclipse and Maven when the developer runs the tests using Maven after Eclipse compiled code, failing to run the annotation processors. The annotation index breaks down in that case because no annotations got indexed. Fix this by running the index annotation even when the tests are run from Maven's surefire plugin (as opposed to from within Eclipse). This will help us also when merging the annotation indexer into scijava-common itself, because scijava-common has annotations itself that need to be indexed, but after the merge, scijava-common itself is the annotation processor (which needs to be disabled in order to compile itself because of a chicken-and-egg problem). While at it, remember which directories we already looked at (and clear that cache when running the EclipseHelper unit test). Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
1 parent 167bf64 commit ea4c3b9

2 files changed

Lines changed: 62 additions & 13 deletions

File tree

src/main/java/org/scijava/annotations/EclipseHelper.java

Lines changed: 60 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,14 @@
3535

3636
import java.io.File;
3737
import java.io.IOException;
38+
import java.net.MalformedURLException;
3839
import java.net.URL;
3940
import java.net.URLClassLoader;
41+
import java.util.HashSet;
42+
import java.util.Set;
43+
import java.util.jar.Attributes.Name;
44+
import java.util.jar.JarFile;
45+
import java.util.jar.Manifest;
4046

4147
/**
4248
* Helps Eclipse's lack of support for annotation processing in incremental
@@ -91,6 +97,8 @@
9197
*/
9298
public class EclipseHelper extends DirectoryIndexer {
9399

100+
static Set<URL> indexed = new HashSet<URL>();
101+
94102
/**
95103
* Updates the annotation index in the current Eclipse project.
96104
* <p>
@@ -109,24 +117,63 @@ public static void updateAnnotationIndex(final ClassLoader loader) {
109117
if (!(loader instanceof URLClassLoader)) {
110118
return;
111119
}
112-
EclipseHelper helper = null;
120+
EclipseHelper helper = new EclipseHelper();
113121
for (final URL url : ((URLClassLoader) loader).getURLs()) {
114-
if (!"file".equals(url.getProtocol())) {
115-
continue;
116-
}
117-
String path = url.getFile();
118-
if (path.indexOf(':') >= 0) {
119-
continue;
122+
helper.maybeIndex(url, loader);
123+
}
124+
}
125+
126+
private void maybeIndex(final URL url, final ClassLoader loader) {
127+
synchronized (indexed) {
128+
if (indexed.contains(url)) {
129+
return;
120130
}
121-
File directory = new File(path);
122-
if (!directory.isDirectory()) {
123-
continue;
131+
indexed.add(url);
132+
}
133+
if (!"file".equals(url.getProtocol())) {
134+
return;
135+
}
136+
String path = url.getFile();
137+
if (path.indexOf(':') >= 0) {
138+
return;
139+
}
140+
if (path.endsWith(".jar")) {
141+
/*
142+
* To support mixed development with Eclipse and Maven, let's handle
143+
* the case where Eclipse compiled classes, did not run the annotation
144+
* processors, then the developer called "mvn test". In this case, we
145+
* have a surefirebooter.jar whose manifest contains the dependencies,
146+
* but crucially also the target/classes/ and target/test-classes/
147+
* directories which may need to be indexed.
148+
*/
149+
if (path.matches(".*/target/surefire/surefirebooter[0-9]*\\.jar")) try {
150+
final JarFile jar = new JarFile(path);
151+
Manifest manifest = jar.getManifest();
152+
if (manifest != null) {
153+
final String classPath =
154+
manifest.getMainAttributes().getValue(Name.CLASS_PATH);
155+
if (classPath != null) {
156+
for (final String element : classPath.split(" +"))
157+
try {
158+
maybeIndex(new URL(element), loader);
159+
}
160+
catch (MalformedURLException e) {
161+
e.printStackTrace();
162+
}
163+
}
164+
}
124165
}
125-
if (helper == null) {
126-
helper = new EclipseHelper();
166+
catch (final IOException e) {
167+
System.err.println("Warning: could not index annotations due to ");
168+
e.printStackTrace();
127169
}
128-
helper.index(directory, loader);
170+
return;
171+
}
172+
File directory = new File(path);
173+
if (!directory.isDirectory()) {
174+
return;
129175
}
176+
index(directory, loader);
130177
}
131178

132179
private void index(File directory, ClassLoader loader) {

src/test/java/org/scijava/annotations/EclipseHelperTest.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ public Class<?> loadClass(final String className)
7979
return super.loadClass(className);
8080
}
8181
};
82+
EclipseHelper.indexed.clear();
8283
EclipseHelper.updateAnnotationIndex(loader);
8384
for (final Class<?> clazz : new Class<?>[] { Complex.class, Simple.class })
8485
{
@@ -96,6 +97,7 @@ public Class<?> loadClass(final String className)
9697
.delete());
9798
}
9899
long now = System.currentTimeMillis();
100+
EclipseHelper.indexed.clear();
99101
EclipseHelper.updateAnnotationIndex(loader);
100102
assertEquals(0, jsonDir.list().length);
101103
/*

0 commit comments

Comments
 (0)