From aa4c0389d4f218eecfe7c05ea5596934a33938ad Mon Sep 17 00:00:00 2001 From: hns Date: Fri, 7 Jun 2002 19:15:51 +0000 Subject: [PATCH] merged in changes from "lazy_typing" branch, prototypes are only initialized on demand. --- src/helma/framework/core/Application.java | 123 ++++---- src/helma/framework/core/Prototype.java | 49 ++- .../framework/core/RequestEvaluator.java | 89 ++++-- src/helma/framework/core/Skin.java | 29 +- src/helma/framework/core/TypeManager.java | 212 ++++--------- src/helma/framework/core/ZippedAppFile.java | 8 + ...gEnvironment.java => ScriptingEngine.java} | 24 +- .../scripting/fesi/FesiEngineFactory.java | 18 ++ src/helma/scripting/fesi/FesiEvaluator.java | 284 ++++++++++++------ .../fesi/FesiScriptingEnvironment.java | 85 ------ 10 files changed, 460 insertions(+), 461 deletions(-) rename src/helma/scripting/{ScriptingEnvironment.java => ScriptingEngine.java} (59%) create mode 100644 src/helma/scripting/fesi/FesiEngineFactory.java delete mode 100644 src/helma/scripting/fesi/FesiScriptingEnvironment.java diff --git a/src/helma/framework/core/Application.java b/src/helma/framework/core/Application.java index 3356377b..9a6d6ff3 100644 --- a/src/helma/framework/core/Application.java +++ b/src/helma/framework/core/Application.java @@ -25,16 +25,13 @@ import java.rmi.server.*; * requests from the Web server or XML-RPC port and dispatches them to * the evaluators. */ -public class Application extends UnicastRemoteObject implements IRemoteApp, IPathElement, IReplicatedApp, Runnable { +public final class Application extends UnicastRemoteObject implements IRemoteApp, IPathElement, IReplicatedApp, Runnable { private String name; SystemProperties props, dbProps; File home, appDir, dbDir; protected NodeManager nmgr; - // the class name of the scripting environment implementation - ScriptingEnvironment scriptingEngine; - // the root of the website, if a custom root object is defined. // otherwise this is managed by the NodeManager and not cached here. Object rootObject = null; @@ -111,9 +108,6 @@ public class Application extends UnicastRemoteObject implements IRemoteApp, IPat // Map of extensions allowed for public skins Properties skinExtensions; - // a cache for parsed skin objects - public CacheMap skincache = new CacheMap (200, 0.80f); - // DocApplication used for introspection public DocApplication docApp; @@ -228,29 +222,29 @@ public class Application extends UnicastRemoteObject implements IRemoteApp, IPat * Get the application ready to run, initializing the evaluators and type manager. */ public void init () throws DatabaseException, ScriptingException { - scriptingEngine = new helma.scripting.fesi.FesiScriptingEnvironment (); - scriptingEngine.init (this, props); - - eval = new RequestEvaluator (this); - logEvent ("Starting evaluators for "+name); - int maxThreads = 12; - try { - maxThreads = Integer.parseInt (props.getProperty ("maxThreads")); - } catch (Exception ignore) {} - freeThreads = new Stack (); - allThreads = new Vector (); - allThreads.addElement (eval); - for (int i=0; i sessionTimeout * 60000) { -// if (session.uid != null) { -// FIXME onlogout()! try {eval.invokeFunction (u, "onLogout", new Object[0]);} catch (Exception ignore) {} -// } + INode usernode = session.getUserNode (); + if (usernode != null) { + try { + eval.invokeFunction (usernode, "onLogout", new Object[0]); + } catch (Exception ignore) {} + } destroySession(session); } } @@ -1080,10 +1100,7 @@ public class Application extends UnicastRemoteObject implements IRemoteApp, IPat worker = null; break; } - - } - logEvent ("Scheduler for "+name+" exiting"); } diff --git a/src/helma/framework/core/Prototype.java b/src/helma/framework/core/Prototype.java index 6a64b5a3..09da43c4 100644 --- a/src/helma/framework/core/Prototype.java +++ b/src/helma/framework/core/Prototype.java @@ -13,22 +13,22 @@ import helma.util.Updatable; /** - * The Prototype class represents JavaScript prototypes defined in HOP - * applications. This manages a prototypes templates, functions and actions + * The Prototype class represents Script prototypes/type defined in a Helma + * application. This class manages a prototypes templates, functions and actions * as well as optional information about the mapping of this type to a * relational database table. */ -public class Prototype { +public final class Prototype { String id; String name; Application app; public HashMap templates, functions, actions, skins, updatables; - long lastUpdate; + long lastUpdate, lastCheck; - Prototype parent; + private Prototype parent; // Tells us whether this prototype is used to script a generic Java object, // as opposed to a Helma objectmodel node object. @@ -39,7 +39,7 @@ public class Prototype { this.app = app; this.name = name; isJavaPrototype = app.isJavaPrototype (name); - lastUpdate = 0; // System.currentTimeMillis (); + lastUpdate = lastCheck = 0; } /** @@ -57,29 +57,7 @@ public class Prototype { // this is not allowed for the hopobject and global prototypes if ("hopobject".equalsIgnoreCase (name) || "global".equalsIgnoreCase (name)) return; - - Prototype old = this.parent; this.parent = parent; - - // if parent has changed, update ES-prototypes in request evaluators - if (parent != old) { - /* Iterator evals = app.typemgr.getRegisteredRequestEvaluators (); - while (evals.hasNext ()) { - try { - RequestEvaluator reval = (RequestEvaluator) evals.next (); - ObjectPrototype op = reval.getPrototype (getName()); - // use hopobject (node) as prototype even if prototype is null - - // this is the case if no hopobject directory exists - ObjectPrototype opp = parent == null ? - reval.esNodePrototype : reval.getPrototype (parent.getName ()); - // don't think this is possible, but check anyway - if (opp == null) - opp = reval.esNodePrototype; - op.setPrototype (opp); - } catch (Exception ignore) { - } - } */ - } } public Prototype getParentPrototype () { @@ -125,10 +103,23 @@ public class Prototype { } } return upd; - } + public long getLastUpdate () { + return lastUpdate; + } + public void markUpdated () { + lastUpdate = System.currentTimeMillis (); + } + + public long getLastCheck () { + return lastCheck; + } + + public void markChecked () { + lastCheck = System.currentTimeMillis (); + } public String toString () { return "[Prototype "+ app.getName()+"/"+name+"]"; diff --git a/src/helma/framework/core/RequestEvaluator.java b/src/helma/framework/core/RequestEvaluator.java index 7fe31068..46cbe6b3 100644 --- a/src/helma/framework/core/RequestEvaluator.java +++ b/src/helma/framework/core/RequestEvaluator.java @@ -18,11 +18,12 @@ import java.util.*; * is killed and an error message is returned. */ -public class RequestEvaluator implements Runnable { +public final class RequestEvaluator implements Runnable { - public Application app; - protected boolean initialized; + public final Application app; + + protected final ScriptingEngine scriptingEngine; public RequestTrans req; public ResponseTrans res; @@ -44,7 +45,7 @@ public class RequestEvaluator implements Runnable { // the object path of the request we're evaluating List requestPath; - // the result of the + // the result of the operation Object result; // the exception thrown by the evaluator, if any. @@ -63,7 +64,7 @@ public class RequestEvaluator implements Runnable { */ public RequestEvaluator (Application app) { this.app = app; - initialized = false; + scriptingEngine = helma.scripting.fesi.FesiEngineFactory.getEngine (app, this); } @@ -79,9 +80,6 @@ public class RequestEvaluator implements Runnable { // long startCheck = System.currentTimeMillis (); app.typemgr.checkPrototypes (); - // evaluators are only initialized as needed, so we need to check that here - // if (!initialized) - // app.typemgr.initRequestEvaluator (this); // System.err.println ("Type check overhead: "+(System.currentTimeMillis ()-startCheck)+" millis"); // object refs to ressolve request path @@ -225,13 +223,16 @@ public class RequestEvaluator implements Runnable { try { localrtx.timer.beginEvent (txname+" execute"); + // enter execution context + scriptingEngine.enterContext (globals); + // set the req.action property, cutting off the _action suffix req.action = action.substring (0, action.length()-7); // try calling onRequest() function on object before // calling the actual action try { - app.scriptingEngine.invoke (currentElement, "onRequest", new Object[0], globals, this); + scriptingEngine.invoke (currentElement, "onRequest", new Object[0]); } catch (RedirectException redir) { throw redir; } catch (Exception ignore) { @@ -239,7 +240,7 @@ public class RequestEvaluator implements Runnable { } // do the actual action invocation - app.scriptingEngine.invoke (currentElement, action, new Object[0], globals, this); + scriptingEngine.invoke (currentElement, action, new Object[0]); localrtx.timer.endEvent (txname+" execute"); } catch (RedirectException redirect) { @@ -324,6 +325,8 @@ public class RequestEvaluator implements Runnable { globals.put ("res", res); globals.put ("app", app); + scriptingEngine.enterContext (globals); + currentElement = root; if (method.indexOf (".") > -1) { @@ -343,7 +346,7 @@ public class RequestEvaluator implements Runnable { String proto = app.getPrototypeName (currentElement); app.checkXmlRpcAccess (proto, method); - result = app.scriptingEngine.invoke (currentElement, method, args, globals, this); + result = scriptingEngine.invoke (currentElement, method, args); commitTransaction (); } catch (Exception wrong) { @@ -366,14 +369,12 @@ public class RequestEvaluator implements Runnable { // avoid going into transaction if called function doesn't exist boolean functionexists = true; - if (thisObject == null) try { - functionexists = app.scriptingEngine.hasFunction (null, method, this); - } catch (ScriptingException ignore) {} + functionexists = scriptingEngine.hasFunction (thisObject, method); - if (!functionexists) - // global function doesn't exist, nothing to do here. + if (!functionexists) { + // function doesn't exist, nothing to do here. reqtype = NONE; - else try { + } else try { localrtx.begin (funcdesc); root = app.getDataRoot (); @@ -383,7 +384,9 @@ public class RequestEvaluator implements Runnable { globals.put ("res", res); globals.put ("app", app); - app.scriptingEngine.invoke (thisObject, method, args, globals, this); + scriptingEngine.enterContext (globals); + + result = scriptingEngine.invoke (thisObject, method, args); commitTransaction (); } catch (Exception wrong) { @@ -403,6 +406,9 @@ public class RequestEvaluator implements Runnable { } + // exit execution context + scriptingEngine.exitContext (); + // make sure there is only one thread running per instance of this class // if localrtx != rtx, the current thread has been aborted and there's no need to notify if (localrtx != rtx) { @@ -454,8 +460,13 @@ public class RequestEvaluator implements Runnable { // wait for request, max 10 min wait (1000*60*10); // if no request arrived, release ressources and thread - if (reqtype == NONE && rtx == localrtx) + if (reqtype == NONE && rtx == localrtx) { + // comment this in to release not just the thread, but also the scripting engine. + // currently we don't do this because of the risk of memory leaks (objects from + // framework referencing into the scripting engine) + // scriptingEngine = null; rtx = null; + } } catch (InterruptedException ir) {} } @@ -469,13 +480,12 @@ public class RequestEvaluator implements Runnable { checkThread (); wait (app.requestTimeout); - if (reqtype != NONE) { + if (reqtype != NONE) { app.logEvent ("Stopping Thread for Request "+app.getName()+"/"+req.path); stopThread (); res.reset (); res.write ("Error in application '"+app.getName()+"':

Request timed out.
"); } - return res; } @@ -505,18 +515,20 @@ public class RequestEvaluator implements Runnable { checkThread (); wait (app.requestTimeout); - if (reqtype != NONE) { + if (reqtype != NONE) { stopThread (); } + // reset res for garbage collection (res.data may hold reference to evaluator) + res = null; if (exception != null) throw (exception); return result; } protected Object invokeDirectFunction (Object obj, String functionName, Object[] args) throws Exception { - return app.scriptingEngine.invoke (obj, functionName, args, null, this); - } + return scriptingEngine.invoke (obj, functionName, args); + } public synchronized Object invokeFunction (Object object, String functionName, Object[] args) throws Exception { @@ -532,10 +544,12 @@ public class RequestEvaluator implements Runnable { checkThread (); wait (60000l*15); // give internal call more time (15 minutes) to complete - if (reqtype != NONE) { + if (reqtype != NONE) { stopThread (); } + // reset res for garbage collection (res.data may hold reference to evaluator) + res = null; if (exception != null) throw (exception); return result; @@ -555,10 +569,12 @@ public class RequestEvaluator implements Runnable { checkThread (); wait (app.requestTimeout); - if (reqtype != NONE) { + if (reqtype != NONE) { stopThread (); } + // reset res for garbage collection (res.data may hold reference to evaluator) + res = null; if (exception != null) throw (exception); return result; @@ -603,7 +619,18 @@ public class RequestEvaluator implements Runnable { } } - + /** + * Null out some fields, mostly for the sake of garbage collection. + */ + public void recycle () { + res = null; + req = null; + session = null; + args = null; + requestPath = null; + result = null; + exception = null; + } /** * Check if an action with a given name is defined for a scripted object. If it is, @@ -613,12 +640,8 @@ public class RequestEvaluator implements Runnable { if (obj == null) return null; String act = action == null ? "main_action" : action+"_action"; - try { - if (app.scriptingEngine.hasFunction (obj, act, this)) - return act; - } catch (ScriptingException x) { - return null; - } + if (scriptingEngine.hasFunction (obj, act)) + return act; return null; } diff --git a/src/helma/framework/core/Skin.java b/src/helma/framework/core/Skin.java index c4b10e13..7ba781f9 100644 --- a/src/helma/framework/core/Skin.java +++ b/src/helma/framework/core/Skin.java @@ -18,19 +18,24 @@ import java.util.*; * from the RequestEvaluator object to resolve Macro handlers by type name. */ -public class Skin { +public final class Skin { + + private Macro[] parts; + private Application app; + private char[] source; + private int sourceLength; + private HashSet sandbox; - Macro[] parts; - Application app; - char[] source; - int sourceLength; - HashSet sandbox; /** * Create a skin without any restrictions on which macros are allowed to be called from it */ public Skin (String content, Application app) { - this (content, app, null); + this.app = app; + sandbox = null; + source = content.toCharArray (); + sourceLength = source.length; + parse (); } /** @@ -50,8 +55,8 @@ public class Skin { public Skin (char[] content, int length, Application app) { this.app = app; this.sandbox = null; - this.source = content; - this.sourceLength = length; + source = content; + sourceLength = length; parse (); } @@ -315,12 +320,12 @@ public class Skin { Object v = null; // remember length of response buffer before calling macro int oldLength = reval.res.getBufferLength (); - if (app.scriptingEngine.hasFunction (handlerObject, name+"_macro", reval)) { + if (reval.scriptingEngine.hasFunction (handlerObject, name+"_macro")) { // System.err.println ("Getting macro from function"); - v = app.scriptingEngine.invoke (handlerObject, name+"_macro", arguments, null, reval); + v = reval.scriptingEngine.invoke (handlerObject, name+"_macro", arguments); } else { // System.err.println ("Getting macro from property"); - v = app.scriptingEngine.get (handlerObject, name, reval); + v = reval.scriptingEngine.get (handlerObject, name); } // check if macro wrote out to response buffer int newLength = reval.res.getBufferLength (); diff --git a/src/helma/framework/core/TypeManager.java b/src/helma/framework/core/TypeManager.java index 2dd8c0e8..8151986a 100644 --- a/src/helma/framework/core/TypeManager.java +++ b/src/helma/framework/core/TypeManager.java @@ -16,7 +16,7 @@ import java.io.*; * applications and updates the evaluators if anything has changed. */ -public class TypeManager { +public final class TypeManager { Application app; File appDir; @@ -26,36 +26,23 @@ public class TypeManager { long idleSeconds = 120; // if idle for longer than 5 minutes, slow down boolean rewire; - // this contains only those evaluatores which have already been initialized - // and thus need to get updates - List registeredEvaluators; - - - static HashSet standardTypes; - static { - standardTypes = new HashSet (); - standardTypes.add ("user"); - standardTypes.add ("global"); - standardTypes.add ("root"); - standardTypes.add ("hopobject"); - } - + static String[] standardTypes = {"user", "global", "root", "hopobject"}; + public TypeManager (Application app) { - this.app = app; - appDir = app.appDir; - // make sure the directories for the standard prototypes exist, and lament otherwise - if (appDir.list().length == 0) { - for (Iterator it=standardTypes.iterator (); it.hasNext (); ) { - File f = new File (appDir, (String) it.next ()); - if (!f.exists() && !f.mkdir ()) - app.logEvent ("Warning: directory "+f.getAbsolutePath ()+" could not be created."); - else if (!f.isDirectory ()) - app.logEvent ("Warning: "+f.getAbsolutePath ()+" is not a directory."); - } - } - prototypes = new HashMap (); - zipfiles = new HashMap (); - registeredEvaluators = Collections.synchronizedList (new ArrayList ()); + this.app = app; + appDir = app.appDir; + // make sure the directories for the standard prototypes exist, and lament otherwise + if (appDir.list().length == 0) { + for (int i=0; i 0) { - try { - FunctionFile ff = new FunctionFile (tmpfile, tmpname, proto); - updatables.put (list[i], ff); - nfunc.put (tmpname, ff); - } catch (Throwable x) { - app.logEvent ("Error creating prototype: "+x); - } - - } else if (list[i].endsWith (app.actionExtension) && tmpfile.length () > 0) { - try { - ActionFile af = new ActionFile (tmpfile, tmpname, proto); - updatables.put (list[i], af); - nact.put (tmpname, af); - } catch (Throwable x) { - app.logEvent ("Error creating prototype: "+x); - } - } else if (list[i].endsWith (app.skinExtension)) { - try { - SkinFile sf = new SkinFile (tmpfile, tmpname, proto); - updatables.put (list[i], sf); - nskins.put (tmpname, sf); - } catch (Throwable x) { - app.logEvent ("Error creating prototype: "+x); - } - } - } - } - // Create and register type properties file File propfile = new File (dir, "type.properties"); SystemProperties props = new SystemProperties (propfile.getAbsolutePath ()); DbMapping dbmap = new DbMapping (app, name, props); updatables.put ("type.properties", dbmap); - proto.templates = ntemp; proto.functions = nfunc; proto.actions = nact; proto.skins = nskins; proto.updatables = updatables; - // init prototype on evaluators that are already initialized. - /* Iterator evals = getRegisteredRequestEvaluators (); - while (evals.hasNext ()) { - RequestEvaluator reval = (RequestEvaluator) evals.next (); - proto.initRequestEvaluator (reval); - }*/ - app.scriptingEngine.updatePrototype (proto); - + // app.scriptingEngine.updatePrototype (proto); } /** * Update a prototype based on the directory which defines it. */ - public void updatePrototype (String name, File dir, Prototype proto) { + public void updatePrototype (String name) { + // System.err.println ("UPDATE PROTO: "+app.getName()+"/"+name); + Prototype proto = getPrototype (name); + if (proto == null) + return; + if (System.currentTimeMillis() - proto.getLastCheck() < 1000) + return; + synchronized (proto) { + if (System.currentTimeMillis() - proto.getLastCheck() < 1000) + return; + + File dir = new File (appDir, name); boolean needsUpdate = false; HashSet updatables = null; @@ -290,22 +229,22 @@ public class TypeManager { if (proto.lastUpdate < dir.lastModified ()) { String[] list = dir.list(); for (int i=0; i "+esv.getClass()); if (esv instanceof ConstructedFunctionObject || esv instanceof FesiActionAdapter.ThrowException) op.deleteProperty (prop, prop.hashCode()); } catch (Exception x) {} @@ -183,51 +237,40 @@ public final class FesiEvaluator { } - /** - * Invoke a function on some object, using the given arguments and global vars. + * 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 executino context. */ - public Object invoke (Object thisObject, String functionName, Object[] args, HashMap globals) throws ScriptingException { - ESObject eso = null; - if (thisObject == null) - eso = global; - else - eso = getElementWrapper (thisObject); - - GlobalObject global = evaluator.getGlobalObject (); - - // if we are provided with global variables to set for this invocation, - // remember the global variables before invocation to be able to reset them afterwards. - Set globalVariables = null; - try { - ESValue[] esv = args == null ? new ESValue[0] : new ESValue[args.length]; - for (int i=0; i 0) { + Prototype p = app.typemgr.getPrototype (info.protoName); + if (p != null) { + app.typemgr.updatePrototype(info.protoName); + if (p.getLastUpdate () > info.lastUpdate) { + evaluatePrototype(p); + info.lastUpdate = p.getLastUpdate (); + } } - globalVariables = tmpGlobal; - - // 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); - ESValue sv = null; + } + } + // set globals on the global object + 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); + ESValue sv = 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 (v instanceof Map) { sv = new ESMapWrapper (this, (Map) v); } else if ("path".equals (k)) { @@ -255,9 +298,53 @@ public final class FesiEvaluator { sv = ESLoader.normalizeValue (v, evaluator); } global.putHiddenProperty (k, sv); + } catch (Exception x) { + app.logEvent ("Error setting global variable "+k+": "+x); } - // remember the globals set on this evaluator - // lastGlobals = globals; + } + } + // 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 () { + // 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) throws ScriptingException { + ESObject eso = null; + if (thisObject == null) + eso = global; + else + eso = getElementWrapper (thisObject); + try { + ESValue[] esv = args == null ? new ESValue[0] : new ESValue[args.length]; + for (int i=0; i info.lastUpdate) { + info.lastUpdate = p.getLastUpdate (); + evaluatePrototype(p); + } + } + } + return info == null? null : info.objectPrototype; } /** @@ -386,7 +477,7 @@ public final class FesiEvaluator { */ public void putPrototype (String protoName, ObjectPrototype op) { if (protoName != null && op != null) - prototypes.put (protoName, op); + prototypes.put (protoName, new TypeInfo (op, protoName)); } @@ -418,7 +509,7 @@ public final class FesiEvaluator { // Gotta find out the prototype name to use for this object... String prototypeName = app.getPrototypeName (e); - + ObjectPrototype op = getPrototype (prototypeName); if (op == null) @@ -430,7 +521,7 @@ public final class FesiEvaluator { /** - * Get a script wrapper for an implemntation of helma.objectmodel.INode + * Get a script wrapper for an instance of helma.objectmodel.INode */ public ESNode getNodeWrapper (INode n) { // FIXME: should this return ESNull.theNull? @@ -440,6 +531,7 @@ public final class FesiEvaluator { ESNode esn = (ESNode) wrappercache.get (n); if (esn == null || esn.getNode() != n) { String protoname = n.getPrototype (); + ObjectPrototype op = null; // set the DbMapping of the node according to its prototype. @@ -511,15 +603,11 @@ public final class FesiEvaluator { updateEvaluator (prototype, reader, es); } - public synchronized void updateEvaluator (Prototype prototype, Reader reader, EvaluationSource source) { - + private synchronized void updateEvaluator (Prototype prototype, Reader reader, EvaluationSource source) { try { - ObjectPrototype op = getPrototype (prototype.getName()); - // do the update, evaluating the file evaluator.evaluate(reader, op, source, false); - } catch (Throwable e) { app.logEvent ("Error parsing function file "+source+": "+e); } finally { @@ -532,4 +620,16 @@ public final class FesiEvaluator { } + class TypeInfo { + + ObjectPrototype objectPrototype; + long lastUpdate = 0; + String protoName; + + public TypeInfo (ObjectPrototype op, String name) { + objectPrototype = op; + protoName = name; + } + } + } diff --git a/src/helma/scripting/fesi/FesiScriptingEnvironment.java b/src/helma/scripting/fesi/FesiScriptingEnvironment.java deleted file mode 100644 index 6e840f28..00000000 --- a/src/helma/scripting/fesi/FesiScriptingEnvironment.java +++ /dev/null @@ -1,85 +0,0 @@ -// 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 final class FesiScriptingEnvironment implements ScriptingEnvironment { - - 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 (); - } - - - /** - * A prototype has been updated and must be re-evaluated. - */ - public void updatePrototype (Prototype prototype) { - for (Iterator i = evaluators.values().iterator(); i.hasNext(); ) { - FesiEvaluator fesi = (FesiEvaluator) i.next(); - fesi.evaluatePrototype (prototype); - } - } - - /** - * Invoke a function on some object, using the given arguments and global vars. - */ - public Object invoke (Object thisObject, String functionName, Object[] args, - HashMap globals, RequestEvaluator reval) - throws ScriptingException { - // check if there is already a FesiEvaluator for this RequestEvaluator. - // if not, create one. - FesiEvaluator fesi = getEvaluator (reval); - return fesi.invoke (thisObject, functionName, args, globals); - } - - /** - * Get a property on an object - */ - public Object get (Object thisObject, String key, RequestEvaluator reval) { - FesiEvaluator fesi = getEvaluator (reval); - return fesi.getProperty (thisObject, key); - } - - /** - * Return true if a function by that name is defined for that object. - */ - public boolean hasFunction (Object thisObject, String functionName, RequestEvaluator reval) - throws ScriptingException { - FesiEvaluator fesi = getEvaluator (reval); - return fesi.hasFunction (thisObject, functionName); - } - - - Collection getEvaluators () { - return evaluators.values(); - } - - private FesiEvaluator getEvaluator (RequestEvaluator reval) { - FesiEvaluator fesi = (FesiEvaluator) evaluators.get (reval); - if (fesi == null) { - fesi = new FesiEvaluator (app, reval); - evaluators.put (reval, fesi); - } - return fesi; - } -}