You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by su...@apache.org on 2017/12/20 00:56:13 UTC
[16/49] groovy git commit: Move source files to proper packages
http://git-wip-us.apache.org/repos/asf/groovy/blob/10110145/src/main/groovy/lang/MetaClassImpl.java
----------------------------------------------------------------------
diff --git a/src/main/groovy/lang/MetaClassImpl.java b/src/main/groovy/lang/MetaClassImpl.java
deleted file mode 100644
index c453a3f..0000000
--- a/src/main/groovy/lang/MetaClassImpl.java
+++ /dev/null
@@ -1,4021 +0,0 @@
-/*
- * 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.lang;
-
-import org.apache.groovy.internal.util.UncheckedThrow;
-import org.codehaus.groovy.GroovyBugError;
-import org.codehaus.groovy.ast.ClassNode;
-import org.codehaus.groovy.classgen.asm.BytecodeHelper;
-import org.codehaus.groovy.control.CompilationUnit;
-import org.codehaus.groovy.control.Phases;
-import org.codehaus.groovy.reflection.CacheAccessControlException;
-import org.codehaus.groovy.reflection.CachedClass;
-import org.codehaus.groovy.reflection.CachedConstructor;
-import org.codehaus.groovy.reflection.CachedField;
-import org.codehaus.groovy.reflection.CachedMethod;
-import org.codehaus.groovy.reflection.ClassInfo;
-import org.codehaus.groovy.reflection.GeneratedMetaMethod;
-import org.codehaus.groovy.reflection.ParameterTypes;
-import org.codehaus.groovy.reflection.ReflectionCache;
-import org.codehaus.groovy.reflection.android.AndroidSupport;
-import org.codehaus.groovy.runtime.ArrayTypeUtils;
-import org.codehaus.groovy.runtime.ConvertedClosure;
-import org.codehaus.groovy.runtime.CurriedClosure;
-import org.codehaus.groovy.runtime.DefaultGroovyMethods;
-import org.codehaus.groovy.runtime.GeneratedClosure;
-import org.codehaus.groovy.runtime.GroovyCategorySupport;
-import org.codehaus.groovy.runtime.InvokerHelper;
-import org.codehaus.groovy.runtime.InvokerInvocationException;
-import org.codehaus.groovy.runtime.MetaClassHelper;
-import org.codehaus.groovy.runtime.MethodClosure;
-import org.codehaus.groovy.runtime.callsite.AbstractCallSite;
-import org.codehaus.groovy.runtime.callsite.CallSite;
-import org.codehaus.groovy.runtime.callsite.ConstructorSite;
-import org.codehaus.groovy.runtime.callsite.MetaClassConstructorSite;
-import org.codehaus.groovy.runtime.callsite.PogoMetaClassSite;
-import org.codehaus.groovy.runtime.callsite.PogoMetaMethodSite;
-import org.codehaus.groovy.runtime.callsite.PojoMetaClassSite;
-import org.codehaus.groovy.runtime.callsite.PojoMetaMethodSite;
-import org.codehaus.groovy.runtime.callsite.StaticMetaClassSite;
-import org.codehaus.groovy.runtime.callsite.StaticMetaMethodSite;
-import org.codehaus.groovy.runtime.metaclass.ClosureMetaMethod;
-import org.codehaus.groovy.runtime.metaclass.MetaClassRegistryImpl;
-import org.codehaus.groovy.runtime.metaclass.MetaMethodIndex;
-import org.codehaus.groovy.runtime.metaclass.MethodMetaProperty.GetBeanMethodMetaProperty;
-import org.codehaus.groovy.runtime.metaclass.MethodMetaProperty.GetMethodMetaProperty;
-import org.codehaus.groovy.runtime.metaclass.MethodSelectionException;
-import org.codehaus.groovy.runtime.metaclass.MissingMethodExceptionNoStack;
-import org.codehaus.groovy.runtime.metaclass.MissingMethodExecutionFailed;
-import org.codehaus.groovy.runtime.metaclass.MissingPropertyExceptionNoStack;
-import org.codehaus.groovy.runtime.metaclass.MixinInstanceMetaMethod;
-import org.codehaus.groovy.runtime.metaclass.MultipleSetterProperty;
-import org.codehaus.groovy.runtime.metaclass.NewInstanceMetaMethod;
-import org.codehaus.groovy.runtime.metaclass.NewMetaMethod;
-import org.codehaus.groovy.runtime.metaclass.NewStaticMetaMethod;
-import org.codehaus.groovy.runtime.metaclass.TransformMetaMethod;
-import org.codehaus.groovy.runtime.typehandling.DefaultTypeTransformation;
-import org.codehaus.groovy.runtime.typehandling.NumberMathModificationInfo;
-import org.codehaus.groovy.runtime.wrappers.Wrapper;
-import org.codehaus.groovy.util.ComplexKeyHashMap;
-import org.codehaus.groovy.util.FastArray;
-import org.codehaus.groovy.util.SingleKeyHashMap;
-import org.objectweb.asm.ClassVisitor;
-
-import java.beans.BeanInfo;
-import java.beans.EventSetDescriptor;
-import java.beans.IntrospectionException;
-import java.beans.Introspector;
-import java.beans.PropertyDescriptor;
-import java.lang.reflect.Array;
-import java.lang.reflect.Constructor;
-import java.lang.reflect.Method;
-import java.lang.reflect.Modifier;
-import java.lang.reflect.Proxy;
-import java.net.URL;
-import java.security.AccessController;
-import java.security.PrivilegedActionException;
-import java.security.PrivilegedExceptionAction;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.LinkedHashSet;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentMap;
-
-import static org.codehaus.groovy.ast.tools.GeneralUtils.inSamePackage;
-import static org.codehaus.groovy.ast.tools.GeneralUtils.isDefaultVisibility;
-import static org.codehaus.groovy.reflection.ReflectionCache.isAssignableFrom;
-
-/**
- * Allows methods to be dynamically added to existing classes at runtime
- * @see groovy.lang.MetaClass
- */
-public class MetaClassImpl implements MetaClass, MutableMetaClass {
-
- public static final Object[] EMPTY_ARGUMENTS = {};
-
- protected static final String STATIC_METHOD_MISSING = "$static_methodMissing";
- protected static final String STATIC_PROPERTY_MISSING = "$static_propertyMissing";
- protected static final String METHOD_MISSING = "methodMissing";
- protected static final String PROPERTY_MISSING = "propertyMissing";
- protected static final String INVOKE_METHOD_METHOD = "invokeMethod";
-
- private static final String CLOSURE_CALL_METHOD = "call";
- private static final String CLOSURE_DO_CALL_METHOD = "doCall";
- private static final String GET_PROPERTY_METHOD = "getProperty";
- private static final String SET_PROPERTY_METHOD = "setProperty";
- private static final Class[] METHOD_MISSING_ARGS = new Class[]{String.class, Object.class};
- private static final Class[] GETTER_MISSING_ARGS = new Class[]{String.class};
- private static final Class[] SETTER_MISSING_ARGS = METHOD_MISSING_ARGS;
- private static final Comparator<CachedClass> CACHED_CLASS_NAME_COMPARATOR = new Comparator<CachedClass>() {
- public int compare(final CachedClass o1, final CachedClass o2) {
- return o1.getName().compareTo(o2.getName());
- }
- };
- private static final MetaMethod[] EMPTY = new MetaMethod[0];
- private static final MetaMethod AMBIGUOUS_LISTENER_METHOD = new DummyMetaMethod();
-
- protected final Class theClass;
- protected final CachedClass theCachedClass;
- protected final boolean isGroovyObject;
- protected final boolean isMap;
- protected final MetaMethodIndex metaMethodIndex;
-
- private final Index classPropertyIndex = new MethodIndex();
- private final SingleKeyHashMap staticPropertyIndex = new SingleKeyHashMap();
- private final Map<String, MetaMethod> listeners = new HashMap<String, MetaMethod>();
- private final List<MetaMethod> allMethods = new ArrayList<MetaMethod>();
- // we only need one of these that can be reused over and over.
- private final MetaProperty arrayLengthProperty = new MetaArrayLengthProperty();
- private final Index classPropertyIndexForSuper = new MethodIndex();
- private final Set<MetaMethod> newGroovyMethodsSet = new HashSet<MetaMethod>();
- private final MetaMethod[] myNewMetaMethods;
- private final MetaMethod[] additionalMetaMethods;
-
- protected MetaMethod getPropertyMethod;
- protected MetaMethod invokeMethodMethod;
- protected MetaMethod setPropertyMethod;
- protected MetaClassRegistry registry;
- private ClassNode classNode;
- private FastArray constructors;
- private volatile boolean initialized;
- private MetaMethod genericGetMethod;
- private MetaMethod genericSetMethod;
- private MetaMethod propertyMissingGet;
- private MetaMethod propertyMissingSet;
- private MetaMethod methodMissing;
- private MetaMethodIndex.Header mainClassMethodHeader;
-
- /**
- * Constructor
- *
- * @param theClass The class this is the metaclass dor
- * @param add The methods for this class
- */
- public MetaClassImpl(final Class theClass, MetaMethod[] add) {
- this.theClass = theClass;
- theCachedClass = ReflectionCache.getCachedClass(theClass);
- this.isGroovyObject = GroovyObject.class.isAssignableFrom(theClass);
- this.isMap = Map.class.isAssignableFrom(theClass);
- this.registry = GroovySystem.getMetaClassRegistry();
- metaMethodIndex = new MetaMethodIndex(theCachedClass);
- final MetaMethod[] metaMethods = theCachedClass.getNewMetaMethods();
- if (add != null && !(add.length == 0)) {
- List<MetaMethod> arr = new ArrayList<MetaMethod>();
- arr.addAll(Arrays.asList(metaMethods));
- arr.addAll(Arrays.asList(add));
- myNewMetaMethods = arr.toArray(new MetaMethod[arr.size()]);
- additionalMetaMethods = metaMethods;
- }
- else {
- myNewMetaMethods = metaMethods;
- additionalMetaMethods = EMPTY;
- }
- }
-
- /**
- * Constructor that sets the methods to null
- *
- * @param theClass The class this is the metaclass dor
- */
- public MetaClassImpl(final Class theClass) {
- this(theClass, null);
- }
-
- /**
- * Constructor with registry
- *
- * @param registry The metaclass registry for this MetaClass
- * @param theClass The class
- * @param add The methods
- */
- public MetaClassImpl(MetaClassRegistry registry, final Class theClass, MetaMethod add []) {
- this(theClass, add);
- this.registry = registry;
- this.constructors = new FastArray(theCachedClass.getConstructors());
- }
-
- /**
- * Constructor with registry setting methods to null
- *
- * @param registry The metaclass registry for this MetaClass
- * @param theClass The class
- */
- public MetaClassImpl(MetaClassRegistry registry, final Class theClass) {
- this(registry, theClass, null);
- }
-
- /**
- * Returns the cached class for this metaclass
- *
- * @return The cached class.
- */
- public final CachedClass getTheCachedClass() {
- return theCachedClass;
- }
-
- /**
- * Returns the registry for this metaclass
- *
- * @return The resgistry
- */
- public MetaClassRegistry getRegistry() {
- return registry;
- }
-
- /**
- * @see MetaObjectProtocol#respondsTo(Object, String, Object[])
- */
- public List respondsTo(Object obj, String name, Object[] argTypes) {
- Class[] classes = MetaClassHelper.castArgumentsToClassArray(argTypes);
- MetaMethod m = getMetaMethod(name, classes);
- if (m!=null) {
- return Collections.singletonList(m);
- }
- return Collections.emptyList();
- }
-
- /**
- * @see MetaObjectProtocol#respondsTo(Object, String)
- */
- public List respondsTo(final Object obj, final String name) {
- final Object o = getMethods(getTheClass(), name, false);
- if (o instanceof FastArray)
- return ((FastArray) o).toList();
- else
- return Collections.singletonList(o);
- }
-
- /**
- * @see MetaObjectProtocol#hasProperty(Object,String)
- */
- public MetaProperty hasProperty(Object obj, String name) {
- return getMetaProperty(name);
- }
-
- /**
- * @see MetaObjectProtocol#getMetaProperty(String)
- */
- public MetaProperty getMetaProperty(String name) {
- SingleKeyHashMap propertyMap = classPropertyIndex.getNotNull(theCachedClass);
- if (propertyMap.containsKey(name)) {
- return (MetaProperty) propertyMap.get(name);
- } else if (staticPropertyIndex.containsKey(name)) {
- return (MetaProperty) staticPropertyIndex.get(name);
- } else {
- propertyMap = classPropertyIndexForSuper.getNotNull(theCachedClass);
- if (propertyMap.containsKey(name))
- return (MetaProperty) propertyMap.get(name);
- else {
- CachedClass superClass = theCachedClass;
- while (superClass != null && superClass != ReflectionCache.OBJECT_CLASS) {
- final MetaBeanProperty property = findPropertyInClassHierarchy(name, superClass);
- if (property != null) {
- onSuperPropertyFoundInHierarchy(property);
- return property;
- }
- superClass = superClass.getCachedSuperClass();
- }
- return null;
- }
- }
- }
-
- /**
- * @see MetaObjectProtocol#getStaticMetaMethod(String, Object[])
- */
- public MetaMethod getStaticMetaMethod(String name, Object[] argTypes) {
- Class[] classes = MetaClassHelper.castArgumentsToClassArray(argTypes);
- return pickStaticMethod(name, classes);
- }
-
-
- /**
- * @see MetaObjectProtocol#getMetaMethod(String, Object[])
- */
- public MetaMethod getMetaMethod(String name, Object[] argTypes) {
- Class[] classes = MetaClassHelper.castArgumentsToClassArray(argTypes);
- return pickMethod(name, classes);
- }
-
- /**
- *Returns the class this object this is the metaclass of.
- *
- * @return The class contained by this metaclass
- */
- public Class getTheClass() {
- return this.theClass;
- }
-
- /**
- * Return wether the class represented by this metaclass instance is an instance of the GroovyObject class
- *
- * @return true if this is a groovy class, false otherwise.
- */
- public boolean isGroovyObject() {
- return isGroovyObject;
- }
-
- /**
- * Fills the method index
- */
- private void fillMethodIndex() {
- mainClassMethodHeader = metaMethodIndex.getHeader(theClass);
- LinkedList<CachedClass> superClasses = getSuperClasses();
- CachedClass firstGroovySuper = calcFirstGroovySuperClass(superClasses);
-
- Set<CachedClass> interfaces = theCachedClass.getInterfaces();
- addInterfaceMethods(interfaces);
-
- populateMethods(superClasses, firstGroovySuper);
-
- inheritInterfaceNewMetaMethods(interfaces);
- if (isGroovyObject) {
- metaMethodIndex.copyMethodsToSuper();
-
- connectMultimethods(superClasses, firstGroovySuper);
- removeMultimethodsOverloadedWithPrivateMethods();
-
- replaceWithMOPCalls(theCachedClass.mopMethods);
- }
- }
-
- private void populateMethods(LinkedList<CachedClass> superClasses, CachedClass firstGroovySuper) {
-
- MetaMethodIndex.Header header = metaMethodIndex.getHeader(firstGroovySuper.getTheClass());
- CachedClass c;
- Iterator<CachedClass> iter = superClasses.iterator();
- for (; iter.hasNext();) {
- c = iter.next();
-
- CachedMethod[] cachedMethods = c.getMethods();
- for (CachedMethod metaMethod : cachedMethods) {
- addToAllMethodsIfPublic(metaMethod);
- if (!metaMethod.isPrivate() || c == firstGroovySuper)
- addMetaMethodToIndex(metaMethod, header);
- }
-
- MetaMethod[] cachedMethods1 = getNewMetaMethods(c);
- for (final MetaMethod method : cachedMethods1) {
- if (!newGroovyMethodsSet.contains(method)) {
- newGroovyMethodsSet.add(method);
- addMetaMethodToIndex(method, header);
- }
- }
-
- if (c == firstGroovySuper)
- break;
- }
-
- MetaMethodIndex.Header last = header;
- for (;iter.hasNext();) {
- c = iter.next();
- header = metaMethodIndex.getHeader(c.getTheClass());
-
- if (last != null) {
- metaMethodIndex.copyNonPrivateMethods(last, header);
- }
- last = header;
-
- for (CachedMethod metaMethod : c.getMethods()) {
- addToAllMethodsIfPublic(metaMethod);
- addMetaMethodToIndex(metaMethod, header);
- }
-
- for (final MetaMethod method : getNewMetaMethods(c)) {
- if (method.getName().equals("<init>") && !method.getDeclaringClass().equals(theCachedClass)) continue;
- if (!newGroovyMethodsSet.contains(method)) {
- newGroovyMethodsSet.add(method);
- addMetaMethodToIndex(method, header);
- }
- }
- }
- }
-
- private MetaMethod[] getNewMetaMethods(CachedClass c) {
- if (theCachedClass != c)
- return c.getNewMetaMethods();
-
- return myNewMetaMethods;
- }
-
- private void addInterfaceMethods(Set<CachedClass> interfaces) {
- MetaMethodIndex.Header header = metaMethodIndex.getHeader(theClass);
- for (CachedClass c : interfaces) {
- final CachedMethod[] m = c.getMethods();
- for (int i = 0; i != m.length; ++i) {
- MetaMethod method = m[i];
- addMetaMethodToIndex(method, header);
- }
- }
- }
-
- protected LinkedList<CachedClass> getSuperClasses() {
- LinkedList<CachedClass> superClasses = new LinkedList<CachedClass>();
-
- if (theClass.isInterface()) {
- superClasses.addFirst(ReflectionCache.OBJECT_CLASS);
- } else {
- for (CachedClass c = theCachedClass; c != null; c = c.getCachedSuperClass()) {
- superClasses.addFirst(c);
- }
- if (theCachedClass.isArray && theClass != Object[].class && !theClass.getComponentType().isPrimitive()) {
- superClasses.addFirst(ReflectionCache.OBJECT_ARRAY_CLASS);
- }
- }
- return superClasses;
- }
-
- private void removeMultimethodsOverloadedWithPrivateMethods() {
- MethodIndexAction mia = new MethodIndexAction() {
- public boolean skipClass(Class clazz) {
- return clazz == theClass;
- }
-
- public void methodNameAction(Class clazz, MetaMethodIndex.Entry e) {
- if (e.methods == null)
- return;
-
- boolean hasPrivate = false;
- if (e.methods instanceof FastArray) {
- FastArray methods = (FastArray) e.methods;
- final int len = methods.size();
- final Object[] data = methods.getArray();
- for (int i = 0; i != len; ++i) {
- MetaMethod method = (MetaMethod) data[i];
- if (method.isPrivate() && clazz == method.getDeclaringClass().getTheClass()) {
- hasPrivate = true;
- break;
- }
- }
- }
- else {
- MetaMethod method = (MetaMethod) e.methods;
- if (method.isPrivate() && clazz == method.getDeclaringClass().getTheClass()) {
- hasPrivate = true;
- }
- }
-
- if (!hasPrivate) return;
-
- // We have private methods for that name, so remove the
- // multimethods. That is the same as in our index for
- // super, so just copy the list from there. It is not
- // possible to use a pointer here, because the methods
- // in the index for super are replaced later by MOP
- // methods like super$5$foo
- final Object o = e.methodsForSuper;
- if (o instanceof FastArray)
- e.methods = ((FastArray) o).copy();
- else
- e.methods = o;
- }
- };
- mia.iterate();
- }
-
-
- private void replaceWithMOPCalls(final CachedMethod[] mopMethods) {
- // no MOP methods if not a child of GroovyObject
- if (!isGroovyObject) return;
-
- class MOPIter extends MethodIndexAction {
- boolean useThis;
-
- @Override
- public void methodNameAction(Class clazz, MetaMethodIndex.Entry e) {
- if (useThis) {
- if (e.methods == null)
- return;
-
- if (e.methods instanceof FastArray) {
- FastArray methods = (FastArray) e.methods;
- processFastArray(methods);
- }
- else {
- MetaMethod method = (MetaMethod) e.methods;
- if (method instanceof NewMetaMethod)
- return;
- if (useThis ^ Modifier.isPrivate(method.getModifiers())) return;
- String mopName = method.getMopName();
- int index = Arrays.binarySearch(mopMethods, mopName, CachedClass.CachedMethodComparatorWithString.INSTANCE);
- if (index >= 0) {
- int from = index;
- while (from > 0 && mopMethods[from-1].getName().equals(mopName))
- from--;
- int to = index;
- while (to < mopMethods.length-1 && mopMethods[to+1].getName().equals(mopName))
- to++;
-
- int matchingMethod = findMatchingMethod(mopMethods, from, to, method);
- if (matchingMethod != -1) {
- e.methods = mopMethods[matchingMethod];
- }
- }
- }
- }
- else {
- if (e.methodsForSuper == null)
- return;
-
- if (e.methodsForSuper instanceof FastArray) {
- FastArray methods = (FastArray) e.methodsForSuper;
- processFastArray(methods);
- }
- else {
- MetaMethod method = (MetaMethod) e.methodsForSuper;
- if (method instanceof NewMetaMethod)
- return;
- if (useThis ^ Modifier.isPrivate(method.getModifiers())) return;
- String mopName = method.getMopName();
- // GROOVY-4922: Due to a numbering scheme change, we must find the super$X$method which exists
- // with the highest number. If we don't, no method may be found, leading to a stack overflow
- String[] decomposedMopName = decomposeMopName(mopName);
- int distance = Integer.parseInt(decomposedMopName[1]);
- while (distance>0) {
- String fixedMopName = decomposedMopName[0] + distance + decomposedMopName[2];
- int index = Arrays.binarySearch(mopMethods, fixedMopName, CachedClass.CachedMethodComparatorWithString.INSTANCE);
- if (index >= 0) {
- int from = index;
- while (from > 0 && mopMethods[from-1].getName().equals(fixedMopName))
- from--;
- int to = index;
- while (to < mopMethods.length-1 && mopMethods[to+1].getName().equals(fixedMopName))
- to++;
-
- int matchingMethod = findMatchingMethod(mopMethods, from, to, method);
- if (matchingMethod != -1) {
- e.methodsForSuper = mopMethods[matchingMethod];
- distance = 0;
- }
- }
- distance--;
- }
- }
- }
- }
-
- private String[] decomposeMopName(final String mopName) {
- int idx = mopName.indexOf("$");
- if (idx>0) {
- int eidx = mopName.indexOf("$", idx+1);
- if (eidx>0) {
- return new String[] {
- mopName.substring(0, idx+1),
- mopName.substring(idx+1, eidx),
- mopName.substring(eidx)
- };
- }
- }
- return new String[]{"","0",mopName};
- }
-
- private void processFastArray(FastArray methods) {
- final int len = methods.size();
- final Object[] data = methods.getArray();
- for (int i = 0; i != len; ++i) {
- MetaMethod method = (MetaMethod) data[i];
- if (method instanceof NewMetaMethod) continue;
- boolean isPrivate = Modifier.isPrivate(method.getModifiers());
- if (useThis ^ isPrivate) continue;
- String mopName = method.getMopName();
- int index = Arrays.binarySearch(mopMethods, mopName, CachedClass.CachedMethodComparatorWithString.INSTANCE);
- if (index >= 0) {
- int from = index;
- while (from > 0 && mopMethods[from-1].getName().equals(mopName))
- from--;
- int to = index;
- while (to < mopMethods.length-1 && mopMethods[to+1].getName().equals(mopName))
- to++;
-
- int matchingMethod = findMatchingMethod(mopMethods, from, to, method);
- if (matchingMethod != -1) {
- methods.set(i, mopMethods[matchingMethod]);
- }
- }
- }
- }
- }
- MOPIter iter = new MOPIter();
-
- // replace all calls for super with the correct MOP method
- iter.useThis = false;
- iter.iterate();
- // replace all calls for this with the correct MOP method
- iter.useThis = true;
- iter.iterate();
- }
-
- private void inheritInterfaceNewMetaMethods(Set<CachedClass> interfaces) {
- // add methods declared by DGM for interfaces
- for (CachedClass cls : interfaces) {
- MetaMethod methods[] = getNewMetaMethods(cls);
- for (MetaMethod method : methods) {
- boolean skip = false;
- // skip DGM methods on an interface if the class already has the method
- // but don't skip for GroovyObject-related methods as it breaks things :-(
- if (method instanceof GeneratedMetaMethod && !isAssignableFrom(GroovyObject.class, method.getDeclaringClass().getTheClass())) {
- for (Method m : theClass.getMethods()) {
- if (method.getName().equals(m.getName())
- // below not true for DGM#push and also co-variant return scenarios
- //&& method.getReturnType().equals(m.getReturnType())
- && MetaMethod.equal(method.getParameterTypes(), m.getParameterTypes())) {
- skip = true;
- break;
- }
- }
- }
- if (!skip) {
- if (!newGroovyMethodsSet.contains(method)) {
- newGroovyMethodsSet.add(method);
- }
- addMetaMethodToIndex(method, mainClassMethodHeader);
- }
- }
- }
- }
-
- private void connectMultimethods(List<CachedClass> superClasses, CachedClass firstGroovyClass) {
- superClasses = DefaultGroovyMethods.reverse(superClasses);
- MetaMethodIndex.Header last = null;
- for (final CachedClass c : superClasses) {
- MetaMethodIndex.Header methodIndex = metaMethodIndex.getHeader(c.getTheClass());
- // We don't copy DGM methods to superclasses' indexes
- // The reason we can do that is particular set of DGM methods in use,
- // if at some point we will define DGM method for some Groovy class or
- // for a class derived from such, we will need to revise this condition.
- // It saves us a lot of space and some noticeable time
- if (last != null) metaMethodIndex.copyNonPrivateNonNewMetaMethods(last, methodIndex);
- last = methodIndex;
-
- if (c == firstGroovyClass)
- break;
- }
- }
-
- private CachedClass calcFirstGroovySuperClass(Collection superClasses) {
- if (theCachedClass.isInterface)
- return ReflectionCache.OBJECT_CLASS;
-
- CachedClass firstGroovy = null;
- Iterator iter = superClasses.iterator();
- for (; iter.hasNext();) {
- CachedClass c = (CachedClass) iter.next();
- if (GroovyObject.class.isAssignableFrom(c.getTheClass())) {
- firstGroovy = c;
- break;
- }
- }
-
- if (firstGroovy == null)
- firstGroovy = theCachedClass;
- else {
- if (firstGroovy.getTheClass() == GroovyObjectSupport.class && iter.hasNext()) {
- firstGroovy = (CachedClass) iter.next();
- if (firstGroovy.getTheClass() == Closure.class && iter.hasNext()) {
- firstGroovy = (CachedClass) iter.next();
- }
- }
- }
-
- return GroovyObject.class.isAssignableFrom(firstGroovy.getTheClass()) ? firstGroovy.getCachedSuperClass() : firstGroovy;
- }
-
- /**
- * Gets all instance methods available on this class for the given name
- *
- * @return all the normal instance methods available on this class for the
- * given name
- */
- private Object getMethods(Class sender, String name, boolean isCallToSuper) {
- Object answer;
-
- final MetaMethodIndex.Entry entry = metaMethodIndex.getMethods(sender, name);
- if (entry == null)
- answer = FastArray.EMPTY_LIST;
- else
- if (isCallToSuper) {
- answer = entry.methodsForSuper;
- } else {
- answer = entry.methods;
- }
-
- if (answer == null) answer = FastArray.EMPTY_LIST;
-
- if (!isCallToSuper) {
- List used = GroovyCategorySupport.getCategoryMethods(name);
- if (used != null) {
- FastArray arr;
- if (answer instanceof MetaMethod) {
- arr = new FastArray();
- arr.add(answer);
- }
- else
- arr = ((FastArray) answer).copy();
-
- for (Iterator iter = used.iterator(); iter.hasNext();) {
- MetaMethod element = (MetaMethod) iter.next();
- if (!element.getDeclaringClass().getTheClass().isAssignableFrom(sender))
- continue;
- filterMatchingMethodForCategory(arr, element);
- }
- answer = arr;
- }
- }
- return answer;
- }
-
- /**
- * Returns all the normal static methods on this class for the given name
- *
- * @return all the normal static methods available on this class for the
- * given name
- */
- private Object getStaticMethods(Class sender, String name) {
- final MetaMethodIndex.Entry entry = metaMethodIndex.getMethods(sender, name);
- if (entry == null)
- return FastArray.EMPTY_LIST;
- Object answer = entry.staticMethods;
- if (answer == null)
- return FastArray.EMPTY_LIST;
- return answer;
- }
-
- /**
- * Returns whether this MetaClassImpl has been modified. Since MetaClassImpl
- * is not designed for modification this method always returns false
- *
- * @return false
- */
- public boolean isModified() {
- return false; // MetaClassImpl not designed for modification, just return false
- }
-
- /**
- *Adds an instance method to this metaclass.
- *
- * @param method The method to be added
- */
- public void addNewInstanceMethod(Method method) {
- final CachedMethod cachedMethod = CachedMethod.find(method);
- NewInstanceMetaMethod newMethod = new NewInstanceMetaMethod(cachedMethod);
- final CachedClass declaringClass = newMethod.getDeclaringClass();
- addNewInstanceMethodToIndex(newMethod, metaMethodIndex.getHeader(declaringClass.getTheClass()));
- }
-
- private void addNewInstanceMethodToIndex(MetaMethod newMethod, MetaMethodIndex.Header header) {
- if (!newGroovyMethodsSet.contains(newMethod)) {
- newGroovyMethodsSet.add(newMethod);
- addMetaMethodToIndex(newMethod, header);
- }
- }
-
- /**
- *Adds a static method to this metaclass.
- *
- * @param method The method to be added
- */
- public void addNewStaticMethod(Method method) {
- final CachedMethod cachedMethod = CachedMethod.find(method);
- NewStaticMetaMethod newMethod = new NewStaticMetaMethod(cachedMethod);
- final CachedClass declaringClass = newMethod.getDeclaringClass();
- addNewStaticMethodToIndex(newMethod, metaMethodIndex.getHeader(declaringClass.getTheClass()));
- }
-
- private void addNewStaticMethodToIndex(MetaMethod newMethod, MetaMethodIndex.Header header) {
- if (!newGroovyMethodsSet.contains(newMethod)) {
- newGroovyMethodsSet.add(newMethod);
- addMetaMethodToIndex(newMethod, header);
- }
- }
-
- /**
- * Invoke a method on the given object with the given arguments.
- *
- * @param object The object the method should be invoked on.
- * @param methodName The name of the method to invoke.
- * @param arguments The arguments to the invoked method as null, a Tuple, an array or a single argument of any type.
- *
- * @return The result of the method invocation.
- */
- public Object invokeMethod(Object object, String methodName, Object arguments) {
- if (arguments == null) {
- return invokeMethod(object, methodName, MetaClassHelper.EMPTY_ARRAY);
- }
- if (arguments instanceof Tuple) {
- Tuple tuple = (Tuple) arguments;
- return invokeMethod(object, methodName, tuple.toArray());
- }
- if (arguments instanceof Object[]) {
- return invokeMethod(object, methodName, (Object[]) arguments);
- } else {
- return invokeMethod(object, methodName, new Object[]{arguments});
- }
- }
-
- /**
- * Invoke a missing method on the given object with the given arguments.
- *
- * @param instance The object the method should be invoked on.
- * @param methodName The name of the method to invoke.
- * @param arguments The arguments to the invoked method.
- *
- * @return The result of the method invocation.
- */
- public Object invokeMissingMethod(Object instance, String methodName, Object[] arguments) {
- return invokeMissingMethod(instance, methodName, arguments, null, false);
- }
-
- /**
- * Invoke a missing property on the given object with the given arguments.
- *
- * @param instance The object the method should be invoked on.
- * @param propertyName The name of the property to invoke.
- * @param optionalValue The (optional) new value for the property
- * @param isGetter Wether the method is a getter
- *
- * @return The result of the method invocation.
- */
- public Object invokeMissingProperty(Object instance, String propertyName, Object optionalValue, boolean isGetter) {
- Class theClass = instance instanceof Class ? (Class)instance : instance.getClass();
- CachedClass superClass = theCachedClass;
- while(superClass != null && superClass != ReflectionCache.OBJECT_CLASS) {
- final MetaBeanProperty property = findPropertyInClassHierarchy(propertyName, superClass);
- if(property != null) {
- onSuperPropertyFoundInHierarchy(property);
- if(!isGetter) {
- property.setProperty(instance, optionalValue);
- return null;
- }
- else {
- return property.getProperty(instance);
- }
- }
- superClass = superClass.getCachedSuperClass();
- }
- // got here to property not found, look for getProperty or setProperty overrides
- if(isGetter) {
- final Class[] getPropertyArgs = {String.class};
- final MetaMethod method = findMethodInClassHierarchy(instance.getClass(), GET_PROPERTY_METHOD, getPropertyArgs, this);
- if(method != null && method instanceof ClosureMetaMethod) {
- onGetPropertyFoundInHierarchy(method);
- return method.invoke(instance,new Object[]{propertyName});
- }
- }
- else {
- final Class[] setPropertyArgs = {String.class, Object.class};
- final MetaMethod method = findMethodInClassHierarchy(instance.getClass(), SET_PROPERTY_METHOD, setPropertyArgs, this);
- if(method != null && method instanceof ClosureMetaMethod) {
- onSetPropertyFoundInHierarchy(method);
- return method.invoke(instance, new Object[]{propertyName, optionalValue});
- }
- }
-
- try {
- if (!(instance instanceof Class)) {
- if (isGetter) {
- if (propertyMissingGet != null) {
- return propertyMissingGet.invoke(instance, new Object[]{propertyName});
- }
- } else {
- if (propertyMissingSet != null) {
- return propertyMissingSet.invoke(instance, new Object[]{propertyName, optionalValue});
- }
- }
- }
- } catch (InvokerInvocationException iie) {
- boolean shouldHandle = isGetter && propertyMissingGet != null;
- if (!shouldHandle) shouldHandle = !isGetter && propertyMissingSet != null;
- if (shouldHandle && iie.getCause() instanceof MissingPropertyException) {
- throw (MissingPropertyException) iie.getCause();
- }
- throw iie;
- }
-
- if (instance instanceof Class && theClass != Class.class) {
- final MetaProperty metaProperty = InvokerHelper.getMetaClass(Class.class).hasProperty(instance, propertyName);
- if (metaProperty != null)
- if (isGetter)
- return metaProperty.getProperty(instance);
- else {
- metaProperty.setProperty(instance, optionalValue);
- return null;
- }
- }
- throw new MissingPropertyExceptionNoStack(propertyName, theClass);
- }
-
- private Object invokeMissingMethod(Object instance, String methodName, Object[] arguments, RuntimeException original, boolean isCallToSuper) {
- if (!isCallToSuper) {
- Class instanceKlazz = instance.getClass();
- if (theClass != instanceKlazz && theClass.isAssignableFrom(instanceKlazz))
- instanceKlazz = theClass;
-
- Class[] argClasses = MetaClassHelper.castArgumentsToClassArray(arguments);
-
- MetaMethod method = findMixinMethod(methodName, argClasses);
- if(method != null) {
- onMixinMethodFound(method);
- return method.invoke(instance, arguments);
- }
-
- method = findMethodInClassHierarchy(instanceKlazz, methodName, argClasses, this);
- if(method != null) {
- onSuperMethodFoundInHierarchy(method);
- return method.invoke(instance, arguments);
- }
-
- // still not method here, so see if there is an invokeMethod method up the hierarchy
- final Class[] invokeMethodArgs = {String.class, Object[].class};
- method = findMethodInClassHierarchy(instanceKlazz, INVOKE_METHOD_METHOD, invokeMethodArgs, this );
- if(method != null && method instanceof ClosureMetaMethod) {
- onInvokeMethodFoundInHierarchy(method);
- return method.invoke(instance, invokeMethodArgs);
- }
- }
-
- if (methodMissing != null) {
- try {
- return methodMissing.invoke(instance, new Object[]{methodName, arguments});
- } catch (InvokerInvocationException iie) {
- if (methodMissing instanceof ClosureMetaMethod && iie.getCause() instanceof MissingMethodException) {
- MissingMethodException mme = (MissingMethodException) iie.getCause();
- throw new MissingMethodExecutionFailed(mme.getMethod(), mme.getClass(),
- mme.getArguments(),mme.isStatic(),mme);
- }
- throw iie;
- } catch (MissingMethodException mme) {
- if (methodMissing instanceof ClosureMetaMethod)
- throw new MissingMethodExecutionFailed(mme.getMethod(), mme.getClass(),
- mme.getArguments(),mme.isStatic(),mme);
- else
- throw mme;
- }
- } else if (original != null) throw original;
- else throw new MissingMethodExceptionNoStack(methodName, theClass, arguments, false);
- }
-
- protected void onSuperPropertyFoundInHierarchy(MetaBeanProperty property) {
- }
-
- protected void onMixinMethodFound(MetaMethod method) {
- }
-
- protected void onSuperMethodFoundInHierarchy(MetaMethod method) {
- }
-
- protected void onInvokeMethodFoundInHierarchy(MetaMethod method) {
- }
-
- protected void onSetPropertyFoundInHierarchy(MetaMethod method) {
- }
-
- protected void onGetPropertyFoundInHierarchy(MetaMethod method) {
- }
-
-
- /**
- * Hook to deal with the case of MissingProperty for static properties. The method will look attempt to look up
- * "propertyMissing" handlers and invoke them otherwise thrown a MissingPropertyException
- *
- * @param instance The instance
- * @param propertyName The name of the property
- * @param optionalValue The value in the case of a setter
- * @param isGetter True if its a getter
- * @return The value in the case of a getter or a MissingPropertyException
- */
- protected Object invokeStaticMissingProperty(Object instance, String propertyName, Object optionalValue, boolean isGetter) {
- MetaClass mc = instance instanceof Class ? registry.getMetaClass((Class) instance) : this;
- if (isGetter) {
- MetaMethod propertyMissing = mc.getMetaMethod(STATIC_PROPERTY_MISSING, GETTER_MISSING_ARGS);
- if (propertyMissing != null) {
- return propertyMissing.invoke(instance, new Object[]{propertyName});
- }
- } else {
- MetaMethod propertyMissing = mc.getMetaMethod(STATIC_PROPERTY_MISSING, SETTER_MISSING_ARGS);
- if (propertyMissing != null) {
- return propertyMissing.invoke(instance, new Object[]{propertyName, optionalValue});
- }
- }
-
- if (instance instanceof Class) {
- throw new MissingPropertyException(propertyName, (Class) instance);
- }
- throw new MissingPropertyException(propertyName, theClass);
- }
-
-
- /**
- * Invokes a method on the given receiver for the specified arguments.
- * The MetaClass will attempt to establish the method to invoke based on the name and arguments provided.
- *
- *
- * @param object The object which the method was invoked on
- * @param methodName The name of the method
- * @param originalArguments The arguments to the method
- *
- * @return The return value of the method
- *
- * @see MetaClass#invokeMethod(Class, Object, String, Object[], boolean, boolean)
- */
- public Object invokeMethod(Object object, String methodName, Object[] originalArguments) {
- return invokeMethod(theClass, object, methodName, originalArguments, false, false);
- }
-
- private Object invokeMethodClosure(Object object, String methodName, Object[] arguments) {
- final MethodClosure mc = (MethodClosure) object;
- final Object owner = mc.getOwner();
-
- methodName = mc.getMethod();
- final Class ownerClass = owner instanceof Class ? (Class) owner : owner.getClass();
- final MetaClass ownerMetaClass = registry.getMetaClass(ownerClass);
-
- // To conform to "Least Surprise" principle, try to invoke method with original arguments first, which can match most of use cases
- try {
- return ownerMetaClass.invokeMethod(ownerClass, owner, methodName, arguments, false, false);
- } catch (MissingMethodExceptionNoStack e) {
- // CONSTRUCTOR REFERENCE
- if (owner instanceof Class && MethodClosure.NEW.equals(methodName)) {
- if (ownerClass.isArray()) {
- if (0 == arguments.length) {
- throw new GroovyRuntimeException("The arguments(specifying size) are required to create array[" + ownerClass.getCanonicalName() + "]");
- }
-
- int arrayDimension = ArrayTypeUtils.dimension(ownerClass);
-
- if (arguments.length > arrayDimension) {
- throw new GroovyRuntimeException("The length[" + arguments.length + "] of arguments should not be greater than the dimensions[" + arrayDimension + "] of array[" + ownerClass.getCanonicalName() + "]");
- }
-
- int[] sizeArray = new int[arguments.length];
-
- for (int i = 0, n = sizeArray.length; i < n; i++) {
- Object argument = arguments[i];
-
- if (argument instanceof Integer) {
- sizeArray[i] = (Integer) argument;
- } else {
- sizeArray[i] = Integer.parseInt(String.valueOf(argument));
- }
- }
-
- Class arrayType =
- arguments.length == arrayDimension
- ? ArrayTypeUtils.elementType(ownerClass) // Just for better performance, though we can use reduceDimension only
- : ArrayTypeUtils.reduceDimension(ownerClass, (arrayDimension - arguments.length));
- return Array.newInstance(arrayType, sizeArray);
- }
-
- return ownerMetaClass.invokeConstructor(arguments);
- }
-
- // METHOD REFERENCE
- // if and only if the owner is a class and the method closure can be related to some instance methods,
- // try to invoke method with adjusted arguments(first argument is the actual owner) again.
- // otherwise throw the MissingMethodExceptionNoStack.
- if (!(owner instanceof Class
- && ((Boolean) mc.getProperty(MethodClosure.ANY_INSTANCE_METHOD_EXISTS)).booleanValue())) {
-
- throw e;
- }
-
- if (arguments.length <= 0) {
- return invokeMissingMethod(object, methodName, arguments);
- }
-
- Object newOwner = arguments[0];
- Object[] newArguments = Arrays.copyOfRange(arguments, 1, arguments.length);
- return ownerMetaClass.invokeMethod(ownerClass, newOwner, methodName, newArguments, false, false);
- }
- }
-
- /**
- * <p>Invokes a method on the given receiver for the specified arguments. The sender is the class that invoked the method on the object.
- * The MetaClass will attempt to establish the method to invoke based on the name and arguments provided.
- *
- * <p>The isCallToSuper and fromInsideClass help the Groovy runtime perform optimisations on the call to go directly
- * to the super class if necessary
- *
- * @param sender The java.lang.Class instance that invoked the method
- * @param object The object which the method was invoked on
- * @param methodName The name of the method
- * @param originalArguments The arguments to the method
- * @param isCallToSuper Whether the method is a call to a super class method
- * @param fromInsideClass Whether the call was invoked from the inside or the outside of the class
- *
- * @return The return value of the method
- *
- * @see MetaClass#invokeMethod(Class, Object, String, Object[], boolean, boolean)
- */
- public Object invokeMethod(Class sender, Object object, String methodName, Object[] originalArguments, boolean isCallToSuper, boolean fromInsideClass) {
- checkInitalised();
- if (object == null) {
- throw new NullPointerException("Cannot invoke method: " + methodName + " on null object");
- }
-
- final Object[] arguments = originalArguments == null ? EMPTY_ARGUMENTS : originalArguments;
-// final Class[] argClasses = MetaClassHelper.convertToTypeArray(arguments);
-//
-// unwrap(arguments);
-
- MetaMethod method = null;
- if (CLOSURE_CALL_METHOD.equals(methodName) && object instanceof GeneratedClosure) {
- method = getMethodWithCaching(sender, "doCall", arguments, isCallToSuper);
- }
- if (method==null) {
- method = getMethodWithCaching(sender, methodName, arguments, isCallToSuper);
- }
- MetaClassHelper.unwrap(arguments);
-
- if (method == null)
- method = tryListParamMetaMethod(sender, methodName, isCallToSuper, arguments);
-
- final boolean isClosure = object instanceof Closure;
- if (isClosure) {
- final Closure closure = (Closure) object;
- final Object owner = closure.getOwner();
-
- if (CLOSURE_CALL_METHOD.equals(methodName) || CLOSURE_DO_CALL_METHOD.equals(methodName)) {
- final Class objectClass = object.getClass();
- if (objectClass == MethodClosure.class) {
- return this.invokeMethodClosure(object, methodName, arguments);
- } else if (objectClass == CurriedClosure.class) {
- final CurriedClosure cc = (CurriedClosure) object;
- // change the arguments for an uncurried call
- final Object[] curriedArguments = cc.getUncurriedArguments(arguments);
- final Class ownerClass = owner instanceof Class ? (Class) owner : owner.getClass();
- final MetaClass ownerMetaClass = registry.getMetaClass(ownerClass);
- return ownerMetaClass.invokeMethod(owner, methodName, curriedArguments);
- }
- if (method==null) invokeMissingMethod(object,methodName,arguments);
- }
-
- final Object delegate = closure.getDelegate();
- final boolean isClosureNotOwner = owner != closure;
- final int resolveStrategy = closure.getResolveStrategy();
-
- final Class[] argClasses = MetaClassHelper.convertToTypeArray(arguments);
-
- switch (resolveStrategy) {
- case Closure.TO_SELF:
- method = closure.getMetaClass().pickMethod(methodName, argClasses);
- if (method != null) return method.invoke(closure, arguments);
- break;
- case Closure.DELEGATE_ONLY:
- if (method == null && delegate != closure && delegate != null) {
- MetaClass delegateMetaClass = lookupObjectMetaClass(delegate);
- method = delegateMetaClass.pickMethod(methodName, argClasses);
- if (method != null)
- return delegateMetaClass.invokeMethod(delegate, methodName, originalArguments);
- else if (delegate != closure && (delegate instanceof GroovyObject)) {
- return invokeMethodOnGroovyObject(methodName, originalArguments, delegate);
- }
- }
- break;
- case Closure.OWNER_ONLY:
- if (method == null && owner != closure) {
- MetaClass ownerMetaClass = lookupObjectMetaClass(owner);
- return ownerMetaClass.invokeMethod(owner, methodName, originalArguments);
- }
- break;
- case Closure.DELEGATE_FIRST:
- if (method == null && delegate != closure && delegate != null) {
- MetaClass delegateMetaClass = lookupObjectMetaClass(delegate);
- method = delegateMetaClass.pickMethod(methodName, argClasses);
- if (method != null)
- return delegateMetaClass.invokeMethod(delegate, methodName, originalArguments);
- }
- if (method == null && owner != closure) {
- MetaClass ownerMetaClass = lookupObjectMetaClass(owner);
- method = ownerMetaClass.pickMethod(methodName, argClasses);
- if (method != null) return ownerMetaClass.invokeMethod(owner, methodName, originalArguments);
- }
- if (method == null && resolveStrategy != Closure.TO_SELF) {
- // still no methods found, test if delegate or owner are GroovyObjects
- // and invoke the method on them if so.
- MissingMethodException last = null;
- if (delegate != closure && (delegate instanceof GroovyObject)) {
- try {
- return invokeMethodOnGroovyObject(methodName, originalArguments, delegate);
- } catch (MissingMethodException mme) {
- if (last == null) last = mme;
- }
- }
- if (isClosureNotOwner && (owner instanceof GroovyObject)) {
- try {
- return invokeMethodOnGroovyObject(methodName, originalArguments, owner);
- } catch (MissingMethodException mme) {
- last = mme;
- }
- }
- if (last != null) return invokeMissingMethod(object, methodName, originalArguments, last, isCallToSuper);
- }
-
- break;
- default:
- if (method == null && owner != closure) {
- MetaClass ownerMetaClass = lookupObjectMetaClass(owner);
- method = ownerMetaClass.pickMethod(methodName, argClasses);
- if (method != null) return ownerMetaClass.invokeMethod(owner, methodName, originalArguments);
- }
- if (method == null && delegate != closure && delegate != null) {
- MetaClass delegateMetaClass = lookupObjectMetaClass(delegate);
- method = delegateMetaClass.pickMethod(methodName, argClasses);
- if (method != null)
- return delegateMetaClass.invokeMethod(delegate, methodName, originalArguments);
- }
- if (method == null && resolveStrategy != Closure.TO_SELF) {
- // still no methods found, test if delegate or owner are GroovyObjects
- // and invoke the method on them if so.
- MissingMethodException last = null;
- if (isClosureNotOwner && (owner instanceof GroovyObject)) {
- try {
- return invokeMethodOnGroovyObject(methodName, originalArguments, owner);
- } catch (MissingMethodException mme) {
- if (methodName.equals(mme.getMethod())) {
- if (last == null) last = mme;
- } else {
- throw mme;
- }
- }
- catch (InvokerInvocationException iie) {
- if (iie.getCause() instanceof MissingMethodException) {
- MissingMethodException mme = (MissingMethodException) iie.getCause();
- if (methodName.equals(mme.getMethod())) {
- if (last == null) last = mme;
- } else {
- throw iie;
- }
- }
- else
- throw iie;
- }
- }
- if (delegate != closure && (delegate instanceof GroovyObject)) {
- try {
- return invokeMethodOnGroovyObject(methodName, originalArguments, delegate);
- } catch (MissingMethodException mme) {
- last = mme;
- }
- catch (InvokerInvocationException iie) {
- if (iie.getCause() instanceof MissingMethodException) {
- last = (MissingMethodException) iie.getCause();
- }
- else
- throw iie;
- }
- }
- if (last != null) return invokeMissingMethod(object, methodName, originalArguments, last, isCallToSuper);
- }
- }
- }
-
- if (method != null) {
- return method.doMethodInvoke(object, arguments);
- } else {
- return invokePropertyOrMissing(object, methodName, originalArguments, fromInsideClass, isCallToSuper);
- }
- }
-
- private MetaMethod tryListParamMetaMethod(Class sender, String methodName, boolean isCallToSuper, Object[] arguments) {
- MetaMethod method = null;
- if (arguments.length == 1 && arguments[0] instanceof List) {
- Object[] newArguments = ((List) arguments[0]).toArray();
- method = createTransformMetaMethod(getMethodWithCaching(sender, methodName, newArguments, isCallToSuper));
- }
- return method;
- }
-
- protected MetaMethod createTransformMetaMethod(MetaMethod method) {
- if (method == null) {
- return null;
- }
-
- return new TransformMetaMethod(method) {
- public Object invoke(Object object, Object[] arguments) {
- Object firstArgument = arguments[0];
- List list = (List) firstArgument;
- arguments = list.toArray();
- return super.invoke(object, arguments);
- }
- };
- }
-
- private Object invokePropertyOrMissing(Object object, String methodName, Object[] originalArguments, boolean fromInsideClass, boolean isCallToSuper) {
- // if no method was found, try to find a closure defined as a field of the class and run it
- Object value = null;
- final MetaProperty metaProperty = this.getMetaProperty(methodName, false);
- if (metaProperty != null)
- value = metaProperty.getProperty(object);
- else {
- if (object instanceof Map)
- value = ((Map)object).get(methodName);
- }
-
- if (value instanceof Closure) { // This test ensures that value != this If you ever change this ensure that value != this
- Closure closure = (Closure) value;
- MetaClass delegateMetaClass = closure.getMetaClass();
- return delegateMetaClass.invokeMethod(closure.getClass(), closure, CLOSURE_DO_CALL_METHOD, originalArguments, false, fromInsideClass);
- }
-
- if (object instanceof Script) {
- Object bindingVar = ((Script) object).getBinding().getVariables().get(methodName);
- if (bindingVar != null) {
- MetaClass bindingVarMC = ((MetaClassRegistryImpl) registry).getMetaClass(bindingVar);
- return bindingVarMC.invokeMethod(bindingVar, CLOSURE_CALL_METHOD, originalArguments);
- }
- }
- return invokeMissingMethod(object, methodName, originalArguments, null, isCallToSuper);
- }
-
- private MetaClass lookupObjectMetaClass(Object object) {
- if (object instanceof GroovyObject) {
- GroovyObject go = (GroovyObject) object;
- return go.getMetaClass();
- }
- Class ownerClass = object.getClass();
- if (ownerClass == Class.class) ownerClass = (Class) object;
- MetaClass metaClass = registry.getMetaClass(ownerClass);
- return metaClass;
- }
-
- private static Object invokeMethodOnGroovyObject(String methodName, Object[] originalArguments, Object owner) {
- GroovyObject go = (GroovyObject) owner;
- return go.invokeMethod(methodName, originalArguments);
- }
-
- public MetaMethod getMethodWithCaching(Class sender, String methodName, Object[] arguments, boolean isCallToSuper) {
- // let's try use the cache to find the method
- if (!isCallToSuper && GroovyCategorySupport.hasCategoryInCurrentThread()) {
- return getMethodWithoutCaching(sender, methodName, MetaClassHelper.convertToTypeArray(arguments), isCallToSuper);
- } else {
- final MetaMethodIndex.Entry e = metaMethodIndex.getMethods(sender, methodName);
- if (e == null)
- return null;
-
- return isCallToSuper ? getSuperMethodWithCaching(arguments, e) : getNormalMethodWithCaching(arguments, e);
- }
- }
-
- private static boolean sameClasses(Class[] params, Class[] arguments) {
- // we do here a null check because the params field might not have been set yet
- if (params == null) return false;
-
- if (params.length != arguments.length)
- return false;
-
- for (int i = params.length - 1; i >= 0; i--) {
- Object arg = arguments[i];
- if (arg != null) {
- if (params[i] != arguments[i]) return false;
- } else return false;
- }
-
- return true;
- }
-
- // This method should be called by CallSite only
- private MetaMethod getMethodWithCachingInternal (Class sender, CallSite site, Class [] params) {
- if (GroovyCategorySupport.hasCategoryInCurrentThread())
- return getMethodWithoutCaching(sender, site.getName (), params, false);
-
- final MetaMethodIndex.Entry e = metaMethodIndex.getMethods(sender, site.getName());
- if (e == null) {
- return null;
- }
-
- MetaMethodIndex.CacheEntry cacheEntry;
- final Object methods = e.methods;
- if (methods == null)
- return null;
-
- cacheEntry = e.cachedMethod;
- if (cacheEntry != null && (sameClasses(cacheEntry.params, params))) {
- return cacheEntry.method;
- }
-
- cacheEntry = new MetaMethodIndex.CacheEntry (params, (MetaMethod) chooseMethod(e.name, methods, params));
- e.cachedMethod = cacheEntry;
- return cacheEntry.method;
- }
-
- private MetaMethod getSuperMethodWithCaching(Object[] arguments, MetaMethodIndex.Entry e) {
- MetaMethodIndex.CacheEntry cacheEntry;
- if (e.methodsForSuper == null)
- return null;
-
- cacheEntry = e.cachedMethodForSuper;
-
- if (cacheEntry != null &&
- MetaClassHelper.sameClasses(cacheEntry.params, arguments, e.methodsForSuper instanceof MetaMethod))
- {
- MetaMethod method = cacheEntry.method;
- if (method!=null) return method;
- }
-
- final Class[] classes = MetaClassHelper.convertToTypeArray(arguments);
- MetaMethod method = (MetaMethod) chooseMethod(e.name, e.methodsForSuper, classes);
- cacheEntry = new MetaMethodIndex.CacheEntry (classes, method.isAbstract()?null:method);
-
- e.cachedMethodForSuper = cacheEntry;
-
- return cacheEntry.method;
- }
-
- private MetaMethod getNormalMethodWithCaching(Object[] arguments, MetaMethodIndex.Entry e) {
- MetaMethodIndex.CacheEntry cacheEntry;
- final Object methods = e.methods;
- if (methods == null)
- return null;
-
- cacheEntry = e.cachedMethod;
-
- if (cacheEntry != null &&
- MetaClassHelper.sameClasses(cacheEntry.params, arguments, methods instanceof MetaMethod))
- {
- MetaMethod method = cacheEntry.method;
- if (method!=null) return method;
- }
-
- final Class[] classes = MetaClassHelper.convertToTypeArray(arguments);
- cacheEntry = new MetaMethodIndex.CacheEntry (classes, (MetaMethod) chooseMethod(e.name, methods, classes));
-
- e.cachedMethod = cacheEntry;
-
- return cacheEntry.method;
- }
-
- public Constructor retrieveConstructor(Class[] arguments) {
- CachedConstructor constructor = (CachedConstructor) chooseMethod("<init>", constructors, arguments);
- if (constructor != null) {
- return constructor.cachedConstructor;
- }
- constructor = (CachedConstructor) chooseMethod("<init>", constructors, arguments);
- if (constructor != null) {
- return constructor.cachedConstructor;
- }
- return null;
- }
-
- public MetaMethod retrieveStaticMethod(String methodName, Object[] arguments) {
- final MetaMethodIndex.Entry e = metaMethodIndex.getMethods(theClass, methodName);
- MetaMethodIndex.CacheEntry cacheEntry;
- if (e != null) {
- cacheEntry = e.cachedStaticMethod;
-
- if (cacheEntry != null &&
- MetaClassHelper.sameClasses(cacheEntry.params, arguments, e.staticMethods instanceof MetaMethod))
- {
- return cacheEntry.method;
- }
-
- final Class[] classes = MetaClassHelper.convertToTypeArray(arguments);
- cacheEntry = new MetaMethodIndex.CacheEntry (classes, pickStaticMethod(methodName, classes));
-
- e.cachedStaticMethod = cacheEntry;
-
- return cacheEntry.method;
- }
- else
- return pickStaticMethod(methodName, MetaClassHelper.convertToTypeArray(arguments));
- }
-
- public MetaMethod getMethodWithoutCaching(Class sender, String methodName, Class[] arguments, boolean isCallToSuper) {
- MetaMethod method = null;
- Object methods = getMethods(sender, methodName, isCallToSuper);
- if (methods != null) {
- method = (MetaMethod) chooseMethod(methodName, methods, arguments);
- }
- return method;
- }
-
- public Object invokeStaticMethod(Object object, String methodName, Object[] arguments) {
- checkInitalised();
-
- final Class sender = object instanceof Class ? (Class) object : object.getClass();
- if (sender != theClass) {
- MetaClass mc = registry.getMetaClass(sender);
- return mc.invokeStaticMethod(sender, methodName, arguments);
- }
- if (sender == Class.class) {
- return invokeMethod(object, methodName, arguments);
- }
-
- if (arguments == null) arguments = EMPTY_ARGUMENTS;
-// Class[] argClasses = MetaClassHelper.convertToTypeArray(arguments);
-
- MetaMethod method = retrieveStaticMethod(methodName, arguments);
- // let's try use the cache to find the method
-
- if (method != null) {
- MetaClassHelper.unwrap(arguments);
- return method.doMethodInvoke(object, arguments);
- }
- Object prop = null;
- try {
- prop = getProperty(theClass, theClass, methodName, false, false);
- } catch (MissingPropertyException mpe) {
- // ignore
- }
-
- if (prop instanceof Closure) {
- return invokeStaticClosureProperty(arguments, prop);
- }
-
- Object[] originalArguments = arguments.clone();
- MetaClassHelper.unwrap(arguments);
-
- Class superClass = sender.getSuperclass();
- Class[] argClasses = MetaClassHelper.convertToTypeArray(arguments);
- while (superClass != Object.class && superClass != null) {
- MetaClass mc = registry.getMetaClass(superClass);
- method = mc.getStaticMetaMethod(methodName, argClasses);
- if (method != null) return method.doMethodInvoke(object, arguments);
-
- try {
- prop = mc.getProperty(superClass, superClass, methodName, false, false);
- } catch (MissingPropertyException mpe) {
- // ignore
- }
-
- if (prop instanceof Closure) {
- return invokeStaticClosureProperty(originalArguments, prop);
- }
-
- superClass = superClass.getSuperclass();
- }
-
- if (prop != null) {
- MetaClass propMC = registry.getMetaClass(prop.getClass());
- return propMC.invokeMethod(prop, CLOSURE_CALL_METHOD, arguments);
- }
-
- return invokeStaticMissingMethod(sender, methodName, arguments);
- }
-
- private static Object invokeStaticClosureProperty(Object[] originalArguments, Object prop) {
- Closure closure = (Closure) prop;
- MetaClass delegateMetaClass = closure.getMetaClass();
- return delegateMetaClass.invokeMethod(closure.getClass(), closure, CLOSURE_DO_CALL_METHOD, originalArguments, false, false);
- }
-
- private Object invokeStaticMissingMethod(Class sender, String methodName, Object[] arguments) {
- MetaMethod metaMethod = getStaticMetaMethod(STATIC_METHOD_MISSING, METHOD_MISSING_ARGS);
- if (metaMethod != null) {
- return metaMethod.invoke(sender, new Object[]{methodName, arguments});
- }
- throw new MissingMethodException(methodName, sender, arguments, true);
- }
-
- private MetaMethod pickStaticMethod(String methodName, Class[] arguments) {
- MetaMethod method = null;
- MethodSelectionException mse = null;
- Object methods = getStaticMethods(theClass, methodName);
-
- if (!(methods instanceof FastArray) || !((FastArray)methods).isEmpty()) {
- try {
- method = (MetaMethod) chooseMethod(methodName, methods, arguments);
- } catch(MethodSelectionException msex) {
- mse = msex;
- }
- }
- if (method == null && theClass != Class.class) {
- MetaClass classMetaClass = registry.getMetaClass(Class.class);
- method = classMetaClass.pickMethod(methodName, arguments);
- }
- if (method == null) {
- method = (MetaMethod) chooseMethod(methodName, methods, MetaClassHelper.convertToTypeArray(arguments));
- }
-
- if (method == null && mse != null) {
- throw mse;
- } else {
- return method;
- }
- }
-
- public Object invokeConstructor(Object[] arguments) {
- return invokeConstructor(theClass, arguments);
- }
-
- public int selectConstructorAndTransformArguments(int numberOfConstructors, Object[] arguments) {
- if (numberOfConstructors==-1) {
- return selectConstructorAndTransformArguments1(arguments);
- } else {
- // falling back to pre 2.1.9 selection algorithm
- // in practice this branch will only be reached if the class calling this code is a Groovy class
- // compiled with an earlier version of the Groovy compiler
- return selectConstructorAndTransformArguments0(numberOfConstructors, arguments);
- }
-
-
- }
-
- private int selectConstructorAndTransformArguments0(final int numberOfConstructors, Object[] arguments) {
- //TODO: that is just a quick prototype, not the real thing!
- if (numberOfConstructors != constructors.size()) {
- throw new IncompatibleClassChangeError("the number of constructors during runtime and compile time for " +
- this.theClass.getName() + " do not match. Expected " + numberOfConstructors + " but got " + constructors.size());
- }
-
- CachedConstructor constructor = createCachedConstructor(arguments);
- List l = new ArrayList(constructors.toList());
- Comparator comp = new Comparator() {
- public int compare(Object arg0, Object arg1) {
- CachedConstructor c0 = (CachedConstructor) arg0;
- CachedConstructor c1 = (CachedConstructor) arg1;
- String descriptor0 = BytecodeHelper.getMethodDescriptor(Void.TYPE, c0.getNativeParameterTypes());
- String descriptor1 = BytecodeHelper.getMethodDescriptor(Void.TYPE, c1.getNativeParameterTypes());
- return descriptor0.compareTo(descriptor1);
- }
- };
- Collections.sort(l, comp);
- int found = -1;
- for (int i = 0; i < l.size(); i++) {
- if (l.get(i) != constructor) continue;
- found = i;
- break;
- }
- // NOTE: must be changed to "1 |" if constructor was vargs
- return 0 | (found << 8);
- }
-
- private CachedConstructor createCachedConstructor(Object[] arguments) {
- if (arguments == null) arguments = EMPTY_ARGUMENTS;
- Class[] argClasses = MetaClassHelper.convertToTypeArray(arguments);
- MetaClassHelper.unwrap(arguments);
- CachedConstructor constructor = (CachedConstructor) chooseMethod("<init>", constructors, argClasses);
- if (constructor == null) {
- constructor = (CachedConstructor) chooseMethod("<init>", constructors, argClasses);
- }
- if (constructor == null) {
- throw new GroovyRuntimeException(
- "Could not find matching constructor for: "
- + theClass.getName()
- + "(" + InvokerHelper.toTypeString(arguments) + ")");
- }
- return constructor;
- }
-
- /**
- * Constructor selection algorithm for Groovy 2.1.9+.
- * This selection algorithm was introduced as a workaround for GROOVY-6080. Instead of generating an index between
- * 0 and N where N is the number of super constructors at the time the class is compiled, this algorithm uses
- * a hash of the constructor descriptor instead.
- *
- * This has the advantage of letting the super class add new constructors while being binary compatible. But there
- * are still problems with this approach:
- * <ul>
- * <li>There's a risk of hash collision, even if it's very low (two constructors of the same class must have the same hash)</li>
- * <li>If the super class adds a new constructor which takes as an argument a superclass of an existing constructor parameter and
- * that this new constructor is selected at runtime, it would not find it.</li>
- * </ul>
- *
- * Hopefully in the last case, the error message is much nicer now since it explains that it's a binary incompatible change.
- *
- * @param arguments the actual constructor call arguments
- * @return a hash used to identify the constructor to be called
- * @since 2.1.9
- */
- private int selectConstructorAndTransformArguments1(Object[] arguments) {
- CachedConstructor constructor = createCachedConstructor(arguments);
- final String methodDescriptor = BytecodeHelper.getMethodDescriptor(Void.TYPE, constructor.getNativeParameterTypes());
- // keeping 3 bits for additional information such as vargs
- return BytecodeHelper.hashCode(methodDescriptor);
- }
-
-
- /**
- * checks if the initialisation of the class id complete.
- * This method should be called as a form of assert, it is no
- * way to test if there is still initialisation work to be done.
- * Such logic must be implemented in a different way.
- *
- * @throws IllegalStateException if the initialisation is incomplete yet
- */
- protected void checkInitalised() {
- if (!isInitialized())
- throw new IllegalStateException(
- "initialize must be called for meta " +
- "class of " + theClass +
- "(" + this.getClass() + ") " +
- "to complete initialisation process " +
- "before any invocation or field/property " +
- "access can be done");
- }
-
- /**
- * This is a helper class introduced in Groovy 2.1.0, which is used only by
- * indy. This class is for internal use only.
- * @since Groovy 2.1.0
- */
- public static final class MetaConstructor extends MetaMethod {
- private final CachedConstructor cc;
- private final boolean beanConstructor;
- private MetaConstructor(CachedConstructor cc, boolean bean) {
- super(cc.getNativeParameterTypes());
- this.setParametersTypes(cc.getParameterTypes());
- this.cc = cc;
- this.beanConstructor = bean;
- }
- @Override
- public int getModifiers() { return cc.getModifiers(); }
- @Override
- public String getName() { return "<init>"; }
- @Override
- public Class getReturnType() { return cc.getCachedClass().getTheClass(); }
- @Override
- public CachedClass getDeclaringClass() { return cc.getCachedClass(); }
- @Override
- public Object invoke(Object object, Object[] arguments) {
- return cc.doConstructorInvoke(arguments);
- }
- public CachedConstructor getCachedConstrcutor() { return cc; }
- public boolean isBeanConstructor() { return beanConstructor; }
- }
-
- /**
- * This is a helper method added in Groovy 2.1.0, which is used only by indy.
- * This method is for internal use only.
- * @since Groovy 2.1.0
- */
- public MetaMethod retrieveConstructor(Object[] arguments) {
- checkInitalised();
- if (arguments == null) arguments = EMPTY_ARGUMENTS;
- Class[] argClasses = MetaClassHelper.convertToTypeArray(arguments);
- MetaClassHelper.unwrap(arguments);
- Object res = chooseMethod("<init>", constructors, argClasses);
- if (res instanceof MetaMethod) return (MetaMethod) res;
- CachedConstructor constructor = (CachedConstructor) res;
- if (constructor != null) return new MetaConstructor(constructor, false);
- if (arguments.length == 1 && arguments[0] instanceof Map) {
- res = chooseMethod("<init>", constructors, MetaClassHelper.EMPTY_TYPE_ARRAY);
- } else if (
- arguments.length == 2 && arguments[1] instanceof Map &&
- theClass.getEnclosingClass()!=null &&
- theClass.getEnclosingClass().isAssignableFrom(argClasses[0]))
- {
- res = chooseMethod("<init>", constructors, new Class[]{argClasses[0]});
- }
- if (res instanceof MetaMethod) return (MetaMethod) res;
- constructor = (CachedConstructor) res;
- if (constructor != null) return new MetaConstructor(constructor, true);
-
- return null;
- }
-
- private Object invokeConstructor(Class at, Object[] arguments) {
- checkInitalised();
- if (arguments == null) arguments = EMPTY_ARGUMENTS;
- Class[] argClasses = MetaClassHelper.convertToTypeArray(arguments);
- MetaClassHelper.unwrap(arguments);
- CachedConstructor constructor = (CachedConstructor) chooseMethod("<init>", constructors, argClasses);
- if (constructor != null) {
- return constructor.doConstructorInvoke(arguments);
- }
-
- if (arguments.length == 1) {
- Object firstArgument = arguments[0];
- if (firstArgument instanceof Map) {
- constructor = (CachedConstructor) chooseMethod("<init>", constructors, MetaClassHelper.EMPTY_TYPE_ARRAY);
- if (constructor != null) {
- Object bean = constructor.doConstructorInvoke(MetaClassHelper.EMPTY_ARRAY);
- setProperties(bean, ((Map) firstArgument));
- return bean;
- }
- }
- }
- throw new GroovyRuntimeException(
- "Could not find matching constructor for: "
- + theClass.getName()
- + "(" + InvokerHelper.toTypeString(arguments) + ")");
- }
-
- /**
- * Sets a number of bean properties from the given Map where the keys are
- * the String names of properties and the values are the values of the
- * properties to set
- */
- public void setProperties(Object bean, Map map) {
- checkInitalised();
- for (Iterator iter = map.entrySet().iterator(); iter.hasNext();) {
- Map.Entry entry = (Map.Entry) iter.next();
- String key = entry.getKey().toString();
-
- Object value = entry.getValue();
- setProperty(bean, key, value);
- }
- }
-
- /**
- * @return the given property's value on the object
- */
- public Object getProperty(Class sender, Object object, String name, boolean useSuper, boolean fromInsideClass) {
-
- //----------------------------------------------------------------------
- // handling of static
- //----------------------------------------------------------------------
- boolean isStatic = theClass != Class.class && object instanceof Class;
- if (isStatic && object != theClass) {
- MetaClass mc = registry.getMetaClass((Class) object);
- return mc.getProperty(sender, object, name, useSuper, false);
- }
-
- checkInitalised();
-
- //----------------------------------------------------------------------
- // turn getProperty on a Map to get on the Map itself
- //----------------------------------------------------------------------
- if (!isStatic && this.isMap) {
- return ((Map) object).get(name);
- }
-
- Tuple2<MetaMethod, MetaProperty> methodAndProperty = createMetaMethodAndMetaProperty(sender, sender, name, useSuper, isStatic);
- MetaMethod method = methodAndProperty.getFirst();
-
- //----------------------------------------------------------------------
- // getter
- //----------------------------------------------------------------------
- MetaProperty mp = methodAndProperty.getSecond();
-
- //----------------------------------------------------------------------
- // field
- //----------------------------------------------------------------------
- if (method == null && mp != null) {
- try {
- return mp.getProperty(object);
- } catch (IllegalArgumentException e) {
- // can't access the field directly but there may be a getter
- mp = null;
- } catch (CacheAccessControlException e) {
- // can't access the field directly but there may be a getter
- mp = null;
- }
- }
-
- //----------------------------------------------------------------------
- // generic get method
- //----------------------------------------------------------------------
- // check for a generic get method provided through a category
- Object[] arguments = EMPTY_ARGUMENTS;
- if (method == null && !useSuper && !isStatic && GroovyCategorySupport.hasCategoryInCurrentThread()) {
- method = getCategoryMethodGetter(sender, "get", true);
- if (method != null) arguments = new Object[]{name};
- }
-
- // the generic method is valid, if available (!=null), if static or
- // if it is not static and we do no static access
- if (method == null && genericGetMethod != null && !(!genericGetMethod.isStatic() && isStatic)) {
- arguments = new Object[]{name};
- method = genericGetMethod;
- }
-
- //----------------------------------------------------------------------
- // special cases
- //----------------------------------------------------------------------
- if (method == null) {
- /** todo these special cases should be special MetaClasses maybe */
- if (theClass != Class.class && object instanceof Class) {
- MetaClass mc = registry.getMetaClass(Class.class);
- return mc.getProperty(Class.class, object, name, useSuper, false);
- } else if (object instanceof Collection) {
- return DefaultGroovyMethods.getAt((Collection) object, name);
- } else if (object instanceof Object[]) {
- return DefaultGroovyMethods.getAt(Arrays.asList((Object[]) object), name);
- } else {
- MetaMethod addListenerMethod = listeners.get(name);
- if (addListenerMethod != null) {
- //TODO: one day we could try return the previously registered Closure listener for easy removal
- return null;
- }
- }
- } else {
-
- //----------------------------------------------------------------------
- // executing the getter method
- //----------------------------------------------------------------------
- return method.doMethodInvoke(object, arguments);
- }
-
- //----------------------------------------------------------------------
- // error due to missing method/field
- //----------------------------------------------------------------------
- if (isStatic || object instanceof Class)
- return invokeStaticMissingProperty(object, name, null, true);
- else
- return invokeMissingProperty(object, name, null, true);
- }
-
- public MetaProperty getEffectiveGetMetaProperty(final Class sender, final Object object, String name, final boolean useSuper) {
-
- //----------------------------------------------------------------------
- // handling of static
- //----------------------------------------------------------------------
- boolean isStatic = theClass != Class.class && object instanceof Class;
- if (isStatic && object != theClass) {
- return new MetaProperty(name, Object.class) {
- final MetaClass mc = registry.getMetaClass((Class) object);
-
- public Object getProperty(Object object) {
- return mc.getProperty(sender, object, name, useSuper,false);
- }
-
- publ
<TRUNCATED>