public Object call()

in src/main/java/org/apache/sling/scripting/core/impl/DefaultSlingScript.java [203:461]


    public Object call(SlingBindings props, String method, Object... args) {
        Bindings bindings = null;
        Reader reader = null;
        boolean disposeScriptHelper = !props.containsKey(SLING);
        ResourceResolver oldResolver = null;
        try {
            bindings = verifySlingBindings(props);

            // use final variable for inner class!
            final Bindings b = bindings;
            // create script context
            final ScriptContext ctx = new ScriptContext() {

                private Bindings globalScope;
                private Bindings engineScope = b;
                private Writer writer = (Writer) b.get(OUT);
                private Writer errorWriter = new LogWriter((Logger) b.get(LOG));
                private Reader reader = (Reader) b.get(READER);
                private Bindings slingScope = new LazyBindings();

                /**
                 * @see javax.script.ScriptContext#setBindings(javax.script.Bindings, int)
                 */
                public void setBindings(final Bindings bindings, final int scope) {
                    switch (scope) {
                        case SlingScriptConstants.SLING_SCOPE:
                            this.slingScope = bindings;
                            break;
                        case 100:
                            if (bindings == null) throw new NullPointerException("Bindings for ENGINE scope is null");
                            this.engineScope = bindings;
                            break;
                        case 200:
                            this.globalScope = bindings;
                            break;
                        default:
                            throw new IllegalArgumentException("Invalid scope");
                    }
                }

                /**
                 * @see javax.script.ScriptContext#getBindings(int)
                 */
                public Bindings getBindings(final int scope) {
                    switch (scope) {
                        case SlingScriptConstants.SLING_SCOPE:
                            return slingScope;
                        case 100:
                            return this.engineScope;
                        case 200:
                            return this.globalScope;
                        default:
                            throw new IllegalArgumentException("Invalid scope");
                    }
                }

                /**
                 * @see javax.script.ScriptContext#setAttribute(java.lang.String, java.lang.Object, int)
                 */
                public void setAttribute(final String name, final Object value, final int scope) {
                    if (name == null) throw new IllegalArgumentException("Name is null");
                    final Bindings bindings = getBindings(scope);
                    if (bindings != null) {
                        bindings.put(name, value);
                    }
                }

                /**
                 * @see javax.script.ScriptContext#getAttribute(java.lang.String, int)
                 */
                public Object getAttribute(final String name, final int scope) {
                    if (name == null) throw new IllegalArgumentException("Name is null");
                    final Bindings bindings = getBindings(scope);
                    if (bindings != null) {
                        return bindings.get(name);
                    }
                    return null;
                }

                /**
                 * @see javax.script.ScriptContext#removeAttribute(java.lang.String, int)
                 */
                public Object removeAttribute(final String name, final int scope) {
                    if (name == null) throw new IllegalArgumentException("Name is null");
                    final Bindings bindings = getBindings(scope);
                    if (bindings != null) {
                        return bindings.remove(name);
                    }
                    return null;
                }

                /**
                 * @see javax.script.ScriptContext#getAttribute(java.lang.String)
                 */
                public Object getAttribute(String name) {
                    if (name == null) throw new IllegalArgumentException("Name is null");
                    for (final int scope : SCOPES) {
                        final Bindings bindings = getBindings(scope);
                        if (bindings != null) {
                            final Object o = bindings.get(name);
                            if (o != null) {
                                return o;
                            }
                        }
                    }
                    return null;
                }

                /**
                 * @see javax.script.ScriptContext#getAttributesScope(java.lang.String)
                 */
                public int getAttributesScope(String name) {
                    if (name == null) throw new IllegalArgumentException("Name is null");
                    for (final int scope : SCOPES) {
                        if ((getBindings(scope) != null) && (getBindings(scope).containsKey(name))) {
                            return scope;
                        }
                    }
                    return -1;
                }

                /**
                 * @see javax.script.ScriptContext#getScopes()
                 */
                public List<Integer> getScopes() {
                    return Arrays.asList(SCOPES);
                }

                /**
                 * @see javax.script.ScriptContext#getWriter()
                 */
                public Writer getWriter() {
                    return this.writer;
                }

                /**
                 * @see javax.script.ScriptContext#getErrorWriter()
                 */
                public Writer getErrorWriter() {
                    return this.errorWriter;
                }

                /**
                 * @see javax.script.ScriptContext#setWriter(java.io.Writer)
                 */
                public void setWriter(Writer writer) {
                    this.writer = writer;
                }

                /**
                 * @see javax.script.ScriptContext#setErrorWriter(java.io.Writer)
                 */
                public void setErrorWriter(Writer writer) {
                    this.errorWriter = writer;
                }

                /**
                 * @see javax.script.ScriptContext#getReader()
                 */
                public Reader getReader() {
                    return this.reader;
                }

                /**
                 * @see javax.script.ScriptContext#setReader(java.io.Reader)
                 */
                public void setReader(Reader reader) {
                    this.reader = reader;
                }
            };

            // set the current resource resolver if a request is available from the bindings
            if (props.getRequest() != null) {
                oldResolver = requestResourceResolver.get();
                requestResourceResolver.set(props.getRequest().getResourceResolver());
            }

            // set the script resource resolver as an attribute
            ctx.setAttribute(
                    SlingScriptConstants.ATTR_SCRIPT_RESOURCE_RESOLVER,
                    this.scriptResource.getResourceResolver(),
                    SlingScriptConstants.SLING_SCOPE);

            reader = getScriptReader();
            if (method != null && !(this.scriptEngine instanceof Invocable)) {
                reader = getWrapperReader(reader, method, args);
            }

            // evaluate the script
            final Object result;
            if (method == null && this.scriptEngine instanceof Compilable) {
                CachedScript cachedScript = scriptCache.getScript(scriptName);
                if (cachedScript == null) {
                    ScriptNameAwareReader snReader = new ScriptNameAwareReader(reader, scriptName);
                    CompiledScript compiledScript = ((Compilable) scriptEngine).compile(snReader);
                    cachedScript = new CachedScriptImpl(scriptName, compiledScript);
                    scriptCache.putScript(cachedScript);
                    LOGGER.debug("Adding {} to the script cache.", scriptName);
                } else {
                    LOGGER.debug("Script {} was already cached.", scriptName);
                }
                result = cachedScript.getCompiledScript().eval(ctx);
            } else {
                result = scriptEngine.eval(reader, ctx);
            }

            // call method - if supplied and script engine supports direct invocation
            if (method != null && (this.scriptEngine instanceof Invocable)) {
                try {
                    ((Invocable) scriptEngine)
                            .invokeFunction(method, Arrays.asList(args).toArray());
                } catch (NoSuchMethodException e) {
                    throw new ScriptEvaluationException(
                            this.scriptName, "Method " + method + " not found in script.", e);
                }
            }
            // optional flush the output channel
            Object flushObject = bindings.get(FLUSH);
            if (Boolean.TRUE.equals(flushObject)) {
                ctx.getWriter().flush();
            }

            // allways flush the error channel
            ctx.getErrorWriter().flush();

            return result;

        } catch (IOException ioe) {
            throw new ScriptEvaluationException(this.scriptName, ioe.getMessage(), ioe);

        } catch (ScriptEvaluationException see) {
            throw see;
        } catch (ScriptException se) {
            Throwable cause = (se.getCause() == null) ? se : se.getCause();
            throw new ScriptEvaluationException(this.scriptName, se.getMessage(), cause);

        } finally {
            if (props.getRequest() != null) {
                requestResourceResolver.set(oldResolver);
            }

            // close the script reader (SLING-380)
            if (reader != null) {
                try {
                    reader.close();
                } catch (IOException ignore) {
                    // don't care
                }
            }

            // dispose of the SlingScriptHelper
            if (bindings != null && disposeScriptHelper) {
                final InternalScriptHelper helper = (InternalScriptHelper) bindings.get(SLING);
                if (helper != null) {
                    helper.cleanup();
                }
            }
        }
    }