/*
 * 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 org.apache.sling.scripting.core.impl;

import static org.apache.sling.api.scripting.SlingBindings.FLUSH;
import static org.apache.sling.api.scripting.SlingBindings.LOG;
import static org.apache.sling.api.scripting.SlingBindings.OUT;
import static org.apache.sling.api.scripting.SlingBindings.READER;
import static org.apache.sling.api.scripting.SlingBindings.REQUEST;
import static org.apache.sling.api.scripting.SlingBindings.RESOURCE;
import static org.apache.sling.api.scripting.SlingBindings.RESOLVER;
import static org.apache.sling.api.scripting.SlingBindings.RESPONSE;
import static org.apache.sling.api.scripting.SlingBindings.SLING;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.io.Reader;
import java.io.StringReader;
import java.io.Writer;
import java.util.Arrays;
import java.util.Collection;
import java.util.Dictionary;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.script.Bindings;
import javax.script.Compilable;
import javax.script.CompiledScript;
import javax.script.Invocable;
import javax.script.ScriptContext;
import javax.script.ScriptEngine;
import javax.script.ScriptException;
import javax.servlet.Servlet;
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

import org.apache.sling.api.SlingConstants;
import org.apache.sling.api.SlingException;
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.SlingHttpServletResponse;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceMetadata;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.api.resource.ResourceWrapper;
import org.apache.sling.api.resource.SyntheticResource;
import org.apache.sling.api.scripting.LazyBindings;
import org.apache.sling.api.scripting.ScriptEvaluationException;
import org.apache.sling.api.scripting.SlingBindings;
import org.apache.sling.api.scripting.SlingScript;
import org.apache.sling.api.scripting.SlingScriptConstants;
import org.apache.sling.api.scripting.SlingScriptHelper;
import org.apache.sling.scripting.api.BindingsValuesProvider;
import org.apache.sling.scripting.api.CachedScript;
import org.apache.sling.scripting.api.ScriptCache;
import org.apache.sling.scripting.core.ScriptNameAwareReader;
import org.apache.sling.scripting.core.impl.helper.CachedScriptImpl;
import org.apache.sling.scripting.core.impl.helper.ProtectedBindings;
import org.osgi.framework.BundleContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

class DefaultSlingScript implements SlingScript, Servlet, ServletConfig {

    /** The logger. */
    private static final Logger LOGGER = LoggerFactory.getLogger(DefaultSlingScript.class);

    /** is defined on multiple files in this bundle*/
    private static final long WARN_LIMIT_FOR_BVP_NANOS = (1000*1000); // 1 ms

    private static final String BINDINGS_THRESHOLD_MESSAGE = "Adding the bindings of %s took %s microseconds which is above the hardcoded" +
            " limit of %s microseconds; if this message appears often it indicates that this BindingsValuesProvider has an impact on " +
            "general page rendering performance.";

    /** Thread local containing the resource resolver. */
    private static ThreadLocal<ResourceResolver> requestResourceResolver = new ThreadLocal<>();

    /** The set of protected keys. */
    private static final Set<String> PROTECTED_KEYS =
        new HashSet<>(Arrays.asList(REQUEST, RESPONSE, READER, SLING, RESOURCE, RESOLVER, OUT, LOG));

    /** The resource pointing to the script. */

    private final Resource scriptResource;

    /** The name of the script (the resource path) */
    private final String scriptName;

    /** The encoding of the script. */
    private final String scriptEncoding;

    /** The script engine for this script. */
    private final ScriptEngine scriptEngine;

    /** The servlet context. */
    private ServletContext servletContext;

    /** The init parameters for this servlet. */
    private Dictionary<String, String> initParameters;

    /** The current bundle context. */
    private final BundleContext bundleContext;

    /** The ScriptBindingsValuesProviders. */
    private final Collection<BindingsValuesProvider> bindingsValuesProviders;

    /** The cache for services. */
    private final ServiceCache cache;

    /* The cache for compiled scripts. */
    private final ScriptCache scriptCache;

    /**
     * Constructor
     * @param bundleContext The bundle context
     * @param scriptResource The script resource
     * @param scriptEngine The script engine
     * @param bindingsValuesProviders additional bindings values providers
     * @param cache serviceCache
     */
    DefaultSlingScript(final BundleContext bundleContext,
            final Resource scriptResource,
            final ScriptEngine scriptEngine,
            final Collection<BindingsValuesProvider> bindingsValuesProviders,
            final ServiceCache cache,
            final ScriptCache scriptCache) {
        this.scriptResource = scriptResource;
        this.scriptEngine = scriptEngine;
        this.bundleContext = bundleContext;
        this.bindingsValuesProviders = bindingsValuesProviders;
        this.cache = cache;
        this.scriptCache = scriptCache;
        this.scriptName = this.scriptResource.getPath();
        // Now know how to get the input stream, we still have to decide
        // on the encoding of the stream's data. Primarily we assume it is
        // UTF-8, which is a default in many places in JCR. Secondarily
        // we try to get a jcr:encoding property besides the data property
        // to provide a possible encoding
        final ResourceMetadata meta = this.scriptResource.getResourceMetadata();
        String encoding = meta.getCharacterEncoding();
        if (encoding == null) {
            encoding = "UTF-8";
        }
        this.scriptEncoding = encoding;
    }

    // ---------- SlingScript interface ----------------------------------------

    /**
     * @see org.apache.sling.api.scripting.SlingScript#getScriptResource()
     */
    public Resource getScriptResource() {
        final ResourceResolver resolver = requestResourceResolver.get();
        if ( resolver == null ) {
            // if we don't have a request resolver we directly return the script resource
            return scriptResource;
        }
        return new LazyScriptResource(this.scriptName,
                this.scriptResource.getResourceType(), resolver);
    }

    /**
     * @see org.apache.sling.api.scripting.SlingScript#eval(org.apache.sling.api.scripting.SlingBindings)
     * @throws ScriptEvaluationException
     */
    public Object eval(SlingBindings props) {
        return this.call(props, null);
    }

    // ---------- Servlet interface --------------------------------------------
    private static final Integer[] SCOPES = { SlingScriptConstants.SLING_SCOPE, Integer.valueOf(100), Integer.valueOf(200) };

    /**
     * @see org.apache.sling.api.scripting.SlingScript#call(org.apache.sling.api.scripting.SlingBindings, java.lang.String, java.lang.Object[])
     * @throws ScriptEvaluationException
     */
    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();
                }
            }

        }
    }

    /**
     * @see javax.servlet.Servlet#init(javax.servlet.ServletConfig)
     */
    public void init(ServletConfig servletConfig) {
        if (servletConfig != null) {
            final Dictionary<String, String> params = new Hashtable<>(); // NOSONAR
            for (Enumeration<?> ne = servletConfig.getInitParameterNames(); ne.hasMoreElements();) {
                String name = String.valueOf(ne.nextElement());
                String value = servletConfig.getInitParameter(name);
                params.put(name, value);
            }
            this.initParameters = params;
            this.servletContext = servletConfig.getServletContext();
        }
    }

    /**
     * @see javax.servlet.Servlet#service(javax.servlet.ServletRequest, javax.servlet.ServletResponse)
     */
    public void service(ServletRequest req, ServletResponse res) {
        final SlingHttpServletRequest request = (SlingHttpServletRequest) req;

        try {
            // prepare the properties for the script
            final SlingBindings props = new SlingBindings();
            props.setRequest((SlingHttpServletRequest) req);
            props.setResponse((SlingHttpServletResponse) res);

            // try to set content type (unless included)
            if (request.getAttribute(SlingConstants.ATTR_INCLUDE_SERVLET_PATH) == null) {
                final String contentType = request.getResponseContentType();
                if (contentType != null) {
                    res.setContentType(contentType);

                    // only set the character encoding for text/ content types
                    // see SLING-679
                    if (contentType.startsWith("text/")) {
                        res.setCharacterEncoding("UTF-8");
                    }
                } else {
                    LOGGER.debug("service: No response content type defined for request {}.", request.getRequestURI());
                }
            } else {
                LOGGER.debug("service: Included request, not setting content type and encoding");
            }

            // evaluate the script now using the ScriptEngine
            eval(props);

        } catch (RuntimeException see) {

            // log in the request progress tracker
            logScriptError(request, see);

            throw see;
        } catch (Exception e) {

            // log in the request progress tracker
            logScriptError(request, e);

            throw new SlingException("Cannot get DefaultSlingScript: "
                + e.getMessage(), e);
        }
    }

    public ServletConfig getServletConfig() {
        return this;
    }

    public String getServletInfo() {
        return "Script " + scriptName;
    }

    /**
     * @see javax.servlet.Servlet#destroy()
     */
    public void destroy() {
        initParameters = null;
        servletContext = null;
    }

    // ---------- ServletConfig ------------------------------------------------

    /**
     * @see javax.servlet.ServletConfig#getInitParameter(java.lang.String)
     */
    public String getInitParameter(String name) {
        final Dictionary<String, String> params = initParameters;
        return (params != null) ? params.get(name) : null;
    }

    /**
     * @see javax.servlet.ServletConfig#getInitParameterNames()
     */
    public Enumeration<String> getInitParameterNames() {
        final Dictionary<String, String> params = initParameters;
        return (params != null) ? params.keys() : null;
    }

    /**
     * @see javax.servlet.ServletConfig#getServletContext()
     */
    public ServletContext getServletContext() {
        return servletContext;
    }

    /**
     * @see javax.servlet.ServletConfig#getServletName()
     */
    public String getServletName() {
        return this.scriptName;
    }

    // ---------- internal -----------------------------------------------------

    private Reader getScriptReader() throws IOException {
        // access the value as a stream and return a buffered reader
        // converting the stream data using UTF-8 encoding, which is
        // the default encoding used
        return new BufferedReader(new InputStreamReader(new LazyInputStream(this.scriptResource), this.scriptEncoding));
    }

    private Reader getWrapperReader(final Reader scriptReader, final String method, final Object... args) {
        final StringBuilder buffer = new StringBuilder(method);
        buffer.append('(');
        for(Object o : args) {
            buffer.append('"');
            buffer.append(o);
            buffer.append('"');
        }
        buffer.append(')');
        final String msg = buffer.toString();
        return new Reader() {

            protected boolean doAppend = false;

            protected StringReader methodReader = new StringReader(msg);
            /**
             * @see java.io.Reader#close()
             */
            @Override
            public void close() throws IOException {
                scriptReader.close();
            }

            @Override
            public int read(char[] cbuf, int start, int len) throws IOException {
                if ( doAppend ) {
                    return methodReader.read(cbuf, start, len);
                }
                int readLen = scriptReader.read(cbuf, start, len);
                if ( readLen == -1 ) {
                    doAppend = true;
                    return this.read(cbuf, start, len);
                }
                return readLen;
            }

            @Override
            public int read() throws IOException {
                if ( doAppend ) {
                    return methodReader.read();
                }
                int value = scriptReader.read();
                if ( value == -1 ) {
                    doAppend = true;
                    return methodReader.read();
                }
                return value;
            }

            @Override
            public int read(char[] cbuf) throws IOException {
                return this.read(cbuf, 0, cbuf.length);
            }

            @Override
            public boolean ready() throws IOException {
                return scriptReader.ready();
            }
        };
    }

    Bindings verifySlingBindings(final SlingBindings slingBindings) throws IOException {

        final Bindings bindings = new LazyBindings();

        final SlingHttpServletRequest request = slingBindings.getRequest();

        // check sling object
        Object slingObject = slingBindings.get(SLING);
        if (slingObject == null) {

            if ( request != null ) {
                slingObject = new InternalScriptHelper(this.bundleContext, this, request, slingBindings.getResponse(), this.cache);
            } else {
                slingObject = new InternalScriptHelper(this.bundleContext, this, this.cache);
            }
        } else if (!(slingObject instanceof SlingScriptHelper) ) {
            throw fail(SLING, "Wrong type");
        }
        final SlingScriptHelper sling = (SlingScriptHelper)slingObject;
        bindings.put(SLING, sling);

        if (request != null) {
        	final SlingHttpServletResponse response = slingBindings.getResponse();
            if (response == null) {
                throw fail(RESPONSE, "Missing or wrong type");
            }

            Object resourceObject = slingBindings.get(RESOURCE);
            if (resourceObject != null && !(resourceObject instanceof Resource)) {
                throw fail(RESOURCE, "Wrong type");
            }

            Object resolverObject = slingBindings.get(RESOLVER);
            if (resolverObject != null && !(resolverObject instanceof ResourceResolver)) {
                throw fail(RESOLVER, "Wrong type");
            }

            Object writerObject = slingBindings.get(OUT);
            if (writerObject != null && !(writerObject instanceof PrintWriter)) {
                throw fail(OUT, "Wrong type");
            }

            // if there is a provided sling script helper, check arguments
            if (slingBindings.get(SLING) != null) {

                if (sling.getRequest() != request) {
                    throw fail(REQUEST,
                        "Not the same as request field of SlingScriptHelper");
                }

                if (sling.getResponse() != response) {
                    throw fail(RESPONSE,
                        "Not the same as response field of SlingScriptHelper");
                }

                if (resourceObject != null
                    && sling.getRequest().getResource() != resourceObject) {
                    throw fail(RESOURCE,
                        "Not the same as resource of the SlingScriptHelper request");
                }

                if (resolverObject != null && sling.getRequest().getResourceResolver() != resolverObject) {
                    throw fail(RESOLVER,
                        "Not the same as the resource resolver of the SlingScriptHelper request's resolver");
                }

                if (writerObject != null
                    && sling.getResponse().getWriter() != writerObject) {
                    throw fail(OUT,
                        "Not the same as writer of the SlingScriptHelper response");
                }
            }

            // set base variables when executing inside a request
            bindings.put(REQUEST, sling.getRequest());
            bindings.put(READER, sling.getRequest().getReader());
            bindings.put(RESPONSE, sling.getResponse());
            bindings.put(RESOURCE, sling.getRequest().getResource());
            bindings.put(RESOLVER, sling.getRequest().getResourceResolver());
            bindings.put(OUT, sling.getResponse().getWriter());
        }

        Object logObject = slingBindings.get(LOG);
        if (logObject == null) {
            logObject = LoggerFactory.getLogger(getLoggerName());
        } else if (!(logObject instanceof Logger)) {
            throw fail(LOG, "Wrong type");
        }
        bindings.put(LOG, logObject);

        // copy non-base variables
        for (Map.Entry<String, Object> entry : slingBindings.entrySet()) {
            if (!bindings.containsKey(entry.getKey())) {
                bindings.put(entry.getKey(), entry.getValue());
            }
        }

        if (!bindingsValuesProviders.isEmpty()) {
            Set<String> protectedKeys = new HashSet<>();
            protectedKeys.addAll(PROTECTED_KEYS);
            ProtectedBindings protectedBindings = new ProtectedBindings(bindings, protectedKeys);
            
            long inclusionStart = System.nanoTime();
            for (BindingsValuesProvider provider : bindingsValuesProviders) {
                long start = System.nanoTime();
                provider.addBindings(protectedBindings);
                long stop = System.nanoTime();
                LOGGER.trace("Invoking addBindings() of {} took {} nanoseconds",
                        provider.getClass().getName(), stop-start);
                if (stop-start > WARN_LIMIT_FOR_BVP_NANOS) {
                    // SLING-11182 - make this work with older implementations of the Sling API
                    if (request != null && request.getRequestProgressTracker() != null) {
                        request.getRequestProgressTracker().log(String.format(BINDINGS_THRESHOLD_MESSAGE, provider.getClass().getName(), (stop-start)/1000, WARN_LIMIT_FOR_BVP_NANOS/1000));
                    } else {
                        if (LOGGER.isInfoEnabled()) {
                            LOGGER.info(String.format(BINDINGS_THRESHOLD_MESSAGE, provider.getClass().getName(), (stop-start)/1000,
                                    WARN_LIMIT_FOR_BVP_NANOS/1000));
                        }
                    }
                }
            }
            // SLING-11182 - make this work with older implementations of the Sling API
            if (request != null && request.getRequestProgressTracker() != null) {
                long duration = (System.nanoTime() - inclusionStart) / 1000;
                request.getRequestProgressTracker().log("Adding bindings took " + duration + " microseconds");
            }
        }

        return bindings;
    }

    private ScriptEvaluationException fail(String variableName, String message) {
        return new ScriptEvaluationException(this.scriptName, variableName + ": "
            + message);
    }

    private String getLoggerName() {
        String name = scriptName;
        name = name.substring(1);       // cut-off leading slash
        name = name.replace('.', '$');  // extension separator as part of name
        name = name.replace('/', '.');  // hierarchy defined by dot
        return name;
    }

    /**
     * Logs the error caused by executing the script in the request progress
     * tracker.
     */
    private void logScriptError(SlingHttpServletRequest request,
            Throwable throwable) {
        String message = throwable.getMessage();
        if (message != null) {
            message = throwable.getMessage().replace('\n', '/');
        } else {
            message = throwable.toString();
        }
        request.getRequestProgressTracker().log("SCRIPT ERROR: {0}", message);
    }

    /**
     * Input stream wrapper which acquires the underlying input stream lazily.
     * This ensures that the input stream is only fetched from the repository
     * if it is really used by the script engines.
     */
    public static final class LazyInputStream extends InputStream {

        /** The script resource which is adapted to an inputm stream. */
        private final Resource resource;

        /** The input stream created on demand, null if not used */
        private InputStream delegatee;

        public LazyInputStream(final Resource resource) {
            this.resource = resource;
        }

        /**
         * Closes the input stream if acquired otherwise does nothing.
         */
        @Override
        public void close() throws IOException {
            if (delegatee != null) {
                delegatee.close();
            }
        }

        @Override
        public int available() throws IOException {
            return getStream().available();
        }

        @Override
        public int read() throws IOException {
            return getStream().read();
        }

        @Override
        public int read(byte[] b) throws IOException {
            return getStream().read(b);
        }

        @Override
        public int read(byte[] b, int off, int len) throws IOException {
            return getStream().read(b, off, len);
        }

        @Override
        public long skip(long n) throws IOException {
            return getStream().skip(n);
        }

        @Override
        public boolean markSupported() {
            try {
                return getStream().markSupported();
            } catch (IOException ioe) {
                // ignore
            }
            return false;
        }

        @Override
        public synchronized void mark(int readlimit) {
            try {
                getStream().mark(readlimit);
            } catch (IOException ioe) {
                // ignore
            }
        }

        @Override
        public synchronized void reset() throws IOException {
            getStream().reset();
        }

        /** Actually retrieves the input stream from the underlying JCR Value */
        private InputStream getStream() throws IOException {
            if (delegatee == null) {
                delegatee = this.resource.adaptTo(InputStream.class);
                if (delegatee == null) {
                    throw new IOException("Cannot get a stream to the script resource "
                        + this.resource.getPath());
                }
            }
            return delegatee;
        }

    }

    /**
     * This is a lazy implementation of the script resource which
     * just returns the path, resource type and resource resolver directly.
     */
    private static final class LazyScriptResource extends ResourceWrapper {

        private final String path;

        private final String resourceType;

        private final ResourceResolver resolver;

        private Resource delegatee;

        public LazyScriptResource(final String path, final String resourceType, final ResourceResolver resolver) {
            super(null); // NOSONAR
            this.path = path;
            this.resourceType = resourceType;
            this.resolver = resolver;
        }

        @Override
        public Resource getResource() {
            if (this.delegatee == null) {
                this.delegatee = this.resolver.getResource(this.path);
                if (this.delegatee == null) {
                    this.delegatee = new SyntheticResource(resolver, this.path,
                        this.resourceType);
                }
            }
            return this.delegatee;
        }

        /**
         * @see org.apache.sling.api.resource.Resource#getPath()
         */
        @Override
        public String getPath() {
            return this.path;
        }

        /**
         * @see org.apache.sling.api.resource.Resource#getResourceType()
         */
        @Override
        public String getResourceType() {
            return this.resourceType;
        }

        /**
         * @see org.apache.sling.api.resource.Resource#getResourceResolver()
         */
        @Override
        public ResourceResolver getResourceResolver() {
            return this.resolver;
        }
    }
}
