[ 
https://issues.apache.org/jira/browse/GROOVY-4097?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Eric Milles reassigned GROOVY-4097:
-----------------------------------

    Assignee: Eric Milles

> MOP implementation does not handle method calls in relation with class 
> objects properly!
> ----------------------------------------------------------------------------------------
>
>                 Key: GROOVY-4097
>                 URL: https://issues.apache.org/jira/browse/GROOVY-4097
>             Project: Groovy
>          Issue Type: Bug
>          Components: groovy-runtime
>    Affects Versions: 1.7.0
>         Environment: Tested on an AMD Turion64 under WinXP with Eclipse 
> Galileo, Java 6u17, will occur on any platform though since this are groovy 
> source code bugs.
>            Reporter: Joscha Drechsler
>            Assignee: Eric Milles
>            Priority: Critical
>         Attachments: GroovyTestClass.groovy
>
>
> In a few places, the Meta Object Protocoll implementation uses parameter 
> objects classes to look up the matching meta methods. But if one of these 
> arguments already is of type Class, instead of using Class<Class<?>>, the 
> original class parameter is used. This leads to a couple of bugs.
> My attached TestCase includes two methods, each demonstrating on of these 
> bugs.
> h4. First example:
> The first method, testClassArguments(), presents a major issue.
> The TestClass has two methods: getSomething(String) and getSomething(Class).
> Using the MetaObjectProtocol, i first retrieve the MetaMethod of getSomething 
> (line 23) for an argument set [String] (line 22). MetaClassImpl looks up this 
> method by taking the classes of [String] (namely  [Class<String>]), and 
> looking for a method with a signature, that matches [Class<String>]. This 
> works fine, the result printed (line 24) is the correct method, and the 
> assertion (line 25) passes.
> Now i do the same thing again, but this time using an argument set 
> [Class<String>] (line 27). getMetaMethod returns a method (line 28). But, as 
> one can see in the output (line 29), the method is once again 
> getSomething(String): Since MetaClassImpl internally looks up the method, by 
> taking the parameters classes, but in the process _skipping_ class 
> transformation for class arguments, it once again looks for a method with 
> signature [Class<String>] instead of [Class<Class<String>>]. Now, invoking 
> getSomething(String) with Class<String> as parameter of course leads to an 
> IllegalArgumentException, thereby failing the test.
> h4. Second example
> This second example, method testInvokeStaticMethod(), demonstrates, how a 
> call to getSuperclass, a normal public instance method for Class<T>, is 
> wrongly executed as a static method call on T.
> This bug does not occur, when using a default MetaClass: since all default 
> MetaClasses are subclasses of MetaClassImpl, and the class 
> org.codehaus.groovy.runtime.callsite.CallSiteArray has an instanceof test at 
> the third line of it's method createCallStaticSite(CallSite,Class,Object[]), 
> this does not happen for any of MetaClassImpl subclasses.
> So the first thing this test does is, to replace its MetaClass with a 
> DelegatingMetaClass, which does nothing except forward all calls to the 
> original MetaClassImpl, but it is not a subclass of MetaClassImpl, so the 
> mentioned instanceof test does not work.
> Firstly, the test now retrieves it's own Class object (line 38), which works 
> as expected.
> Now, the tests asserts, that its own superclass is GroovyTestCase (line 39), 
> but this assertion fails. The actually returned value of the 
> clazz.getSuperclass() call is "This was the wrong method!", which is returned 
> by the test cases static getSuperclass() method (lines 42 to 44).
> So what happened here? That is pretty simple:
> A normal static call to the getSuperclass() method at lines 42 to 44 would be 
> translated to invokeStaticMethod(GroovyTestCase.class, "getSuperclass", []) 
> on the MetaClass of GroovyTestCase.
> The superclass call at line 39 *should* have been translated to 
> invokeMethod(clazz, "getSuperclass", []) on the MetaClass of Class<T>.
> But what happened instead is, since clazz == GroovyTestCase.clazz, the call 
> site was simply "mistaken" for a static call site, and delegated to the wrong 
> MetaClass.
> h5. some final words
> though the displayed test cases may seem a little artificially constructed, i 
> actually stumbled over both of these bugs in my project, after renaming a few 
> java files to groovy. So please note that these are real issues, the examples 
> only may seem that surreal because i reduced them to a minimum. This stuff 
> does  regularly break code when doing some heavy MOP related work.



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to