GroovyClassLoader and loading external groovy code

View: New views
4 Messages — Rating Filter:   Alert me  

GroovyClassLoader and loading external groovy code

by Philip Crotwell :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

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) I am trying to dynamically
load the groovy code from within the gradle buildfile. I found two
items that seem to help with this:

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.

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?

And if the root GroovyClassLoader is the correct way, how do I get it?

thanks,
Philip

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

    http://xircles.codehaus.org/manage_email



Re: GroovyClassLoader and loading external groovy code

by Adam Murdoch-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message



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



Re: GroovyClassLoader and loading external groovy code

by Philip Crotwell :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

I am using a separate file because I have a dozen projects that I want
to use this code (it will create a bash run script) and as they are
unrelated projects they don't really fit into the "multiproject" idea.
Since this will hopefully be multipurpose code seems reasonable to
have it separate from any one particular project and just be loaded by
those that need it.

I can also imagine the use case of making use of third party groovy
code within a build. You certainly wouldn't want to copy/paste it into
build.gradle and would rather import/load the file.

What I am trying to do might be better done as a gradle plugin instead
of just some groovy code laying around but as I am just starting I
didn't want to deal with the extra level of complication. I may pursue
that once I have something working.

Your "new GroovyClassLoader(this.class.classloader)" suggestion work
perfectly, so I am all set.

I would think that making use of groovy code in separate files would
be a common need, not just in gradle but in groovy in general. Too bad
there isn't something more straightforward to accomplish this, like a
source("myfile.groovy")
but I guess that is a question for the groovy people.

thanks for the help,
Philip


On Thu, Jul 9, 2009 at 3:03 AM, Adam Murdoch<a@...> wrote:

>
>
> 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
>
>
>

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

    http://xircles.codehaus.org/manage_email



Re: GroovyClassLoader and loading external groovy code

by levi_h :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

I don't know which source control system you're using, but I am very happy with svn:externals for a use case similar to this.

On Thu, Jul 9, 2009 at 7:51 PM, Philip Crotwell <crotwell@...> wrote:
I am using a separate file because I have a dozen projects that I want
to use this code (it will create a bash run script) and as they are
unrelated projects they don't really fit into the "multiproject" idea.
Since this will hopefully be multipurpose code seems reasonable to
have it separate from any one particular project and just be loaded by
those that need it.

I can also imagine the use case of making use of third party groovy
code within a build. You certainly wouldn't want to copy/paste it into
build.gradle and would rather import/load the file.

What I am trying to do might be better done as a gradle plugin instead
of just some groovy code laying around but as I am just starting I
didn't want to deal with the extra level of complication. I may pursue
that once I have something working.

Your "new GroovyClassLoader(this.class.classloader)" suggestion work
perfectly, so I am all set.

I would think that making use of groovy code in separate files would
be a common need, not just in gradle but in groovy in general. Too bad
there isn't something more straightforward to accomplish this, like a
source("myfile.groovy")
but I guess that is a question for the groovy people.

thanks for the help,
Philip


On Thu, Jul 9, 2009 at 3:03 AM, Adam Murdoch<a@...> wrote:
>
>
> 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
>
>
>

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

   http://xircles.codehaus.org/manage_email