Search in sources :

Example 21 with MethodClosure

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

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 22 with MethodClosure

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

the class ScriptTest method testInvokeMethodFallsThroughToMethodClosureInBinding.

/**
 * When a method is not found in the current script, checks that it's possible to call a method closure from the binding.
 *
 * @throws IOException
 * @throws CompilationFailedException
 * @throws IllegalAccessException
 * @throws InstantiationException
 */
public void testInvokeMethodFallsThroughToMethodClosureInBinding() throws IOException, CompilationFailedException, IllegalAccessException, InstantiationException {
    String text = "if (method() == 3) { println 'succeeded' }";
    GroovyCodeSource codeSource = new GroovyCodeSource(text, "groovy.script", "groovy.script");
    GroovyClassLoader loader = new GroovyClassLoader(Thread.currentThread().getContextClassLoader());
    Class clazz = loader.parseClass(codeSource);
    Script script = ((Script) clazz.newInstance());
    Binding binding = new Binding();
    binding.setVariable("method", new MethodClosure(new Dummy(), "method"));
    script.setBinding(binding);
    script.run();
}
Also used : MethodClosure(org.codehaus.groovy.runtime.MethodClosure)

Example 23 with MethodClosure

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

the class GroovyScriptEngineImpl method eval.

// package-privates
Object eval(Class scriptClass, final ScriptContext ctx) throws ScriptException {
    // Only initialize once.
    if (null == ctx.getAttribute("context", ScriptContext.ENGINE_SCOPE)) {
        // add context to bindings
        ctx.setAttribute("context", ctx, ScriptContext.ENGINE_SCOPE);
        // direct output to ctx.getWriter
        // If we're wrapping with a PrintWriter here,
        // enable autoFlush because otherwise it might not get done!
        final Writer writer = ctx.getWriter();
        ctx.setAttribute("out", (writer instanceof PrintWriter) ? writer : new PrintWriter(writer, true), ScriptContext.ENGINE_SCOPE);
    // Not going to do this after all (at least for now).
    // Scripts can use context.{reader, writer, errorWriter}.
    // That is a modern version of System.{in, out, err} or Console.{reader, writer}().
    // 
    // // New I/O names consistent with ScriptContext and java.io.Console.
    // 
    // ctx.setAttribute("writer", writer, ScriptContext.ENGINE_SCOPE);
    // 
    // // Direct errors to ctx.getErrorWriter
    // final Writer errorWriter = ctx.getErrorWriter();
    // ctx.setAttribute("errorWriter", (errorWriter instanceof PrintWriter) ?
    // errorWriter :
    // new PrintWriter(errorWriter),
    // ScriptContext.ENGINE_SCOPE);
    // 
    // // Get input from ctx.getReader
    // // We don't wrap with BufferedReader here because we expect that if
    // // the host wants that they do it.  Either way Groovy scripts will
    // // always have readLine because the GDK supplies it for Reader.
    // ctx.setAttribute("reader", ctx.getReader(), ScriptContext.ENGINE_SCOPE);
    }
    // Fix for GROOVY-3669: Can't use several times the same JSR-223 ScriptContext for differents groovy script
    if (ctx.getWriter() != null) {
        ctx.setAttribute("out", new PrintWriter(ctx.getWriter(), true), ScriptContext.ENGINE_SCOPE);
    }
    /*
         * We use the following Binding instance so that global variable lookup
         * will be done in the current ScriptContext instance.
         */
    Binding binding = new Binding(ctx.getBindings(ScriptContext.ENGINE_SCOPE)) {

        @Override
        public Object getVariable(String name) {
            synchronized (ctx) {
                int scope = ctx.getAttributesScope(name);
                if (scope != -1) {
                    return ctx.getAttribute(name, scope);
                }
            }
            throw new MissingPropertyException(name, getClass());
        }

        @Override
        public void setVariable(String name, Object value) {
            synchronized (ctx) {
                int scope = ctx.getAttributesScope(name);
                if (scope == -1) {
                    scope = ScriptContext.ENGINE_SCOPE;
                }
                ctx.setAttribute(name, value, scope);
            }
        }
    };
    try {
        // then simply return that class
        if (!Script.class.isAssignableFrom(scriptClass)) {
            return scriptClass;
        } else {
            // it's a script
            Script scriptObject = InvokerHelper.createScript(scriptClass, binding);
            // save all current closures into global closures map
            Method[] methods = scriptClass.getMethods();
            for (Method m : methods) {
                String name = m.getName();
                globalClosures.put(name, new MethodClosure(scriptObject, name));
            }
            MetaClass oldMetaClass = scriptObject.getMetaClass();
            /*
                * We override the MetaClass of this script object so that we can
                * forward calls to global closures (of previous or future "eval" calls)
                * This gives the illusion of working on the same "global" scope.
                */
            scriptObject.setMetaClass(new DelegatingMetaClass(oldMetaClass) {

                @Override
                public Object invokeMethod(Object object, String name, Object args) {
                    if (args == null) {
                        return invokeMethod(object, name, MetaClassHelper.EMPTY_ARRAY);
                    }
                    if (args instanceof Tuple) {
                        return invokeMethod(object, name, ((Tuple) args).toArray());
                    }
                    if (args instanceof Object[]) {
                        return invokeMethod(object, name, (Object[]) args);
                    } else {
                        return invokeMethod(object, name, new Object[] { args });
                    }
                }

                @Override
                public Object invokeMethod(Object object, String name, Object[] args) {
                    try {
                        return super.invokeMethod(object, name, args);
                    } catch (MissingMethodException mme) {
                        return callGlobal(name, args, ctx);
                    }
                }

                @Override
                public Object invokeStaticMethod(Object object, String name, Object[] args) {
                    try {
                        return super.invokeStaticMethod(object, name, args);
                    } catch (MissingMethodException mme) {
                        return callGlobal(name, args, ctx);
                    }
                }
            });
            return scriptObject.run();
        }
    } catch (Exception e) {
        throw new ScriptException(e);
    } finally {
        // Fix for GROOVY-3669: Can't use several times the same JSR-223 ScriptContext for different groovy script
        // Groovy's scripting engine implementation adds those two variables in the binding
        // but should clean up afterwards
        ctx.removeAttribute("context", ScriptContext.ENGINE_SCOPE);
        ctx.removeAttribute("out", ScriptContext.ENGINE_SCOPE);
    }
}
Also used : Binding(groovy.lang.Binding) Script(groovy.lang.Script) CompiledScript(javax.script.CompiledScript) MissingPropertyException(groovy.lang.MissingPropertyException) String(java.lang.String) Method(java.lang.reflect.Method) MethodClosure(org.codehaus.groovy.runtime.MethodClosure) MissingPropertyException(groovy.lang.MissingPropertyException) ScriptException(javax.script.ScriptException) MissingMethodException(groovy.lang.MissingMethodException) IOException(java.io.IOException) CompilationFailedException(org.codehaus.groovy.control.CompilationFailedException) SyntaxException(org.codehaus.groovy.syntax.SyntaxException) ScriptException(javax.script.ScriptException) MissingMethodException(groovy.lang.MissingMethodException) MetaClass(groovy.lang.MetaClass) DelegatingMetaClass(groovy.lang.DelegatingMetaClass) DelegatingMetaClass(groovy.lang.DelegatingMetaClass) PrintWriter(java.io.PrintWriter) Writer(java.io.Writer) Tuple(groovy.lang.Tuple) PrintWriter(java.io.PrintWriter)

