/*
 *  Copyright 2009 the Helma Project
 *
 *  Licensed 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.helma.javascript;

import org.mozilla.javascript.*;
import org.mozilla.javascript.tools.shell.Global;

import java.security.AccessController;
import java.security.PrivilegedAction;

public class HelmaGlobal extends Global {
    public HelmaGlobal(Context cx) {
        init(cx);
    }

    public void init(Context cx) {
        // Define some global functions particular to the shell. Note
        // that these functions are not part of ECMA.
        initStandardObjects(cx, false);
        String[] names = {
            "defineClass",
            "doctest",
            "gc",
            "load",
            "loadClass",
            "print",
            "quit",
            "readFile",
            "readUrl",
            "runCommand",
            "seal",
            "spawn",
            "sync",
            "toint32",
            "version",
        };
        defineFunctionProperties(names, Global.class,
                                 ScriptableObject.DONTENUM);
        names = new String[] {
            "privileged"
        };
        defineFunctionProperties(names, HelmaGlobal.class,
                                 ScriptableObject.DONTENUM);
    }

    public static Object privileged(final Context cx, Scriptable thisObj, Object[] args,
                                    Function funObj) {
        if (args.length != 1 || !(args[0] instanceof Function)) {
            throw Context.reportRuntimeError("privileged() requires a function argument");
        }
        final Scriptable scope = getTopLevelScope(thisObj);
        Scriptable s = cx.newObject(scope);
        s.put("run", s, args[0]);
        final Object[] jargs = {new NativeJavaClass(scope, PrivilegedAction.class), s};
        PrivilegedAction action = AccessController.doPrivileged(
                new PrivilegedAction<PrivilegedAction>() {
                    public PrivilegedAction run() {
                        return (PrivilegedAction) ((Wrapper) cx.newObject(scope, "JavaAdapter", jargs)).unwrap();
                    }
                }
        );
        // PrivilegedAction action = (PrivilegedAction) InterfaceAdapter.create(cx, PrivilegedAction.class, (Callable) args[0]);
        return AccessController.doPrivileged(action);
    }


}

@@ -718,16 +718,71 @@
 .Global;
+%0Aimport org.mozilla.javascript.tools.ToolErrorReporter;
 %0A%0Aimport
@@ -1699,16 +1699,40 @@
 vileged%22
+,%0A            %22trycatch%22
 %0A       
@@ -2930,11 +2930,587 @@
 %0A    %7D%0A%0A
+    public static Object trycatch(final Context cx, Scriptable thisObj, Object%5B%5D args,%0A                                    Function funObj) %7B%0A        if (args.length != 1 %7C%7C !(args%5B0%5D instanceof Function)) %7B%0A            throw Context.reportRuntimeError(%22trycatch() requires a function argument%22);%0A        %7D%0A        Scriptable scope = getTopLevelScope(thisObj);%0A        try %7B%0A            return ((Function)args%5B0%5D).call(cx, scope, thisObj, RhinoEngine.EMPTY_ARGS);%0A        %7D catch (RhinoException re) %7B%0A            return new NativeJavaObject(scope, re, null);%0A        %7D%0A    %7D%0A
 %0A%7D%0A

Add experimental trycatch to be able to access script stack traces from js.