Details
-
Type:
Bug
-
Status:
Closed
-
Priority:
Major
-
Resolution: Won't Fix
-
Affects Version/s: 1.6
-
Fix Version/s: None
-
Component/s: Grape
-
Labels:None
-
Environment:MacOS 10.5, junit tests run in maven build
-
Testcase included:yes
-
Number of attachments :
Description
I have a test script which uses Grab ...
@Grab(group='commons-primitives', module='commons-primitives', version='1.0') public class GrapeClass { def createEmptyInts() { new ArrayIntList() } def verify() { def ints = createEmptyInts() ints.add(0, 42) assert ints.size() == 1 assert ints.get(0) == 42 return "ok" } }
which is successfully loaded via a GroovyClassLoader as follows
public class GrapeTestCase extends GroovyTestCase { void testGrape() { def loader = new GroovyClassLoader(this.class.classLoader) assert loader.parseClass( new File("target/test-classes/sites/thirdparty/plugins/GrapeClass.groovy")) .newInstance().verify()=="ok" } }
but not via a GroovyScriptEngine ...
public class GroovySriptEngineGrapeTestCase extends GroovyTestCase { void testGrape() { GroovyScriptEngine gse = new GroovyScriptEngine("target/test-classes/sites/thirdparty/plugins/"); Class<?> clazz = gse.loadScriptByName("GrapeClass"); assert clazz.newInstance().verify() == "ok"; } }
This final test cases throws the error
Test set: com.bemoko.live.platform.test.thirdparty.groovy.GroovySriptEngineGrapeTestCase
-------------------------------------------------------------------------------
Tests run: 1, Failures: 0, Errors: 1, Skipped: 0, Time elapsed: 1.358 sec <<< FAILURE!
testGrape(com.bemoko.live.platform.test.thirdparty.groovy.GroovySriptEngineGrapeTestCase) Time elapsed: 1.335 sec <<< ERROR!
groovy.util.ScriptException: Could not parse scriptName: GrapeClass.groovy
at groovy.util.GroovyScriptEngine.updateCacheEntry(GroovyScriptEngine.java:335)
at groovy.util.GroovyScriptEngine.loadScriptByName(GroovyScriptEngine.java:282)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.codehaus.groovy.runtime.callsite.PojoMetaMethodSite$PojoCachedMethodSiteNoUnwrapNoCoerce.invoke(PojoMetaMethodSite.java:229)
at org.codehaus.groovy.runtime.callsite.PojoMetaMethodSite.call(PojoMetaMethodSite.java:52)
at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:43)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:116)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:124)
at com.bemoko.live.platform.test.thirdparty.groovy.GroovySriptEngineGrapeTestCase.testGrape(GroovySriptEngineGrapeTestCase.groovy:9)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at junit.framework.TestCase.runTest(TestCase.java:168)
at junit.framework.TestCase.runBare(TestCase.java:134)
at junit.framework.TestResult$1.protect(TestResult.java:110)
at junit.framework.TestResult.runProtected(TestResult.java:128)
at junit.framework.TestResult.run(TestResult.java:113)
at junit.framework.TestCase.run(TestCase.java:124)
at junit.framework.TestSuite.runTest(TestSuite.java:232)
at junit.framework.TestSuite.run(TestSuite.java:227)
at org.junit.internal.runners.JUnit38ClassRunner.run(JUnit38ClassRunner.java:79)
at org.apache.maven.surefire.junit4.JUnit4TestSet.execute(JUnit4TestSet.java:62)
at org.apache.maven.surefire.suite.AbstractDirectoryTestSuite.executeTestSet(AbstractDirectoryTestSuite.java:140)
at org.apache.maven.surefire.suite.AbstractDirectoryTestSuite.execute(AbstractDirectoryTestSuite.java:127)
at org.apache.maven.surefire.Surefire.run(Surefire.java:177)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.apache.maven.surefire.booter.SurefireBooter.runSuitesInProcess(SurefireBooter.java:345)
at org.apache.maven.surefire.booter.SurefireBooter.main(SurefireBooter.java:1009)
Caused by: org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed, GrapeClass.groovy: 7: unable to resolve class org.apache.commons.collecti
ons.primitives.ArrayIntList
@ line 7, column 1.
1 error
at org.codehaus.groovy.control.ErrorCollector.failIfErrors(ErrorCollector.java:296)
at org.codehaus.groovy.control.CompilationUnit.applyToSourceUnits(CompilationUnit.java:816)
at org.codehaus.groovy.control.CompilationUnit.compile(CompilationUnit.java:466)
at groovy.lang.GroovyClassLoader.parseClass(GroovyClassLoader.java:281)
at groovy.lang.GroovyClassLoader.parseClass(GroovyClassLoader.java:252)
at groovy.lang.GroovyClassLoader.parseClass(GroovyClassLoader.java:247)
at groovy.util.GroovyScriptEngine.updateCacheEntry(GroovyScriptEngine.java:333)
... 34 more
Which seems to indicate that the class can't be found via the classloader. If I dump the classpath of the classloader then I see that the jar is on the classpath ...
log.debug(this.class.classLoader.classPath.join(":"))
outputs
/Users/ianhomer/.groovy/grapes/commons-primitives/commons-primitives/jars/commons-primitives-1.0.jar
I think the problem is that ScriptClassLoader overrides findClass without ever calling the URLClassloader (which is where the Grab dependency is found)
Not sure on the appropriate fix for this as the findClass method get's called mutliple times trying to find the appropriate script / class name, e.g.
DEBUG : findClass : java.lang.org$apache$commons$collections$primitives$ArrayIntList
DEBUG : findClass : java.io.org$apache$commons$collections$primitives$ArrayIntList
DEBUG : findClass : java.net.org$apache$commons$collections$primitives$ArrayIntList
DEBUG : findClass : java.util.org$apache$commons$collections$primitives$ArrayIntList
DEBUG : findClass : groovy.lang.org$apache$commons$collections$primitives$ArrayIntList
DEBUG : findClass : groovy.util.org$apache$commons$collections$primitives$ArrayIntList
DEBUG : findClass : org.apache$commons$collections$primitives$ArrayIntList
DEBUG : findClass : org.apache.commons$collections$primitives$ArrayIntList
DEBUG : findClass : org.apache.commons.collections$primitives$ArrayIntList
DEBUG : findClass : org.apache.commons.collections.primitives$ArrayIntList
DEBUG : findClass : org.apache.commons.collections.primitives.ArrayIntList
however a naive fix where we return the super.findClass value if we get a ResourceException in the ScriptClassLoader.findClass execution.
} catch (ResourceException e) {
{ return super.findClass(className); }try
catch (ClassNotFoundException cnfe)
{ throw new ClassNotFoundException("Could not read " + scriptName + ": " + e;); }This seems to works in our system stack, however it bypasses the search for alternative script names listed above since it'll find it on the first pass through. I think this'd be a problem if a grabbed jar included a class that overrode a groovy script in our GroovyScriptEngine directories.