Example 24 with MethodClosure

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

the class ServletBinding method lazyInit.

private void lazyInit() {
    if (initialized)
        return;
    initialized = true;
    HttpServletResponse response = (HttpServletResponse) super.getVariable("response");
    ServletOutput output = new ServletOutput(response);
    super.setVariable("out", output.getWriter());
    super.setVariable("sout", output.getOutputStream());
    MarkupBuilder builder = new MarkupBuilder(output.getWriter());
    builder.setExpandEmptyElements(true);
    super.setVariable("html", builder);
    try {
        Class jsonBuilderClass = this.getClass().getClassLoader().loadClass("groovy.json.StreamingJsonBuilder");
        Constructor writerConstructor = jsonBuilderClass.getConstructor(Writer.class);
        super.setVariable("json", writerConstructor.newInstance(output.getWriter()));
    } catch (Throwable t) {
        t.printStackTrace();
    }
    // bind forward method
    MethodClosure c = new MethodClosure(this, "forward");
    super.setVariable("forward", c);
    // bind include method
    c = new MethodClosure(this, "include");
    super.setVariable("include", c);
    // bind redirect method
    c = new MethodClosure(this, "redirect");
    super.setVariable("redirect", c);
}
Also used : Constructor(java.lang.reflect.Constructor) HttpServletResponse(javax.servlet.http.HttpServletResponse) MarkupBuilder(groovy.xml.MarkupBuilder) MethodClosure(org.codehaus.groovy.runtime.MethodClosure)

Example 25 with MethodClosure

use of org.codehaus.groovy.runtime.MethodClosure in project gremlin by tinkerpop.

the class GremlinGroovyScriptEngine method eval.

