Lots of fixes and cleanup.

This commit is contained in:
hns 2003-06-24 14:02:35 +00:00
parent 4236304e84
commit 052b847c7a
5 changed files with 128 additions and 61 deletions

View file

@ -16,6 +16,7 @@
package helma.scripting.rhino;
import helma.scripting.rhino.extensions.*;
import helma.framework.*;
import helma.framework.core.*;
import helma.objectmodel.*;

View file

@ -23,6 +23,7 @@ import helma.objectmodel.*;
import helma.objectmodel.db.*;
import org.mozilla.javascript.*;
import java.lang.reflect.Method;
import java.lang.reflect.Constructor;
import java.util.ArrayList;
import java.util.Date;
import java.util.Enumeration;
@ -73,22 +74,52 @@ public class HopObject extends ScriptableObject {
*/
public static Object hopObjectConstructor(Context cx, Object[] args,
Function ctorObj, boolean inNewExpr)
throws ScriptingException {
throws JavaScriptException, ScriptingException {
RhinoEngine engine = (RhinoEngine) cx.getThreadLocal("engine");
RhinoCore c = engine.core;
String prototype = ((FunctionObject) ctorObj).getFunctionName();
INode n = new helma.objectmodel.db.Node(prototype, prototype,
// if this is a java object prototype, create a new java object
// of the given class instead of a HopObject.
if (c.app.isJavaPrototype(prototype)) {
String classname = c.app.getJavaClassForPrototype(prototype);
try {
Class clazz = Class.forName(classname);
Constructor[] cnst = clazz.getConstructors();
// brute force loop through constructors -
// alas, this isn't very pretty.
for (int i=0; i<cnst.length; i++) try {
FunctionObject fo = new FunctionObject("ctor", cnst[i], engine.global);
Object obj = fo.call(cx, engine.global, null, args);
return cx.toObject(obj, engine.global);
} catch (JavaScriptException x) {
Object value = x.getValue();
if (value instanceof Throwable) {
((Throwable) value).printStackTrace();
}
throw new JavaScriptException("Error in Java constructor: "+value);
} catch (Exception ignore) {
// constructor arguments didn't match
}
throw new ScriptingException("No matching Java Constructor found in "+clazz);
} catch (Exception x) {
System.err.println("Error in Java constructor: "+x);
throw new JavaScriptException(x);
}
} else {
INode n = new helma.objectmodel.db.Node(prototype, prototype,
c.app.getWrappedNodeManager());
HopObject hobj = new HopObject(prototype);
HopObject hobj = new HopObject(prototype);
hobj.init(c, n);
Scriptable p = c.getPrototype(prototype);
if (p != null) {
hobj.setPrototype(p);
engine.invoke(hobj, "constructor", args, false);
hobj.init(c, n);
Scriptable p = c.getPrototype(prototype);
if (p != null) {
hobj.setPrototype(p);
engine.invoke(hobj, "constructor", args, false);
}
return hobj;
}
return hobj;
}
/**
@ -111,6 +142,15 @@ public class HopObject extends ScriptableObject {
node = n;
}
/**
* Return the INode wrapped by this HopObject.
*
* @return the wrapped INode instance
*/
public INode getNode() {
return node;
}
/**
*
*

View file

@ -29,13 +29,27 @@ import java.util.HashMap;
import java.util.Map;
/**
*
*
*/
public class JavaObject extends NativeJavaObject {
RhinoCore core;
Scriptable prototype;
static HashMap overload;
static {
overload = new HashMap();
Method[] m = JavaObject.class.getMethods();
for (int i=0; i<m.length; i++) {
if ("href".equals(m[i].getName()) ||
"renderSkin".equals(m[i].getName()) ||
"renderSkinAsString".equals(m[i].getName())) {
overload.put(m[i].getName(), m[i]);
}
}
}
/**
* Creates a new JavaObject wrapper.
*/
@ -168,19 +182,17 @@ public class JavaObject extends NativeJavaObject {
public Object get(String name, Scriptable start) {
// System.err.println ("GET: "+name);
Object obj = prototype.get(name, start);
if (obj != null && obj != UniqueTag.NOT_FOUND)
return obj;
Method[] m = JavaObject.class.getMethods();
for (int i=0; i<m.length; i++) {
if (name.equals(m[i].getName())) {
obj = new FunctionObject(name, m[i], this);
// System.err.println ("GOT: "+obj);
return obj;
}
Object obj = overload.get(name);
if (obj != null) {
return new FunctionObject(name, (Method) obj, this);
}
return super.get(name, start);
obj = prototype.get(name, start);
if (obj != null && obj != UniqueTag.NOT_FOUND) {
return obj;
}
return super.get(name, start);
}
}

View file

@ -16,6 +16,7 @@
package helma.scripting.rhino;
import helma.scripting.rhino.extensions.*;
import helma.framework.*;
import helma.framework.core.*;
import helma.main.Server;
@ -144,7 +145,7 @@ public final class RhinoCore {
if (!"global".equalsIgnoreCase(name) && !"hopobject".equalsIgnoreCase(name) &&
(opp == null)) {
if (app.isJavaPrototype(name)) {
opp = getRawPrototype("__javaobject__");
opp = null;
} else {
opp = getRawPrototype("hopobject");
}
@ -177,9 +178,7 @@ public final class RhinoCore {
// the actual (scripted) constructor on it.
if (!"global".equalsIgnoreCase(name) && !"root".equalsIgnoreCase(name)) {
try {
FunctionObject fp = new FunctionObject(name, HopObject.hopObjCtor, global);
installConstructor(fp, op);
installConstructor(name, op);
} catch (Exception ignore) {
System.err.println("Error adding ctor for " + name + ": " + ignore);
ignore.printStackTrace();
@ -213,7 +212,7 @@ public final class RhinoCore {
if (!"global".equalsIgnoreCase(name) && !"hopobject".equalsIgnoreCase(name) &&
(opp == null)) {
if (app.isJavaPrototype(name)) {
opp = getPrototype("__javaobject__");
opp = null;
} else {
opp = getPrototype("hopobject");
}
@ -244,20 +243,6 @@ public final class RhinoCore {
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);
installConstructor(fp, 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();
@ -276,13 +261,14 @@ public final class RhinoCore {
* that does not set the constructor property in the prototype. This is because
* we want our own scripted constructor function to prevail, if it is defined.
*/
private void installConstructor(FunctionObject fo, Scriptable prototype) {
private void installConstructor(String name, Scriptable prototype) {
FunctionObject fo = new FunctionObject(name, HopObject.hopObjCtor, global);
ScriptRuntime.setFunctionProtoAndParent(global, fo);
fo.setImmunePrototypeProperty(prototype);
prototype.setParentScope(fo);
String name = prototype.getClassName();
ScriptableObject.defineProperty(global, name, fo, ScriptableObject.DONTENUM);
fo.setParentScope(global);
@ -563,7 +549,7 @@ public final class RhinoCore {
/**
* Register an object prototype for a certain prototype name.
*/
public void putPrototype(String protoName, Scriptable op) {
private void putPrototype(String protoName, Scriptable op) {
if ((protoName != null) && (op != null)) {
prototypes.put(protoName, new TypeInfo(op, protoName));
}
@ -575,7 +561,7 @@ public final class RhinoCore {
* 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.
*/
protected Scriptable getElementWrapper(Object e) {
public Scriptable getElementWrapper(Object e) {
Scriptable w = (Scriptable) wrappercache.get(e);
@ -600,7 +586,7 @@ public final class RhinoCore {
/**
* Get a script wrapper for an instance of helma.objectmodel.INode
*/
protected Scriptable getNodeWrapper(INode n) {
public Scriptable getNodeWrapper(INode n) {
// FIXME: is this needed? should this return ESNull.theNull?
if (n == null) {
return null;
@ -710,6 +696,16 @@ public final class RhinoCore {
}
}
/**
* Return the global scope of this RhinoCore.
*/
public Scriptable getScope() {
return global;
}
/**
* TypeInfo helper class
*/
class TypeInfo {
Scriptable objectPrototype;
long lastUpdate = 0;
@ -725,16 +721,18 @@ public final class RhinoCore {
}
}
/**
* Object wrapper class
*/
class Wrapper extends WrapFactory {
public Object wrap(Context cx, Scriptable scope, Object obj, Class staticType) {
// System.err.println ("Wrapping: "+obj);
if (obj instanceof INode) {
return getNodeWrapper((INode) obj);
}
if (obj instanceof IPathElement) {
if (obj != null && app.getPrototypeName(obj) != null) {
return getElementWrapper(obj);
}
@ -750,7 +748,7 @@ public final class RhinoCore {
}
public Scriptable wrapAsJavaObject(Context cx, Scriptable scope, Object javaObject) {
if (javaObject instanceof IPathElement) {
if (javaObject != null && app.getPrototypeName(javaObject) != null) {
return getElementWrapper(javaObject);
}
@ -763,7 +761,7 @@ public final class RhinoCore {
return getNodeWrapper((INode) obj);
}
if (obj instanceof IPathElement) {
if (obj != null && app.getPrototypeName(obj) != null) {
return getElementWrapper(obj);
}

View file

@ -26,7 +26,6 @@ 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.*;
@ -37,6 +36,7 @@ import java.util.*;
* This is the implementation of ScriptingEnvironment for the Mozilla Rhino EcmaScript interpreter.
*/
public final class RhinoEngine implements ScriptingEngine {
// map for Application to RhinoCore binding
static Map coreMap;
// the application we're running in
@ -123,7 +123,7 @@ public final class RhinoEngine implements ScriptingEngine {
RhinoCore core = null;
if (coreMap == null) {
coreMap = new HashMap();
coreMap = new WeakHashMap();
} else {
core = (RhinoCore) coreMap.get(app);
}
@ -227,17 +227,17 @@ public final class RhinoEngine implements ScriptingEngine {
thread = null;
// loop through previous globals and unset them, if necessary.
/* if (lastGlobals != null) {
if (lastGlobals != null) {
for (Iterator i=lastGlobals.keySet().iterator(); i.hasNext(); ) {
String g = (String) i.next ();
try {
global.deleteProperty (g, g.hashCode());
global.delete (g);
} catch (Exception x) {
System.err.println ("Error resetting global property: "+g);
}
}
lastGlobals = null;
} */
}
}
/**
@ -298,10 +298,15 @@ public final class RhinoEngine implements ScriptingEngine {
}
// has the request timed out? If so, throw TimeoutException
// if (evaluator.thread != Thread.currentThread())
// throw new TimeoutException ();
if (thread != Thread.currentThread())
throw new TimeoutException ();
// create and throw a ScriptingException with the right message
String msg = x.toString();
String msg;
if (x instanceof JavaScriptException) {
msg = ((JavaScriptException) x).getValue().toString();
} else {
msg = x.toString();
}
if (app.debug()) {
System.err.println("Error in Script: " + msg);
@ -416,16 +421,27 @@ public final class RhinoEngine implements ScriptingEngine {
}
/**
* Return the Response object of the current evaluation context. Proxy method to RequestEvaluator.
* 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.
* Return the Request object of the current evaluation context.
* Proxy method to RequestEvaluator.
*/
public RequestTrans getRequest() {
return reval.req;
}
/**
* Return the RhinoCore object for the application this engine belongs to.
*
* @return this engine's RhinoCore instance
*/
public RhinoCore getCore() {
return core;
}
}