Search in sources :

Example 1 with GeneratedClosure

use of org.codehaus.groovy.runtime.GeneratedClosure in project groovy by apache.

the class MetaClassImpl method invokeMethod.

/**
     * <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) {
                final MethodClosure mc = (MethodClosure) object;
                methodName = mc.getMethod();
                final Class ownerClass = owner instanceof Class ? (Class) owner : owner.getClass();
                final MetaClass ownerMetaClass = registry.getMetaClass(ownerClass);
                return ownerMetaClass.invokeMethod(ownerClass, owner, methodName, arguments, false, false);
            } 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);
    }
}
Also used : NewInstanceMetaMethod(org.codehaus.groovy.runtime.metaclass.NewInstanceMetaMethod) NewMetaMethod(org.codehaus.groovy.runtime.metaclass.NewMetaMethod) MixinInstanceMetaMethod(org.codehaus.groovy.runtime.metaclass.MixinInstanceMetaMethod) NewStaticMetaMethod(org.codehaus.groovy.runtime.metaclass.NewStaticMetaMethod) GeneratedMetaMethod(org.codehaus.groovy.reflection.GeneratedMetaMethod) ClosureMetaMethod(org.codehaus.groovy.runtime.metaclass.ClosureMetaMethod) TransformMetaMethod(org.codehaus.groovy.runtime.metaclass.TransformMetaMethod) MethodClosure(org.codehaus.groovy.runtime.MethodClosure) GeneratedClosure(org.codehaus.groovy.runtime.GeneratedClosure) CurriedClosure(org.codehaus.groovy.runtime.CurriedClosure) ConvertedClosure(org.codehaus.groovy.runtime.ConvertedClosure) InvokerInvocationException(org.codehaus.groovy.runtime.InvokerInvocationException) MethodClosure(org.codehaus.groovy.runtime.MethodClosure) GeneratedClosure(org.codehaus.groovy.runtime.GeneratedClosure) CurriedClosure(org.codehaus.groovy.runtime.CurriedClosure) CachedClass(org.codehaus.groovy.reflection.CachedClass)

Example 2 with GeneratedClosure

use of org.codehaus.groovy.runtime.GeneratedClosure in project gradle by gradle.

the class MixInClosurePropertiesAsMethodsDynamicObject method tryInvokeMethod.

@Override
public DynamicInvokeResult tryInvokeMethod(String name, Object... arguments) {
    DynamicInvokeResult result = super.tryInvokeMethod(name, arguments);
    if (result.isFound()) {
        return result;
    }
    DynamicInvokeResult propertyResult = tryGetProperty(name);
    if (propertyResult.isFound()) {
        Object property = propertyResult.getValue();
        if (property instanceof Closure) {
            Closure closure = (Closure) property;
            closure.setResolveStrategy(Closure.DELEGATE_FIRST);
            BeanDynamicObject dynamicObject = new BeanDynamicObject(closure);
            result = dynamicObject.tryInvokeMethod("doCall", arguments);
            if (!result.isFound() && !(closure instanceof GeneratedClosure)) {
                return DynamicInvokeResult.found(closure.call(arguments));
            }
            return result;
        }
    }
    return DynamicInvokeResult.notFound();
}
Also used : GeneratedClosure(org.codehaus.groovy.runtime.GeneratedClosure) Closure(groovy.lang.Closure) GeneratedClosure(org.codehaus.groovy.runtime.GeneratedClosure)

Example 3 with GeneratedClosure

use of org.codehaus.groovy.runtime.GeneratedClosure in project groovy-core by groovy.

the class ClosureMetaMethod method createMethodList.

public static List<MetaMethod> createMethodList(final String name, final Class declaringClass, final Closure closure) {
    List<MetaMethod> res = new ArrayList<MetaMethod>();
    if (closure instanceof MethodClosure) {
        MethodClosure methodClosure = (MethodClosure) closure;
        Object owner = closure.getOwner();
        Class ownerClass = (Class) (owner instanceof Class ? owner : owner.getClass());
        for (CachedMethod method : ReflectionCache.getCachedClass(ownerClass).getMethods()) {
            if (method.getName().equals(methodClosure.getMethod())) {
                MetaMethod metaMethod = new MethodClosureMetaMethod(name, declaringClass, closure, method);
                res.add(adjustParamTypesForStdMethods(metaMethod, name));
            }
        }
    } else {
        if (closure instanceof GeneratedClosure) {
            for (CachedMethod method : ReflectionCache.getCachedClass(closure.getClass()).getMethods()) {
                if (method.getName().equals("doCall")) {
                    MetaMethod metaMethod = new ClosureMetaMethod(name, declaringClass, closure, method);
                    res.add(adjustParamTypesForStdMethods(metaMethod, name));
                }
            }
        } else {
            MetaMethod metaMethod = new AnonymousMetaMethod(closure, name, declaringClass);
            res.add(adjustParamTypesForStdMethods(metaMethod, name));
        }
    }
    return res;
}
Also used : MetaMethod(groovy.lang.MetaMethod) ArrayList(java.util.ArrayList) CachedMethod(org.codehaus.groovy.reflection.CachedMethod) CachedClass(org.codehaus.groovy.reflection.CachedClass) MethodClosure(org.codehaus.groovy.runtime.MethodClosure) GeneratedClosure(org.codehaus.groovy.runtime.GeneratedClosure)

Example 4 with GeneratedClosure

use of org.codehaus.groovy.runtime.GeneratedClosure in project gradle by gradle.

the class ConfigureUtil method configureTarget.

private static <T> void configureTarget(Closure configureClosure, T target, ConfigureDelegate closureDelegate) {
    if (!(configureClosure instanceof GeneratedClosure)) {
        new ClosureBackedAction<T>(configureClosure, Closure.DELEGATE_FIRST, false).execute(target);
        return;
    }
    // Hackery to make closure execution faster, by short-circuiting the expensive property and method lookup on Closure
    Closure withNewOwner = configureClosure.rehydrate(target, closureDelegate, configureClosure.getThisObject());
    new ClosureBackedAction<T>(withNewOwner, Closure.OWNER_ONLY, false).execute(target);
}
Also used : GeneratedClosure(org.codehaus.groovy.runtime.GeneratedClosure) Closure(groovy.lang.Closure) GeneratedClosure(org.codehaus.groovy.runtime.GeneratedClosure)

Example 5 with GeneratedClosure

use of org.codehaus.groovy.runtime.GeneratedClosure in project gradle by gradle.

the class ConfigureUtil method configureTarget.

private static <T> void configureTarget(Closure configureClosure, T target, ConfigureDelegate closureDelegate) {
    if (!(configureClosure instanceof GeneratedClosure)) {
        new ClosureBackedAction<T>(configureClosure, Closure.DELEGATE_FIRST, false).execute(target);
        return;
    }
    // Hackery to make closure execution faster, by short-circuiting the expensive property and method lookup on Closure
    Closure withNewOwner = configureClosure.rehydrate(target, closureDelegate, configureClosure.getThisObject());
    new ClosureBackedAction<T>(withNewOwner, Closure.OWNER_ONLY, false).execute(target);
}
Also used : GeneratedClosure(org.codehaus.groovy.runtime.GeneratedClosure) Closure(groovy.lang.Closure) GeneratedClosure(org.codehaus.groovy.runtime.GeneratedClosure)

Aggregations

GeneratedClosure (org.codehaus.groovy.runtime.GeneratedClosure)10 Closure (groovy.lang.Closure)5 CachedClass (org.codehaus.groovy.reflection.CachedClass)4 MethodClosure (org.codehaus.groovy.runtime.MethodClosure)4 GeneratedMetaMethod (org.codehaus.groovy.reflection.GeneratedMetaMethod)3 ClosureMetaMethod (org.codehaus.groovy.runtime.metaclass.ClosureMetaMethod)3 MixinInstanceMetaMethod (org.codehaus.groovy.runtime.metaclass.MixinInstanceMetaMethod)3 NewInstanceMetaMethod (org.codehaus.groovy.runtime.metaclass.NewInstanceMetaMethod)3 NewMetaMethod (org.codehaus.groovy.runtime.metaclass.NewMetaMethod)3 NewStaticMetaMethod (org.codehaus.groovy.runtime.metaclass.NewStaticMetaMethod)3 TransformMetaMethod (org.codehaus.groovy.runtime.metaclass.TransformMetaMethod)3 MetaMethod (groovy.lang.MetaMethod)2 ArrayList (java.util.ArrayList)2 CachedMethod (org.codehaus.groovy.reflection.CachedMethod)2 ConvertedClosure (org.codehaus.groovy.runtime.ConvertedClosure)2 CurriedClosure (org.codehaus.groovy.runtime.CurriedClosure)2 InvokerInvocationException (org.codehaus.groovy.runtime.InvokerInvocationException)2 NamedDomainObjectContainer (org.gradle.api.NamedDomainObjectContainer)1 BeanDynamicObject (org.gradle.internal.metaobject.BeanDynamicObject)1 CompositeDynamicObject (org.gradle.internal.metaobject.CompositeDynamicObject)1