/*****************************************************************************
* Copyright (C) The Apache Software Foundation. All rights reserved. *
* ------------------------------------------------------------------------- *
* This software is published under the terms of the Apache Software License *
* version 1.1, a copy of which has been included with this distribution in *
* the LICENSE file. *
*****************************************************************************/
package org.apache.batik.script.rhino;
import java.io.IOException;
import java.io.StringReader;
import java.security.AccessControlContext;
import java.security.AccessController;
import java.security.PrivilegedAction;
import org.apache.batik.script.InterpreterException;
import org.apache.batik.script.Window;
import org.mozilla.javascript.Context;
import org.mozilla.javascript.Function;
import org.mozilla.javascript.ImporterTopLevel;
import org.mozilla.javascript.JavaScriptException;
import org.mozilla.javascript.NativeJavaObject;
import org.mozilla.javascript.NativeObject;
import org.mozilla.javascript.PropertyException;
import org.mozilla.javascript.Scriptable;
import org.mozilla.javascript.ScriptableObject;
import org.mozilla.javascript.WrappedException;
import org.w3c.dom.Document;
/**
* This class wraps a Window object to expose it to the interpreter.
* This will be the Global Object of our interpreter.
*
* @author <a href="mailto:cjolif@ilog.fr">Christophe Jolif</a>
* @author <a href="mailto:stephane@hillion.org">Stephane Hillion</a>
* @version $Id: WindowWrapper.java,v 1.15 2003/07/09 02:10:11 deweese Exp $
*/
public class WindowWrapper extends ImporterTopLevel {
private final static Object[] EMPTY_ARGUMENTS = new Object[0];
/**
* Creates a new WindowWrapper.
*/
public WindowWrapper(Context context) {
super(context);
String[] names = { "setInterval", "setTimeout", "clearInterval", "clearTimeout",
"parseXML", "getURL", "alert", "confirm", "prompt" };
try {
this.defineFunctionProperties(names, WindowWrapper.class,
ScriptableObject.DONTENUM);
} catch (PropertyException e) {
throw new Error(); // should never happen
}
}
public String getClassName() {
return "Window";
}
public String toString() {
return "[object Window]";
}
/**
* Wraps the 'setInterval' methods of the Window interface.
*/
public static Object setInterval(Context cx,
Scriptable thisObj,
Object[] args,
Function funObj)
throws JavaScriptException {
int len = args.length;
Window window = ((RhinoInterpreter.ExtendedContext)cx).getWindow();
if (len < 2) {
throw Context.reportRuntimeError("invalid argument count");
}
long to = ((Long)Context.toType(args[1], Long.TYPE)).longValue();
if (args[0] instanceof Function) {
RhinoInterpreter interp =
(RhinoInterpreter)window.getInterpreter();
FunctionWrapper fw;
fw = new FunctionWrapper(interp, (Function)args[0],
EMPTY_ARGUMENTS);
return window.setInterval(fw, to);
}
String script =
(String)Context.toType(args[0], String.class);
return window.setInterval(script, to);
}
/**
* Wraps the 'setTimeout' methods of the Window interface.
*/
public static Object setTimeout(Context cx,
Scriptable thisObj,
Object[] args,
Function funObj)
throws JavaScriptException {
int len = args.length;
Window window = ((RhinoInterpreter.ExtendedContext)cx).getWindow();
if (len < 2) {
throw Context.reportRuntimeError("invalid argument count");
}
long to = ((Long)Context.toType(args[1], Long.TYPE)).longValue();
if (args[0] instanceof Function) {
RhinoInterpreter interp =
(RhinoInterpreter)window.getInterpreter();
FunctionWrapper fw;
fw = new FunctionWrapper(interp, (Function)args[0],
EMPTY_ARGUMENTS);
return window.setTimeout(fw, to);
}
String script =
(String)Context.toType(args[0], String.class);
return window.setTimeout(script, to);
}
/**
* Wraps the 'clearInterval' method of the Window interface.
*/
public static void clearInterval(Context cx,
Scriptable thisObj,
Object[] args,
Function funObj)
throws JavaScriptException {
int len = args.length;
Window window = ((RhinoInterpreter.ExtendedContext)cx).getWindow();
if (len >= 1) {
window.clearInterval(Context.toType(args[0], Object.class));
}
}
/**
* Wraps the 'clearTimeout' method of the Window interface.
*/
public static void clearTimeout(Context cx,
Scriptable thisObj,
Object[] args,
Function funObj)
throws JavaScriptException {
int len = args.length;
Window window = ((RhinoInterpreter.ExtendedContext)cx).getWindow();
if (len >= 1) {
window.clearTimeout(Context.toType(args[0], Object.class));
}
}
/**
* Wraps the 'parseXML' method of the Window interface.
*/
public static Object parseXML(Context cx,
Scriptable thisObj,
final Object[] args,
Function funObj)
throws JavaScriptException {
int len = args.length;
final Window window =
((RhinoInterpreter.ExtendedContext)cx).getWindow();
if (len < 2) {
throw Context.reportRuntimeError("invalid argument count");
}
AccessControlContext acc =
((RhinoInterpreter)window.getInterpreter()).getAccessControlContext();
return AccessController.doPrivileged( new PrivilegedAction() {
public Object run() {
return window.parseXML
((String)Context.toType(args[0], String.class),
(Document)Context.toType(args[1], Document.class));
}
}, acc);
}
/**
* Wraps the 'getURL' method of the Window interface.
*/
public static void getURL(Context cx,
Scriptable thisObj,
final Object[] args,
Function funObj)
throws JavaScriptException {
int len = args.length;
final Window window = ((RhinoInterpreter.ExtendedContext)cx).getWindow();
final ScriptableObject go = ((RhinoInterpreter.ExtendedContext)cx).getGlobalObject();
if (len < 2) {
throw Context.reportRuntimeError("invalid argument count");
}
RhinoInterpreter interp =
(RhinoInterpreter)window.getInterpreter();
final String uri = (String)Context.toType(args[0], String.class);
Window.GetURLHandler urlHandler = null;
if (args[1] instanceof Function) {
urlHandler = new GetURLFunctionWrapper
(interp, (Function)args[1], go);
} else {
urlHandler = new GetURLObjectWrapper
(interp, (NativeObject)args[1], go);
}
final Window.GetURLHandler fw = urlHandler;
AccessControlContext acc =
((RhinoInterpreter)window.getInterpreter()).getAccessControlContext();
if (len == 2) {
AccessController.doPrivileged(new PrivilegedAction() {
public Object run(){
window.getURL(uri, fw);
return null;
}
}, acc);
} else {
AccessController.doPrivileged(new PrivilegedAction() {
public Object run() {
window.getURL
(uri, fw,
(String)Context.toType(args[2], String.class));
return null;
}
}, acc);
}
}
/**
* Wraps the 'alert' method of the Window interface.
*/
public static void alert(Context cx,
Scriptable thisObj,
Object[] args,
Function funObj)
throws JavaScriptException {
int len = args.length;
Window window = ((RhinoInterpreter.ExtendedContext)cx).getWindow();
if (len >= 1) {
String message =
(String)Context.toType(args[0], String.class);
window.alert(message);
}
}
/**
* Wraps the 'confirm' method of the Window interface.
*/
public static boolean confirm(Context cx,
Scriptable thisObj,
Object[] args,
Function funObj)
throws JavaScriptException {
int len = args.length;
Window window = ((RhinoInterpreter.ExtendedContext)cx).getWindow();
if (len >= 1) {
String message =
(String)Context.toType(args[0], String.class);
return window.confirm(message);
}
return false;
}
/**
* Wraps the 'prompt' method of the Window interface.
*/
public static String prompt(Context cx,
Scriptable thisObj,
Object[] args,
Function funObj)
throws JavaScriptException {
int len = args.length;
Window window = ((RhinoInterpreter.ExtendedContext)cx).getWindow();
switch (len) {
case 0:
return "";
case 1:
String message =
(String)Context.toType(args[0], String.class);
return window.prompt(message);
default:
message =
(String)Context.toType(args[0], String.class);
String defVal =
(String)Context.toType(args[1], String.class);
return window.prompt(message, defVal);
}
}
/**
* To wrap a function in an handler.
*/
protected static class FunctionWrapper implements Runnable {
/**
* The current interpreter.
*/
protected RhinoInterpreter interpreter;
/**
* The function wrapper.
*/
protected Function function;
/**
* The arguments.
*/
protected Object[] arguments;
/**
* Creates a function wrapper.
*/
public FunctionWrapper(RhinoInterpreter ri,
Function f,
Object[] args) {
interpreter = ri;
function = f;
arguments = args;
}
/**
* Calls the function.
*/
public void run() {
try {
interpreter.callHandler(function, arguments);
} catch (JavaScriptException e) {
throw new WrappedException(e);
}
}
}
/**
* To wrap a function passed to getURL().
*/
protected static class GetURLFunctionWrapper
implements Window.GetURLHandler {
/**
* The current interpreter.
*/
protected RhinoInterpreter interpreter;
/**
* The function wrapper.
*/
protected Function function;
/**
* The Scope for callback
*/
protected ScriptableObject scope;
/**
* Creates a wrapper.
*/
public GetURLFunctionWrapper(RhinoInterpreter ri, Function fct,
ScriptableObject sc) {
interpreter = ri;
function = fct;
scope = sc;
}
/**
* Called before 'getURL()' returns.
* @param success Whether the data was successfully retreived.
* @param mime The data MIME type.
* @param content The data.
*/
public void getURLDone(final boolean success,
final String mime,
final String content) {
try {
interpreter.callHandler(function,
new RhinoInterpreter.ArgumentsBuilder() {
public Object[] buildArguments() {
try {
Object[] arguments = new Object[1];
ScriptableObject so =
(ScriptableObject)interpreter.evaluate
(new StringReader("new Object()"));
so.put("success", so,
(success) ?
Boolean.TRUE : Boolean.FALSE);
if (mime != null) {
so.put("contentType", so,
Context.toObject(mime, scope));
}
if (content != null) {
so.put("content", so,
Context.toObject(content, scope));
}
arguments[0] = so;
return arguments;
} catch (IOException e) {
throw new WrappedException(e);
} catch (InterpreterException e) {
throw new WrappedException(e);
}
}
});
} catch (JavaScriptException e) {
throw new WrappedException(e);
}
}
}
/**
* To wrap an object passed to getURL().
*/
private static class GetURLObjectWrapper
implements Window.GetURLHandler {
/**
* The current interpreter.
*/
private RhinoInterpreter interpreter;
/**
* The object wrapper.
*/
private ScriptableObject object;
/**
* The Scope for the callback.
*/
private ScriptableObject scope;
private Object[] array = new Object[1];
private static final String COMPLETE = "operationComplete";
/**
* Creates a wrapper.
*/
public GetURLObjectWrapper(RhinoInterpreter ri,
ScriptableObject obj,
ScriptableObject sc) {
interpreter = ri;
object = obj;
scope = sc;
}
/**
* Called before 'getURL()' returns.
* @param success Whether the data was successfully retreived.
* @param mime The data MIME type.
* @param content The data.
*/
public void getURLDone(final boolean success,
final String mime,
final String content) {
try {
interpreter.callMethod
(object, COMPLETE,
new RhinoInterpreter.ArgumentsBuilder() {
public Object[] buildArguments() {
Object[] arguments = new Object[1];
ScriptableObject so =
new NativeObject();
so.put("success", so,
(success) ?
Boolean.TRUE : Boolean.FALSE);
if (mime != null) {
so.put("contentType", so,
Context.toObject(mime, scope));
}
if (content != null) {
so.put("content", so,
Context.toObject(content, scope));
}
arguments[0] = so;
return arguments;
}
});
} catch (JavaScriptException e) {
Context.exit();
throw new WrappedException(e);
}
}
}
}