[groovy-user] If I have a ClassNode, is there a way to get a Class?

4 views
Skip to first unread message

Eyvind W. Axelsen

unread,
Mar 24, 2009, 10:54:05 AM3/24/09
to us...@groovy.codehaus.org
Say I have an instance of org.codehaus.groovy.ast.ClassNode, and that
I would like to somehow 'compile' this into a java.lang.Class, how
would I approach this? The ClassNode itself stems from a custom
ClassCodeVisitorSupport, and I have done some modifications to its
contents.

Thankful for any hints,

Eyvind.

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

http://xircles.codehaus.org/manage_email


Jochen Theodorou

unread,
Mar 24, 2009, 1:05:01 PM3/24/09
to us...@groovy.codehaus.org
Eyvind W. Axelsen schrieb:

> Say I have an instance of org.codehaus.groovy.ast.ClassNode, and that
> I would like to somehow 'compile' this into a java.lang.Class, how
> would I approach this? The ClassNode itself stems from a custom
> ClassCodeVisitorSupport, and I have done some modifications to its
> contents.

hmm... you need a CompilationUnit and then you call addClassNode to add
your ClassNode, and after that you call compile on the CompilationUnit
to let it compile the ClassNode. There might be problems, because this
is not thought to compile a class without any source.

bye blackdrag

--
Jochen "blackdrag" Theodorou
The Groovy Project Tech Lead (http://groovy.codehaus.org)
http://blackdragsview.blogspot.com/

Eyvind W. Axelsen

unread,
Mar 24, 2009, 3:43:01 PM3/24/09
to us...@groovy.codehaus.org
On Tue, Mar 24, 2009 at 6:05 PM, Jochen Theodorou <blac...@gmx.org> wrote:
>
> hmm... you need a CompilationUnit and then you call addClassNode to add your
> ClassNode, and after that you call compile on the CompilationUnit to let it
> compile the ClassNode. There might be problems, because this is not thought
> to compile a class without any source.
>

Thank you for your reply.

I have already tried that, and the compile method on the
CompilationUnit throws a NullPointerException, unfortunately. Any
ideas on how to fix that?

Eyvind.

Jochen Theodorou

unread,
Mar 24, 2009, 4:06:20 PM3/24/09
to us...@groovy.codehaus.org
Eyvind W. Axelsen schrieb:

> On Tue, Mar 24, 2009 at 6:05 PM, Jochen Theodorou <blac...@gmx.org> wrote:
>> hmm... you need a CompilationUnit and then you call addClassNode to add your
>> ClassNode, and after that you call compile on the CompilationUnit to let it
>> compile the ClassNode. There might be problems, because this is not thought
>> to compile a class without any source.
>>
>
> Thank you for your reply.
>
> I have already tried that, and the compile method on the
> CompilationUnit throws a NullPointerException, unfortunately. Any
> ideas on how to fix that?

could you give me the trace?

bye blackdrag


--
Jochen "blackdrag" Theodorou
The Groovy Project Tech Lead (http://groovy.codehaus.org)
http://blackdragsview.blogspot.com/

Eyvind W. Axelsen

unread,
Mar 25, 2009, 5:41:36 PM3/25/09
to us...@groovy.codehaus.org
Jochen,

What I do is basically

CompilationUnit cu = new CompilationUnit()
cu.addClassNode(classNode)
cu.compile()

The resulting stack trace is as follows:

Exception in thread "main" java.lang.NullPointerException
at org.codehaus.groovy.ast.CodeVisitorSupport.visitBlockStatement(CodeVisitorSupport.java:37)
at org.codehaus.groovy.ast.stmt.BlockStatement.visit(BlockStatement.java:52)
at org.codehaus.groovy.classgen.Verifier.visitMethod(Verifier.java:403)
at org.codehaus.groovy.ast.ClassNode.visitContents(ClassNode.java:907)
at org.codehaus.groovy.classgen.Verifier.visitClass(Verifier.java:284)
at org.codehaus.groovy.control.CompilationUnit$10.call(CompilationUnit.java:653)
at org.codehaus.groovy.control.CompilationUnit.applyToPrimaryClassNodes(CompilationUnit.java:885)
at org.codehaus.groovy.control.CompilationUnit.compile(CompilationUnit.java:436)
at org.codehaus.groovy.control.CompilationUnit.compile(CompilationUnit.java:417)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:86)
at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:230)
at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:912)
at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:756)
at org.codehaus.groovy.runtime.InvokerHelper.invokePojoMethod(InvokerHelper.java:766)
at org.codehaus.groovy.runtime.InvokerHelper.invokeMethod(InvokerHelper.java:754)
at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.invokeMethodN(ScriptBytecodeAdapter.java:170)
at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.invokeMethod0(ScriptBytecodeAdapter.java:198)
at CustomSourceOperation.call(TestClassNode.groovy:36)
at org.codehaus.groovy.control.CompilationUnit.applyToPrimaryClassNodes(CompilationUnit.java:885)
at org.codehaus.groovy.control.CompilationUnit.compile(CompilationUnit.java:436)
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.lang.GroovyClassLoader.parseClass(GroovyClassLoader.java:209)
at groovy.lang.GroovyClassLoader.parseClass(GroovyClassLoader.java:219)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:86)
at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:230)
at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:912)
at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:756)
at org.codehaus.groovy.runtime.InvokerHelper.invokePogoMethod(InvokerHelper.java:778)
at org.codehaus.groovy.runtime.InvokerHelper.invokeMethod(InvokerHelper.java:758)
at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.invokeMethodN(ScriptBytecodeAdapter.java:170)
at TestClassNode.run(TestClassNode.groovy:55)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:86)
at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:230)
at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:912)
at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:756)
at org.codehaus.groovy.runtime.InvokerHelper.invokePogoMethod(InvokerHelper.java:778)
at org.codehaus.groovy.runtime.InvokerHelper.invokeMethod(InvokerHelper.java:758)
at org.codehaus.groovy.runtime.InvokerHelper.runScript(InvokerHelper.java:401)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:86)
at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:230)
at groovy.lang.MetaClassImpl.invokeStaticMethod(MetaClassImpl.java:1105)
at org.codehaus.groovy.runtime.InvokerHelper.invokeMethod(InvokerHelper.java:749)
at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.invokeMethodN(ScriptBytecodeAdapter.java:170)
at TestClassNode.main(TestClassNode.groovy)

