Added code for Rhino scripting engine.
This commit is contained in:
parent
78411bea50
commit
1ea945f82a
8 changed files with 2822 additions and 0 deletions
283
src/helma/scripting/rhino/GlobalObject.java
Normal file
283
src/helma/scripting/rhino/GlobalObject.java
Normal file
|
@ -0,0 +1,283 @@
|
||||||
|
/*
|
||||||
|
* Helma License Notice
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the Helma License
|
||||||
|
* Version 2.0 (the "License"). You may not use this file except in
|
||||||
|
* compliance with the License. A copy of the License is available at
|
||||||
|
* http://adele.helma.org/download/helma/license.txt
|
||||||
|
*
|
||||||
|
* Copyright 1998-2003 Helma Software. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* $RCSfile$
|
||||||
|
* $Author$
|
||||||
|
* $Revision$
|
||||||
|
* $Date$
|
||||||
|
*/
|
||||||
|
|
||||||
|
package helma.scripting.rhino;
|
||||||
|
|
||||||
|
import helma.framework.*;
|
||||||
|
import helma.framework.core.*;
|
||||||
|
import helma.objectmodel.*;
|
||||||
|
import helma.objectmodel.db.*;
|
||||||
|
import helma.util.HtmlEncoder;
|
||||||
|
import org.mozilla.javascript.*;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class GlobalObject extends ScriptableObject {
|
||||||
|
Application app;
|
||||||
|
RhinoCore core;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new GlobalObject object.
|
||||||
|
*
|
||||||
|
* @param core ...
|
||||||
|
* @param app ...
|
||||||
|
*
|
||||||
|
* @throws PropertyException ...
|
||||||
|
*/
|
||||||
|
public GlobalObject(RhinoCore core, Application app)
|
||||||
|
throws PropertyException {
|
||||||
|
this.core = core;
|
||||||
|
this.app = app;
|
||||||
|
|
||||||
|
String[] globalFuncs = {
|
||||||
|
"renderSkin", "renderSkinAsString", "getProperty",
|
||||||
|
"authenticate", "createSkin", "format", "encode",
|
||||||
|
"encodeXml", "encodeForm", "stripTags"
|
||||||
|
};
|
||||||
|
|
||||||
|
defineFunctionProperties(globalFuncs, GlobalObject.class, 0);
|
||||||
|
put("app", this, new ApplicationBean(app));
|
||||||
|
put("Xml", this, new XmlObject(core));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @return ...
|
||||||
|
*/
|
||||||
|
public String getClassName() {
|
||||||
|
return "GlobalObject";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @param skin ...
|
||||||
|
* @param param ...
|
||||||
|
*
|
||||||
|
* @return ...
|
||||||
|
*/
|
||||||
|
public boolean renderSkin(Object skin, Object param) {
|
||||||
|
// System.err.println ("RENDERSKIN CALLED WITH PARAM "+param);
|
||||||
|
Context cx = Context.getCurrentContext();
|
||||||
|
RequestEvaluator reval = (RequestEvaluator) cx.getThreadLocal("reval");
|
||||||
|
Skin s;
|
||||||
|
|
||||||
|
if (skin instanceof Skin) {
|
||||||
|
s = (Skin) skin;
|
||||||
|
} else {
|
||||||
|
s = core.app.getSkin(null, skin.toString(), null);
|
||||||
|
}
|
||||||
|
|
||||||
|
Map p = null;
|
||||||
|
|
||||||
|
if ((param != null) && (param != Undefined.instance)) {
|
||||||
|
p = new HashMap();
|
||||||
|
|
||||||
|
if (param instanceof Scriptable) {
|
||||||
|
Scriptable sp = (Scriptable) param;
|
||||||
|
Object[] ids = sp.getIds();
|
||||||
|
|
||||||
|
for (int i = 0; i < ids.length; i++) {
|
||||||
|
Object obj = sp.get(ids[i].toString(), sp);
|
||||||
|
if (obj instanceof NativeJavaObject) {
|
||||||
|
p.put(ids[i], ((NativeJavaObject) obj).unwrap());
|
||||||
|
} else {
|
||||||
|
p.put(ids[i], obj);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (s != null) {
|
||||||
|
s.render(reval, null, p);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @param skin ...
|
||||||
|
* @param param ...
|
||||||
|
*
|
||||||
|
* @return ...
|
||||||
|
*/
|
||||||
|
public String renderSkinAsString(Object skin, Object param) {
|
||||||
|
Context cx = Context.getCurrentContext();
|
||||||
|
RequestEvaluator reval = (RequestEvaluator) cx.getThreadLocal("reval");
|
||||||
|
Skin s;
|
||||||
|
|
||||||
|
if (skin instanceof Skin) {
|
||||||
|
s = (Skin) skin;
|
||||||
|
} else {
|
||||||
|
s = core.app.getSkin(null, skin.toString(), null);
|
||||||
|
}
|
||||||
|
|
||||||
|
Map p = null;
|
||||||
|
|
||||||
|
if ((param != null) && (param != Undefined.instance)) {
|
||||||
|
p = new HashMap();
|
||||||
|
|
||||||
|
if (param instanceof Scriptable) {
|
||||||
|
Scriptable sp = (Scriptable) param;
|
||||||
|
Object[] ids = sp.getIds();
|
||||||
|
|
||||||
|
for (int i = 0; i < ids.length; i++) {
|
||||||
|
Object obj = sp.get(ids[i].toString(), sp);
|
||||||
|
if (obj instanceof NativeJavaObject) {
|
||||||
|
p.put(ids[i], ((NativeJavaObject) obj).unwrap());
|
||||||
|
} else {
|
||||||
|
p.put(ids[i], obj);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (s != null) {
|
||||||
|
reval.res.pushStringBuffer();
|
||||||
|
s.render(reval, null, p);
|
||||||
|
|
||||||
|
return reval.res.popStringBuffer();
|
||||||
|
}
|
||||||
|
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @param propname ...
|
||||||
|
*
|
||||||
|
* @return ...
|
||||||
|
*/
|
||||||
|
public String getProperty(String propname) {
|
||||||
|
return app.getProperty(propname);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @param user ...
|
||||||
|
* @param pwd ...
|
||||||
|
*
|
||||||
|
* @return ...
|
||||||
|
*/
|
||||||
|
public boolean authenticate(String user, String pwd) {
|
||||||
|
return app.authenticate(user, pwd);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @param str ...
|
||||||
|
*
|
||||||
|
* @return ...
|
||||||
|
*/
|
||||||
|
public Skin createSkin(String str) {
|
||||||
|
return new Skin(str, app);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @param str ...
|
||||||
|
*
|
||||||
|
* @return ...
|
||||||
|
*/
|
||||||
|
public String encode(String str) {
|
||||||
|
return HtmlEncoder.encodeAll(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @param str ...
|
||||||
|
*
|
||||||
|
* @return ...
|
||||||
|
*/
|
||||||
|
public String encodeXml(String str) {
|
||||||
|
return HtmlEncoder.encodeXml(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @param str ...
|
||||||
|
*
|
||||||
|
* @return ...
|
||||||
|
*/
|
||||||
|
public String encodeForm(String str) {
|
||||||
|
return HtmlEncoder.encodeFormValue(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @param str ...
|
||||||
|
*
|
||||||
|
* @return ...
|
||||||
|
*/
|
||||||
|
public String format(String str) {
|
||||||
|
return HtmlEncoder.encode(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @param str ...
|
||||||
|
*
|
||||||
|
* @return ...
|
||||||
|
*/
|
||||||
|
public String stripTags(String str) {
|
||||||
|
if (str == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
char[] c = str.toCharArray();
|
||||||
|
boolean inTag = false;
|
||||||
|
int i;
|
||||||
|
int j = 0;
|
||||||
|
|
||||||
|
for (i = 0; i < c.length; i++) {
|
||||||
|
if (c[i] == '<') {
|
||||||
|
inTag = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!inTag) {
|
||||||
|
if (i > j) {
|
||||||
|
c[j] = c[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
j++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (c[i] == '>') {
|
||||||
|
inTag = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i > j) {
|
||||||
|
return new String(c, 0, j);
|
||||||
|
}
|
||||||
|
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
}
|
738
src/helma/scripting/rhino/HopObject.java
Normal file
738
src/helma/scripting/rhino/HopObject.java
Normal file
|
@ -0,0 +1,738 @@
|
||||||
|
/*
|
||||||
|
* Helma License Notice
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the Helma License
|
||||||
|
* Version 2.0 (the "License"). You may not use this file except in
|
||||||
|
* compliance with the License. A copy of the License is available at
|
||||||
|
* http://adele.helma.org/download/helma/license.txt
|
||||||
|
*
|
||||||
|
* Copyright 1998-2003 Helma Software. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* $RCSfile$
|
||||||
|
* $Author$
|
||||||
|
* $Revision$
|
||||||
|
* $Date$
|
||||||
|
*/
|
||||||
|
|
||||||
|
package helma.scripting.rhino;
|
||||||
|
|
||||||
|
import helma.framework.*;
|
||||||
|
import helma.framework.core.*;
|
||||||
|
import helma.objectmodel.*;
|
||||||
|
import helma.objectmodel.db.*;
|
||||||
|
import org.mozilla.javascript.*;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.Enumeration;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class HopObject extends ScriptableObject {
|
||||||
|
static Method hopObjCtor;
|
||||||
|
|
||||||
|
static {
|
||||||
|
Method[] methods = HopObject.class.getMethods();
|
||||||
|
|
||||||
|
for (int i = 0; i < methods.length; i++) {
|
||||||
|
if ("hopObjectConstructor".equals(methods[i].getName())) {
|
||||||
|
hopObjCtor = methods[i];
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
String className;
|
||||||
|
INode node;
|
||||||
|
RhinoCore core;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new HopObject object.
|
||||||
|
*/
|
||||||
|
public HopObject() {
|
||||||
|
className = "HopObject";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new HopObject object.
|
||||||
|
*
|
||||||
|
* @param cname ...
|
||||||
|
*/
|
||||||
|
public HopObject(String cname) {
|
||||||
|
className = cname;
|
||||||
|
}
|
||||||
|
|
||||||
|
// public void jsConstructor () {
|
||||||
|
|
||||||
|
/* Context cx = Context.getCurrentContext ();
|
||||||
|
RhinoEngine engine = (RhinoEngine) cx.getThreadLocal ("engine");
|
||||||
|
core = engine.core;
|
||||||
|
node = new helma.objectmodel.db.Node (null, null, core.app.getWrappedNodeManager ()); */
|
||||||
|
|
||||||
|
// }
|
||||||
|
public static Object hopObjectConstructor(Context cx, Object[] args,
|
||||||
|
Function ctorObj, boolean inNewExpr) {
|
||||||
|
RhinoEngine engine = (RhinoEngine) cx.getThreadLocal("engine");
|
||||||
|
RhinoCore c = engine.core;
|
||||||
|
String prototype = ((FunctionObject) ctorObj).getFunctionName();
|
||||||
|
INode n = new helma.objectmodel.db.Node(prototype, prototype,
|
||||||
|
c.app.getWrappedNodeManager());
|
||||||
|
HopObject hobj = new HopObject(prototype);
|
||||||
|
|
||||||
|
hobj.init(c, n);
|
||||||
|
|
||||||
|
return hobj;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @return ...
|
||||||
|
*/
|
||||||
|
public String getClassName() {
|
||||||
|
return className;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @param c ...
|
||||||
|
* @param n ...
|
||||||
|
*/
|
||||||
|
public void init(RhinoCore c, INode n) {
|
||||||
|
core = c;
|
||||||
|
node = n;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @return ...
|
||||||
|
*/
|
||||||
|
public Object jsGet_cache() {
|
||||||
|
if (node == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return node.getCacheNode();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @param skin ...
|
||||||
|
* @param param ...
|
||||||
|
*
|
||||||
|
* @return ...
|
||||||
|
*/
|
||||||
|
public boolean jsFunction_renderSkin(Object skin, Object param) {
|
||||||
|
// System.err.println ("RENDERSKIN CALLED WITH PARAM "+param);
|
||||||
|
Context cx = Context.getCurrentContext();
|
||||||
|
RequestEvaluator reval = (RequestEvaluator) cx.getThreadLocal("reval");
|
||||||
|
Skin s;
|
||||||
|
|
||||||
|
if (skin instanceof Skin) {
|
||||||
|
s = (Skin) skin;
|
||||||
|
} else {
|
||||||
|
s = core.app.getSkin(node, skin.toString(), null);
|
||||||
|
}
|
||||||
|
|
||||||
|
Map p = null;
|
||||||
|
|
||||||
|
if ((param != null) && (param != Undefined.instance)) {
|
||||||
|
p = new HashMap();
|
||||||
|
|
||||||
|
if (param instanceof Scriptable) {
|
||||||
|
Scriptable sp = (Scriptable) param;
|
||||||
|
Object[] ids = sp.getIds();
|
||||||
|
|
||||||
|
for (int i = 0; i < ids.length; i++) {
|
||||||
|
Object obj = sp.get(ids[i].toString(), sp);
|
||||||
|
if (obj instanceof NativeJavaObject) {
|
||||||
|
p.put(ids[i], ((NativeJavaObject) obj).unwrap());
|
||||||
|
} else {
|
||||||
|
p.put(ids[i], obj);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (s != null) {
|
||||||
|
s.render(reval, node, p);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @param skin ...
|
||||||
|
* @param param ...
|
||||||
|
*
|
||||||
|
* @return ...
|
||||||
|
*/
|
||||||
|
public String jsFunction_renderSkinAsString(Object skin, Object param) {
|
||||||
|
// System.err.println ("RENDERSKIN CALLED WITH PARAM "+param);
|
||||||
|
Context cx = Context.getCurrentContext();
|
||||||
|
RequestEvaluator reval = (RequestEvaluator) cx.getThreadLocal("reval");
|
||||||
|
Skin s;
|
||||||
|
|
||||||
|
if (skin instanceof Skin) {
|
||||||
|
s = (Skin) skin;
|
||||||
|
} else {
|
||||||
|
s = core.app.getSkin(node, skin.toString(), null);
|
||||||
|
}
|
||||||
|
|
||||||
|
Map p = null;
|
||||||
|
|
||||||
|
if ((param != null) && (param != Undefined.instance)) {
|
||||||
|
p = new HashMap();
|
||||||
|
|
||||||
|
if (param instanceof Scriptable) {
|
||||||
|
Scriptable sp = (Scriptable) param;
|
||||||
|
Object[] ids = sp.getIds();
|
||||||
|
|
||||||
|
for (int i = 0; i < ids.length; i++) {
|
||||||
|
Object obj = sp.get(ids[i].toString(), sp);
|
||||||
|
if (obj instanceof NativeJavaObject) {
|
||||||
|
p.put(ids[i], ((NativeJavaObject) obj).unwrap());
|
||||||
|
} else {
|
||||||
|
p.put(ids[i], obj);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (s != null) {
|
||||||
|
reval.res.pushStringBuffer();
|
||||||
|
s.render(reval, node, p);
|
||||||
|
|
||||||
|
return reval.res.popStringBuffer();
|
||||||
|
}
|
||||||
|
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @param action ...
|
||||||
|
*
|
||||||
|
* @return ...
|
||||||
|
*/
|
||||||
|
public Object jsFunction_href(Object action) {
|
||||||
|
if (node == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
String act = null;
|
||||||
|
|
||||||
|
if (action != null) {
|
||||||
|
if (action instanceof NativeJavaObject) {
|
||||||
|
act = ((NativeJavaObject) action).unwrap().toString();
|
||||||
|
} else if (!(action instanceof Undefined)) {
|
||||||
|
act = action.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return core.app.getNodeHref(node, act);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @param id ...
|
||||||
|
*
|
||||||
|
* @return ...
|
||||||
|
*/
|
||||||
|
public Object jsFunction_get(Object id) {
|
||||||
|
if ((node == null) || (id == null)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
Context cx = Context.getCurrentContext();
|
||||||
|
Object n = null;
|
||||||
|
|
||||||
|
if (id instanceof Number) {
|
||||||
|
n = node.getSubnodeAt(((Number) id).intValue());
|
||||||
|
} else {
|
||||||
|
n = node.getChildElement(id.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (n == null) {
|
||||||
|
return null;
|
||||||
|
} else {
|
||||||
|
return cx.toObject(n, core.global);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @return ...
|
||||||
|
*/
|
||||||
|
public int jsFunction_count() {
|
||||||
|
if (node == null) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return node.numberOfNodes();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @return ...
|
||||||
|
*/
|
||||||
|
public int jsFunction_size() {
|
||||||
|
return jsFunction_count();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prefetch child objects from (relational) database.
|
||||||
|
*/
|
||||||
|
public void jsFunction_prefetchChildren() {
|
||||||
|
jsFunction_prefetchChildren(0, 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prefetch child objects from (relational) database.
|
||||||
|
*/
|
||||||
|
public void jsFunction_prefetchChildren(int start, int length) {
|
||||||
|
if (!(node instanceof helma.objectmodel.db.Node)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
((helma.objectmodel.db.Node) node).prefetchChildren(start, length);
|
||||||
|
} catch (Exception x) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @return ...
|
||||||
|
*/
|
||||||
|
public Object[] jsFunction_list() {
|
||||||
|
int l = node.numberOfNodes();
|
||||||
|
Enumeration e = node.getSubnodes();
|
||||||
|
ArrayList a = new ArrayList();
|
||||||
|
|
||||||
|
while ((e != null) && e.hasMoreElements()) {
|
||||||
|
a.add(e.nextElement());
|
||||||
|
}
|
||||||
|
|
||||||
|
return a.toArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @param child ...
|
||||||
|
*
|
||||||
|
* @return ...
|
||||||
|
*/
|
||||||
|
public boolean jsFunction_add(Object child) {
|
||||||
|
if ((node == null) || (child == null)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (child instanceof HopObject) {
|
||||||
|
INode added = node.addNode(((HopObject) child).node);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
} else if (child instanceof INode) {
|
||||||
|
INode added = node.addNode((INode) child);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @param index ...
|
||||||
|
* @param child ...
|
||||||
|
*
|
||||||
|
* @return ...
|
||||||
|
*/
|
||||||
|
public boolean jsFunction_addAt(int index, Object child) {
|
||||||
|
if (child == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (child instanceof HopObject) {
|
||||||
|
INode added = node.addNode(((HopObject) child).node, index);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
} else if (child instanceof INode) {
|
||||||
|
INode added = node.addNode((INode) child, index);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove node itself or one or more subnodes.
|
||||||
|
*/
|
||||||
|
public boolean jsFunction_remove(Object child) {
|
||||||
|
// semantics: if called without arguments, remove self.
|
||||||
|
// otherwise, remove given subnodes.
|
||||||
|
if (child == null) {
|
||||||
|
return node.remove();
|
||||||
|
} else if (node != null) {
|
||||||
|
try {
|
||||||
|
if (child instanceof HopObject) {
|
||||||
|
HopObject hobj = (HopObject) child;
|
||||||
|
|
||||||
|
if (hobj.node != null) {
|
||||||
|
node.removeNode(hobj.node);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception x) {
|
||||||
|
System.err.println("XXX: " + x);
|
||||||
|
x.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invalidate the node itself or a subnode
|
||||||
|
*/
|
||||||
|
public boolean jsFunction_invalidate(String childId) {
|
||||||
|
if (node instanceof helma.objectmodel.db.Node) {
|
||||||
|
if (childId == null) {
|
||||||
|
((helma.objectmodel.db.Node) node).invalidate();
|
||||||
|
} else {
|
||||||
|
((helma.objectmodel.db.Node) node).invalidateNode(childId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if node is contained in subnodes
|
||||||
|
*/
|
||||||
|
public int jsFunction_contains(Object obj) {
|
||||||
|
if ((node != null) && (obj != null) && obj instanceof HopObject) {
|
||||||
|
return node.contains(((HopObject) obj).node);
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @param name ...
|
||||||
|
* @param start ...
|
||||||
|
* @param value ...
|
||||||
|
*/
|
||||||
|
public void put(String name, Scriptable start, Object value) {
|
||||||
|
if (node == null) {
|
||||||
|
super.put(name, start, value);
|
||||||
|
} else {
|
||||||
|
if (value instanceof NativeJavaObject) {
|
||||||
|
value = ((NativeJavaObject) value).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((value == null) || (value == Undefined.instance)) {
|
||||||
|
node.unset(name);
|
||||||
|
} else if (value instanceof Scriptable) {
|
||||||
|
Scriptable s = (Scriptable) value;
|
||||||
|
|
||||||
|
if ("Date".equals(s.getClassName())) {
|
||||||
|
node.setDate(name, new Date((long) ScriptRuntime.toNumber(s)));
|
||||||
|
} else {
|
||||||
|
node.setString(name, s.toString());
|
||||||
|
}
|
||||||
|
} else if (value instanceof String) {
|
||||||
|
node.setString(name, value.toString());
|
||||||
|
} else if (value instanceof Boolean) {
|
||||||
|
node.setBoolean(name, ((Boolean) value).booleanValue());
|
||||||
|
} else if (value instanceof Number) {
|
||||||
|
node.setFloat(name, ((Number) value).doubleValue());
|
||||||
|
} else if (value instanceof Date) {
|
||||||
|
node.setDate(name, (Date) value);
|
||||||
|
} else if (value instanceof INode) {
|
||||||
|
node.setNode(name, (INode) value);
|
||||||
|
} else if (value instanceof HopObject) {
|
||||||
|
node.setNode(name, ((HopObject) value).node);
|
||||||
|
} else {
|
||||||
|
node.setJavaObject(name, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @param name ...
|
||||||
|
* @param start ...
|
||||||
|
*
|
||||||
|
* @return ...
|
||||||
|
*/
|
||||||
|
public boolean has(String name, Scriptable start) {
|
||||||
|
if (super.has(name, start)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((prototype != null) && prototype.has(name, start)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((node != null) && (node.get(name) != null)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @param name ...
|
||||||
|
*/
|
||||||
|
public void delete(String name) {
|
||||||
|
if ((node != null)) {
|
||||||
|
node.unset(name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @param name ...
|
||||||
|
* @param start ...
|
||||||
|
*
|
||||||
|
* @return ...
|
||||||
|
*/
|
||||||
|
public Object get(String name, Scriptable start) {
|
||||||
|
// System.err.println ("GET from "+node+": "+name);
|
||||||
|
Object retval = super.get(name, start);
|
||||||
|
|
||||||
|
if (retval != ScriptableObject.NOT_FOUND) {
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (prototype != null) {
|
||||||
|
retval = prototype.get(name, start);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (retval != ScriptableObject.NOT_FOUND) {
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (node != null) {
|
||||||
|
// Everything starting with an underscore is interpreted as internal property
|
||||||
|
if (name.startsWith("_")) {
|
||||||
|
return getInternalProperty(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
IProperty p = node.get(name);
|
||||||
|
|
||||||
|
if (p != null) {
|
||||||
|
if (p.getType() == IProperty.STRING) {
|
||||||
|
return p.getStringValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (p.getType() == IProperty.BOOLEAN) {
|
||||||
|
return p.getBooleanValue() ? Boolean.TRUE : Boolean.FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (p.getType() == IProperty.INTEGER) {
|
||||||
|
return new Long(p.getIntegerValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (p.getType() == IProperty.FLOAT) {
|
||||||
|
return new Double(p.getFloatValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
Context cx = Context.getCurrentContext();
|
||||||
|
|
||||||
|
if (p.getType() == IProperty.DATE) {
|
||||||
|
Date d = p.getDateValue();
|
||||||
|
|
||||||
|
if (d == null) {
|
||||||
|
return NOT_FOUND;
|
||||||
|
} else {
|
||||||
|
Object[] args = { new Long(d.getTime()) };
|
||||||
|
try {
|
||||||
|
return cx.newObject(core.global, "Date", args);
|
||||||
|
} catch (PropertyException px) {
|
||||||
|
return NOT_FOUND;
|
||||||
|
} catch (NotAFunctionException nafx) {
|
||||||
|
return NOT_FOUND;
|
||||||
|
} catch (JavaScriptException nafx) {
|
||||||
|
return NOT_FOUND;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (p.getType() == IProperty.NODE) {
|
||||||
|
INode n = p.getNodeValue();
|
||||||
|
|
||||||
|
if (n == null) {
|
||||||
|
return NOT_FOUND;
|
||||||
|
} else {
|
||||||
|
return cx.toObject(n, core.global);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (p.getType() == IProperty.JAVAOBJECT) {
|
||||||
|
Object obj = p.getJavaObjectValue();
|
||||||
|
|
||||||
|
if (obj == null) {
|
||||||
|
return NOT_FOUND;
|
||||||
|
} else {
|
||||||
|
return cx.toObject(obj, core.global);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// as last resort, try to get property as anonymous subnode
|
||||||
|
Object anon = node.getChildElement(name);
|
||||||
|
|
||||||
|
if (anon != null) {
|
||||||
|
return anon;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NOT_FOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Object getInternalProperty(String name) {
|
||||||
|
if ("__id__".equals(name) || "_id".equals(name)) {
|
||||||
|
return node.getID();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ("__prototype__".equals(name) || "_prototype".equals(name)) {
|
||||||
|
return node.getPrototype();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ("__parent__".equals(name) || "_parent".equals(name)) {
|
||||||
|
return core.getNodeWrapper(node.getParent());
|
||||||
|
}
|
||||||
|
|
||||||
|
// some more internal properties
|
||||||
|
if ("__name__".equals(name)) {
|
||||||
|
return node.getName();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ("__fullname__".equals(name)) {
|
||||||
|
return node.getFullName();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ("__hash__".equals(name)) {
|
||||||
|
return Integer.toString(node.hashCode());
|
||||||
|
}
|
||||||
|
|
||||||
|
if ("__node__".equals(name)) {
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ("__created__".equalsIgnoreCase(name)) {
|
||||||
|
return new Date(node.created());
|
||||||
|
}
|
||||||
|
|
||||||
|
if ("__lastmodified__".equalsIgnoreCase(name)) {
|
||||||
|
return new Date(node.lastModified());
|
||||||
|
}
|
||||||
|
|
||||||
|
return NOT_FOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @return ...
|
||||||
|
*/
|
||||||
|
public Object[] getIds() {
|
||||||
|
if (node == null) {
|
||||||
|
return new Object[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
Enumeration enum = node.properties();
|
||||||
|
ArrayList list = new ArrayList();
|
||||||
|
|
||||||
|
while (enum.hasMoreElements())
|
||||||
|
list.add(enum.nextElement());
|
||||||
|
|
||||||
|
return list.toArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @param name ...
|
||||||
|
* @param start ...
|
||||||
|
*
|
||||||
|
* @return ...
|
||||||
|
*/
|
||||||
|
public boolean has(int idx, Scriptable start) {
|
||||||
|
if (node != null) {
|
||||||
|
return (0 <= idx && idx < node.numberOfNodes());
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @param name ...
|
||||||
|
* @param start ...
|
||||||
|
*
|
||||||
|
* @return ...
|
||||||
|
*/
|
||||||
|
public Object get(int idx, Scriptable start) {
|
||||||
|
if (node != null) {
|
||||||
|
INode n = node.getSubnodeAt(idx);
|
||||||
|
|
||||||
|
if (n == null) {
|
||||||
|
return NOT_FOUND;
|
||||||
|
} else {
|
||||||
|
Context cx = Context.getCurrentContext();
|
||||||
|
return cx.toObject(n, core.global);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NOT_FOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @param hint ...
|
||||||
|
*
|
||||||
|
* @return ...
|
||||||
|
*/
|
||||||
|
public Object getDefaultValue(Class hint) {
|
||||||
|
return (className != null) ? ("[HopObject " + className + "]") : "[HopObject]";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @return ...
|
||||||
|
*/
|
||||||
|
public String toString() {
|
||||||
|
return (className != null) ? ("[HopObject " + className + "]") : "[HopObject]";
|
||||||
|
}
|
||||||
|
}
|
176
src/helma/scripting/rhino/JavaObject.java
Normal file
176
src/helma/scripting/rhino/JavaObject.java
Normal file
|
@ -0,0 +1,176 @@
|
||||||
|
/*
|
||||||
|
* Helma License Notice
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the Helma License
|
||||||
|
* Version 2.0 (the "License"). You may not use this file except in
|
||||||
|
* compliance with the License. A copy of the License is available at
|
||||||
|
* http://adele.helma.org/download/helma/license.txt
|
||||||
|
*
|
||||||
|
* Copyright 1998-2003 Helma Software. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* $RCSfile$
|
||||||
|
* $Author$
|
||||||
|
* $Revision$
|
||||||
|
* $Date$
|
||||||
|
*/
|
||||||
|
|
||||||
|
package helma.scripting.rhino;
|
||||||
|
|
||||||
|
import helma.framework.*;
|
||||||
|
import helma.framework.core.*;
|
||||||
|
import helma.objectmodel.*;
|
||||||
|
import helma.objectmodel.db.*;
|
||||||
|
import org.mozilla.javascript.*;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.Enumeration;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class JavaObject extends NativeJavaObject {
|
||||||
|
|
||||||
|
RhinoCore core;
|
||||||
|
Scriptable prototype;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new JavaObject wrapper.
|
||||||
|
*/
|
||||||
|
public JavaObject(Scriptable scope, Object obj, Scriptable prototype) {
|
||||||
|
this.parent = scope;
|
||||||
|
this.javaObject = obj;
|
||||||
|
this.prototype = prototype;
|
||||||
|
staticType = obj.getClass();
|
||||||
|
initMembers();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @param skin ...
|
||||||
|
* @param param ...
|
||||||
|
*
|
||||||
|
* @return ...
|
||||||
|
*/
|
||||||
|
public boolean jsFunction_renderSkin(Object skin, Object param) {
|
||||||
|
// System.err.println ("RENDERSKIN CALLED WITH PARAM "+param);
|
||||||
|
Context cx = Context.getCurrentContext();
|
||||||
|
RequestEvaluator reval = (RequestEvaluator) cx.getThreadLocal("reval");
|
||||||
|
Skin s;
|
||||||
|
|
||||||
|
if (skin instanceof Skin) {
|
||||||
|
s = (Skin) skin;
|
||||||
|
} else {
|
||||||
|
s = core.app.getSkin(javaObject, skin.toString(), null);
|
||||||
|
}
|
||||||
|
|
||||||
|
Map p = null;
|
||||||
|
|
||||||
|
if ((param != null) && (param != Undefined.instance)) {
|
||||||
|
p = new HashMap();
|
||||||
|
|
||||||
|
if (param instanceof Scriptable) {
|
||||||
|
Scriptable sp = (Scriptable) param;
|
||||||
|
Object[] ids = sp.getIds();
|
||||||
|
|
||||||
|
for (int i = 0; i < ids.length; i++)
|
||||||
|
p.put(ids[i], sp.get(ids[i].toString(), sp));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (s != null) {
|
||||||
|
s.render(reval, javaObject, p);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @param skin ...
|
||||||
|
* @param param ...
|
||||||
|
*
|
||||||
|
* @return ...
|
||||||
|
*/
|
||||||
|
public String jsFunction_renderSkinAsString(Object skin, Object param) {
|
||||||
|
// System.err.println ("RENDERSKIN CALLED WITH PARAM "+param);
|
||||||
|
Context cx = Context.getCurrentContext();
|
||||||
|
RequestEvaluator reval = (RequestEvaluator) cx.getThreadLocal("reval");
|
||||||
|
Skin s;
|
||||||
|
|
||||||
|
if (skin instanceof Skin) {
|
||||||
|
s = (Skin) skin;
|
||||||
|
} else {
|
||||||
|
s = core.app.getSkin(javaObject, skin.toString(), null);
|
||||||
|
}
|
||||||
|
|
||||||
|
Map p = null;
|
||||||
|
|
||||||
|
if ((param != null) && (param != Undefined.instance)) {
|
||||||
|
p = new HashMap();
|
||||||
|
|
||||||
|
if (param instanceof Scriptable) {
|
||||||
|
Scriptable sp = (Scriptable) param;
|
||||||
|
Object[] ids = sp.getIds();
|
||||||
|
|
||||||
|
for (int i = 0; i < ids.length; i++)
|
||||||
|
p.put(ids[i], sp.get(ids[i].toString(), sp));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (s != null) {
|
||||||
|
reval.res.pushStringBuffer();
|
||||||
|
s.render(reval, javaObject, p);
|
||||||
|
|
||||||
|
return reval.res.popStringBuffer();
|
||||||
|
}
|
||||||
|
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @param action ...
|
||||||
|
*
|
||||||
|
* @return ...
|
||||||
|
*/
|
||||||
|
public Object jsFunction_href(Object action) {
|
||||||
|
if (javaObject == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
String act = null;
|
||||||
|
|
||||||
|
if (action != null) {
|
||||||
|
if (action instanceof NativeJavaObject) {
|
||||||
|
act = ((NativeJavaObject) action).unwrap().toString();
|
||||||
|
} else if (!(action instanceof Undefined)) {
|
||||||
|
act = action.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return core.app.getNodeHref(javaObject, act);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean has(String name, Scriptable start) {
|
||||||
|
System.err.println ("HAS: "+name);
|
||||||
|
if (prototype.has(name, start))
|
||||||
|
return true;
|
||||||
|
return super.has(name, start);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object get(String name, Scriptable start) {
|
||||||
|
System.err.println ("GET: "+name);
|
||||||
|
Object obj = prototype.get(name, start);
|
||||||
|
if (obj != null && obj != Undefined.instance)
|
||||||
|
return obj;
|
||||||
|
return super.get(name, start);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
139
src/helma/scripting/rhino/MapWrapper.java
Normal file
139
src/helma/scripting/rhino/MapWrapper.java
Normal file
|
@ -0,0 +1,139 @@
|
||||||
|
/*
|
||||||
|
* Helma License Notice
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the Helma License
|
||||||
|
* Version 2.0 (the "License"). You may not use this file except in
|
||||||
|
* compliance with the License. A copy of the License is available at
|
||||||
|
* http://adele.helma.org/download/helma/license.txt
|
||||||
|
*
|
||||||
|
* Copyright 1998-2003 Helma Software. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* $RCSfile$
|
||||||
|
* $Author$
|
||||||
|
* $Revision$
|
||||||
|
* $Date$
|
||||||
|
*/
|
||||||
|
|
||||||
|
package helma.scripting.rhino;
|
||||||
|
|
||||||
|
import org.mozilla.javascript.Context;
|
||||||
|
import org.mozilla.javascript.Scriptable;
|
||||||
|
import org.mozilla.javascript.ScriptableObject;
|
||||||
|
import org.mozilla.javascript.NativeJavaObject;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class MapWrapper extends ScriptableObject {
|
||||||
|
Map map;
|
||||||
|
RhinoCore core;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new MapWrapper object.
|
||||||
|
*/
|
||||||
|
public MapWrapper() {
|
||||||
|
map = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new MapWrapper object.
|
||||||
|
*
|
||||||
|
* @param map ...
|
||||||
|
* @param core ...
|
||||||
|
*/
|
||||||
|
public MapWrapper(Map map, RhinoCore core) {
|
||||||
|
this.map = map;
|
||||||
|
this.core = core;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @param name ...
|
||||||
|
* @param start ...
|
||||||
|
* @param value ...
|
||||||
|
*/
|
||||||
|
public void put(String name, Scriptable start, Object value) {
|
||||||
|
if (map == null) {
|
||||||
|
map = new HashMap();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value instanceof NativeJavaObject) {
|
||||||
|
map.put(name, ((NativeJavaObject) value).unwrap());
|
||||||
|
} else {
|
||||||
|
map.put(name, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @param name ...
|
||||||
|
* @param start ...
|
||||||
|
*
|
||||||
|
* @return ...
|
||||||
|
*/
|
||||||
|
public Object get(String name, Scriptable start) {
|
||||||
|
if (map == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
Object obj = map.get(name);
|
||||||
|
|
||||||
|
if (obj != null) {
|
||||||
|
Context cx = Context.getCurrentContext();
|
||||||
|
|
||||||
|
return cx.toObject(obj, core.global);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @param name ...
|
||||||
|
* @param start ...
|
||||||
|
*
|
||||||
|
* @return ...
|
||||||
|
*/
|
||||||
|
public boolean has(String name, Scriptable start) {
|
||||||
|
return (map != null) && map.containsKey(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @param name ...
|
||||||
|
*/
|
||||||
|
public void delete(String name) {
|
||||||
|
if (map != null) {
|
||||||
|
map.remove(name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @return ...
|
||||||
|
*/
|
||||||
|
public Object[] getIds() {
|
||||||
|
if (map == null) {
|
||||||
|
return new Object[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
return map.keySet().toArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @return ...
|
||||||
|
*/
|
||||||
|
public String getClassName() {
|
||||||
|
return "[MapWrapper]";
|
||||||
|
}
|
||||||
|
}
|
84
src/helma/scripting/rhino/RhinoActionAdapter.java
Normal file
84
src/helma/scripting/rhino/RhinoActionAdapter.java
Normal file
|
@ -0,0 +1,84 @@
|
||||||
|
/*
|
||||||
|
* Helma License Notice
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the Helma License
|
||||||
|
* Version 2.0 (the "License"). You may not use this file except in
|
||||||
|
* compliance with the License. A copy of the License is available at
|
||||||
|
* http://adele.helma.org/download/helma/license.txt
|
||||||
|
*
|
||||||
|
* Copyright 1998-2003 Helma Software. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* $RCSfile$
|
||||||
|
* $Author$
|
||||||
|
* $Revision$
|
||||||
|
* $Date$
|
||||||
|
*/
|
||||||
|
|
||||||
|
package helma.scripting.rhino;
|
||||||
|
|
||||||
|
import helma.scripting.*;
|
||||||
|
|
||||||
|
// import java.util.Vector;
|
||||||
|
// import java.util.Iterator;
|
||||||
|
import java.io.*;
|
||||||
|
|
||||||
|
// import helma.framework.*;
|
||||||
|
// import helma.framework.core.*;
|
||||||
|
// import helma.util.Updatable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An class that updates fesi interpreters with actionfiles and templates.
|
||||||
|
*/
|
||||||
|
public class RhinoActionAdapter {
|
||||||
|
String sourceName;
|
||||||
|
String function;
|
||||||
|
String functionAsString;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new RhinoActionAdapter object.
|
||||||
|
*
|
||||||
|
* @param action ...
|
||||||
|
*/
|
||||||
|
public RhinoActionAdapter(ActionFile action) {
|
||||||
|
String content = action.getContent();
|
||||||
|
String functionName = action.getFunctionName();
|
||||||
|
|
||||||
|
sourceName = action.toString();
|
||||||
|
function = composeFunction(functionName,
|
||||||
|
"arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10",
|
||||||
|
content);
|
||||||
|
|
||||||
|
// check if this is a template and we need to generate an "_as_string" variant
|
||||||
|
if (action instanceof Template) {
|
||||||
|
functionAsString = composeFunction(functionName + "_as_string",
|
||||||
|
"arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10",
|
||||||
|
"res.pushStringBuffer(); " + content +
|
||||||
|
"\r\nreturn res.popStringBuffer();\r\n");
|
||||||
|
} else {
|
||||||
|
functionAsString = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String composeFunction(String funcname, String params, String body) {
|
||||||
|
if ((body == null) || "".equals(body.trim())) {
|
||||||
|
body = ";\r\n";
|
||||||
|
} else {
|
||||||
|
body = body + "\r\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (params == null) {
|
||||||
|
params = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
StringBuffer f = new StringBuffer("function ");
|
||||||
|
|
||||||
|
f.append(funcname);
|
||||||
|
f.append(" (");
|
||||||
|
f.append(params);
|
||||||
|
f.append(") {\n");
|
||||||
|
f.append(body);
|
||||||
|
f.append("\n}");
|
||||||
|
|
||||||
|
return f.toString();
|
||||||
|
}
|
||||||
|
}
|
686
src/helma/scripting/rhino/RhinoCore.java
Normal file
686
src/helma/scripting/rhino/RhinoCore.java
Normal file
|
@ -0,0 +1,686 @@
|
||||||
|
/*
|
||||||
|
* Helma License Notice
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the Helma License
|
||||||
|
* Version 2.0 (the "License"). You may not use this file except in
|
||||||
|
* compliance with the License. A copy of the License is available at
|
||||||
|
* http://adele.helma.org/download/helma/license.txt
|
||||||
|
*
|
||||||
|
* Copyright 1998-2003 Helma Software. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* $RCSfile$
|
||||||
|
* $Author$
|
||||||
|
* $Revision$
|
||||||
|
* $Date$
|
||||||
|
*/
|
||||||
|
|
||||||
|
package helma.scripting.rhino;
|
||||||
|
|
||||||
|
import helma.framework.*;
|
||||||
|
import helma.framework.core.*;
|
||||||
|
import helma.main.Server;
|
||||||
|
import helma.objectmodel.*;
|
||||||
|
import helma.objectmodel.db.DbMapping;
|
||||||
|
import helma.objectmodel.db.Relation;
|
||||||
|
import helma.scripting.*;
|
||||||
|
import helma.util.CacheMap;
|
||||||
|
import helma.util.Updatable;
|
||||||
|
import org.mozilla.javascript.*;
|
||||||
|
import java.io.*;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is the implementation of ScriptingEnvironment for the Mozilla Rhino EcmaScript interpreter.
|
||||||
|
*/
|
||||||
|
public final class RhinoCore implements WrapHandler {
|
||||||
|
// the application we're running in
|
||||||
|
public final Application app;
|
||||||
|
|
||||||
|
// the global object
|
||||||
|
Scriptable global;
|
||||||
|
|
||||||
|
// caching table for JavaScript object wrappers
|
||||||
|
CacheMap wrappercache;
|
||||||
|
|
||||||
|
// table containing JavaScript prototypes
|
||||||
|
Hashtable prototypes;
|
||||||
|
long lastUpdate = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a Rhino evaluator for the given application and request evaluator.
|
||||||
|
*/
|
||||||
|
public RhinoCore(Application app) {
|
||||||
|
this.app = app;
|
||||||
|
wrappercache = new CacheMap(500, .75f);
|
||||||
|
prototypes = new Hashtable();
|
||||||
|
|
||||||
|
Context context = Context.enter();
|
||||||
|
|
||||||
|
context.setCompileFunctionsWithDynamicScope(true);
|
||||||
|
context.setWrapHandler(this);
|
||||||
|
|
||||||
|
int optLevel = 0;
|
||||||
|
|
||||||
|
try {
|
||||||
|
optLevel = Integer.parseInt(app.getProperty("rhino.optlevel"));
|
||||||
|
} catch (Exception ignore) {
|
||||||
|
}
|
||||||
|
|
||||||
|
// System.err.println("Setting Rhino optlevel to " + optLevel);
|
||||||
|
context.setOptimizationLevel(optLevel);
|
||||||
|
|
||||||
|
try {
|
||||||
|
GlobalObject g = new GlobalObject(this, app);
|
||||||
|
|
||||||
|
global = context.initStandardObjects(g);
|
||||||
|
ScriptableObject.defineClass(global, HopObject.class);
|
||||||
|
putPrototype("hopobject",
|
||||||
|
ScriptableObject.getClassPrototype(global, "HopObject"));
|
||||||
|
putPrototype("global", global);
|
||||||
|
initialize();
|
||||||
|
} catch (Exception e) {
|
||||||
|
System.err.println("Cannot initialize interpreter");
|
||||||
|
System.err.println("Error: " + e);
|
||||||
|
e.printStackTrace();
|
||||||
|
throw new RuntimeException(e.getMessage());
|
||||||
|
} finally {
|
||||||
|
context.exit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize the evaluator, making sure the minimum type information
|
||||||
|
* necessary to bootstrap the rest is parsed.
|
||||||
|
*/
|
||||||
|
private synchronized void initialize() {
|
||||||
|
Collection protos = app.getPrototypes();
|
||||||
|
|
||||||
|
for (Iterator i = protos.iterator(); i.hasNext();) {
|
||||||
|
Prototype proto = (Prototype) i.next();
|
||||||
|
|
||||||
|
initPrototype(proto);
|
||||||
|
}
|
||||||
|
|
||||||
|
// always fully initialize global prototype, because
|
||||||
|
// we always need it and there's no chance to trigger
|
||||||
|
// creation on demand.
|
||||||
|
getPrototype("global");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize a prototype without fully parsing its script files.
|
||||||
|
*/
|
||||||
|
synchronized void initPrototype(Prototype prototype) {
|
||||||
|
// System.err.println ("FESI INIT PROTO "+prototype);
|
||||||
|
Scriptable op = null;
|
||||||
|
String name = prototype.getName();
|
||||||
|
|
||||||
|
// get the prototype's prototype if possible and necessary
|
||||||
|
Scriptable opp = null;
|
||||||
|
Prototype parent = prototype.getParentPrototype();
|
||||||
|
|
||||||
|
if (parent != null) {
|
||||||
|
// see if parent prototype is already registered. if not, register it
|
||||||
|
opp = getRawPrototype(parent.getName());
|
||||||
|
|
||||||
|
if (opp == null) {
|
||||||
|
initPrototype(parent);
|
||||||
|
opp = getRawPrototype(parent.getName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!"global".equalsIgnoreCase(name) && !"hopobject".equalsIgnoreCase(name) &&
|
||||||
|
(opp == null)) {
|
||||||
|
if (app.isJavaPrototype(name)) {
|
||||||
|
opp = getRawPrototype("__javaobject__");
|
||||||
|
} else {
|
||||||
|
opp = getRawPrototype("hopobject");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// if prototype doesn't exist (i.e. is a standard prototype built by HopExtension), create it.
|
||||||
|
op = getRawPrototype(name);
|
||||||
|
|
||||||
|
if (op == null) {
|
||||||
|
try {
|
||||||
|
Context context = Context.getCurrentContext();
|
||||||
|
|
||||||
|
op = new HopObject(name); // context.newObject (global /*, "HopObject" */);
|
||||||
|
op.setPrototype(opp);
|
||||||
|
op.setParentScope(global);
|
||||||
|
op.put("prototypename", op, name);
|
||||||
|
} catch (Exception ignore) {
|
||||||
|
System.err.println("Error creating prototype: " + ignore);
|
||||||
|
ignore.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
putPrototype(name, op);
|
||||||
|
} else {
|
||||||
|
// set parent prototype just in case it has been changed
|
||||||
|
op.setPrototype(opp);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Register a constructor for all types except global.
|
||||||
|
// This will first create a new prototyped hopobject and then calls
|
||||||
|
// the actual (scripted) constructor on it.
|
||||||
|
if (!"global".equalsIgnoreCase(name) && !"root".equalsIgnoreCase(name)) {
|
||||||
|
try {
|
||||||
|
FunctionObject fp = new FunctionObject(name, HopObject.hopObjCtor, global);
|
||||||
|
|
||||||
|
fp.addAsConstructor(global, op);
|
||||||
|
} catch (Exception ignore) {
|
||||||
|
System.err.println("Error adding ctor for " + name + ": " + ignore);
|
||||||
|
ignore.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set up a prototype, parsing and compiling all its script files.
|
||||||
|
*/
|
||||||
|
synchronized void evaluatePrototype(Prototype prototype) {
|
||||||
|
// System.err.println ("FESI EVALUATE PROTO "+prototype+" FOR "+this);
|
||||||
|
Scriptable op = null;
|
||||||
|
|
||||||
|
// get the prototype's prototype if possible and necessary
|
||||||
|
Scriptable opp = null;
|
||||||
|
Prototype parent = prototype.getParentPrototype();
|
||||||
|
|
||||||
|
if (parent != null) {
|
||||||
|
// see if parent prototype is already registered. if not, register it
|
||||||
|
opp = getPrototype(parent.getName());
|
||||||
|
|
||||||
|
if (opp == null) {
|
||||||
|
evaluatePrototype(parent);
|
||||||
|
opp = getPrototype(parent.getName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
String name = prototype.getName();
|
||||||
|
|
||||||
|
if (!"global".equalsIgnoreCase(name) && !"hopobject".equalsIgnoreCase(name) &&
|
||||||
|
(opp == null)) {
|
||||||
|
if (app.isJavaPrototype(name)) {
|
||||||
|
opp = getPrototype("__javaobject__");
|
||||||
|
} else {
|
||||||
|
opp = getPrototype("hopobject");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// if prototype doesn't exist (i.e. is a standard prototype built by HopExtension), create it.
|
||||||
|
op = getPrototype(name);
|
||||||
|
|
||||||
|
if (op == null) {
|
||||||
|
try {
|
||||||
|
Context context = Context.getCurrentContext();
|
||||||
|
|
||||||
|
op = new HopObject(name); // context.newObject (global /*, "HopObject" */);
|
||||||
|
op.setPrototype(opp);
|
||||||
|
op.setParentScope(global);
|
||||||
|
op.put("prototypename", op, name);
|
||||||
|
} catch (Exception ignore) {
|
||||||
|
System.err.println("Error creating prototype: " + ignore);
|
||||||
|
ignore.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
putPrototype(name, op);
|
||||||
|
} else {
|
||||||
|
// reset prototype to original state
|
||||||
|
resetPrototype(op);
|
||||||
|
|
||||||
|
// set parent prototype just in case it has been changed
|
||||||
|
op.setPrototype(opp);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Register a constructor for all types except global.
|
||||||
|
// This will first create a new prototyped hopobject and then calls
|
||||||
|
// the actual (scripted) constructor on it.
|
||||||
|
if (!"global".equalsIgnoreCase(name) && !"root".equalsIgnoreCase(name)) {
|
||||||
|
try {
|
||||||
|
FunctionObject fp = new FunctionObject(name, HopObject.hopObjCtor, global);
|
||||||
|
|
||||||
|
fp.addAsConstructor(global, op);
|
||||||
|
} catch (Exception ignore) {
|
||||||
|
System.err.println("Error adding ctor for " + name + ": " + ignore);
|
||||||
|
ignore.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Iterator it = prototype.getZippedCode().values().iterator(); it.hasNext();) {
|
||||||
|
Object code = it.next();
|
||||||
|
|
||||||
|
evaluate(prototype, code);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Iterator it = prototype.getCode().values().iterator(); it.hasNext();) {
|
||||||
|
Object code = it.next();
|
||||||
|
|
||||||
|
evaluate(prototype, code);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return an object prototype to its initial state, removing all application specific
|
||||||
|
* functions.
|
||||||
|
*/
|
||||||
|
synchronized void resetPrototype(Scriptable op) {
|
||||||
|
Object[] ids = op.getIds();
|
||||||
|
|
||||||
|
for (int i = 0; i < ids.length; i++) {
|
||||||
|
/* String prop = en.nextElement ().toString ();
|
||||||
|
try {
|
||||||
|
ESValue esv = op.getProperty (prop, prop.hashCode ());
|
||||||
|
if (esv instanceof ConstructedFunctionObject || esv instanceof FesiActionAdapter.ThrowException)
|
||||||
|
op.deleteProperty (prop, prop.hashCode());
|
||||||
|
} catch (Exception x) {} */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method is called before an execution context is entered to let the
|
||||||
|
* engine know it should update its prototype information.
|
||||||
|
*/
|
||||||
|
public synchronized void updatePrototypes() {
|
||||||
|
if ((System.currentTimeMillis() - lastUpdate) < 1000L) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Collection protos = app.getPrototypes();
|
||||||
|
|
||||||
|
for (Iterator i = protos.iterator(); i.hasNext();) {
|
||||||
|
Prototype proto = (Prototype) i.next();
|
||||||
|
TypeInfo info = (TypeInfo) prototypes.get(proto.getName());
|
||||||
|
|
||||||
|
if (info == null) {
|
||||||
|
// a prototype we don't know anything about yet. Init local update info.
|
||||||
|
initPrototype(proto);
|
||||||
|
info = (TypeInfo) prototypes.get(proto.getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
// only update prototype if it has already been initialized.
|
||||||
|
// otherwise, this will be done on demand
|
||||||
|
// System.err.println ("CHECKING PROTO "+proto+": "+info);
|
||||||
|
if (info.lastUpdate > 0) {
|
||||||
|
Prototype p = app.typemgr.getPrototype(info.protoName);
|
||||||
|
|
||||||
|
if (p != null) {
|
||||||
|
// System.err.println ("UPDATING PROTO: "+p);
|
||||||
|
app.typemgr.updatePrototype(p);
|
||||||
|
|
||||||
|
if (p.getLastUpdate() > info.lastUpdate) {
|
||||||
|
evaluatePrototype(p);
|
||||||
|
info.lastUpdate = p.getLastUpdate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
lastUpdate = System.currentTimeMillis();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if an object has a function property (public method if it
|
||||||
|
* is a java object) with that name.
|
||||||
|
*/
|
||||||
|
public boolean hasFunction(String protoname, String fname) {
|
||||||
|
// System.err.println ("HAS_FUNC: "+fname);
|
||||||
|
try {
|
||||||
|
Scriptable op = getPrototype(protoname);
|
||||||
|
|
||||||
|
// if this is an untyped object return false
|
||||||
|
if (op == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Object func = ScriptableObject.getProperty(op, fname);
|
||||||
|
|
||||||
|
if ((func != null) && func instanceof Function) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} catch (Exception esx) {
|
||||||
|
// System.err.println ("Error in hasFunction: "+esx);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert an input argument from Java to the scripting runtime
|
||||||
|
* representation.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* public static ESValue processXmlRpcArgument (Object what, Evaluator evaluator) throws Exception {
|
||||||
|
if (what == null)
|
||||||
|
return ESNull.theNull;
|
||||||
|
if (what instanceof Vector) {
|
||||||
|
Vector v = (Vector) what;
|
||||||
|
ArrayPrototype retval = new ArrayPrototype (evaluator.getArrayPrototype (), evaluator);
|
||||||
|
int l = v.size ();
|
||||||
|
for (int i=0; i<l; i++)
|
||||||
|
retval.putProperty (i, processXmlRpcArgument (v.elementAt (i), evaluator));
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
if (what instanceof Hashtable) {
|
||||||
|
Hashtable t = (Hashtable) what;
|
||||||
|
ESObject retval = new ObjectPrototype (evaluator.getObjectPrototype (), evaluator);
|
||||||
|
for (Enumeration e=t.keys(); e.hasMoreElements(); ) {
|
||||||
|
String next = (String) e.nextElement ();
|
||||||
|
retval.putProperty (next, processXmlRpcArgument (t.get (next), evaluator), next.hashCode ());
|
||||||
|
}
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
if (what instanceof String)
|
||||||
|
return new ESString (what.toString ());
|
||||||
|
if (what instanceof Number)
|
||||||
|
return new ESNumber (new Double (what.toString ()).doubleValue ());
|
||||||
|
if (what instanceof Boolean)
|
||||||
|
return ESBoolean.makeBoolean (((Boolean) what).booleanValue ());
|
||||||
|
if (what instanceof Date)
|
||||||
|
return new DatePrototype (evaluator, (Date) what);
|
||||||
|
return ESLoader.normalizeValue (what, evaluator);
|
||||||
|
} */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* convert a JavaScript Object object to a generic Java object stucture.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* public static Object processXmlRpcResponse (ESValue what) throws EcmaScriptException {
|
||||||
|
if (what == null || what instanceof ESNull)
|
||||||
|
return null;
|
||||||
|
if (what instanceof ArrayPrototype) {
|
||||||
|
ArrayPrototype a = (ArrayPrototype) what;
|
||||||
|
int l = a.size ();
|
||||||
|
Vector v = new Vector ();
|
||||||
|
for (int i=0; i<l; i++) {
|
||||||
|
Object nj = processXmlRpcResponse (a.getProperty (i));
|
||||||
|
v.addElement (nj);
|
||||||
|
}
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
if (what instanceof ObjectPrototype) {
|
||||||
|
ObjectPrototype o = (ObjectPrototype) what;
|
||||||
|
Hashtable t = new Hashtable ();
|
||||||
|
for (Enumeration e=o.getProperties (); e.hasMoreElements (); ) {
|
||||||
|
String next = (String) e.nextElement ();
|
||||||
|
// We don't do deep serialization of HopObjects to avoid
|
||||||
|
// that the whole web site structure is sucked out with one
|
||||||
|
// object. Instead we return some kind of "proxy" objects
|
||||||
|
// that only contain the prototype and id of the HopObject property.
|
||||||
|
Object nj = null;
|
||||||
|
ESValue esv = o.getProperty (next, next.hashCode ());
|
||||||
|
if (esv instanceof ESNode) {
|
||||||
|
INode node = ((ESNode) esv).getNode ();
|
||||||
|
if (node != null) {
|
||||||
|
Hashtable nt = new Hashtable ();
|
||||||
|
nt.put ("id", node.getID());
|
||||||
|
if (node.getPrototype() != null)
|
||||||
|
nt.put ("prototype", node.getPrototype ());
|
||||||
|
nj = nt;
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
nj = processXmlRpcResponse (esv);
|
||||||
|
if (nj != null) // can't put null as value in hashtable
|
||||||
|
t.put (next, nj);
|
||||||
|
}
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
if (what instanceof ESUndefined || what instanceof ESNull)
|
||||||
|
return null;
|
||||||
|
Object jval = what.toJavaObject ();
|
||||||
|
if (jval instanceof Byte || jval instanceof Short)
|
||||||
|
jval = new Integer (jval.toString ());
|
||||||
|
return jval;
|
||||||
|
} */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the application we're running in
|
||||||
|
*/
|
||||||
|
public Application getApplication() {
|
||||||
|
return app;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a raw prototype, i.e. in potentially unfinished state
|
||||||
|
* without checking if it needs to be updated.
|
||||||
|
*/
|
||||||
|
private Scriptable getRawPrototype(String protoName) {
|
||||||
|
if (protoName == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
TypeInfo info = (TypeInfo) prototypes.get(protoName);
|
||||||
|
|
||||||
|
return (info == null) ? null : info.objectPrototype;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the object prototype for a prototype name and initialize/update it
|
||||||
|
* if necessary.
|
||||||
|
*/
|
||||||
|
public Scriptable getPrototype(String protoName) {
|
||||||
|
if (protoName == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
TypeInfo info = (TypeInfo) prototypes.get(protoName);
|
||||||
|
|
||||||
|
if ((info != null) && (info.lastUpdate == 0)) {
|
||||||
|
Prototype p = app.typemgr.getPrototype(protoName);
|
||||||
|
|
||||||
|
if (p != null) {
|
||||||
|
app.typemgr.updatePrototype(p);
|
||||||
|
|
||||||
|
if (p.getLastUpdate() > info.lastUpdate) {
|
||||||
|
info.lastUpdate = p.getLastUpdate();
|
||||||
|
evaluatePrototype(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
// set info.lastUpdate to 1 if it is 0 so we know we
|
||||||
|
// have initialized this prototype already, even if
|
||||||
|
// it is empty (i.e. doesn't contain any scripts/skins/actoins
|
||||||
|
if (info.lastUpdate == 0) {
|
||||||
|
info.lastUpdate = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (info == null) ? null : info.objectPrototype;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register an object prototype for a certain prototype name.
|
||||||
|
*/
|
||||||
|
public void putPrototype(String protoName, Scriptable op) {
|
||||||
|
if ((protoName != null) && (op != null)) {
|
||||||
|
prototypes.put(protoName, new TypeInfo(op, protoName));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @param scope ...
|
||||||
|
* @param obj ...
|
||||||
|
* @param staticType ...
|
||||||
|
*
|
||||||
|
* @return ...
|
||||||
|
*/
|
||||||
|
public Object wrap(Scriptable scope, Object obj, Class staticType) {
|
||||||
|
if (obj instanceof INode) {
|
||||||
|
return getNodeWrapper((INode) obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (obj instanceof IPathElement) {
|
||||||
|
return getElementWrapper(obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (obj instanceof Map) {
|
||||||
|
return new MapWrapper((Map) obj, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a Script wrapper for an object. In contrast to getElementWrapper, this is called for
|
||||||
|
* any Java object, not just the ones in the request path which we know are scripted.
|
||||||
|
* So what we do is check if the object belongs to a scripted class. If so, we call getElementWrapper()
|
||||||
|
* with the object, otherwise we return a generic unscripted object wrapper.
|
||||||
|
*/
|
||||||
|
/* public Scriptable getObjectWrapper(Object e) {
|
||||||
|
if (app.getPrototypeName(e) != null) {
|
||||||
|
return getElementWrapper(e);
|
||||||
|
}
|
||||||
|
/ else if (e instanceof INode)
|
||||||
|
return new ESNode ((INode) e, this); /
|
||||||
|
else {
|
||||||
|
return Context.getCurrentContext().toObject(e, global);
|
||||||
|
}
|
||||||
|
} */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a Script wrapper for any given object. If the object implements the IPathElement
|
||||||
|
* interface, the getPrototype method will be used to retrieve the name of the prototype
|
||||||
|
* to use. Otherwise, a Java-Class-to-Script-Prototype mapping is consulted.
|
||||||
|
*/
|
||||||
|
public Scriptable getElementWrapper(Object e) {
|
||||||
|
// Gotta find out the prototype name to use for this object...
|
||||||
|
String prototypeName = app.getPrototypeName(e);
|
||||||
|
|
||||||
|
Scriptable op = getPrototype(prototypeName);
|
||||||
|
|
||||||
|
if (op == null) {
|
||||||
|
op = getPrototype("hopobject");
|
||||||
|
}
|
||||||
|
|
||||||
|
return new JavaObject(global, e, op);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a script wrapper for an instance of helma.objectmodel.INode
|
||||||
|
*/
|
||||||
|
public Scriptable getNodeWrapper(INode n) {
|
||||||
|
// FIXME: should this return ESNull.theNull?
|
||||||
|
if (n == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
HopObject esn = (HopObject) wrappercache.get(n);
|
||||||
|
|
||||||
|
if (esn == null) {
|
||||||
|
try {
|
||||||
|
String protoname = n.getPrototype();
|
||||||
|
|
||||||
|
Scriptable op = null;
|
||||||
|
|
||||||
|
// set the DbMapping of the node according to its prototype.
|
||||||
|
// this *should* be done on the objectmodel level, but isn't currently
|
||||||
|
// for embedded nodes since there's not enough type info at the objectmodel level
|
||||||
|
// for those nodes.
|
||||||
|
if ((protoname != null) && (protoname.length() > 0) &&
|
||||||
|
(n.getDbMapping() == null)) {
|
||||||
|
n.setDbMapping(app.getDbMapping(protoname));
|
||||||
|
}
|
||||||
|
|
||||||
|
op = getPrototype(protoname);
|
||||||
|
|
||||||
|
// no prototype found for this node?
|
||||||
|
if (op == null) {
|
||||||
|
op = getPrototype("hopobject");
|
||||||
|
}
|
||||||
|
|
||||||
|
esn = new HopObject();
|
||||||
|
esn.init(this, n);
|
||||||
|
esn.setPrototype(op);
|
||||||
|
|
||||||
|
wrappercache.put(n, esn);
|
||||||
|
|
||||||
|
// app.logEvent ("Wrapper for "+n+" created");
|
||||||
|
} catch (Exception x) {
|
||||||
|
System.err.println("Error creating node wrapper: " + x);
|
||||||
|
throw new RuntimeException(x.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return esn;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register a new Node wrapper with the wrapper cache. This is used by the
|
||||||
|
* Node constructor.
|
||||||
|
*/
|
||||||
|
public void putNodeWrapper(INode n, Scriptable esn) {
|
||||||
|
wrappercache.put(n, esn);
|
||||||
|
}
|
||||||
|
|
||||||
|
private synchronized void evaluate(Prototype prototype, Object code) {
|
||||||
|
if (code instanceof FunctionFile) {
|
||||||
|
FunctionFile funcfile = (FunctionFile) code;
|
||||||
|
File file = funcfile.getFile();
|
||||||
|
|
||||||
|
if (file != null) {
|
||||||
|
try {
|
||||||
|
FileReader fr = new FileReader(file);
|
||||||
|
|
||||||
|
updateEvaluator(prototype, fr, funcfile.getSourceName());
|
||||||
|
} catch (IOException iox) {
|
||||||
|
app.logEvent("Error updating function file: " + iox);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
StringReader reader = new StringReader(funcfile.getContent());
|
||||||
|
|
||||||
|
updateEvaluator(prototype, reader, funcfile.getSourceName());
|
||||||
|
}
|
||||||
|
} else if (code instanceof ActionFile) {
|
||||||
|
ActionFile action = (ActionFile) code;
|
||||||
|
RhinoActionAdapter fa = new RhinoActionAdapter(action);
|
||||||
|
|
||||||
|
try {
|
||||||
|
updateEvaluator(prototype, new StringReader(fa.function),
|
||||||
|
action.getSourceName());
|
||||||
|
} catch (Exception esx) {
|
||||||
|
app.logEvent("Error parsing " + action + ": " + esx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private synchronized void updateEvaluator(Prototype prototype, Reader reader,
|
||||||
|
String sourceName) {
|
||||||
|
// context = Context.enter(context);
|
||||||
|
try {
|
||||||
|
Scriptable op = getPrototype(prototype.getName());
|
||||||
|
|
||||||
|
// get the current context
|
||||||
|
Context cx = Context.getCurrentContext();
|
||||||
|
|
||||||
|
// do the update, evaluating the file
|
||||||
|
cx.evaluateReader(op, reader, sourceName, 1, null);
|
||||||
|
} catch (Throwable e) {
|
||||||
|
app.logEvent("Error parsing function file " + sourceName + ": " + e);
|
||||||
|
e.printStackTrace();
|
||||||
|
} finally {
|
||||||
|
if (reader != null) {
|
||||||
|
try {
|
||||||
|
reader.close();
|
||||||
|
} catch (IOException ignore) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class TypeInfo {
|
||||||
|
Scriptable objectPrototype;
|
||||||
|
long lastUpdate = 0;
|
||||||
|
String protoName;
|
||||||
|
|
||||||
|
public TypeInfo(Scriptable op, String name) {
|
||||||
|
objectPrototype = op;
|
||||||
|
protoName = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
return ("TypeInfo[" + protoName + "," + new Date(lastUpdate) + "]");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
442
src/helma/scripting/rhino/RhinoEngine.java
Normal file
442
src/helma/scripting/rhino/RhinoEngine.java
Normal file
|
@ -0,0 +1,442 @@
|
||||||
|
/*
|
||||||
|
* Helma License Notice
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the Helma License
|
||||||
|
* Version 2.0 (the "License"). You may not use this file except in
|
||||||
|
* compliance with the License. A copy of the License is available at
|
||||||
|
* http://adele.helma.org/download/helma/license.txt
|
||||||
|
*
|
||||||
|
* Copyright 1998-2003 Helma Software. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* $RCSfile$
|
||||||
|
* $Author$
|
||||||
|
* $Revision$
|
||||||
|
* $Date$
|
||||||
|
*/
|
||||||
|
|
||||||
|
package helma.scripting.rhino;
|
||||||
|
|
||||||
|
import helma.extensions.ConfigurationException;
|
||||||
|
import helma.extensions.HelmaExtension;
|
||||||
|
import helma.framework.*;
|
||||||
|
import helma.framework.core.*;
|
||||||
|
import helma.main.Server;
|
||||||
|
import helma.objectmodel.*;
|
||||||
|
import helma.objectmodel.db.DbMapping;
|
||||||
|
import helma.objectmodel.db.Relation;
|
||||||
|
import helma.scripting.*;
|
||||||
|
import helma.scripting.fesi.extensions.*;
|
||||||
|
import helma.util.CacheMap;
|
||||||
|
import helma.util.Updatable;
|
||||||
|
import org.mozilla.javascript.*;
|
||||||
|
import java.io.*;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is the implementation of ScriptingEnvironment for the Mozilla Rhino EcmaScript interpreter.
|
||||||
|
*/
|
||||||
|
public final class RhinoEngine implements ScriptingEngine {
|
||||||
|
static Map coreMap;
|
||||||
|
|
||||||
|
// the application we're running in
|
||||||
|
public Application app;
|
||||||
|
|
||||||
|
// The Rhino context
|
||||||
|
Context context;
|
||||||
|
|
||||||
|
// the global object
|
||||||
|
Scriptable global;
|
||||||
|
|
||||||
|
// the request evaluator instance owning this fesi evaluator
|
||||||
|
RequestEvaluator reval;
|
||||||
|
RhinoCore core;
|
||||||
|
|
||||||
|
// remember global variables from last invokation to be able to
|
||||||
|
// do lazy cleanup
|
||||||
|
Map lastGlobals = null;
|
||||||
|
|
||||||
|
// the global vars set by extensions
|
||||||
|
HashMap extensionGlobals;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Zero argument constructor.
|
||||||
|
*/
|
||||||
|
public RhinoEngine() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Init the scripting engine with an application and a request evaluator
|
||||||
|
*/
|
||||||
|
public void init(Application app, RequestEvaluator reval) {
|
||||||
|
this.app = app;
|
||||||
|
this.reval = reval;
|
||||||
|
core = getRhinoCore(app);
|
||||||
|
context = Context.enter();
|
||||||
|
context.setCompileFunctionsWithDynamicScope(true);
|
||||||
|
|
||||||
|
try {
|
||||||
|
global = context.newObject(core.global);
|
||||||
|
global.setPrototype(core.global);
|
||||||
|
global.setParentScope(null);
|
||||||
|
|
||||||
|
// context.putThreadLocal ("reval", reval);
|
||||||
|
// context.putThreadLocal ("engine", this);
|
||||||
|
extensionGlobals = new HashMap();
|
||||||
|
|
||||||
|
Vector extVec = Server.getServer().getExtensions();
|
||||||
|
|
||||||
|
for (int i = 0; i < extVec.size(); i++) {
|
||||||
|
HelmaExtension ext = (HelmaExtension) extVec.get(i);
|
||||||
|
|
||||||
|
try {
|
||||||
|
HashMap tmpGlobals = ext.initScripting(app, this);
|
||||||
|
|
||||||
|
if (tmpGlobals != null) {
|
||||||
|
extensionGlobals.putAll(tmpGlobals);
|
||||||
|
}
|
||||||
|
} catch (ConfigurationException e) {
|
||||||
|
app.logEvent("Couldn't initialize extension " + ext.getName() + ": " +
|
||||||
|
e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// context.removeThreadLocal ("reval");
|
||||||
|
// context.removeThreadLocal ("engine");
|
||||||
|
} catch (Exception e) {
|
||||||
|
System.err.println("Cannot initialize interpreter");
|
||||||
|
System.err.println("Error: " + e);
|
||||||
|
e.printStackTrace();
|
||||||
|
throw new RuntimeException(e.getMessage());
|
||||||
|
} finally {
|
||||||
|
// Context.exit ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static synchronized RhinoCore getRhinoCore(Application app) {
|
||||||
|
RhinoCore core = null;
|
||||||
|
|
||||||
|
if (coreMap == null) {
|
||||||
|
coreMap = new HashMap();
|
||||||
|
} else {
|
||||||
|
core = (RhinoCore) coreMap.get(app);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (core == null) {
|
||||||
|
core = new RhinoCore(app);
|
||||||
|
coreMap.put(app, core);
|
||||||
|
}
|
||||||
|
|
||||||
|
return core;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method is called before an execution context is entered to let the
|
||||||
|
* engine know it should update its prototype information.
|
||||||
|
*/
|
||||||
|
public void updatePrototypes() {
|
||||||
|
context = Context.enter(context);
|
||||||
|
context.setCompileFunctionsWithDynamicScope(true);
|
||||||
|
context.setWrapHandler(core);
|
||||||
|
|
||||||
|
int optLevel = 0;
|
||||||
|
|
||||||
|
try {
|
||||||
|
optLevel = Integer.parseInt(app.getProperty("rhino.optlevel"));
|
||||||
|
} catch (Exception ignore) {
|
||||||
|
}
|
||||||
|
|
||||||
|
context.setOptimizationLevel(optLevel);
|
||||||
|
core.updatePrototypes();
|
||||||
|
context.putThreadLocal("reval", reval);
|
||||||
|
context.putThreadLocal("engine", this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method is called when an execution context for a request
|
||||||
|
* evaluation is entered. The globals parameter contains the global values
|
||||||
|
* to be applied during this execution context.
|
||||||
|
*/
|
||||||
|
public void enterContext(HashMap globals) throws ScriptingException {
|
||||||
|
// set the thread filed in the FESI evaluator
|
||||||
|
// evaluator.thread = Thread.currentThread ();
|
||||||
|
// set globals on the global object
|
||||||
|
// context = Context.enter (context);
|
||||||
|
globals.putAll(extensionGlobals);
|
||||||
|
|
||||||
|
if ((globals != null) && (globals != lastGlobals)) {
|
||||||
|
// loop through global vars and set them
|
||||||
|
for (Iterator i = globals.keySet().iterator(); i.hasNext();) {
|
||||||
|
String k = (String) i.next();
|
||||||
|
Object v = globals.get(k);
|
||||||
|
Scriptable scriptable = null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
// we do a lot of extra work to make access to global variables
|
||||||
|
// comfortable to EcmaScript coders, i.e. we use a lot of custom wrappers
|
||||||
|
// that expose properties and functions in a special way instead of just going
|
||||||
|
// with the standard java object wrappers.
|
||||||
|
if ("path".equals(k)) {
|
||||||
|
Scriptable arr = context.newObject(global, "Array");
|
||||||
|
List path = (List) v;
|
||||||
|
|
||||||
|
// register path elements with their prototype
|
||||||
|
for (int j = 0; j < path.size(); j++) {
|
||||||
|
Object pathElem = path.get(j);
|
||||||
|
Scriptable wrappedElement = context.toObject(pathElem, global);
|
||||||
|
|
||||||
|
arr.put(j, arr, wrappedElement);
|
||||||
|
|
||||||
|
String protoname = app.getPrototypeName(pathElem);
|
||||||
|
|
||||||
|
if (protoname != null) {
|
||||||
|
arr.put(protoname, arr, wrappedElement);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
v = arr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* if (v instanceof Map) {
|
||||||
|
sv = new ESMapWrapper (this, (Map) v);
|
||||||
|
} else if ("path".equals (k)) {
|
||||||
|
ArrayPrototype parr = new ArrayPrototype (evaluator.getArrayPrototype(), evaluator);
|
||||||
|
List path = (List) v;
|
||||||
|
// register path elements with their prototype
|
||||||
|
for (int j=0; j<path.size(); j++) {
|
||||||
|
Object pathElem = path.get (j);
|
||||||
|
ESValue wrappedElement = getElementWrapper (pathElem);
|
||||||
|
parr.putProperty (j, wrappedElement);
|
||||||
|
String protoname = app.getPrototypeName (pathElem);
|
||||||
|
if (protoname != null)
|
||||||
|
parr.putHiddenProperty (protoname, wrappedElement);
|
||||||
|
}
|
||||||
|
sv = parr;
|
||||||
|
} else if ("req".equals (k)) {
|
||||||
|
sv = new ESBeanWrapper (new RequestBean ((RequestTrans) v), this);
|
||||||
|
} else if ("res".equals (k)) {
|
||||||
|
sv = new ESBeanWrapper (new ResponseBean ((ResponseTrans) v), this);
|
||||||
|
} else if ("session".equals (k)) {
|
||||||
|
sv = new ESBeanWrapper (new SessionBean ((Session)v), this);
|
||||||
|
} else if ("app".equals (k)) {
|
||||||
|
sv = new ESBeanWrapper (new ApplicationBean ((Application)v), this);
|
||||||
|
} else if (v instanceof ESValue) {
|
||||||
|
sv = (ESValue)v;
|
||||||
|
} else {
|
||||||
|
sv = ESLoader.normalizeValue (v, evaluator);
|
||||||
|
} */
|
||||||
|
scriptable = context.toObject(v, global);
|
||||||
|
global.put(k, global, scriptable);
|
||||||
|
} catch (Exception x) {
|
||||||
|
app.logEvent("Error setting global variable " + k + ": " + x);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// remember the globals set on this evaluator
|
||||||
|
lastGlobals = globals;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method is called to let the scripting engine know that the current
|
||||||
|
* execution context has terminated.
|
||||||
|
*/
|
||||||
|
public void exitContext() {
|
||||||
|
context.exit();
|
||||||
|
context.removeThreadLocal("reval");
|
||||||
|
context.removeThreadLocal("engine");
|
||||||
|
|
||||||
|
// unset the thread filed in the FESI evaluator
|
||||||
|
// evaluator.thread = null;
|
||||||
|
// loop through previous globals and unset them, if necessary.
|
||||||
|
|
||||||
|
/* if (lastGlobals != null) {
|
||||||
|
for (Iterator i=lastGlobals.keySet().iterator(); i.hasNext(); ) {
|
||||||
|
String g = (String) i.next ();
|
||||||
|
try {
|
||||||
|
global.deleteProperty (g, g.hashCode());
|
||||||
|
} catch (Exception x) {
|
||||||
|
System.err.println ("Error resetting global property: "+g);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
lastGlobals = null;
|
||||||
|
} */
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invoke a function on some object, using the given arguments and global vars.
|
||||||
|
*/
|
||||||
|
public Object invoke(Object thisObject, String functionName, Object[] args,
|
||||||
|
boolean xmlrpc) throws ScriptingException {
|
||||||
|
Scriptable eso = null;
|
||||||
|
|
||||||
|
if (thisObject == null) {
|
||||||
|
eso = global;
|
||||||
|
} else {
|
||||||
|
eso = context.toObject(thisObject, global);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
for (int i = 0; i < args.length; i++) {
|
||||||
|
// XML-RPC requires special argument conversion
|
||||||
|
// if (xmlrpc)
|
||||||
|
// esv[i] = processXmlRpcArgument (args[i], evaluator);
|
||||||
|
// for java.util.Map objects, we use the special "tight" wrapper
|
||||||
|
// that makes the Map look like a native object
|
||||||
|
|
||||||
|
/* else if (args[i] instanceof Map)
|
||||||
|
esv[i] = new ESMapWrapper (this, (Map) args[i]);
|
||||||
|
else
|
||||||
|
esv[i] = ESLoader.normalizeValue (args[i], evaluator); */
|
||||||
|
args[i] = context.toObject(args[i], global);
|
||||||
|
}
|
||||||
|
|
||||||
|
Object f = ScriptableObject.getProperty(eso, functionName);
|
||||||
|
|
||||||
|
if ((f == ScriptableObject.NOT_FOUND) || !(f instanceof Function)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
Object retval = ((Function) f).call(context, global, eso, args);
|
||||||
|
|
||||||
|
// if (xmlrpc)
|
||||||
|
// return processXmlRpcResponse (retval);
|
||||||
|
if ((retval == null) || (retval == Undefined.instance)) {
|
||||||
|
return null;
|
||||||
|
} else if (retval instanceof NativeJavaObject) {
|
||||||
|
return ((NativeJavaObject) retval).unwrap();
|
||||||
|
} else {
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
} catch (RedirectException redirect) {
|
||||||
|
throw redirect;
|
||||||
|
} catch (TimeoutException timeout) {
|
||||||
|
throw timeout;
|
||||||
|
} catch (ConcurrencyException concur) {
|
||||||
|
throw concur;
|
||||||
|
} catch (Exception x) {
|
||||||
|
// check if this is a redirect exception, which has been converted by fesi
|
||||||
|
// into an EcmaScript exception, which is why we can't explicitly catch it
|
||||||
|
if (reval.res.getRedirect() != null) {
|
||||||
|
throw new RedirectException(reval.res.getRedirect());
|
||||||
|
}
|
||||||
|
|
||||||
|
// do the same for not-modified responses
|
||||||
|
if (reval.res.getNotModified()) {
|
||||||
|
throw new RedirectException(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
// has the request timed out? If so, throw TimeoutException
|
||||||
|
// if (evaluator.thread != Thread.currentThread())
|
||||||
|
// throw new TimeoutException ();
|
||||||
|
// create and throw a ScriptingException with the right message
|
||||||
|
String msg = x.toString();
|
||||||
|
|
||||||
|
if (app.debug()) {
|
||||||
|
System.err.println("Error in Script: " + msg);
|
||||||
|
x.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new ScriptingException(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Let the evaluator know that the current evaluation has been
|
||||||
|
* aborted. This is done by setting the thread ref in the evaluator
|
||||||
|
* object to null.
|
||||||
|
*/
|
||||||
|
public void abort() {
|
||||||
|
// unset the thread filed in the FESI evaluator
|
||||||
|
// evaluator.thread = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if an object has a function property (public method if it
|
||||||
|
* is a java object) with that name.
|
||||||
|
*/
|
||||||
|
public boolean hasFunction(Object obj, String fname) {
|
||||||
|
// System.err.println ("HAS_FUNC: "+fname);
|
||||||
|
return core.hasFunction(app.getPrototypeName(obj), fname);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if an object has a defined property (public field if it
|
||||||
|
* is a java object) with that name.
|
||||||
|
*/
|
||||||
|
public Object get(Object obj, String propname) {
|
||||||
|
if ((obj == null) || (propname == null)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
String prototypeName = app.getPrototypeName(obj);
|
||||||
|
|
||||||
|
if ("user".equalsIgnoreCase(prototypeName) &&
|
||||||
|
"password".equalsIgnoreCase(propname)) {
|
||||||
|
return "[macro access to password property not allowed]";
|
||||||
|
}
|
||||||
|
|
||||||
|
// if this is a HopObject, check if the property is defined
|
||||||
|
// in the type.properties db-mapping.
|
||||||
|
if (obj instanceof INode) {
|
||||||
|
DbMapping dbm = app.getDbMapping(prototypeName);
|
||||||
|
|
||||||
|
if (dbm != null) {
|
||||||
|
Relation rel = dbm.propertyToRelation(propname);
|
||||||
|
|
||||||
|
if ((rel == null) || !rel.isPrimitive()) {
|
||||||
|
return "[property \"" + propname + "\" is not defined for " +
|
||||||
|
prototypeName + "]";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Scriptable so = context.toObject(obj, global);
|
||||||
|
|
||||||
|
try {
|
||||||
|
Object prop = so.get(propname, so);
|
||||||
|
|
||||||
|
if (prop != Undefined.instance) {
|
||||||
|
return prop;
|
||||||
|
}
|
||||||
|
} catch (Exception esx) {
|
||||||
|
// System.err.println ("Error in getProperty: "+esx);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get an introspector to this engine. FIXME: not yet implemented for the rhino engine.
|
||||||
|
*/
|
||||||
|
public IPathElement getIntrospector() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the application we're running in
|
||||||
|
*/
|
||||||
|
public Application getApplication() {
|
||||||
|
return app;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the RequestEvaluator owning and driving this FESI evaluator.
|
||||||
|
*/
|
||||||
|
public RequestEvaluator getRequestEvaluator() {
|
||||||
|
return reval;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the Response object of the current evaluation context. Proxy method to RequestEvaluator.
|
||||||
|
*/
|
||||||
|
public ResponseTrans getResponse() {
|
||||||
|
return reval.res;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the Request object of the current evaluation context. Proxy method to RequestEvaluator.
|
||||||
|
*/
|
||||||
|
public RequestTrans getRequest() {
|
||||||
|
return reval.req;
|
||||||
|
}
|
||||||
|
}
|
274
src/helma/scripting/rhino/XmlObject.java
Normal file
274
src/helma/scripting/rhino/XmlObject.java
Normal file
|
@ -0,0 +1,274 @@
|
||||||
|
/*
|
||||||
|
* Helma License Notice
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the Helma License
|
||||||
|
* Version 2.0 (the "License"). You may not use this file except in
|
||||||
|
* compliance with the License. A copy of the License is available at
|
||||||
|
* http://adele.helma.org/download/helma/license.txt
|
||||||
|
*
|
||||||
|
* Copyright 1998-2003 Helma Software. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* $RCSfile$
|
||||||
|
* $Author$
|
||||||
|
* $Revision$
|
||||||
|
* $Date$
|
||||||
|
*/
|
||||||
|
|
||||||
|
package helma.scripting.rhino;
|
||||||
|
|
||||||
|
import helma.framework.core.Application;
|
||||||
|
import helma.framework.core.RequestEvaluator;
|
||||||
|
import helma.objectmodel.INode;
|
||||||
|
import helma.objectmodel.db.Node;
|
||||||
|
import helma.objectmodel.dom.*;
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.StringReader;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class XmlObject {
|
||||||
|
RhinoCore core;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new XmlObject object.
|
||||||
|
*
|
||||||
|
* @param core ...
|
||||||
|
*/
|
||||||
|
public XmlObject(RhinoCore core) {
|
||||||
|
this.core = core;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @param hopObject ...
|
||||||
|
* @param file ...
|
||||||
|
*
|
||||||
|
* @return ...
|
||||||
|
*
|
||||||
|
* @throws IOException ...
|
||||||
|
* @throws RuntimeException ...
|
||||||
|
*/
|
||||||
|
public boolean write(Object hopObject, String file)
|
||||||
|
throws IOException {
|
||||||
|
INode node = null;
|
||||||
|
|
||||||
|
if (hopObject instanceof HopObject) {
|
||||||
|
node = ((HopObject) hopObject).node;
|
||||||
|
}
|
||||||
|
|
||||||
|
// we definitly need a node
|
||||||
|
if (node == null) {
|
||||||
|
throw new RuntimeException("First argument in Xml.write() is not an hopobject");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (file == null) {
|
||||||
|
throw new RuntimeException("Second argument file name must not be null");
|
||||||
|
}
|
||||||
|
|
||||||
|
File tmpFile = new File(file + ".tmp." + XmlWriter.generateID());
|
||||||
|
XmlWriter writer = new XmlWriter(tmpFile, "UTF-8");
|
||||||
|
|
||||||
|
writer.setDatabaseMode(false);
|
||||||
|
|
||||||
|
boolean result = writer.write(node);
|
||||||
|
|
||||||
|
writer.close();
|
||||||
|
|
||||||
|
File finalFile = new File(file);
|
||||||
|
|
||||||
|
tmpFile.renameTo(finalFile);
|
||||||
|
core.getApplication().logEvent("wrote xml to " + finalFile.getAbsolutePath());
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Xml.create() is used to get a string containing the xml-content.
|
||||||
|
* Useful if Xml-content should be made public through the web.
|
||||||
|
*/
|
||||||
|
public String writeToString(Object hopObject) throws IOException {
|
||||||
|
INode node = null;
|
||||||
|
|
||||||
|
if (hopObject instanceof HopObject) {
|
||||||
|
node = ((HopObject) hopObject).node;
|
||||||
|
}
|
||||||
|
|
||||||
|
// we definitly need a node
|
||||||
|
if (node == null) {
|
||||||
|
throw new RuntimeException("First argument in Xml.write() is not an hopobject");
|
||||||
|
}
|
||||||
|
|
||||||
|
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||||
|
XmlWriter writer = new XmlWriter(out, "UTF-8");
|
||||||
|
|
||||||
|
// in case we ever want to limit serialization depth...
|
||||||
|
// if (arguments.length > 1 && arguments[1] instanceof ESNumber)
|
||||||
|
// writer.setMaxLevels(arguments[1].toInt32());
|
||||||
|
writer.setDatabaseMode(false);
|
||||||
|
|
||||||
|
boolean result = writer.write(node);
|
||||||
|
|
||||||
|
writer.flush();
|
||||||
|
|
||||||
|
return out.toString("UTF-8");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @param file ...
|
||||||
|
*
|
||||||
|
* @return ...
|
||||||
|
*
|
||||||
|
* @throws RuntimeException ...
|
||||||
|
*/
|
||||||
|
public Object read(String file) throws RuntimeException {
|
||||||
|
return read(file, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @param file ...
|
||||||
|
* @param hopObject ...
|
||||||
|
*
|
||||||
|
* @return ...
|
||||||
|
*
|
||||||
|
* @throws RuntimeException ...
|
||||||
|
*/
|
||||||
|
public Object read(String file, Object hopObject) throws RuntimeException {
|
||||||
|
if (file == null) {
|
||||||
|
throw new RuntimeException("Missing arguments in Xml.read()");
|
||||||
|
}
|
||||||
|
|
||||||
|
INode node = null;
|
||||||
|
|
||||||
|
if (hopObject instanceof HopObject) {
|
||||||
|
node = ((HopObject) hopObject).node;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (node == null) {
|
||||||
|
// make sure we have a node, even if 2nd arg doesn't exist or is not a node
|
||||||
|
node = new Node((String) null, (String) null,
|
||||||
|
core.getApplication().getWrappedNodeManager());
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
XmlReader reader = new XmlReader();
|
||||||
|
INode result = reader.read(new File(file), node);
|
||||||
|
|
||||||
|
return core.getNodeWrapper(result);
|
||||||
|
} catch (NoClassDefFoundError e) {
|
||||||
|
throw new RuntimeException("Can't load XML parser:" + e);
|
||||||
|
} catch (Exception f) {
|
||||||
|
throw new RuntimeException(f.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @param str ...
|
||||||
|
*
|
||||||
|
* @return ...
|
||||||
|
*
|
||||||
|
* @throws RuntimeException ...
|
||||||
|
*/
|
||||||
|
public Object readFromString(String str) throws RuntimeException {
|
||||||
|
return readFromString(str, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @param str ...
|
||||||
|
* @param hopObject ...
|
||||||
|
*
|
||||||
|
* @return ...
|
||||||
|
*
|
||||||
|
* @throws RuntimeException ...
|
||||||
|
*/
|
||||||
|
public Object readFromString(String str, Object hopObject)
|
||||||
|
throws RuntimeException {
|
||||||
|
if (str == null) {
|
||||||
|
throw new RuntimeException("Missing arguments in Xml.read()");
|
||||||
|
}
|
||||||
|
|
||||||
|
INode node = null;
|
||||||
|
|
||||||
|
if (hopObject instanceof HopObject) {
|
||||||
|
node = ((HopObject) hopObject).node;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (node == null) {
|
||||||
|
// make sure we have a node, even if 2nd arg doesn't exist or is not a node
|
||||||
|
node = new Node((String) null, (String) null,
|
||||||
|
core.getApplication().getWrappedNodeManager());
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
XmlReader reader = new XmlReader();
|
||||||
|
INode result = reader.read(new StringReader(str), node);
|
||||||
|
|
||||||
|
return core.getNodeWrapper(result);
|
||||||
|
} catch (NoClassDefFoundError e) {
|
||||||
|
throw new RuntimeException("Can't load XML parser:" + e);
|
||||||
|
} catch (Exception f) {
|
||||||
|
throw new RuntimeException(f.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* class XmlGet extends BuiltinFunctionObject {
|
||||||
|
XmlGet(String name, Evaluator evaluator, FunctionPrototype fp) {
|
||||||
|
super(fp, evaluator, name, 1);
|
||||||
|
}
|
||||||
|
public ESValue callFunction(ESObject thisObject, ESValue[] arguments) throws EcmaScriptException {
|
||||||
|
if ( arguments==null || arguments.length==0 )
|
||||||
|
throw new EcmaScriptException("Xml.get() needs a location as an argument");
|
||||||
|
try {
|
||||||
|
XmlConverter converter;
|
||||||
|
if ( arguments.length>1 ) {
|
||||||
|
converter = new XmlConverter (arguments[1].toString());
|
||||||
|
} else {
|
||||||
|
converter = new XmlConverter ();
|
||||||
|
}
|
||||||
|
INode node = new helma.objectmodel.db.Node ( (String)null, (String)null, this.evaluator.engine.getApplication().getWrappedNodeManager() );
|
||||||
|
INode result = converter.convert (arguments[0].toString(),node);
|
||||||
|
return this.evaluator.engine.getNodeWrapper(result);
|
||||||
|
} catch ( NoClassDefFoundError e ) {
|
||||||
|
throw new EcmaScriptException("Can't load dom-capable xml parser.");
|
||||||
|
} catch ( RuntimeException f ) {
|
||||||
|
throw new EcmaScriptException(f.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
class XmlGetFromString extends BuiltinFunctionObject {
|
||||||
|
XmlGetFromString(String name, Evaluator evaluator, FunctionPrototype fp) {
|
||||||
|
super(fp, evaluator, name, 1);
|
||||||
|
}
|
||||||
|
public ESValue callFunction(ESObject thisObject, ESValue[] arguments) throws EcmaScriptException {
|
||||||
|
if ( arguments==null || arguments.length==0 )
|
||||||
|
throw new EcmaScriptException("Xml.getFromString() needs an XML string as parameter");
|
||||||
|
try {
|
||||||
|
XmlConverter converter;
|
||||||
|
if ( arguments.length>1 ) {
|
||||||
|
converter = new XmlConverter (arguments[1].toString());
|
||||||
|
} else {
|
||||||
|
converter = new XmlConverter ();
|
||||||
|
}
|
||||||
|
INode node = new helma.objectmodel.db.Node ( (String)null, (String)null, this.evaluator.engine.getApplication().getWrappedNodeManager() );
|
||||||
|
INode result = converter.convertFromString (arguments[0].toString(),node);
|
||||||
|
return this.evaluator.engine.getNodeWrapper(result);
|
||||||
|
} catch ( NoClassDefFoundError e ) {
|
||||||
|
throw new EcmaScriptException("Can't load dom-capable xml parser.");
|
||||||
|
} catch ( RuntimeException f ) {
|
||||||
|
throw new EcmaScriptException(f.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} */
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue