Search in sources :

Example 1 with ProxyMetaClass

use of groovy.lang.ProxyMetaClass in project groovy by apache.

the class ClosureMetaClass method invokeMethod.

@Override
public Object invokeMethod(final Class sender, final Object object, final String methodName, final Object[] originalArguments, final boolean isCallToSuper, final boolean fromInsideClass) {
    checkInitalised();
    if (object == null) {
        throw new NullPointerException("Cannot invoke method: " + methodName + " on null object");
    }
    final Object[] arguments = makeArguments(originalArguments, methodName);
    final Class<?>[] argClasses = MetaClassHelper.convertToTypeArray(arguments);
    unwrap(arguments);
    MetaMethod method = null;
    final Closure<?> closure = (Closure<?>) object;
    final int resolveStrategy = closure.getResolveStrategy();
    if (CLOSURE_DO_CALL_METHOD.equals(methodName) || CLOSURE_CALL_METHOD.equals(methodName)) {
        method = pickClosureMethod(argClasses);
        if (method == null && arguments.length == 1 && arguments[0] instanceof List) {
            Object[] newArguments = ((List<?>) arguments[0]).toArray();
            Class<?>[] newArgClasses = MetaClassHelper.convertToTypeArray(newArguments);
            method = createTransformMetaMethod(pickClosureMethod(newArgClasses));
        }
        if (method == null)
            throw new MissingMethodException(methodName, theClass, arguments, false);
    }
    boolean shouldDefer = resolveStrategy == Closure.DELEGATE_ONLY && isInternalMethod(methodName);
    if (method == null && !shouldDefer) {
        method = CLOSURE_METACLASS.pickMethod(methodName, argClasses);
    }
    if (method != null)
        return method.doMethodInvoke(object, arguments);
    MissingMethodException last = null;
    Object callObject = object;
    final Object owner = closure.getOwner();
    final Object delegate = closure.getDelegate();
    boolean invokeOnDelegate = false;
    boolean invokeOnOwner = false;
    boolean ownerFirst = true;
    switch(resolveStrategy) {
        case Closure.TO_SELF:
            break;
        case Closure.DELEGATE_ONLY:
            method = getDelegateMethod(closure, delegate, methodName, argClasses);
            callObject = delegate;
            if (method == null) {
                invokeOnDelegate = delegate != closure && (delegate instanceof GroovyObject);
            }
            break;
        case Closure.OWNER_ONLY:
            method = getDelegateMethod(closure, owner, methodName, argClasses);
            callObject = owner;
            if (method == null) {
                invokeOnOwner = owner != closure && (owner instanceof GroovyObject);
            }
            break;
        case Closure.DELEGATE_FIRST:
            method = getDelegateMethod(closure, delegate, methodName, argClasses);
            callObject = delegate;
            if (method == null) {
                invokeOnDelegate = delegate != closure;
                invokeOnOwner = owner != closure;
                ownerFirst = false;
            }
            break;
        default:
            // Closure.OWNER_FIRST:
            method = getDelegateMethod(closure, owner, methodName, argClasses);
            callObject = owner;
            if (method == null) {
                invokeOnDelegate = delegate != closure;
                invokeOnOwner = owner != closure;
                ownerFirst = true;
            }
            break;
    }
    if (method == null && (invokeOnOwner || invokeOnDelegate)) {
        try {
            if (ownerFirst) {
                return invokeOnDelegationObjects(invokeOnOwner, owner, invokeOnDelegate, delegate, methodName, arguments);
            } else {
                return invokeOnDelegationObjects(invokeOnDelegate, delegate, invokeOnOwner, owner, methodName, arguments);
            }
        } catch (MissingMethodException mme) {
            last = mme;
        }
    }
    if (method != null) {
        MetaClass metaClass = registry.getMetaClass(callObject.getClass());
        if (metaClass instanceof ProxyMetaClass) {
            return metaClass.invokeMethod(callObject, methodName, arguments);
        } else {
            return method.doMethodInvoke(callObject, arguments);
        }
    } else {
        // no method was found; try to find a closure defined as a field of the class and run it
        Object value = null;
        try {
            value = getProperty(sender, object, methodName, isCallToSuper, fromInsideClass);
        } catch (MissingPropertyException mpe) {
        // ignore
        }
        if (value instanceof Closure) {
            // This test ensures that value != this If you ever change this ensure that value != this
            Closure<?> cl = (Closure<?>) value;
            MetaClass delegateMetaClass = cl.getMetaClass();
            return delegateMetaClass.invokeMethod(cl.getClass(), closure, CLOSURE_DO_CALL_METHOD, originalArguments, false, fromInsideClass);
        }
    }
    throw last != null ? last : new MissingMethodException(methodName, theClass, arguments, false);
}
Also used : MetaMethod(groovy.lang.MetaMethod) Closure(groovy.lang.Closure) ProxyMetaClass(groovy.lang.ProxyMetaClass) MissingPropertyException(groovy.lang.MissingPropertyException) GroovyObject(groovy.lang.GroovyObject) MissingMethodException(groovy.lang.MissingMethodException) ExpandoMetaClass(groovy.lang.ExpandoMetaClass) ProxyMetaClass(groovy.lang.ProxyMetaClass) MetaClass(groovy.lang.MetaClass) GroovyObject(groovy.lang.GroovyObject) ExpandoMetaClass(groovy.lang.ExpandoMetaClass) ProxyMetaClass(groovy.lang.ProxyMetaClass) MetaClass(groovy.lang.MetaClass) CachedClass(org.codehaus.groovy.reflection.CachedClass) ArrayList(java.util.ArrayList) List(java.util.List)

Aggregations

Closure (groovy.lang.Closure)1 ExpandoMetaClass (groovy.lang.ExpandoMetaClass)1 GroovyObject (groovy.lang.GroovyObject)1 MetaClass (groovy.lang.MetaClass)1 MetaMethod (groovy.lang.MetaMethod)1 MissingMethodException (groovy.lang.MissingMethodException)1 MissingPropertyException (groovy.lang.MissingPropertyException)1 ProxyMetaClass (groovy.lang.ProxyMetaClass)1 ArrayList (java.util.ArrayList)1 List (java.util.List)1 CachedClass (org.codehaus.groovy.reflection.CachedClass)1