/*
 * 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.javascript;

import java.io.Reader;
import java.util.Map.Entry;

import javax.script.Bindings;
import javax.script.ScriptContext;
import javax.script.ScriptEngineFactory;
import javax.script.ScriptException;

import org.apache.sling.api.scripting.SlingBindings;
import org.apache.sling.api.scripting.SlingScriptHelper;
import org.apache.sling.scripting.api.AbstractSlingScriptEngine;
import org.apache.sling.scripting.javascript.helper.EspReader;
import org.apache.sling.scripting.javascript.helper.SlingWrapFactory;
import org.mozilla.javascript.Context;
import org.mozilla.javascript.NativeObject;
import org.mozilla.javascript.ScriptRuntime;
import org.mozilla.javascript.Scriptable;
import org.mozilla.javascript.ScriptableObject;

/**
 * A ScriptEngine that uses the Rhino interpreter to process Sling requests with
 * server-side javascript.
 */
public class RhinoJavaScriptEngine extends AbstractSlingScriptEngine {

    private Scriptable rootScope;

    public RhinoJavaScriptEngine(ScriptEngineFactory factory, Scriptable rootScope) {
        super(factory);
        this.rootScope = rootScope;
    }

    public Object eval(Reader scriptReader, ScriptContext scriptContext)
            throws ScriptException {
        Bindings bindings = scriptContext.getBindings(ScriptContext.ENGINE_SCOPE);
        String scriptName = "NO_SCRIPT_NAME";
        {
            SlingScriptHelper helper = (SlingScriptHelper) bindings.get(SlingBindings.SLING);
            if(helper != null) {
                scriptName = helper.getScript().getScriptResource().getPath();
            }
        }

        // wrap the reader in an EspReader for ESP scripts
        if (scriptName.endsWith(RhinoJavaScriptEngineFactory.ESP_SCRIPT_EXTENSION)) {
            scriptReader = new EspReader(scriptReader);
        }

        // create a rhino Context and execute the script
        try {
            final Context rhinoContext = Context.enter();
            final ScriptableObject scope = new NativeObject();

            // Set the global scope to be our prototype
            scope.setPrototype(rootScope);

            // We want "scope" to be a new top-level scope, so set its parent
            // scope to null. This means that any variables created by assignments
            // will be properties of "scope".
            scope.setParentScope(null);

            // setup the context for use
            rhinoContext.setWrapFactory(SlingWrapFactory.INSTANCE);

            // add initial properties to the scope
            for (Object entryObject : bindings.entrySet()) {
                Entry<?, ?> entry = (Entry<?, ?>) entryObject;
                Object wrapped = ScriptRuntime.toObject(scope, entry.getValue());
                ScriptableObject.putProperty(scope, (String) entry.getKey(),
                    wrapped);
            }

            final int lineNumber = 1;
            final Object securityDomain = null;

            rhinoContext.evaluateReader(scope, scriptReader, scriptName,
                lineNumber, securityDomain);
        } catch (Throwable t) {
            throw new ScriptException("Failure running script " + scriptName
                + ": " + t.getMessage());
        } finally {
            Context.exit();
        }
        return null;
    }

}

@@ -3914,21 +3914,42 @@
         
-throw
+final ScriptException se =
  new Scr
@@ -4038,24 +4038,75 @@
 Message());%0A
+            se.initCause(t);%0A            throw se;%0A
         %7D fi

Include cause in ScriptException