Skip to content

Commit 3eff3e7

Browse files
committed
GRAILS-11790 Support per-instance DelegatingMetaClass instances in Grails
1 parent 05257bc commit 3eff3e7

File tree

2 files changed

+39
-0
lines changed

2 files changed

+39
-0
lines changed

grails-core/src/main/groovy/org/codehaus/groovy/grails/commons/GrailsMetaClassUtils.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import groovy.lang.AdaptingMetaClass;
1919
import groovy.lang.Closure;
2020
import groovy.lang.ClosureInvokingMethod;
21+
import groovy.lang.DelegatingMetaClass;
2122
import groovy.lang.ExpandoMetaClass;
2223
import groovy.lang.GroovyObject;
2324
import groovy.lang.GroovySystem;
@@ -42,6 +43,7 @@
4243
*/
4344
public class GrailsMetaClassUtils {
4445

46+
private static final int MAX_DELEGATE_LEVELS = 10;
4547
private static final Log LOG = LogFactory.getLog(GrailsMetaClassUtils.class);
4648
private static final Object[] NO_ARGS = new Object[0];
4749

@@ -162,6 +164,9 @@ public static MetaClass getMetaClass(Object instance) {
162164
if (instance instanceof GroovyObject) {
163165
GroovyObject groovyObject = (GroovyObject) instance;
164166
MetaClass metaClass = groovyObject.getMetaClass();
167+
168+
metaClass = unwrapDelegatingMetaClass(metaClass);
169+
165170
if (!(metaClass instanceof ExpandoMetaClass)) {
166171
metaClass = getExpandoMetaClass(instance.getClass());
167172
groovyObject.setMetaClass(metaClass);
@@ -172,6 +177,14 @@ public static MetaClass getMetaClass(Object instance) {
172177
return getExpandoMetaClass(instance.getClass());
173178
}
174179

180+
private static MetaClass unwrapDelegatingMetaClass(MetaClass metaClass) {
181+
int counter=0;
182+
while(metaClass instanceof DelegatingMetaClass && counter++ < MAX_DELEGATE_LEVELS) {
183+
metaClass = ((DelegatingMetaClass)metaClass).getAdaptee();
184+
}
185+
return metaClass;
186+
}
187+
175188
/**
176189
* Obtains a property of an instance if it exists
177190
*
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package org.codehaus.groovy.grails.commons
2+
3+
import spock.lang.Specification
4+
5+
class GrailsMetaClassUtilsSpec extends Specification {
6+
static {
7+
ExpandoMetaClass.enableGlobally()
8+
}
9+
10+
def "delegating metaclass shouldn't be replaced"() {
11+
given:
12+
def obj = new MySampleClass(name: 'John Doe')
13+
def dmc = new DelegatingMetaClass(MySampleClass)
14+
obj.metaClass = dmc
15+
when:
16+
MetaClass mc = GrailsMetaClassUtils.getMetaClass(obj)
17+
then:
18+
mc instanceof ExpandoMetaClass
19+
obj.getMetaClass().getAdaptee() == dmc
20+
}
21+
22+
}
23+
24+
class MySampleClass {
25+
String name
26+
}

0 commit comments

Comments
 (0)