Object eval(final Class scriptClass, final ScriptContext context) throws ScriptException {
    this.checkClearCache();
    context.setAttribute("context", context, ScriptContext.ENGINE_SCOPE);
    java.io.Writer writer = context.getWriter();
    context.setAttribute("out", writer instanceof PrintWriter ? writer : new PrintWriter(writer), ScriptContext.ENGINE_SCOPE);
    Binding binding = new Binding() {

        public Object getVariable(String name) {
            synchronized (context) {
                int scope = context.getAttributesScope(name);
                if (scope != -1) {
                    return context.getAttribute(name, scope);
                }
                throw new MissingPropertyException(name, getClass());
            }
        }

        public void setVariable(String name, Object value) {
            synchronized (context) {
                int scope = context.getAttributesScope(name);
                if (scope == -1) {
                    scope = ScriptContext.ENGINE_SCOPE;
                }
                context.setAttribute(name, value, scope);
            }
        }
    };
    try {
        Script scriptObject = InvokerHelper.createScript(scriptClass, binding);
        Method[] methods = scriptClass.getMethods();
        Map<String, MethodClosure> closures = new HashMap<String, MethodClosure>();
        for (Method m : methods) {
            String name = m.getName();
            closures.put(name, new MethodClosure(scriptObject, name));
        }
        globalClosures.putAll(closures);
        final MetaClass oldMetaClass = scriptObject.getMetaClass();
        scriptObject.setMetaClass(new DelegatingMetaClass(oldMetaClass) {

            public Object invokeMethod(Object object, String name, Object args) {
                if (args == null) {
                    return invokeMethod(object, name, MetaClassHelper.EMPTY_ARRAY);
                } else if (args instanceof Tuple) {
                    return invokeMethod(object, name, ((Tuple) args).toArray());
                } else if (args instanceof Object[]) {
                    return invokeMethod(object, name, (Object[]) args);
                } else {
                    return invokeMethod(object, name, new Object[] { args });
                }
            }

            public Object invokeMethod(Object object, String name, Object[] args) {
                try {
                    return super.invokeMethod(object, name, args);
                } catch (MissingMethodException mme) {
                    return callGlobal(name, args, context);
                }
            }

            public Object invokeStaticMethod(Object object, String name, Object[] args) {
                try {
                    return super.invokeStaticMethod(object, name, args);
                } catch (MissingMethodException mme) {
                    return callGlobal(name, args, context);
                }
            }
        });
        return scriptObject.run();
    } catch (Exception e) {
        throw new ScriptException(e);
    }
}
Also used : Binding(groovy.lang.Binding) Script(groovy.lang.Script) CompiledScript(javax.script.CompiledScript) GroovyCompiledScript(org.codehaus.groovy.jsr223.GroovyCompiledScript) HashMap(java.util.HashMap) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) MissingPropertyException(groovy.lang.MissingPropertyException) Method(java.lang.reflect.Method) MethodClosure(org.codehaus.groovy.runtime.MethodClosure) MissingPropertyException(groovy.lang.MissingPropertyException) ScriptException(javax.script.ScriptException) MissingMethodException(groovy.lang.MissingMethodException) IOException(java.io.IOException) CompilationFailedException(org.codehaus.groovy.control.CompilationFailedException) SyntaxException(org.codehaus.groovy.syntax.SyntaxException) ScriptException(javax.script.ScriptException) MissingMethodException(groovy.lang.MissingMethodException) MetaClass(groovy.lang.MetaClass) DelegatingMetaClass(groovy.lang.DelegatingMetaClass) DelegatingMetaClass(groovy.lang.DelegatingMetaClass) Tuple(groovy.lang.Tuple) PrintWriter(java.io.PrintWriter)

Aggregations

MethodClosure (org.codehaus.groovy.runtime.MethodClosure)28 IOException (java.io.IOException)5 CachedClass (org.codehaus.groovy.reflection.CachedClass)5 GeneratedClosure (org.codehaus.groovy.runtime.GeneratedClosure)4 Test (org.junit.Test)4 Binding (groovy.lang.Binding)3 Closure (groovy.lang.Closure)3 DelegatingMetaClass (groovy.lang.DelegatingMetaClass)3 MetaClass (groovy.lang.MetaClass)3 MissingMethodException (groovy.lang.MissingMethodException)3 MissingPropertyException (groovy.lang.MissingPropertyException)3 Script (groovy.lang.Script)3 Tuple (groovy.lang.Tuple)3 PrintWriter (java.io.PrintWriter)3 Method (java.lang.reflect.Method)3 ArrayList (java.util.ArrayList)3 CompiledScript (javax.script.CompiledScript)3 ScriptException (javax.script.ScriptException)3 CompilationFailedException (org.codehaus.groovy.control.CompilationFailedException)3 InvokerInvocationException (org.codehaus.groovy.runtime.InvokerInvocationException)3