What steps will reproduce the problem?
1. Add the attached jar file to the classpath
2. Create a Reflections object with following code
Reflections r = new Reflections(new ConfigurationBuilder().setUrls(
ClasspathHelper.getUrlsForCurrentClasspath()).setScanners(new TypesScanner(),
new TypeAnnotationsScanner()));
-----------------------------
Ideally:
The parsing of the classpath should not throw any exception.
Instead:
The execution of the above code crashes with following exception:
Caused by: java.util.concurrent.ExecutionException: java.lang.RuntimeException:
could not create class file from class
at java.util.concurrent.FutureTask$Sync.innerGet(FutureTask.java:222)
at java.util.concurrent.FutureTask.get(FutureTask.java:83)
at org.reflections.Reflections.scan(Reflections.java:162)
... 14 more
Caused by: java.lang.RuntimeException: could not create class file from class
at org.reflections.scanners.TypesScanner.scan(TypesScanner.java:28)
at org.reflections.Reflections$2.run(Reflections.java:149)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:441)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)
at java.util.concurrent.FutureTask.run(FutureTask.java:138)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
... 1 more
Caused by: java.io.IOException: bad magic number: 230a2320
at javassist.bytecode.ClassFile.read(ClassFile.java:689)
at javassist.bytecode.ClassFile.<init>(ClassFile.java:85)
at org.reflections.adapters.JavassistAdapter.createClassObject(JavassistAdapter.java:86)
at org.reflections.adapters.JavassistAdapter.createClassObject(JavassistAdapter.java:22)
at org.reflections.scanners.TypesScanner.scan(TypesScanner.java:25)
... 7 more
-----------------------------
The used version is: 0.9.5-RC2 / on Win 7 Pro (reproducible on Win XP Pro)
-----------------------------
Most of the type related scanners have one default implementation of the
acceptsInput() method, which looks like:
public boolean acceptsInput(String file) {
return file.endsWith(".class"); //classes only
}
The problem comes when the class-path contains a file like (inside a jar):
camel-core-2.7.0.jar/META-INF/services/org/apache/camel/component/class
Normally this file should be avoided by the above filter code(does not end with
.class) but unfortunately before calling the scanners the Reflection object
transforms the above path into:
META-INF.services.org.apache.camel.component.class
and this gets passed to the scanners acceptsInput() method, which normally
returns true.
Because of this the file gets passed to the scan() method of the scanner which
fails.
The problem seems to be in the Reflections class scan() method, where the
following code is found:
....
for (final Vfs.File file : files) {
Future<?> future = executorService.submit(new Runnable() {
public void run() {
String input = file.getRelativePath().replace('/', '.');
if (configuration.acceptsInput(input)) {
for (Scanner scanner : configuration.getScanners()) {
if (scanner.acceptsInput(input)) {
scanner.scan(file);
}
}
}
}
});
futures.add(future);
}
....
(decompiled code)
Unfortunately I could not understand what purpose does it serve the following
line of code?:
String input = file.getRelativePath().replace('/', '.');
Because of this it is impossible to solve the mentioned bug in the Scanner
acceptInput() method.
Shouldn't this be just?
String input = file.getRelativePath();
I think it should cover all situations for files inside jars. Or?
Original issue reported on code.google.com by norbert....@gmail.com on 30 Jun 2011 at 10:35
Original issue reported on code.google.com by
norbert....@gmail.com
on 30 Jun 2011 at 10:35Attachments: