diff --git a/src/helma/scripting/ScriptingEnvironment.java b/src/helma/scripting/ScriptingEnvironment.java index 4c75bc93..3e8f0554 100644 --- a/src/helma/scripting/ScriptingEnvironment.java +++ b/src/helma/scripting/ScriptingEnvironment.java @@ -3,9 +3,9 @@ package helma.scripting; - +import helma.framework.core.Application; import java.util.*; - +import java.io.File; /** * This is the interface that must be implemented to make a scripting environment @@ -16,45 +16,26 @@ public interface ScriptingEnvironment { /** * Initialize the environment using the given properties */ - public void init (Properties props) throws ScriptingException; + public void init (Application app, Properties props) throws ScriptingException; + /** + * Evaluate a source file on a given type/class/prototype + */ + public void evaluate (File file, String type) throws ScriptingException; /** * Invoke a function on some object, using the given arguments and global vars. */ - public Object invoke (Object thisObject, Object[] args, HashMap globals) throws ScriptingException; + public Object invoke (Object thisObject, String functionName, Object[] args, HashMap globals) throws ScriptingException; + /** + * Get a property on an object + */ + public Object get (Object thisObject, String key); + + /** + * Return true if a function by that name is defined for that object. + */ + public boolean hasFunction (Object thisObject, String functionName) throws ScriptingException; } - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/helma/scripting/fesi/ESAppNode.java b/src/helma/scripting/fesi/ESAppNode.java index f31f28ec..83b3e15f 100644 --- a/src/helma/scripting/fesi/ESAppNode.java +++ b/src/helma/scripting/fesi/ESAppNode.java @@ -20,11 +20,11 @@ public class ESAppNode extends ESNode { private Application app; private DatePrototype createtime; - public ESAppNode (INode node, RequestEvaluator eval) throws EcmaScriptException { - super (eval.esNodePrototype, eval.evaluator, node, eval); - app = eval.app; - createtime = new DatePrototype (eval.evaluator, node.created()); - FunctionPrototype fp = (FunctionPrototype) eval.evaluator.getFunctionPrototype(); + public ESAppNode (INode node, FesiEvaluator eval) throws EcmaScriptException { + super (eval.getPrototype("hopobject"), eval.getEvaluator(), node, eval); + app = eval.getApplication(); + createtime = new DatePrototype (evaluator, node.created()); + FunctionPrototype fp = (FunctionPrototype) evaluator.getFunctionPrototype(); putHiddenProperty("getThreads", new AppCountThreads ("getThreads", evaluator, fp)); putHiddenProperty("getMaxThreads", new AppCountEvaluators ("getMaxThreads", evaluator, fp)); putHiddenProperty("getFreeThreads", new AppCountFreeEvaluators ("getFreeThreads", evaluator, fp)); diff --git a/src/helma/scripting/fesi/ESGenericObject.java b/src/helma/scripting/fesi/ESGenericObject.java index e70b64f9..c396bf74 100644 --- a/src/helma/scripting/fesi/ESGenericObject.java +++ b/src/helma/scripting/fesi/ESGenericObject.java @@ -107,54 +107,3 @@ public class ESGenericObject extends ObjectPrototype { } - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/helma/scripting/fesi/ESNode.java b/src/helma/scripting/fesi/ESNode.java index 9f1474d6..caf8d1b5 100644 --- a/src/helma/scripting/fesi/ESNode.java +++ b/src/helma/scripting/fesi/ESNode.java @@ -35,23 +35,23 @@ public class ESNode extends ObjectPrototype { NodeHandle handle; DbMapping dbmap; Throwable lastError = null; - RequestEvaluator eval; + FesiEvaluator eval; /** * Constructor used to create transient cache nodes */ - public ESNode (INode node, RequestEvaluator eval) { - super (eval.esNodePrototype, eval.evaluator); + public ESNode (INode node, FesiEvaluator eval) { + super (eval.getPrototype("hopobject"), eval.getEvaluator()); this.eval = eval; this.node = node; cache = null; cacheWrapper = null; - + // this is a transient node, set node handle to null handle = null; } - - public ESNode (ESObject prototype, Evaluator evaluator, Object obj, RequestEvaluator eval) { + + public ESNode (ESObject prototype, Evaluator evaluator, Object obj, FesiEvaluator eval) { super (prototype, evaluator); // eval.app.logEvent ("in ESNode constructor: "+o.getClass ()); this.eval = eval; diff --git a/src/helma/scripting/fesi/ESUser.java b/src/helma/scripting/fesi/ESUser.java index 0c97e1eb..57819880 100644 --- a/src/helma/scripting/fesi/ESUser.java +++ b/src/helma/scripting/fesi/ESUser.java @@ -27,8 +27,8 @@ public class ESUser extends ESNode { /** if the user is online, this is his/her online session object */ public User user; - public ESUser (INode node, RequestEvaluator eval, User user) { - super (eval.esUserPrototype, eval.evaluator, node, eval); + public ESUser (INode node, FesiEvaluator eval, User user) { + super (eval.getPrototype("user"), eval.getEvaluator(), node, eval); this.user = user; if (user != null) { cache = user.getCache (); diff --git a/src/helma/scripting/fesi/FesiEvaluator.java b/src/helma/scripting/fesi/FesiEvaluator.java new file mode 100644 index 00000000..5760af49 --- /dev/null +++ b/src/helma/scripting/fesi/FesiEvaluator.java @@ -0,0 +1,164 @@ +// FesiScriptingEnvironment.java +// Copyright (c) Hannes Wallnöfer 2002 + +package helma.scripting.fesi; + +import helma.scripting.*; +import helma.scripting.fesi.extensions.*; +import helma.framework.core.*; +import helma.objectmodel.INode; +import helma.objectmodel.db.DbMapping; +import java.util.*; +import java.io.File; +import FESI.Data.*; +import FESI.Interpreter.*; +import FESI.Exceptions.*; +import Acme.LruHashtable; + +/** + * This is the implementation of ScriptingEnvironment for the FESI EcmaScript interpreter. + */ + +public class FesiEvaluator { + + // the application we're running in + Application app; + + // The FESI evaluator + Evaluator evaluator; + + // the globa object + GlobalObject global; + + // caching table for JavaScript object wrappers + LruHashtable wrappercache; + + // table containing JavaScript prototypes + Hashtable prototypes; + + + // extensions loaded by this evaluator + static String[] extensions = new String[] { + "FESI.Extensions.BasicIO", + "FESI.Extensions.FileIO", + "helma.xmlrpc.fesi.FesiRpcExtension", + "helma.scripting.fesi.extensions.ImageExtension", + "helma.scripting.fesi.extensions.FtpExtension", + "FESI.Extensions.JavaAccess", + "FESI.Extensions.OptionalRegExp"}; + + public FesiEvaluator (Application app) { + this.app = app; + wrappercache = new LruHashtable (100, .80f); + prototypes = new Hashtable (); + initEvaluator (); + initialized = false; + } + + + // init Script Evaluator + private void initEvaluator () { + try { + evaluator = new Evaluator(); + // evaluator.reval = this; + global = evaluator.getGlobalObject(); + for (int i=0; i 0 && n.getDbMapping () == null) { + n.setDbMapping (app.getDbMapping (protoname)); + } + + op = getPrototype (protoname); + + // no prototype found for this node? + if (op == null) + op = getPrototype("hopobject"); + + + DbMapping dbm = n.getDbMapping (); + if (dbm != null && dbm.isInstanceOf ("user")) + esn = new ESUser (n, this, null); + else + esn = new ESNode (op, evaluator, n, this); + + wrappercache.put (n, esn); + // app.logEvent ("Wrapper for "+n+" created"); + } + + return esn; + } + + +} diff --git a/src/helma/scripting/fesi/FesiScriptingEnvironment.java b/src/helma/scripting/fesi/FesiScriptingEnvironment.java new file mode 100644 index 00000000..4f60e815 --- /dev/null +++ b/src/helma/scripting/fesi/FesiScriptingEnvironment.java @@ -0,0 +1,59 @@ +// FesiScriptingEnvironment.java +// Copyright (c) Hannes Wallnöfer 2002 + +package helma.scripting.fesi; + +import helma.scripting.*; +import helma.framework.core.*; +import java.util.*; +import java.io.File; +import FESI.Data.*; +import FESI.Interpreter.*; +import FESI.Exceptions.*; + +/** + * This is the implementation of ScriptingEnvironment for the FESI EcmaScript interpreter. + */ +public class FesiScriptingEnvironment { + + Application app; + Properties props; + HashMap evaluators; + + /** + * Initialize the environment using the given properties + */ + public void init (Application app, Properties props) throws ScriptingException { + this.app = app; + this.props = props; + evaluators = new HashMap (); + } + + /** + * Evaluate a source file on a given type/class/prototype + */ + public void evaluate (File file, String type) throws ScriptingException { + } + + /** + * Invoke a function on some object, using the given arguments and global vars. + */ + public Object invoke (Object thisObject, String functionName, Object[] args, HashMap globals) throws ScriptingException { + return null; + } + + /** + * Get a property on an object + */ + public Object get (Object thisObject, String key) { + return null; + } + + /** + * Return true if a function by that name is defined for that object. + */ + public boolean hasFunction (Object thisObject, String functionName) throws ScriptingException { + return false; + } + +} diff --git a/src/helma/scripting/fesi/HopExtension.java b/src/helma/scripting/fesi/HopExtension.java index d028e123..c5f0aba0 100644 --- a/src/helma/scripting/fesi/HopExtension.java +++ b/src/helma/scripting/fesi/HopExtension.java @@ -18,28 +18,28 @@ import java.text.*; import org.xml.sax.InputSource; /** - * This is the basic Extension for FESI interpreters used in HOP. It sets up - * varios constructors, global functions and properties etc. + * This is the basic Extension for FESI interpreters used in HOP. It sets up + * varios constructors, global functions and properties etc. */ - + public class HopExtension { protected Application app; - protected RequestEvaluator reval; + protected FesiEvaluator fesi; - public HopExtension () { - super(); + public HopExtension (Application app) { + this.app = app; } /** * Called by the evaluator after the extension is loaded. */ - public void initializeExtension (RequestEvaluator reval) throws EcmaScriptException { + public void initializeExtension (FesiEvaluator fesi) throws EcmaScriptException { + + this.fesi = fesi; + Evaluator evaluator = fesi.getEvaluator (); - this.reval = reval; - this.app = reval.app; - Evaluator evaluator = reval.evaluator; GlobalObject go = evaluator.getGlobalObject(); FunctionPrototype fp = (FunctionPrototype) evaluator.getFunctionPrototype(); @@ -57,41 +57,41 @@ public class HopExtension { dp.putHiddenProperty ("format", new DatePrototypeFormat ("format", evaluator, fp)); // generic (Java wrapper) object prototype - reval.esObjectPrototype = new ObjectPrototype (op, evaluator); + ObjectPrototype esObjectPrototype = new ObjectPrototype (op, evaluator); // the Node prototype - reval.esNodePrototype = new ObjectPrototype(op, evaluator); + ObjectPrototype esNodePrototype = new ObjectPrototype(op, evaluator); // the User prototype - reval.esUserPrototype = new ObjectPrototype (reval.esNodePrototype, evaluator); + ObjectPrototype esUserPrototype = new ObjectPrototype (esNodePrototype, evaluator); // the Node constructor - ESObject node = new NodeConstructor ("Node", fp, reval); + ESObject node = new NodeConstructor ("Node", fp, fesi); // register the default methods of Node objects in the Node prototype - reval.esNodePrototype.putHiddenProperty ("add", new NodeAdd ("add", evaluator, fp)); - reval.esNodePrototype.putHiddenProperty ("addAt", new NodeAddAt ("addAt", evaluator, fp)); - reval.esNodePrototype.putHiddenProperty ("remove", new NodeRemove ("remove", evaluator, fp)); - reval.esNodePrototype.putHiddenProperty ("link", new NodeLink ("link", evaluator, fp)); - reval.esNodePrototype.putHiddenProperty ("list", new NodeList ("list", evaluator, fp)); - reval.esNodePrototype.putHiddenProperty ("set", new NodeSet ("set", evaluator, fp)); - reval.esNodePrototype.putHiddenProperty ("get", new NodeGet ("get", evaluator, fp)); - reval.esNodePrototype.putHiddenProperty ("count", new NodeCount ("count", evaluator, fp)); - reval.esNodePrototype.putHiddenProperty ("contains", new NodeContains ("contains", evaluator, fp)); - reval.esNodePrototype.putHiddenProperty ("size", new NodeCount ("size", evaluator, fp)); - reval.esNodePrototype.putHiddenProperty ("editor", new NodeEditor ("editor", evaluator, fp)); - reval.esNodePrototype.putHiddenProperty ("path", new NodeHref ("path", evaluator, fp)); - reval.esNodePrototype.putHiddenProperty ("href", new NodeHref ("href", evaluator, fp)); - reval.esNodePrototype.putHiddenProperty ("setParent", new NodeSetParent ("setParent", evaluator, fp)); - reval.esNodePrototype.putHiddenProperty ("invalidate", new NodeInvalidate ("invalidate", evaluator, fp)); - reval.esNodePrototype.putHiddenProperty ("renderSkin", new RenderSkin ("renderSkin", evaluator, fp, false, false)); - reval.esNodePrototype.putHiddenProperty ("renderSkinAsString", new RenderSkin ("renderSkinAsString", evaluator, fp, false, true)); - reval.esNodePrototype.putHiddenProperty ("clearCache", new NodeClearCache ("clearCache", evaluator, fp)); + esNodePrototype.putHiddenProperty ("add", new NodeAdd ("add", evaluator, fp)); + esNodePrototype.putHiddenProperty ("addAt", new NodeAddAt ("addAt", evaluator, fp)); + esNodePrototype.putHiddenProperty ("remove", new NodeRemove ("remove", evaluator, fp)); + esNodePrototype.putHiddenProperty ("link", new NodeLink ("link", evaluator, fp)); + esNodePrototype.putHiddenProperty ("list", new NodeList ("list", evaluator, fp)); + esNodePrototype.putHiddenProperty ("set", new NodeSet ("set", evaluator, fp)); + esNodePrototype.putHiddenProperty ("get", new NodeGet ("get", evaluator, fp)); + esNodePrototype.putHiddenProperty ("count", new NodeCount ("count", evaluator, fp)); + esNodePrototype.putHiddenProperty ("contains", new NodeContains ("contains", evaluator, fp)); + esNodePrototype.putHiddenProperty ("size", new NodeCount ("size", evaluator, fp)); + esNodePrototype.putHiddenProperty ("editor", new NodeEditor ("editor", evaluator, fp)); + esNodePrototype.putHiddenProperty ("path", new NodeHref ("path", evaluator, fp)); + esNodePrototype.putHiddenProperty ("href", new NodeHref ("href", evaluator, fp)); + esNodePrototype.putHiddenProperty ("setParent", new NodeSetParent ("setParent", evaluator, fp)); + esNodePrototype.putHiddenProperty ("invalidate", new NodeInvalidate ("invalidate", evaluator, fp)); + esNodePrototype.putHiddenProperty ("renderSkin", new RenderSkin ("renderSkin", evaluator, fp, false, false)); + esNodePrototype.putHiddenProperty ("renderSkinAsString", new RenderSkin ("renderSkinAsString", evaluator, fp, false, true)); + esNodePrototype.putHiddenProperty ("clearCache", new NodeClearCache ("clearCache", evaluator, fp)); - // default methods for generic Java wrapper object prototype. + // default methods for generic Java wrapper object prototype. // This is a small subset of the methods in esNodePrototype. - reval.esObjectPrototype.putHiddenProperty ("href", new NodeHref ("href", evaluator, fp)); - reval.esObjectPrototype.putHiddenProperty("renderSkin", new RenderSkin ("renderSkin", evaluator, fp, false, false)); - reval.esObjectPrototype.putHiddenProperty("renderSkinAsString", new RenderSkin ("renderSkinAsString", evaluator, fp, false, true)); + esObjectPrototype.putHiddenProperty ("href", new NodeHref ("href", evaluator, fp)); + esObjectPrototype.putHiddenProperty("renderSkin", new RenderSkin ("renderSkin", evaluator, fp, false, false)); + esObjectPrototype.putHiddenProperty("renderSkinAsString", new RenderSkin ("renderSkinAsString", evaluator, fp, false, true)); - // methods that give access to properties and global user lists + // methods that give access to properties and global user lists go.putHiddenProperty("Node", node); // register the constructor for a plain Node object. go.putHiddenProperty("HopObject", node); // HopObject is the new name for node. go.putHiddenProperty("getProperty", new GlobalGetProperty ("getProperty", evaluator, fp)); @@ -117,17 +117,22 @@ public class HopExtension { go.putHiddenProperty("renderSkin", new RenderSkin ("renderSkin", evaluator, fp, true, false)); go.putHiddenProperty("renderSkinAsString", new RenderSkin ("renderSkinAsString", evaluator, fp, true, true)); go.putHiddenProperty("authenticate", new GlobalAuthenticate ("authenticate", evaluator, fp)); + // don't allow script writers to shut down Helma... ;-) go.deleteProperty("exit", "exit".hashCode()); // and some methods for session management from JS... - reval.esUserPrototype.putHiddenProperty("logon", new UserLogin ("logon", evaluator, fp)); - reval.esUserPrototype.putHiddenProperty("login", new UserLogin ("login", evaluator, fp)); - reval.esUserPrototype.putHiddenProperty("register", new UserRegister ("register", evaluator, fp)); - reval.esUserPrototype.putHiddenProperty("logout", new UserLogout ("logout", evaluator, fp)); - reval.esUserPrototype.putHiddenProperty("onSince", new UserOnSince ("onSince", evaluator, fp)); - reval.esUserPrototype.putHiddenProperty("lastActive", new UserLastActive ("lastActive", evaluator, fp)); - reval.esUserPrototype.putHiddenProperty("touch", new UserTouch ("touch", evaluator, fp)); + esUserPrototype.putHiddenProperty("logon", new UserLogin ("logon", evaluator, fp)); + esUserPrototype.putHiddenProperty("login", new UserLogin ("login", evaluator, fp)); + esUserPrototype.putHiddenProperty("register", new UserRegister ("register", evaluator, fp)); + esUserPrototype.putHiddenProperty("logout", new UserLogout ("logout", evaluator, fp)); + esUserPrototype.putHiddenProperty("onSince", new UserOnSince ("onSince", evaluator, fp)); + esUserPrototype.putHiddenProperty("lastActive", new UserLastActive ("lastActive", evaluator, fp)); + esUserPrototype.putHiddenProperty("touch", new UserTouch ("touch", evaluator, fp)); + // register object prototypes with FesiEvaluator + fesi.putPrototype ("global", go); + fesi.putPrototype ("hopobject", esNodePrototype); + fesi.putPrototype ("user", esUserPrototype); } class NodeAdd extends BuiltinFunctionObject { @@ -427,7 +432,7 @@ public class HopExtension { if (unode == null) return ESNull.theNull; else - return reval.getNodeWrapper (unode); + return fesi.getNodeWrapper (unode); } } @@ -542,12 +547,13 @@ public class HopExtension { } public ESValue callFunction (ESObject thisObj, ESValue[] arguments) throws EcmaScriptException { if (arguments.length < 1 || arguments.length > 2 || arguments[0] ==null || arguments[0] == ESNull.theNull) - throw new EcmaScriptException ("renderSkin must be called with one Skin argument and an optional parameter argument"); + throw new EcmaScriptException ("renderSkin requires one argument containing the skin name and an optional parameter object argument"); try { Skin skin = null; ESObject thisObject = global ? null : thisObj; HashMap params = null; if (arguments.length > 1 && arguments[1] instanceof ESObject) { + // create an parameter object to pass to the skin ESObject paramObject = (ESObject) arguments[1]; params = new HashMap (); for (Enumeration en=paramObject.getProperties(); en.hasMoreElements(); ) { @@ -563,13 +569,13 @@ public class HopExtension { skin = (Skin) obj; } + Object javaObject = thisObject == null ? null : thisObject.toJavaObject (); if (skin == null) - skin = reval.getSkin (thisObject, arguments[0].toString ()); + skin = app.getSkin (javaObject, arguments[0].toString ()); if (asString) reval.res.pushStringBuffer (); - Object javaObj = thisObject == null ? null : thisObject.toJavaObject (); if (skin != null) - skin.render (reval, javaObj, params); + skin.render (reval, javaObject, params); else reval.res.write ("[Skin not found: "+arguments[0]+"]"); if (asString) @@ -599,7 +605,7 @@ public class HopExtension { } if (user == null) return ESNull.theNull; - return reval.getNodeWrapper (user); + return fesi.getNodeWrapper (user); } } @@ -616,7 +622,7 @@ public class HopExtension { if (user == null || user.getUID() == null) return ESNull.theNull; user.touch (); - return reval.getNodeWrapper (user.getNode ()); + return fesi.getNodeWrapper (user.getNode ()); } } @@ -653,7 +659,7 @@ public class HopExtension { User u = (User) e.nextElement (); // Note: we previously sorted out duplicate users - now we simply enumerate all active sessions. // if (u.uid == null || !visited.containsKey (u.uid)) { - theArray.setElementAt (reval.getNodeWrapper (u), i++); + theArray.setElementAt (fesi.getNodeWrapper (u), i++); // if (u.uid != null) visited.put (u.uid, u); // } } @@ -892,17 +898,6 @@ public class HopExtension { } - /* class NodePath extends BuiltinFunctionObject { - NodePath (String name, Evaluator evaluator, FunctionPrototype fp) { - super (fp, evaluator, name, 1); - } - public ESValue callFunction (ESObject thisObject, ESValue[] arguments) throws EcmaScriptException { - INode n = ((ESNode) thisObject).getNode (); - String tmpname = arguments[0].toString (); - return new ESString (app.getNodePath (n, tmpname)); - } - } */ - class NodeSetParent extends BuiltinFunctionObject { NodeSetParent (String name, Evaluator evaluator, FunctionPrototype fp) { super (fp, evaluator, name, 2); @@ -975,7 +970,7 @@ public class HopExtension { double d = from <= to ? 1.0 : -1.0; for (double i=from; i*d<=to*d; i+=step) { if (Math.abs (i%1) < l) { - int j = (int) i; + int j = (int) i; b.append ("