From cdb255f15d09f752bfc32ef2df13fca2ad72c478 Mon Sep 17 00:00:00 2001 From: John Wagenleitner Date: Sat, 26 Dec 2015 19:17:07 -0800 Subject: [PATCH] GROOVY-7709 - ConvertedClosure/ConvertedMap do not work with interface extending GroovyObject --- .../groovy/runtime/ConversionHandler.java | 26 ++++++++++++ src/test/groovy/bugs/Groovy7709Bug.groovy | 41 +++++++++++++++++++ 2 files changed, 67 insertions(+) create mode 100644 src/test/groovy/bugs/Groovy7709Bug.groovy diff --git a/src/main/org/codehaus/groovy/runtime/ConversionHandler.java b/src/main/org/codehaus/groovy/runtime/ConversionHandler.java index d628ea16fbf..929642d2dbb 100644 --- a/src/main/org/codehaus/groovy/runtime/ConversionHandler.java +++ b/src/main/org/codehaus/groovy/runtime/ConversionHandler.java @@ -18,7 +18,11 @@ */ package org.codehaus.groovy.runtime; +import groovy.lang.GroovyObject; import groovy.lang.GroovyRuntimeException; +import groovy.lang.GroovySystem; +import groovy.lang.MetaClass; +import org.codehaus.groovy.runtime.metaclass.MetaClassRegistryImpl; import org.codehaus.groovy.vmplugin.VMPlugin; import org.codehaus.groovy.vmplugin.VMPluginFactory; @@ -45,6 +49,8 @@ public abstract class ConversionHandler implements InvocationHandler, Serializab if (VMPluginFactory.getPlugin().getVersion()>=7) handleCache = new ConcurrentHashMap(); } + private MetaClass metaClass; + /** * Creates a ConversionHandler with an delegate. * @@ -102,6 +108,13 @@ public Object invoke(Object proxy, Method method, Object[] args) throws Throwabl if (!checkMethod(method)) { try { + if (method.getDeclaringClass() == GroovyObject.class) { + if ("getMetaClass".equals(method.getName())) { + return getMetaClass(proxy); + } else if ("setMetaClass".equals(method.getName())) { + return setMetaClass((MetaClass) args[0]); + } + } return invokeCustom(proxy, method, args); } catch (GroovyRuntimeException gre) { throw ScriptBytecodeAdapter.unwrap(gre); @@ -189,4 +202,17 @@ public static boolean isCoreObjectMethod(Method method) { return Object.class.equals(method.getDeclaringClass()); } + private MetaClass setMetaClass(MetaClass mc) { + metaClass = mc; + return mc; + } + + private MetaClass getMetaClass(Object proxy) { + MetaClass mc = metaClass; + if (mc == null) { + mc = ((MetaClassRegistryImpl) GroovySystem.getMetaClassRegistry()).getMetaClass(proxy); + metaClass = mc; + } + return mc; + } } diff --git a/src/test/groovy/bugs/Groovy7709Bug.groovy b/src/test/groovy/bugs/Groovy7709Bug.groovy new file mode 100644 index 00000000000..be5e7895aeb --- /dev/null +++ b/src/test/groovy/bugs/Groovy7709Bug.groovy @@ -0,0 +1,41 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package groovy.bugs + +class Groovy7709Bug extends GroovyTestCase { + + void testConvertedClosureAsGroovyObject() { + def closure = { 43 } + def proxy = closure as Groovy7709BugY + assert proxy instanceof GroovyObject + assert proxy.foo() == 43 + } + + void testConvertedMapAsGroovyObject() { + def map = [foo: { 43 }] + def proxy = map as Groovy7709BugY + assert proxy instanceof GroovyObject + assert proxy.foo() == 43 + } + +} + +interface Groovy7709BugY extends GroovyObject { + int foo() +}