Eyvind.

--

Sent from: Oslo 03 Norway.

Jochen Theodorou

unread,
Mar 25, 2009, 6:19:52 PM3/25/09
to us...@groovy.codehaus.org
Eyvind W. Axelsen schrieb:

> Jochen,
>
> What I do is basically
>
> CompilationUnit cu = new CompilationUnit()
> cu.addClassNode(classNode)
> cu.compile()
>
> The resulting stack trace is as follows:
>
> Exception in thread "main" java.lang.NullPointerException
> at org.codehaus.groovy.ast.CodeVisitorSupport.visitBlockStatement(CodeVisitorSupport.java:37)
> at org.codehaus.groovy.ast.stmt.BlockStatement.visit(BlockStatement.java:52)
[...]

That means you have a BlockStatement, that contains a null value as
statment. That won't do. BlockStatement might be empty, but if it
contains a statement it must not be null

Frank D. Greco

unread,
Mar 25, 2009, 8:50:01 PM3/25/09
to us...@groovy.codehaus.org
Anyone know of a decent GSP tutorial that I can give to people that
are not familiar with JSP's? I didn't see anything off the Groovy
home page. Thx.

Frank G.
--
+==============================================+
| Crossroads Technologies Inc. |
| www.CrossroadsTech dot com |
| fgreco at REMOVEtheX!cross!roads!tech!dotXcom|
+==============================================+
--

Adwin Wijaya

unread,
Mar 25, 2009, 9:29:06 PM3/25/09
to us...@groovy.codehaus.org
You should search it on Grails.org .. it belongs to Grails.

actually it almost same with plain html tag... easier to understand than jsp (for me)
--
regards
Adwin Wijaya

Eyvind W. Axelsen

unread,
Mar 26, 2009, 5:46:11 AM3/26/09
to us...@groovy.codehaus.org
Thanks again, Jochen.

I am not sure how to approach or correct this. Below is (a simplified
version of) my code, would you care to take a look?

Eyvind.

import org.codehaus.groovy.ast.CodeVisitorSupport
import org.codehaus.groovy.ast.expr.*
import org.codehaus.groovy.ast.stmt.*
import org.codehaus.groovy.ast.*
import org.codehaus.groovy.control.*
import org.codehaus.groovy.classgen.*
import java.security.CodeSource

def scriptText = "class A { def foo() { println(\"hello\") } }\n"

// Dummy operation that only stores the class node for later use
class DummyOperation extends CompilationUnit.PrimaryClassNodeOperation {
ClassNode cn
void call(SourceUnit source, GeneratorContext context, ClassNode
classNode) throws CompilationFailedException {
cn = classNode
}
}

//use a class loader to add the dummy operation to the compilation process
class MyClassLoader extends GroovyClassLoader {

DummyOperation dummyOp = new DummyOperation()
protected CompilationUnit
createCompilationUnit(CompilerConfiguration config, CodeSource source)
{
CompilationUnit cu = super.createCompilationUnit(config, source)
cu.addPhaseOperation(dummyOp, Phases.CLASS_GENERATION)
return cu
}
}

def myCL = new MyClassLoader()
myCL.parseClass(scriptText)

