« Return to Thread: GroovyClassLoader and loading external groovy code

Re: GroovyClassLoader and loading external groovy code

by Adam Murdoch-2 :: Rate this Message:

Reply to Author | View in Thread



Philip Crotwell wrote:
> Hi
>
> I am trying to use a groovy class in my build.gradle that is defined
> in a separate file. Because I want all my build scripts to not require
> external configuration (like classpath)

Why does it need to be a separate file? I'm curious, because we are
making some improvements to build script classpath handling in Gradle
0.7, and I would like to understand what your use case is, and whether
we would solve it with the 0.7 changes.

>  I am trying to dynamically
> load the groovy code from within the gradle buildfile. I found two
> items that seem to help with this:
>  

Another option you have is to place the file under
buildSrc/src/main/groovy. It will then be automatically compiled and
included in the build script classpath.

> http://groovy.codehaus.org/Influencing+class+loading+at+runtime
> http://www.nabble.com/run-main%2C-package-all-libs%2C-run-easyb-td22395236.html#a22410033
>
> Both say that you should add the URL to the root GroovyClassLoader.
> However, when I try this in my build.gradle:
>
> createTask('play') {
>     println 'rootLoader: '+this.class.classLoader.rootLoader
>     def classLoader = this.class.classLoader
>     while (classLoader != null) {
>         println 'parent loader '+classLoader.class+'  '+classLoader
>         classLoader = classLoader.parent
>     }
> }
>
> I get this:
> crotwell$ gradle play
> :TauP:play
> rootLoader: null
> parent loader class java.net.URLClassLoader  java.net.URLClassLoader@c9e1cc
> parent loader class java.net.URLClassLoader  java.net.URLClassLoader@cd8669
> parent loader class java.net.URLClassLoader  java.net.URLClassLoader@337838
> parent loader class sun.misc.Launcher$ExtClassLoader
> sun.misc.Launcher$ExtClassLoader@cc7ad6
>
> BUILD SUCCESSFUL
>
> and so it would seem that there is no GroovyClassLoader in the class
> loader hierarchy that you get from this.class.classLoader. That seems
> strange as I thought we were using groovy inside of a Task.
>
>  

In this case, 'this' refers to the build script, rather than the task.
The build script is compiled into the cache in the .gradle directory,
and then loaded using a URLClassLoader, rather than a GroovyClassLoader
(I wonder if we should use a GroovyClassLoader, instead).

> I found another post that just constructed a GroovyClassLoader and used it,
> http://www.mail-archive.com/user@.../msg01296.html
> Which more or less works. If I create a GroovyClassLoader myself, I
> can load my class, but it of course is missing all the gradle stuff so
> I can't do something like:
> import org.gradle.api.artifacts.report.IvyDependency
>
> So, what is the correct way to load groovy code from a separate file
> into a gradle build, and still have access to the gradle classes?
>
>  

There's no one way to do this. GroovyClassLoader is a good option.
GroovyShell is another option if you want to execute a script.

Either way, you need to construct the GroovyClassLoader or GroovyShell
with the build script's ClassLoader as its parent ClassLoader. This way
any classes loaded by the ClassLoader will be able to see all classes
visible to the build script:

def classLoader = new GroovyClassLoader(this.class.classLoader)
classLoader.addClasspath(... some path ...) // or addURL()
def myObject = classLoader.parseClass(new File(... some groovy file
...)).newInstance()


Adam


---------------------------------------------------------------------
To unsubscribe from this list, please visit:

    http://xircles.codehaus.org/manage_email


 « Return to Thread: GroovyClassLoader and loading external groovy code