CompilationUnit unit = new CompilationUnit();
unit.addClassNode(myCL.dummyOp.cn)
unit.compile() // fails with NullPointerException in CodeVisitorSupport.java:37

--

Sent from: Oslo 03 Norway.

---------------------------------------------------------------------

Eyvind W. Axelsen

unread,
Mar 29, 2009, 2:10:35 PM3/29/09
to us...@groovy.codehaus.org
Anyone?

Peter Niederwieser

unread,
Mar 30, 2009, 4:25:46 AM3/30/09
to us...@groovy.codehaus.org

What's your use case? Why capture a ClassNode and compile it separately?
GroovyClassLoader.parseClass() already gives you a java.lang.Class. Which
Groovy version are you using?

Cheers,
Peter

--
View this message in context: http://www.nabble.com/If-I-have-a-ClassNode%2C-is-there-a-way-to-get-a-Class--tp22682215p22778347.html
Sent from the groovy - user mailing list archive at Nabble.com.

Eyvind W. Axelsen

unread,
Mar 30, 2009, 4:40:23 AM3/30/09
to us...@groovy.codehaus.org
My use case is that at runtime, I wish to make changes to certain
classes (say, rename a method or a class, add methods or fields,
remove methods etc), and compile this into a new class. I have looked
at the ExpandoMetaClass, and I need more than what is available there.
Hence, I would like to store the AST for the full flexibility of
manipulation, and be able to make changes and then compile to a new
class.

groovy - version on the command line prints "Groovy Version: 1.6.0
JVM: 1.6.0_11"

Thanks,


Eyvind.

Guillaume Laforge

unread,
Mar 30, 2009, 4:53:23 AM3/30/09
to us...@groovy.codehaus.org
When you say "a new class", you mean, a new class in addition to the
one that was originally compiled?
You don't want to just modify/change the one being compiled?

--
Guillaume Laforge
Groovy Project Manager
Head of Groovy Development at SpringSource
http://www.springsource.com/g2one

Attend the GR8 Conference, a conference dedicated to Groovy, Grails and Griffon
http://www.gr8conf.org

Read the blog: http://www.gr8conf.org/blog/list
Follow us on Twitter: http://twitter.com/gr8conf

Eyvind W. Axelsen

unread,
Mar 30, 2009, 4:56:24 AM3/30/09
to us...@groovy.codehaus.org
Yes, I want to make a new one, based on the 'old' one with possible
modifications. (I am aware that no modifications are made in my dumbed
down example code below, as I tried to make it as simple as possible.)

Thanks,

Eyvind.

Peter Niederwieser

unread,
Mar 30, 2009, 4:56:44 AM3/30/09
to us...@groovy.codehaus.org

How about keeping the original source code and creating a new ClassNode every
time you wish to do some manipulation? Is that an option?


Eyvind W. Axelsen wrote:
>
> My use case is that at runtime, I wish to make changes to certain
> classes (say, rename a method or a class, add methods or fields,
> remove methods etc), and compile this into a new class. I have looked
> at the ExpandoMetaClass, and I need more than what is available there.
> Hence, I would like to store the AST for the full flexibility of
> manipulation, and be able to make changes and then compile to a new
> class.
>

--
View this message in context: http://www.nabble.com/If-I-have-a-ClassNode%2C-is-there-a-way-to-get-a-Class--tp22682215p22778797.html

Eyvind W. Axelsen

unread,
Mar 30, 2009, 5:07:13 AM3/30/09
to us...@groovy.codehaus.org
Peter,

Keeping the source code is an option, but I am not sure that I follow
you completely here. If at all possible, I do not wish to make textual
modifications at the source code level, so how would I go about
creating a ClassNode that I could modify to my needs from the original
source?

Eyvind.

--

Sent from: Oslo 03 Norway.

---------------------------------------------------------------------

Peter Niederwieser

unread,
Mar 30, 2009, 5:29:34 AM3/30/09
to us...@groovy.codehaus.org

Eyvind W. Axelsen wrote:
>
> so how would I go about creating a ClassNode that I could modify to my
> needs from the original source?
>

As in your example, just that instead of saving the ClassNode you modify it.
Then myCL.parseClass() will return the java.lang.Class for the modified
ClassNode.

One more thing: I'm not sure how much of a difference it makes, but I'd
rather do AST manipulation in phase CANONICALIZATION instead of
CLASS_GENERATION.

Cheers,
Peter
--
View this message in context: http://www.nabble.com/If-I-have-a-ClassNode%2C-is-there-a-way-to-get-a-Class--tp22682215p22779278.html

Eyvind W. Axelsen

unread,
Mar 30, 2009, 5:32:16 AM3/30/09
to us...@groovy.codehaus.org
Thanks Peter, I will look into it.

Eyvind.

--

Sent from: Oslo 03 Norway.

---------------------------------------------------------------------

Reply all
Reply to author
Forward
0 new messages