merged changes from refactor_scripting_05_02 branch
This commit is contained in:
parent
5a015fbbc5
commit
1bd0fe6c05
22 changed files with 1419 additions and 1438 deletions
|
@ -3,14 +3,13 @@
|
|||
|
||||
package helma.framework;
|
||||
|
||||
import FESI.Exceptions.EcmaScriptException;
|
||||
|
||||
/**
|
||||
* RedirectException is thrown internally when a response is redirected to a
|
||||
* new URL.
|
||||
*/
|
||||
|
||||
public class RedirectException extends EcmaScriptException {
|
||||
public class RedirectException extends RuntimeException {
|
||||
|
||||
String url;
|
||||
|
||||
|
|
|
@ -35,8 +35,7 @@ public class Application extends UnicastRemoteObject implements IRemoteApp, IPat
|
|||
protected NodeManager nmgr;
|
||||
|
||||
// the class name of the scripting environment implementation
|
||||
static final String scriptEnvironmentName = "helma.scripting.fesi.Environment";
|
||||
ScriptingEnvironment scriptEnv;
|
||||
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.
|
||||
|
@ -49,6 +48,11 @@ public class Application extends UnicastRemoteObject implements IRemoteApp, IPat
|
|||
*/
|
||||
public TypeManager typemgr;
|
||||
|
||||
/**
|
||||
* The skin manager for this application
|
||||
*/
|
||||
protected SkinManager skinmgr;
|
||||
|
||||
/**
|
||||
* Each application has one internal request evaluator for calling
|
||||
* the scheduler and other internal functions.
|
||||
|
@ -227,7 +231,9 @@ public class Application extends UnicastRemoteObject implements IRemoteApp, IPat
|
|||
/**
|
||||
* Get the application ready to run, initializing the evaluators and type manager.
|
||||
*/
|
||||
public void init () throws DbException {
|
||||
public void init () throws DbException, ScriptingException {
|
||||
scriptingEngine = new helma.scripting.fesi.FesiScriptingEnvironment ();
|
||||
scriptingEngine.init (this, props);
|
||||
|
||||
eval = new RequestEvaluator (this);
|
||||
logEvent ("Starting evaluators for "+name);
|
||||
|
@ -249,6 +255,8 @@ public class Application extends UnicastRemoteObject implements IRemoteApp, IPat
|
|||
typemgr.createPrototypes ();
|
||||
// logEvent ("Started type manager for "+name);
|
||||
|
||||
skinmgr = new SkinManager (this);
|
||||
|
||||
rootMapping = getDbMapping ("root");
|
||||
userMapping = getDbMapping ("user");
|
||||
SystemProperties p = new SystemProperties ();
|
||||
|
@ -366,7 +374,7 @@ public class Application extends UnicastRemoteObject implements IRemoteApp, IPat
|
|||
try {
|
||||
RequestEvaluator re = (RequestEvaluator) freeThreads.pop ();
|
||||
allThreads.removeElement (re);
|
||||
typemgr.unregisterRequestEvaluator (re);
|
||||
// typemgr.unregisterRequestEvaluator (re);
|
||||
re.stopThread ();
|
||||
} catch (EmptyStackException empty) {
|
||||
return false;
|
||||
|
@ -520,6 +528,13 @@ public class Application extends UnicastRemoteObject implements IRemoteApp, IPat
|
|||
return nmgr.safe;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a transient node that is shared by all evaluators of this application ("app node")
|
||||
*/
|
||||
public INode getAppNode () {
|
||||
return appnode;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns a Node representing a registered user of this application by his or her user name.
|
||||
|
@ -555,6 +570,13 @@ public class Application extends UnicastRemoteObject implements IRemoteApp, IPat
|
|||
return typemgr.prototypes.values ();
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrurn a skin for a given object. The skin is found by determining the prototype
|
||||
* to use for the object, then looking up the skin for the prototype.
|
||||
*/
|
||||
public Skin getSkin (Object object, String skinname, Object[] skinpath) {
|
||||
return skinmgr.getSkin (object, skinname, skinpath); // not yet implemented
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the user currently associated with a given Hop session ID. This may be
|
||||
|
@ -815,6 +837,8 @@ public class Application extends UnicastRemoteObject implements IRemoteApp, IPat
|
|||
* within the Helma scripting and rendering framework.
|
||||
*/
|
||||
public String getPrototypeName (Object obj) {
|
||||
if (obj == null)
|
||||
return "global";
|
||||
// check if e implements the IPathElement interface
|
||||
if (obj instanceof IPathElement)
|
||||
// e implements the getPrototype() method
|
||||
|
@ -902,6 +926,14 @@ public class Application extends UnicastRemoteObject implements IRemoteApp, IPat
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get scripting environment for this application
|
||||
*/
|
||||
public ScriptingEnvironment getScriptingEnvironment () {
|
||||
return scriptingEngine;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The run method performs periodic tasks like executing the scheduler method and
|
||||
* kicking out expired user sessions.
|
||||
|
@ -917,7 +949,9 @@ public class Application extends UnicastRemoteObject implements IRemoteApp, IPat
|
|||
|
||||
try {
|
||||
eval.invokeFunction ((INode) null, "onStart", new Object[0]);
|
||||
} catch (Exception ignore) {}
|
||||
} catch (Exception ignore) {
|
||||
System.err.println ("Error in "+name+"/onStart(): "+ignore);
|
||||
}
|
||||
|
||||
while (Thread.currentThread () == worker) {
|
||||
// get session timeout
|
||||
|
@ -1022,7 +1056,7 @@ public class Application extends UnicastRemoteObject implements IRemoteApp, IPat
|
|||
* Check whether a prototype is for scripting a java class, i.e. if there's an entry
|
||||
* for it in the class.properties file.
|
||||
*/
|
||||
protected boolean isJavaPrototype (String typename) {
|
||||
public boolean isJavaPrototype (String typename) {
|
||||
for (Enumeration en = classMapping.elements(); en.hasMoreElements(); ) {
|
||||
String value = (String) en.nextElement ();
|
||||
if (typename.equals (value))
|
||||
|
@ -1129,7 +1163,9 @@ public class Application extends UnicastRemoteObject implements IRemoteApp, IPat
|
|||
*
|
||||
*/
|
||||
public int countMaxActiveEvaluators () {
|
||||
return typemgr.countRegisteredRequestEvaluators () -1;
|
||||
// return typemgr.countRegisteredRequestEvaluators () -1;
|
||||
// not available due to framework refactoring
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1194,7 +1230,7 @@ class XmlRpcInvoker implements XmlRpcHandler {
|
|||
RequestEvaluator ev = null;
|
||||
try {
|
||||
ev = app.getEvaluator ();
|
||||
retval = ev.invokeXmlRpc (method, argvec);
|
||||
retval = ev.invokeXmlRpc (method, argvec.toArray());
|
||||
} finally {
|
||||
app.releaseEvaluator (ev);
|
||||
}
|
||||
|
|
|
@ -8,11 +8,8 @@ import java.util.Iterator;
|
|||
import java.io.*;
|
||||
import helma.framework.*;
|
||||
import helma.scripting.*;
|
||||
import helma.scripting.fesi.*;
|
||||
import helma.objectmodel.*;
|
||||
import helma.util.Updatable;
|
||||
import FESI.Data.*;
|
||||
import FESI.Exceptions.EcmaScriptException;
|
||||
|
||||
|
||||
/**
|
||||
|
@ -66,7 +63,7 @@ public class Prototype {
|
|||
|
||||
// if parent has changed, update ES-prototypes in request evaluators
|
||||
if (parent != old) {
|
||||
Iterator evals = app.typemgr.getRegisteredRequestEvaluators ();
|
||||
/* Iterator evals = app.typemgr.getRegisteredRequestEvaluators ();
|
||||
while (evals.hasNext ()) {
|
||||
try {
|
||||
RequestEvaluator reval = (RequestEvaluator) evals.next ();
|
||||
|
@ -81,7 +78,7 @@ public class Prototype {
|
|||
op.setPrototype (opp);
|
||||
} catch (Exception ignore) {
|
||||
}
|
||||
}
|
||||
} */
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -97,8 +94,8 @@ public class Prototype {
|
|||
return (FunctionFile) functions.get (ffname);
|
||||
}
|
||||
|
||||
public Action getAction (String afname) {
|
||||
return (Action) actions.get (afname);
|
||||
public ActionFile getActionFile (String afname) {
|
||||
return (ActionFile) actions.get (afname);
|
||||
}
|
||||
|
||||
public SkinFile getSkinFile (String sfname) {
|
||||
|
@ -131,71 +128,6 @@ public class Prototype {
|
|||
|
||||
}
|
||||
|
||||
public void initRequestEvaluator (RequestEvaluator reval) {
|
||||
// see if we already registered with this evaluator
|
||||
if (reval.getPrototype (name) != null)
|
||||
return;
|
||||
|
||||
ObjectPrototype op = null;
|
||||
|
||||
// get the prototype's prototype if possible and necessary
|
||||
ObjectPrototype opp = null;
|
||||
if (parent != null) {
|
||||
// see if parent prototype is already registered. if not, register it
|
||||
opp = reval.getPrototype (parent.getName ());
|
||||
if (opp == null) {
|
||||
parent.initRequestEvaluator (reval);
|
||||
opp = reval.getPrototype (parent.getName ());
|
||||
}
|
||||
}
|
||||
if (!"global".equalsIgnoreCase (name) && !"hopobject".equalsIgnoreCase (name) && opp == null) {
|
||||
if (isJavaPrototype)
|
||||
opp = reval.esObjectPrototype;
|
||||
else
|
||||
opp = reval.esNodePrototype;
|
||||
}
|
||||
|
||||
if ("user".equalsIgnoreCase (name)) {
|
||||
op = reval.esUserPrototype;
|
||||
op.setPrototype (opp);
|
||||
} else if ("global".equalsIgnoreCase (name))
|
||||
op = reval.global;
|
||||
else if ("hopobject".equalsIgnoreCase (name))
|
||||
op = reval.esNodePrototype;
|
||||
else {
|
||||
op = new ObjectPrototype (opp, reval.evaluator);
|
||||
try {
|
||||
op.putProperty ("prototypename", new ESString (name), "prototypename".hashCode ());
|
||||
} catch (EcmaScriptException ignore) {}
|
||||
}
|
||||
reval.putPrototype (name, op);
|
||||
|
||||
// Register a constructor for all types except global.
|
||||
// This will first create a node and then call the actual (scripted) constructor on it.
|
||||
if (!"global".equalsIgnoreCase (name)) {
|
||||
try {
|
||||
FunctionPrototype fp = (FunctionPrototype) reval.evaluator.getFunctionPrototype();
|
||||
reval.global.putHiddenProperty (name, new NodeConstructor (name, fp, reval));
|
||||
} catch (EcmaScriptException ignore) {}
|
||||
}
|
||||
for (Iterator it = functions.values().iterator(); it.hasNext(); ) {
|
||||
FunctionFile ff = (FunctionFile) it.next ();
|
||||
ff.updateRequestEvaluator (reval);
|
||||
}
|
||||
for (Iterator it = templates.values().iterator(); it.hasNext(); ) {
|
||||
Template tmp = (Template) it.next ();
|
||||
try {
|
||||
tmp.updateRequestEvaluator (reval);
|
||||
} catch (EcmaScriptException ignore) {}
|
||||
}
|
||||
for (Iterator it = actions.values().iterator(); it.hasNext(); ) {
|
||||
Action act = (Action) it.next ();
|
||||
try {
|
||||
act.updateRequestEvaluator (reval);
|
||||
} catch (EcmaScriptException ignore) {}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
public String toString () {
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -278,9 +278,9 @@ public class Skin {
|
|||
if (handlerObject == null) {
|
||||
// eiter because thisObject == null or the right object wasn't found in the object's parent path
|
||||
// go check request path for an object with matching prototype
|
||||
int l = reval.reqPath.size();
|
||||
int l = reval.requestPath.size();
|
||||
for (int i=l-1; i>=0; i--) {
|
||||
Object pathelem = reval.reqPath.getProperty (i).toJavaObject ();
|
||||
Object pathelem = reval.requestPath.get (i);
|
||||
if (handler.equalsIgnoreCase (app.getPrototypeName (pathelem))) {
|
||||
handlerObject = pathelem;
|
||||
break;
|
||||
|
@ -302,12 +302,12 @@ public class Skin {
|
|||
// if so, the macro evaluates to the function. Otherwise,
|
||||
// a property/field with the name is used, if defined.
|
||||
Object v = null;
|
||||
if (reval.hasFunction (handlerObject, name+"_macro")) {
|
||||
if (app.scriptingEngine.hasFunction (handlerObject, name+"_macro", reval)) {
|
||||
// System.err.println ("Getting macro from function");
|
||||
v = reval.invokeDirectFunction (handlerObject, name+"_macro", arguments);
|
||||
v = app.scriptingEngine.invoke (handlerObject, name+"_macro", arguments, null, reval);
|
||||
} else {
|
||||
// System.err.println ("Getting macro from property");
|
||||
v = reval.getProperty (handlerObject, name);
|
||||
v = app.scriptingEngine.get (handlerObject, name, reval);
|
||||
}
|
||||
if (v != null)
|
||||
writeToResponse (v.toString (), reval.res);
|
||||
|
|
134
src/helma/framework/core/SkinManager.java
Normal file
134
src/helma/framework/core/SkinManager.java
Normal file
|
@ -0,0 +1,134 @@
|
|||
// SkinManager.java
|
||||
// Copyright (c) Hannes Wallnöfer 2002
|
||||
|
||||
package helma.framework.core;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import helma.objectmodel.INode;
|
||||
import java.io.*;
|
||||
|
||||
|
||||
/**
|
||||
* Manages skins for a Helma application
|
||||
*/
|
||||
|
||||
|
||||
public class SkinManager {
|
||||
|
||||
Application app;
|
||||
|
||||
|
||||
public SkinManager (Application app) {
|
||||
this.app = app;
|
||||
}
|
||||
|
||||
public Skin getSkin (Object object, String skinname, Object[] skinpath) {
|
||||
Prototype proto = app.getPrototype (object);
|
||||
return getSkin (proto, skinname, "skin", skinpath);
|
||||
}
|
||||
|
||||
|
||||
public Skin getSkin (Prototype proto, String skinname, String extension, Object[] skinpath) {
|
||||
if (proto == null)
|
||||
return null;
|
||||
Skin skin = null;
|
||||
// First check if the skin has been already used within the execution of this request
|
||||
/* SkinKey key = new SkinKey (proto.getName(), skinname, extension);
|
||||
Skin skin = (Skin) skincache.get (key);
|
||||
if (skin != null) {
|
||||
return skin;
|
||||
} */
|
||||
// check for skinsets set via res.skinpath property
|
||||
do {
|
||||
if (skinpath != null) {
|
||||
for (int i=0; i<skinpath.length; i++) {
|
||||
skin = getSkinInternal (skinpath[i], proto.getName (), skinname, extension);
|
||||
if (skin != null) {
|
||||
// skincache.put (key, skin);
|
||||
return skin;
|
||||
}
|
||||
}
|
||||
}
|
||||
// skin for this prototype wasn't found in the skinsets.
|
||||
// the next step is to look if it is defined as skin file in the application directory
|
||||
skin = proto.getSkin (skinname);
|
||||
if (skin != null) {
|
||||
// skincache.put (key, skin);
|
||||
return skin;
|
||||
}
|
||||
// still not found. See if there is a parent prototype which might define the skin.
|
||||
proto = proto.getParentPrototype ();
|
||||
} while (proto != null);
|
||||
// looked every where, nothing to be found
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
protected Skin getSkinInternal (Object skinset, String prototype, String skinname, String extension) {
|
||||
if (prototype == null || skinset == null)
|
||||
return null;
|
||||
// check if the skinset object is a HopObject (db based skin)
|
||||
// or a String (file based skin)
|
||||
if (skinset instanceof INode) {
|
||||
INode n = ((INode) skinset).getNode (prototype, false);
|
||||
if (n != null) {
|
||||
n = n.getNode (skinname, false);
|
||||
if (n != null) {
|
||||
String skin = n.getString (extension, false);
|
||||
if (skin != null) {
|
||||
Skin s = (Skin) app.skincache.get (skin);
|
||||
if (s == null) {
|
||||
s = new Skin (skin, app);
|
||||
app.skincache.put (skin, s);
|
||||
}
|
||||
return s;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Skinset is interpreted as directory name from which to
|
||||
// retrieve the skin
|
||||
File f = new File (skinset.toString (), prototype);
|
||||
f = new File (f, skinname+"."+extension);
|
||||
if (f.exists() && f.canRead()) {
|
||||
SkinFile sf = new SkinFile (f, skinname, app);
|
||||
Skin s = sf.getSkin ();
|
||||
return s;
|
||||
}
|
||||
}
|
||||
// Inheritance is taken care of in the above getSkin method.
|
||||
// the sequence is prototype.skin-from-db, prototype.skin-from-file, parent.from-db, parent.from-file etc.
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Utility class to use for caching skins in a Hashtable.
|
||||
* The key consists out of two strings: prototype name and skin name.
|
||||
*/
|
||||
final class SkinKey {
|
||||
|
||||
final String first, second, third;
|
||||
|
||||
public SkinKey (String first, String second, String third) {
|
||||
this.first = first;
|
||||
this.second = second;
|
||||
this.third = third;
|
||||
}
|
||||
|
||||
public boolean equals (Object other) {
|
||||
try {
|
||||
SkinKey key = (SkinKey) other;
|
||||
return first.equals (key.first) && second.equals (key.second) && third.equals (key.third);
|
||||
} catch (Exception x) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public int hashCode () {
|
||||
return first.hashCode () + second.hashCode () + third.hashCode ();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -225,7 +225,7 @@ public class TypeManager {
|
|||
|
||||
} else if (list[i].endsWith (app.actionExtension) && tmpfile.length () > 0) {
|
||||
try {
|
||||
Action af = new Action (tmpfile, tmpname, proto);
|
||||
ActionFile af = new ActionFile (tmpfile, tmpname, proto);
|
||||
updatables.put (list[i], af);
|
||||
nact.put (tmpname, af);
|
||||
} catch (Throwable x) {
|
||||
|
@ -257,11 +257,12 @@ public class TypeManager {
|
|||
proto.updatables = updatables;
|
||||
|
||||
// init prototype on evaluators that are already initialized.
|
||||
Iterator evals = getRegisteredRequestEvaluators ();
|
||||
/* Iterator evals = getRegisteredRequestEvaluators ();
|
||||
while (evals.hasNext ()) {
|
||||
RequestEvaluator reval = (RequestEvaluator) evals.next ();
|
||||
proto.initRequestEvaluator (reval);
|
||||
}
|
||||
}*/
|
||||
app.scriptingEngine.updatePrototype (proto);
|
||||
|
||||
}
|
||||
|
||||
|
@ -347,7 +348,7 @@ public class TypeManager {
|
|||
|
||||
} else if (list[i].endsWith (app.actionExtension)) {
|
||||
try {
|
||||
Action af = new Action (tmpfile, tmpname, proto);
|
||||
ActionFile af = new ActionFile (tmpfile, tmpname, proto);
|
||||
proto.updatables.put (list[i], af);
|
||||
proto.actions.put (tmpname, af);
|
||||
} catch (Throwable x) {
|
||||
|
@ -362,8 +363,7 @@ public class TypeManager {
|
|||
}
|
||||
|
||||
// next go through existing updatables
|
||||
if (updatables == null)
|
||||
return;
|
||||
if (updatables != null) {
|
||||
for (Iterator i = updatables.iterator(); i.hasNext(); ) {
|
||||
Updatable upd = (Updatable) i.next();
|
||||
|
||||
|
@ -381,10 +381,11 @@ public class TypeManager {
|
|||
}
|
||||
}
|
||||
}
|
||||
app.scriptingEngine.updatePrototype (proto);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public void initRequestEvaluator (RequestEvaluator reval) {
|
||||
/*public void initRequestEvaluator (RequestEvaluator reval) {
|
||||
if (!registeredEvaluators.contains (reval))
|
||||
registeredEvaluators.add (reval);
|
||||
for (Iterator it = prototypes.values().iterator(); it.hasNext(); ) {
|
||||
|
@ -404,7 +405,7 @@ public class TypeManager {
|
|||
|
||||
public int countRegisteredRequestEvaluators () {
|
||||
return registeredEvaluators.size ();
|
||||
}
|
||||
} */
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -72,16 +72,14 @@ public class ZippedAppFile implements Updatable {
|
|||
String name = fname.substring (0, fname.lastIndexOf ("."));
|
||||
String content = getZipEntryContent (zip, entry);
|
||||
// System.err.println ("["+content+"]");
|
||||
Action act = new Action (null, name, proto);
|
||||
act.update (content);
|
||||
ActionFile act = new ActionFile (content, name, proto);
|
||||
proto.actions.put (name, act);
|
||||
}
|
||||
else if (fname.endsWith (".hsp")) {
|
||||
String name = fname.substring (0, fname.lastIndexOf ("."));
|
||||
String content = getZipEntryContent (zip, entry);
|
||||
// System.err.println ("["+content+"]");
|
||||
Template tmp = new Template (null, name, proto);
|
||||
tmp.update (content);
|
||||
Template tmp = new Template (content, name, proto);
|
||||
proto.templates.put (name, tmp);
|
||||
}
|
||||
else if (fname.endsWith (".skin")) {
|
||||
|
|
128
src/helma/scripting/ActionFile.java
Normal file
128
src/helma/scripting/ActionFile.java
Normal file
|
@ -0,0 +1,128 @@
|
|||
// ActionFile.java
|
||||
// Copyright (c) Helma.org 1998-2002
|
||||
|
||||
package 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 ActionFile is a file containing function code that is exposed as a URI
|
||||
* of objects of this class/type. It is
|
||||
* usually represented by a file with extension .hac (hop action file)
|
||||
* that contains the raw body of the function.
|
||||
*/
|
||||
|
||||
|
||||
public class ActionFile implements Updatable {
|
||||
|
||||
String name;
|
||||
String functionName;
|
||||
Prototype prototype;
|
||||
Application app;
|
||||
File file;
|
||||
String content;
|
||||
long lastmod;
|
||||
|
||||
|
||||
public ActionFile (File file, String name, Prototype proto) {
|
||||
this.prototype = proto;
|
||||
this.app = proto.getApplication ();
|
||||
this.name = name;
|
||||
functionName = getName()+"_action";
|
||||
this.file = file;
|
||||
this.content = null;
|
||||
if (file != null)
|
||||
update ();
|
||||
}
|
||||
|
||||
public ActionFile (String content, String name, Prototype proto) {
|
||||
this.prototype = proto;
|
||||
this.app = proto.getApplication ();
|
||||
this.name = name;
|
||||
functionName = getName()+"_action";
|
||||
this.file = null;
|
||||
this.content = content;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Abstract method that must be implemented by subclasses to update evaluators with
|
||||
* new content of action file.
|
||||
*/
|
||||
// protected abstract void update (String content) throws Exception;
|
||||
|
||||
/**
|
||||
* Abstract method that must be implemented by subclasses to remove
|
||||
* action from evaluators.
|
||||
*/
|
||||
// protected abstract void remove ();
|
||||
|
||||
|
||||
/**
|
||||
* Tell the type manager whether we need an update. this is the case when
|
||||
* the file has been modified or deleted.
|
||||
*/
|
||||
public boolean needsUpdate () {
|
||||
return lastmod != file.lastModified ();
|
||||
}
|
||||
|
||||
|
||||
public void update () {
|
||||
|
||||
if (!file.exists ()) {
|
||||
// remove functions declared by this from all object prototypes
|
||||
remove ();
|
||||
} else {
|
||||
try {
|
||||
FileReader reader = new FileReader (file);
|
||||
char cbuf[] = new char[(int) file.length ()];
|
||||
reader.read (cbuf);
|
||||
reader.close ();
|
||||
content = new String (cbuf);
|
||||
// update (content);
|
||||
} catch (Exception filex) {
|
||||
app.logEvent ("*** Error reading action file "+file+": "+filex);
|
||||
}
|
||||
lastmod = file.lastModified ();
|
||||
}
|
||||
}
|
||||
|
||||
protected void remove () {
|
||||
prototype.actions.remove (name);
|
||||
if (file != null)
|
||||
prototype.updatables.remove (file.getName());
|
||||
}
|
||||
|
||||
public String getName () {
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getContent () {
|
||||
return content;
|
||||
}
|
||||
|
||||
public String getFunctionName () {
|
||||
return functionName;
|
||||
}
|
||||
|
||||
public Prototype getPrototype () {
|
||||
return prototype;
|
||||
}
|
||||
|
||||
public Application getApplication () {
|
||||
return app;
|
||||
}
|
||||
|
||||
public String toString () {
|
||||
return "ActionFile["+prototype.getName()+"/"+functionName+"]";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -11,13 +11,10 @@ import java.io.*;
|
|||
import helma.framework.*;
|
||||
import helma.framework.core.*;
|
||||
import helma.util.Updatable;
|
||||
import FESI.Data.*;
|
||||
import FESI.Exceptions.EcmaScriptException;
|
||||
import FESI.Interpreter.*;
|
||||
|
||||
|
||||
/**
|
||||
* This represents a File containing JavaScript functions for a given Object.
|
||||
* This represents a File containing script functions for a given class/prototype.
|
||||
*/
|
||||
|
||||
|
||||
|
@ -54,20 +51,7 @@ public class FunctionFile implements Updatable {
|
|||
this.name = name;
|
||||
this.file = null;
|
||||
this.content = body;
|
||||
|
||||
Iterator evals = app.typemgr.getRegisteredRequestEvaluators ();
|
||||
while (evals.hasNext ()) {
|
||||
try {
|
||||
|
||||
StringEvaluationSource es = new StringEvaluationSource (body, null);
|
||||
StringReader reader = new StringReader (body);
|
||||
|
||||
RequestEvaluator reval = (RequestEvaluator) evals.next ();
|
||||
updateRequestEvaluator (reval, reader, es);
|
||||
|
||||
} catch (Exception ignore) {}
|
||||
}
|
||||
|
||||
update ();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -75,108 +59,41 @@ public class FunctionFile implements Updatable {
|
|||
* the file has been modified or deleted.
|
||||
*/
|
||||
public boolean needsUpdate () {
|
||||
return lastmod != file.lastModified ();
|
||||
return file != null && lastmod != file.lastModified ();
|
||||
}
|
||||
|
||||
|
||||
public void update () {
|
||||
|
||||
if (file != null) {
|
||||
if (!file.exists ()) {
|
||||
remove ();
|
||||
|
||||
} else {
|
||||
|
||||
lastmod = file.lastModified ();
|
||||
// app.typemgr.readFunctionFile (file, prototype.getName ());
|
||||
|
||||
Iterator evals = app.typemgr.getRegisteredRequestEvaluators ();
|
||||
while (evals.hasNext ()) {
|
||||
try {
|
||||
|
||||
RequestEvaluator reval = (RequestEvaluator) evals.next ();
|
||||
FileReader fr = new FileReader(file);
|
||||
EvaluationSource es = new FileEvaluationSource(file.getPath(), null);
|
||||
updateRequestEvaluator (reval, fr, es);
|
||||
|
||||
} catch (Throwable ignore) {}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
public synchronized void updateRequestEvaluator (RequestEvaluator reval) {
|
||||
if (file != null) {
|
||||
try {
|
||||
FileReader fr = new FileReader (file);
|
||||
EvaluationSource es = new FileEvaluationSource (file.getPath (), null);
|
||||
updateRequestEvaluator (reval, fr, es);
|
||||
} catch (IOException iox) {
|
||||
app.logEvent ("Error updating function file: "+iox);
|
||||
// app.getScriptingEnvironment().evaluateFile (prototype, file);
|
||||
}
|
||||
} else {
|
||||
StringReader reader = new StringReader (content);
|
||||
StringEvaluationSource es = new StringEvaluationSource (content, null);
|
||||
updateRequestEvaluator (reval, reader, es);
|
||||
// app.getScriptingEnvironment().evaluateString (prototype, content);
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void updateRequestEvaluator (RequestEvaluator reval, Reader reader, EvaluationSource source) {
|
||||
|
||||
HashMap priorProps = null;
|
||||
HashSet newProps = null;
|
||||
|
||||
try {
|
||||
|
||||
ObjectPrototype op = reval.getPrototype (prototype.getName());
|
||||
|
||||
// extract all properties from prototype _before_ evaluation, so we can compare afterwards
|
||||
// but only do this is declaredProps is not up to date yet
|
||||
if (declaredPropsTimestamp != lastmod) {
|
||||
priorProps = new HashMap ();
|
||||
// remember properties before evaluation, so we can tell what's new afterwards
|
||||
try {
|
||||
for (Enumeration en=op.getAllProperties(); en.hasMoreElements(); ) {
|
||||
String prop = (String) en.nextElement ();
|
||||
priorProps.put (prop, op.getProperty (prop, prop.hashCode()));
|
||||
}
|
||||
} catch (Exception ignore) {}
|
||||
/* public void evaluate (ScriptingEnvironment env) {
|
||||
if (file != null)
|
||||
env.evaluateFile (prototype, file);
|
||||
else
|
||||
env.evaluateString (prototype, content);
|
||||
}*/
|
||||
public boolean hasFile () {
|
||||
return file != null;
|
||||
}
|
||||
|
||||
// do the update, evaluating the file
|
||||
reval.evaluator.evaluate(reader, op, source, false);
|
||||
|
||||
// check what's new
|
||||
if (declaredPropsTimestamp != lastmod) try {
|
||||
newProps = new HashSet ();
|
||||
for (Enumeration en=op.getAllProperties(); en.hasMoreElements(); ) {
|
||||
String prop = (String) en.nextElement ();
|
||||
if (priorProps.get (prop) == null || op.getProperty (prop, prop.hashCode()) != priorProps.get (prop))
|
||||
newProps.add (prop);
|
||||
}
|
||||
} catch (Exception ignore) {}
|
||||
|
||||
} catch (Throwable e) {
|
||||
app.logEvent ("Error parsing function file "+source+": "+e);
|
||||
} finally {
|
||||
if (reader != null) {
|
||||
try {
|
||||
reader.close();
|
||||
} catch (IOException ignore) {}
|
||||
public File getFile () {
|
||||
return file;
|
||||
}
|
||||
|
||||
// now remove the props that were not refreshed, and set declared props to new collection
|
||||
if (declaredPropsTimestamp != lastmod) {
|
||||
declaredPropsTimestamp = lastmod;
|
||||
if (declaredProps != null) {
|
||||
declaredProps.removeAll (newProps);
|
||||
removeProperties (declaredProps);
|
||||
}
|
||||
declaredProps = newProps;
|
||||
// System.err.println ("DECLAREDPROPS = "+declaredProps);
|
||||
}
|
||||
|
||||
}
|
||||
public String getContent () {
|
||||
return content;
|
||||
}
|
||||
|
||||
|
||||
|
@ -185,10 +102,10 @@ public class FunctionFile implements Updatable {
|
|||
prototype.updatables.remove (file.getName());
|
||||
|
||||
// if we did not add anything to any evaluator, we're done
|
||||
if (declaredProps == null || declaredProps.size() == 0)
|
||||
/* if (declaredProps == null || declaredProps.size() == 0)
|
||||
return;
|
||||
|
||||
removeProperties (declaredProps);
|
||||
removeProperties (declaredProps); */
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -199,7 +116,7 @@ public class FunctionFile implements Updatable {
|
|||
void removeProperties (HashSet props) {
|
||||
// first loop through other function files in this prototype to make a set of properties
|
||||
// owned by other files.
|
||||
HashSet otherFiles = new HashSet ();
|
||||
/* HashSet otherFiles = new HashSet ();
|
||||
for (Iterator it=prototype.functions.values ().iterator (); it.hasNext (); ) {
|
||||
FunctionFile other = (FunctionFile) it.next ();
|
||||
if (other != this && other.declaredProps != null)
|
||||
|
@ -220,7 +137,7 @@ public class FunctionFile implements Updatable {
|
|||
// System.err.println ("REMOVING PROP: "+fname);
|
||||
}
|
||||
} catch (Exception ignore) {}
|
||||
}
|
||||
} */
|
||||
}
|
||||
|
||||
public String toString () {
|
||||
|
@ -234,40 +151,3 @@ public class FunctionFile implements Updatable {
|
|||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -3,9 +3,11 @@
|
|||
|
||||
package helma.scripting;
|
||||
|
||||
|
||||
import helma.framework.core.Application;
|
||||
import helma.framework.core.Prototype;
|
||||
import helma.framework.core.RequestEvaluator;
|
||||
import java.util.*;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
/**
|
||||
* This is the interface that must be implemented to make a scripting environment
|
||||
|
@ -16,14 +18,30 @@ 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;
|
||||
|
||||
/**
|
||||
* A prototype has been updated and must be re-evaluated.
|
||||
*/
|
||||
public void updatePrototype (Prototype prototype);
|
||||
|
||||
/**
|
||||
* 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, RequestEvaluator reval)
|
||||
throws ScriptingException;
|
||||
|
||||
/**
|
||||
* Get a property on an object
|
||||
*/
|
||||
public Object get (Object thisObject, String key, RequestEvaluator reval);
|
||||
|
||||
/**
|
||||
* Return true if a function by that name is defined for that object.
|
||||
*/
|
||||
public boolean hasFunction (Object thisObject, String functionName, RequestEvaluator reval)
|
||||
throws ScriptingException;
|
||||
|
||||
}
|
||||
|
||||
|
@ -51,9 +69,6 @@ public interface ScriptingEnvironment {
|
|||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -9,8 +9,8 @@ import java.util.Iterator;
|
|||
import java.util.StringTokenizer;
|
||||
import helma.framework.*;
|
||||
import helma.framework.core.*;
|
||||
import FESI.Data.*;
|
||||
import FESI.Exceptions.*;
|
||||
// import FESI.Data.*;
|
||||
// import FESI.Exceptions.*;
|
||||
|
||||
|
||||
/**
|
||||
|
@ -24,18 +24,24 @@ import FESI.Exceptions.*;
|
|||
* template files to do the formatting.
|
||||
*/
|
||||
|
||||
public class Template extends Action {
|
||||
public class Template extends ActionFile {
|
||||
|
||||
// this is the *_as_string function, which is in addition to the normal one
|
||||
TypeUpdater psfunc;
|
||||
// TypeUpdater psfunc;
|
||||
|
||||
|
||||
public Template (File file, String name, Prototype proto) {
|
||||
super (file, name, proto);
|
||||
functionName = name;
|
||||
}
|
||||
|
||||
public Template (String content, String name, Prototype proto) {
|
||||
super (content, name, proto);
|
||||
functionName = name;
|
||||
}
|
||||
|
||||
|
||||
public void update (String content) throws Exception {
|
||||
public String getContent () {
|
||||
// IServer.getLogger().log ("Reading text template " + name);
|
||||
|
||||
Vector partBuffer = new Vector ();
|
||||
|
@ -99,7 +105,7 @@ public class Template extends Action {
|
|||
// append a CRLF
|
||||
newLineCount++;
|
||||
templateBody.append ("\\r\\n");
|
||||
} else if (!"\r".equals (nextLine)){
|
||||
} else if (!"\r".equals (nextLine)) try {
|
||||
StringReader lineReader = new StringReader (nextLine);
|
||||
int c = lineReader.read ();
|
||||
while (c > -1) {
|
||||
|
@ -109,7 +115,7 @@ public class Template extends Action {
|
|||
templateBody.append ((char) c);
|
||||
c = lineReader.read ();
|
||||
}
|
||||
}
|
||||
} catch (IOException srx) {}
|
||||
|
||||
nextLine = st.hasMoreTokens () ? st.nextToken () : null;
|
||||
|
||||
|
@ -137,7 +143,9 @@ public class Template extends Action {
|
|||
}
|
||||
// templateBody.append ("\r\nreturn null;\r\n");
|
||||
|
||||
functionName = name;
|
||||
return templateBody.toString ();
|
||||
|
||||
/*
|
||||
String fname = name+"_as_string";
|
||||
String body = templateBody.toString ();
|
||||
|
||||
|
@ -164,14 +172,15 @@ public class Template extends Action {
|
|||
RequestEvaluator reval = (RequestEvaluator) evals.next ();
|
||||
updateRequestEvaluator (reval);
|
||||
} catch (Exception ignore) {}
|
||||
}
|
||||
} */
|
||||
}
|
||||
|
||||
void remove () {
|
||||
protected void remove () {
|
||||
prototype.templates.remove (name);
|
||||
if (file != null)
|
||||
prototype.updatables.remove (file.getName());
|
||||
|
||||
Iterator evals = app.typemgr.getRegisteredRequestEvaluators ();
|
||||
/* Iterator evals = app.typemgr.getRegisteredRequestEvaluators ();
|
||||
while (evals.hasNext ()) {
|
||||
try {
|
||||
RequestEvaluator reval = (RequestEvaluator) evals.next ();
|
||||
|
@ -187,16 +196,16 @@ public class Template extends Action {
|
|||
op.deleteProperty (fname, fname.hashCode());
|
||||
}
|
||||
} catch (Exception ignore) {}
|
||||
}
|
||||
} */
|
||||
}
|
||||
|
||||
|
||||
public synchronized void updateRequestEvaluator (RequestEvaluator reval) throws EcmaScriptException {
|
||||
/* public synchronized void updateRequestEvaluator (RequestEvaluator reval) throws EcmaScriptException {
|
||||
if (pfunc != null)
|
||||
pfunc.updateRequestEvaluator (reval);
|
||||
if (psfunc != null)
|
||||
psfunc.updateRequestEvaluator (reval);
|
||||
}
|
||||
} */
|
||||
|
||||
class Part {
|
||||
|
||||
|
@ -224,34 +233,9 @@ public class Template extends Action {
|
|||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -107,54 +107,3 @@ public class ESGenericObject extends ObjectPrototype {
|
|||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -20,16 +20,16 @@ import java.util.*;
|
|||
public class ESMapWrapper extends ESWrapper {
|
||||
|
||||
private Map data;
|
||||
private RequestEvaluator reval;
|
||||
private FesiEvaluator fesi;
|
||||
|
||||
public ESMapWrapper (RequestEvaluator reval) {
|
||||
super (new Object(), reval.evaluator);
|
||||
this.reval = reval;
|
||||
public ESMapWrapper (FesiEvaluator fesi) {
|
||||
super (new Object(), fesi.getEvaluator ());
|
||||
this.fesi = fesi;
|
||||
}
|
||||
|
||||
public ESMapWrapper (RequestEvaluator reval, Map data) {
|
||||
super (new Object(), reval.evaluator);
|
||||
this.reval = reval;
|
||||
public ESMapWrapper (FesiEvaluator fesi, Map data) {
|
||||
super (new Object(), fesi.getEvaluator ());
|
||||
this.fesi = fesi;
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
|
@ -63,7 +63,7 @@ public class ESMapWrapper extends ESWrapper {
|
|||
if (val instanceof String)
|
||||
return new ESString ((String) val);
|
||||
else if (val instanceof INode)
|
||||
return reval.getNodeWrapper ((INode) val);
|
||||
return fesi.getNodeWrapper ((INode) val);
|
||||
else if (val instanceof ESValue)
|
||||
return (ESValue) val;
|
||||
return ESLoader.normalizeValue(val, evaluator);
|
||||
|
|
|
@ -35,13 +35,13 @@ 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;
|
||||
|
@ -51,7 +51,7 @@ public class ESNode extends ObjectPrototype {
|
|||
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;
|
||||
|
|
|
@ -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 ();
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
// Action.java
|
||||
// ActionFile.java
|
||||
// Copyright (c) Hannes Wallnöfer 1998-2000
|
||||
|
||||
package helma.scripting;
|
||||
package helma.scripting.fesi;
|
||||
|
||||
import helma.scripting.*;
|
||||
import java.util.Vector;
|
||||
import java.util.Iterator;
|
||||
import java.io.*;
|
||||
|
@ -20,90 +21,46 @@ import FESI.Exceptions.*;
|
|||
|
||||
|
||||
/**
|
||||
* An Action is a JavaScript function that is exposed as a URI. It is
|
||||
* usually represented by a file with extension .hac (hop action file)
|
||||
* that contains the pure JavaScript body of the function.
|
||||
* An class that updates fesi interpreters with actionfiles and templates.
|
||||
*/
|
||||
|
||||
|
||||
public class Action implements Updatable {
|
||||
public class FesiActionAdapter {
|
||||
|
||||
String name;
|
||||
String functionName;
|
||||
Prototype prototype;
|
||||
Application app;
|
||||
File file;
|
||||
long lastmod;
|
||||
|
||||
String sourceName;
|
||||
// this is the parsed function which can be easily applied to RequestEvaluator objects
|
||||
TypeUpdater pfunc;
|
||||
|
||||
|
||||
public Action (File file, String name, Prototype proto) {
|
||||
this.prototype = proto;
|
||||
this.app = proto.getApplication ();
|
||||
this.name = name;
|
||||
this.file = file;
|
||||
if (file != null)
|
||||
update ();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tell the type manager whether we need an update. this is the case when
|
||||
* the file has been modified or deleted.
|
||||
*/
|
||||
public boolean needsUpdate () {
|
||||
return lastmod != file.lastModified ();
|
||||
}
|
||||
|
||||
|
||||
public void update () {
|
||||
|
||||
if (!file.exists ()) {
|
||||
// remove functions declared by this from all object prototypes
|
||||
remove ();
|
||||
} else {
|
||||
try {
|
||||
FileReader reader = new FileReader (file);
|
||||
char cbuf[] = new char[(int) file.length ()];
|
||||
reader.read (cbuf);
|
||||
reader.close ();
|
||||
String content = new String (cbuf);
|
||||
update (content);
|
||||
} catch (Exception filex) {
|
||||
app.logEvent ("*** Error reading action file "+file+": "+filex);
|
||||
}
|
||||
|
||||
lastmod = file.lastModified ();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void update (String content) throws Exception {
|
||||
// app.logEvent ("Reading text template " + name);
|
||||
|
||||
functionName = name+"_action";
|
||||
|
||||
public FesiActionAdapter (ActionFile action) {
|
||||
prototype = action.getPrototype ();
|
||||
app = action.getApplication ();
|
||||
String content = action.getContent ();
|
||||
String functionName = action.getFunctionName ();
|
||||
sourceName = action.toString ();
|
||||
try {
|
||||
pfunc = parseFunction (functionName, "arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10", content);
|
||||
} catch (Throwable x) {
|
||||
String message = x.getMessage ();
|
||||
pfunc = new ErrorFeedback (functionName, message);
|
||||
}
|
||||
}
|
||||
|
||||
Iterator evals = app.typemgr.getRegisteredRequestEvaluators ();
|
||||
/* protected void update (FesiEvaluator fesi) throws Exception {
|
||||
// app.logEvent ("Reading text template " + name);
|
||||
|
||||
FesiScriptingEnvironment scriptEnv = (FesiScriptingEnvironment) app.getScriptingEnvironment ();
|
||||
Iterator evals = scriptEnv.getEvaluators().iterator();
|
||||
while (evals.hasNext ()) {
|
||||
try {
|
||||
RequestEvaluator reval = (RequestEvaluator) evals.next ();
|
||||
updateRequestEvaluator (reval);
|
||||
FesiEvaluator fesi = (FesiEvaluator) evals.next ();
|
||||
updateEvaluator (fesi);
|
||||
} catch (Exception ignore) {}
|
||||
}
|
||||
}
|
||||
|
||||
void remove () {
|
||||
prototype.actions.remove (name);
|
||||
prototype.updatables.remove (file.getName());
|
||||
} */
|
||||
|
||||
/* protected void remove () {
|
||||
Iterator evals = app.typemgr.getRegisteredRequestEvaluators ();
|
||||
while (evals.hasNext ()) {
|
||||
try {
|
||||
|
@ -116,23 +73,12 @@ public class Action implements Updatable {
|
|||
}
|
||||
} catch (Exception ignore) {}
|
||||
}
|
||||
}
|
||||
} */
|
||||
|
||||
public String getName () {
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getFunctionName () {
|
||||
return functionName;
|
||||
}
|
||||
|
||||
public String toString () {
|
||||
return prototype.getName()+"/"+file.getName();
|
||||
}
|
||||
|
||||
public synchronized void updateRequestEvaluator (RequestEvaluator reval) throws EcmaScriptException {
|
||||
public synchronized void updateEvaluator (FesiEvaluator fesi) throws EcmaScriptException {
|
||||
if (pfunc != null)
|
||||
pfunc.updateRequestEvaluator (reval);
|
||||
pfunc.updateEvaluator (fesi);
|
||||
}
|
||||
|
||||
protected TypeUpdater parseFunction (String funcname, String params, String body) throws EcmaScriptException {
|
||||
|
@ -176,10 +122,10 @@ public class Action implements Updatable {
|
|||
sl = (ASTStatementList) parser.StatementList();
|
||||
is.close();
|
||||
} catch (ParseException x) {
|
||||
app.logEvent ("Error parsing file "+app.getName()+":"+prototype.getName()+"/"+file.getName()+": "+x);
|
||||
app.logEvent ("Error parsing file "+app.getName()+":"+sourceName+": "+x);
|
||||
throw new EcmaScriptParseException (x, new StringEvaluationSource(fulltext, null));
|
||||
} catch (Exception x) {
|
||||
app.logEvent ("Error parsing file "+app.getName()+":"+prototype.getName()+"/"+file.getName()+": "+x);
|
||||
app.logEvent ("Error parsing file "+app.getName()+":"+sourceName+": "+x);
|
||||
throw new RuntimeException (x.getMessage ());
|
||||
}
|
||||
|
||||
|
@ -204,15 +150,15 @@ public class Action implements Updatable {
|
|||
this.functionName = functionName;
|
||||
}
|
||||
|
||||
public void updateRequestEvaluator (RequestEvaluator reval) throws EcmaScriptException {
|
||||
public void updateEvaluator (FesiEvaluator fesi) throws EcmaScriptException {
|
||||
|
||||
ObjectPrototype op = reval.getPrototype (prototype.getName());
|
||||
ObjectPrototype op = fesi.getPrototype (prototype.getName());
|
||||
|
||||
EcmaScriptVariableVisitor vdvisitor = reval.evaluator.getVarDeclarationVisitor();
|
||||
EcmaScriptVariableVisitor vdvisitor = fesi.evaluator.getVarDeclarationVisitor();
|
||||
Vector vnames = vdvisitor.processVariableDeclarations(sl, fes);
|
||||
|
||||
FunctionPrototype fp = ConstructedFunctionObject.makeNewConstructedFunction (
|
||||
reval.evaluator, functionName, fes,
|
||||
fesi.evaluator, functionName, fes,
|
||||
fullFunctionText, fpl.getArguments(), vnames, sl);
|
||||
op.putHiddenProperty (functionName, fp);
|
||||
}
|
||||
|
@ -228,12 +174,12 @@ public class Action implements Updatable {
|
|||
errorMessage = msg;
|
||||
}
|
||||
|
||||
public void updateRequestEvaluator (RequestEvaluator reval) throws EcmaScriptException {
|
||||
public void updateEvaluator (FesiEvaluator fesi) throws EcmaScriptException {
|
||||
|
||||
ObjectPrototype op = reval.getPrototype (prototype.getName ());
|
||||
ObjectPrototype op = fesi.getPrototype (prototype.getName ());
|
||||
|
||||
FunctionPrototype fp = (FunctionPrototype) reval.evaluator.getFunctionPrototype ();
|
||||
FunctionPrototype func = new ThrowException (functionName, reval.evaluator, fp, errorMessage);
|
||||
FunctionPrototype fp = (FunctionPrototype) fesi.evaluator.getFunctionPrototype ();
|
||||
FunctionPrototype func = new ThrowException (functionName, fesi.evaluator, fp, errorMessage);
|
||||
op.putHiddenProperty (functionName, func);
|
||||
|
||||
}
|
||||
|
@ -254,38 +200,8 @@ public class Action implements Updatable {
|
|||
}
|
||||
|
||||
interface TypeUpdater {
|
||||
public void updateRequestEvaluator (RequestEvaluator reval) throws EcmaScriptException;
|
||||
public void updateEvaluator (FesiEvaluator fesi) throws EcmaScriptException;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
584
src/helma/scripting/fesi/FesiEvaluator.java
Normal file
584
src/helma/scripting/fesi/FesiEvaluator.java
Normal file
|
@ -0,0 +1,584 @@
|
|||
// FesiScriptingEnvironment.java
|
||||
// Copyright (c) Hannes Wallnöfer 2002
|
||||
|
||||
package helma.scripting.fesi;
|
||||
|
||||
import helma.scripting.*;
|
||||
import helma.scripting.fesi.extensions.*;
|
||||
import helma.framework.*;
|
||||
import helma.framework.core.*;
|
||||
import helma.objectmodel.*;
|
||||
import helma.objectmodel.db.DbMapping;
|
||||
import helma.objectmodel.db.Relation;
|
||||
import helma.util.Updatable;
|
||||
import java.util.*;
|
||||
import java.io.*;
|
||||
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
|
||||
public Application app;
|
||||
|
||||
// The FESI evaluator
|
||||
Evaluator evaluator;
|
||||
|
||||
// the global object
|
||||
GlobalObject global;
|
||||
|
||||
// caching table for JavaScript object wrappers
|
||||
LruHashtable wrappercache;
|
||||
|
||||
// table containing JavaScript prototypes
|
||||
Hashtable prototypes;
|
||||
|
||||
// the request evaluator instance owning this fesi evaluator
|
||||
RequestEvaluator reval;
|
||||
|
||||
// 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, RequestEvaluator reval) {
|
||||
this.app = app;
|
||||
this.reval = reval;
|
||||
wrappercache = new LruHashtable (100, .80f);
|
||||
prototypes = new Hashtable ();
|
||||
try {
|
||||
evaluator = new Evaluator();
|
||||
evaluator.reval = this;
|
||||
global = evaluator.getGlobalObject();
|
||||
for (int i=0; i<extensions.length; i++)
|
||||
evaluator.addExtension (extensions[i]);
|
||||
HopExtension hopx = new HopExtension (app);
|
||||
hopx.initializeExtension (this);
|
||||
MailExtension mailx = (MailExtension) evaluator.addExtension ("helma.scripting.fesi.extensions.MailExtension");
|
||||
mailx.setProperties (app.getProperties ());
|
||||
Database dbx = (Database) evaluator.addExtension ("helma.scripting.fesi.extensions.Database");
|
||||
dbx.setApplication (app);
|
||||
|
||||
// fake a cache member like the one found in ESNodes
|
||||
global.putHiddenProperty ("cache", new ESNode (new TransientNode ("cache"), this));
|
||||
global.putHiddenProperty ("undefined", ESUndefined.theUndefined);
|
||||
ESAppNode appnode = new ESAppNode (app.getAppNode (), this);
|
||||
global.putHiddenProperty ("app", appnode);
|
||||
initialize();
|
||||
} catch (Exception e) {
|
||||
System.err.println("Cannot initialize interpreter");
|
||||
System.err.println("Error: " + e);
|
||||
e.printStackTrace ();
|
||||
throw new RuntimeException (e.getMessage ());
|
||||
}
|
||||
}
|
||||
|
||||
private void initialize () {
|
||||
Collection prototypes = app.getPrototypes();
|
||||
for (Iterator i=prototypes.iterator(); i.hasNext(); ) {
|
||||
Prototype proto = (Prototype) i.next ();
|
||||
evaluatePrototype (proto);
|
||||
}
|
||||
}
|
||||
|
||||
void evaluatePrototype (Prototype prototype) {
|
||||
|
||||
ObjectPrototype op = null;
|
||||
|
||||
// get the prototype's prototype if possible and necessary
|
||||
ObjectPrototype 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) {
|
||||
op = new ObjectPrototype (opp, evaluator);
|
||||
try {
|
||||
op.putProperty ("prototypename", new ESString (name), "prototypename".hashCode ());
|
||||
} catch (EcmaScriptException ignore) {}
|
||||
putPrototype (name, op);
|
||||
} else {
|
||||
// set parent prototype just in case it has been changed
|
||||
op.setPrototype (opp);
|
||||
}
|
||||
|
||||
resetPrototype (op);
|
||||
|
||||
// Register a constructor for all types except global.
|
||||
// This will first create a node and then call the actual (scripted) constructor on it.
|
||||
if (!"global".equalsIgnoreCase (name)) {
|
||||
try {
|
||||
FunctionPrototype fp = (FunctionPrototype) evaluator.getFunctionPrototype();
|
||||
evaluator.getGlobalObject().putHiddenProperty (name, new NodeConstructor (name, fp, this));
|
||||
} catch (EcmaScriptException ignore) {}
|
||||
}
|
||||
for (Iterator it = prototype.functions.values().iterator(); it.hasNext(); ) {
|
||||
FunctionFile ff = (FunctionFile) it.next ();
|
||||
if (ff.hasFile ())
|
||||
evaluateFile (prototype, ff.getFile ());
|
||||
else
|
||||
evaluateString (prototype, ff.getContent ());
|
||||
}
|
||||
/* for (Iterator it = prototype.templates.values().iterator(); it.hasNext(); ) {
|
||||
Template tmp = (Template) it.next ();
|
||||
try {
|
||||
tmp.updateRequestEvaluator (reval);
|
||||
} catch (EcmaScriptException ignore) {}
|
||||
} */
|
||||
for (Iterator it = prototype.actions.values().iterator(); it.hasNext(); ) {
|
||||
ActionFile act = (ActionFile) it.next ();
|
||||
try {
|
||||
FesiActionAdapter adp = new FesiActionAdapter (act);
|
||||
adp.updateEvaluator (this);
|
||||
} catch (EcmaScriptException ignore) {}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an object prototype to its initial state, removing all application specific
|
||||
* functions.
|
||||
*/
|
||||
void resetPrototype (ObjectPrototype op) {
|
||||
for (Enumeration en = op.getAllProperties(); en.hasMoreElements(); ) {
|
||||
String prop = en.nextElement ().toString ();
|
||||
try {
|
||||
ESValue esv = op.getProperty (prop, prop.hashCode ());
|
||||
// System.err.println (protoname+"."+obj+" -> "+esv.getClass());
|
||||
if (esv instanceof ConstructedFunctionObject || esv instanceof FesiActionAdapter.ThrowException)
|
||||
op.deleteProperty (prop, prop.hashCode());
|
||||
} catch (Exception x) {}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 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 {
|
||||
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<esv.length; i++) {
|
||||
// for java.util.Map objects, we use the special "tight" wrapper
|
||||
// that makes the Map look like a native object
|
||||
if (args[i] instanceof Map)
|
||||
esv[i] = new ESMapWrapper (this, (Map) args[i]);
|
||||
else
|
||||
esv[i] = ESLoader.normalizeValue (args[i], evaluator);
|
||||
}
|
||||
|
||||
if (globals != null) {
|
||||
// remember all global variables before invocation
|
||||
Set tmpGlobal = new HashSet ();
|
||||
for (Enumeration en = global.getAllProperties(); en.hasMoreElements(); ) {
|
||||
tmpGlobal.add (en.nextElement ().toString ());
|
||||
}
|
||||
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;
|
||||
// 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 RequestTrans)
|
||||
((RequestTrans) v).data = new ESMapWrapper (this, ((RequestTrans) v).getRequestData ());
|
||||
else if (v instanceof ResponseTrans)
|
||||
((ResponseTrans) v).data = new ESMapWrapper (this, ((ResponseTrans) v).getResponseData ());
|
||||
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;
|
||||
for (int j=0; j<path.size(); j++) {
|
||||
Object pathElem = path.get (j);
|
||||
ESValue wrappedElement = getElementWrapper (pathElem);
|
||||
parr.putProperty (j, wrappedElement);
|
||||
parr.putHiddenProperty (app.getPrototypeName(pathElem), wrappedElement);
|
||||
}
|
||||
sv = parr;
|
||||
} else if ("user".equals (k)) {
|
||||
sv = getNodeWrapper ((User) v);
|
||||
} else if ("app".equals (k)) {
|
||||
sv = new ESAppNode ((INode) v, this);
|
||||
}
|
||||
else
|
||||
sv = ESLoader.normalizeValue (v, evaluator);
|
||||
global.putHiddenProperty (k, sv);
|
||||
}
|
||||
}
|
||||
evaluator.thread = Thread.currentThread ();
|
||||
ESValue retval = eso.doIndirectCall (evaluator, eso, functionName, esv);
|
||||
return retval == null ? null : retval.toJavaObject ();
|
||||
} 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 ());
|
||||
// create and throw a ScriptingException with the right message
|
||||
String msg = x.getMessage ();
|
||||
if (msg == null || msg.length() < 10)
|
||||
msg = x.toString ();
|
||||
// System.err.println ("INVOKE-ERROR: "+msg);
|
||||
// x.printStackTrace ();
|
||||
throw new ScriptingException (msg);
|
||||
} finally {
|
||||
// remove global variables that have been added during invocation.
|
||||
// this are typically undeclared variables, and we don't want them to
|
||||
// endure from one request to the next since this leads to buggy code that
|
||||
// relies on requests being served by the same evaluator, which is typically the
|
||||
// case under development conditions but not in deployment.
|
||||
if (globalVariables != null) {
|
||||
for (Enumeration en = global.getAllProperties(); en.hasMoreElements(); ) {
|
||||
String g = en.nextElement ().toString ();
|
||||
if (!globalVariables.contains (g)) try {
|
||||
global.deleteProperty (g, g.hashCode());
|
||||
} catch (Exception x) {
|
||||
System.err.println ("Error resetting global property: "+g);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
ESObject eso = null;
|
||||
if (obj == null)
|
||||
eso = evaluator.getGlobalObject ();
|
||||
else
|
||||
eso = getElementWrapper (obj);
|
||||
try {
|
||||
ESValue func = eso.getProperty (fname, fname.hashCode());
|
||||
if (func != null && func instanceof FunctionPrototype)
|
||||
return true;
|
||||
} catch (EcmaScriptException esx) {
|
||||
// System.err.println ("Error in hasFunction: "+esx);
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Check if an object has a defined property (public field if it
|
||||
* is a java object) with that name.
|
||||
*/
|
||||
public Object getProperty (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+"]";
|
||||
}
|
||||
}
|
||||
|
||||
ESObject eso = getElementWrapper (obj);
|
||||
try {
|
||||
ESValue prop = eso.getProperty (propname, propname.hashCode());
|
||||
if (prop != null && !(prop instanceof ESNull) &&
|
||||
!(prop instanceof ESUndefined))
|
||||
return prop.toJavaObject ();
|
||||
} catch (EcmaScriptException esx) {
|
||||
// System.err.println ("Error in getProperty: "+esx);
|
||||
return null;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the FESI Evaluator object wrapped by this object.
|
||||
*/
|
||||
public Evaluator getEvaluator () {
|
||||
return evaluator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the application we're running in
|
||||
*/
|
||||
public Application getApplication () {
|
||||
return app;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the object prototype for a prototype name
|
||||
*/
|
||||
public ObjectPrototype getPrototype (String protoName) {
|
||||
if (protoName == null)
|
||||
return null;
|
||||
return (ObjectPrototype) prototypes.get (protoName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register an object prototype for a certain prototype name.
|
||||
*/
|
||||
public void putPrototype (String protoName, ObjectPrototype op) {
|
||||
if (protoName != null && op != null)
|
||||
prototypes.put (protoName, op);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 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 ESValue getObjectWrapper (Object e) {
|
||||
if (app.getPrototypeName (e) != null)
|
||||
return getElementWrapper (e);
|
||||
/* else if (e instanceof INode)
|
||||
return new ESNode ((INode) e, this); */
|
||||
else
|
||||
return new ESWrapper (e, evaluator);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 ESObject getElementWrapper (Object e) {
|
||||
|
||||
// check if e is an instance of a helma objectmodel node.
|
||||
if (e instanceof INode)
|
||||
return getNodeWrapper ((INode) e);
|
||||
|
||||
// Gotta find out the prototype name to use for this object...
|
||||
String prototypeName = app.getPrototypeName (e);
|
||||
|
||||
ObjectPrototype op = getPrototype (prototypeName);
|
||||
|
||||
if (op == null)
|
||||
op = getPrototype ("hopobject");
|
||||
|
||||
return new ESGenericObject (op, evaluator, e);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Get a script wrapper for an implemntation of helma.objectmodel.INode
|
||||
*/
|
||||
public ESNode getNodeWrapper (INode n) {
|
||||
|
||||
if (n == null)
|
||||
return null;
|
||||
|
||||
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.
|
||||
// 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");
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Register a new Node wrapper with the wrapper cache. This is used by the
|
||||
* Node constructor.
|
||||
*/
|
||||
public void putNodeWrapper (INode n, ESNode esn) {
|
||||
wrappercache.put (n, esn);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a scripting wrapper object for a user object. Active user objects are represented by
|
||||
* the special ESUser wrapper class.
|
||||
*/
|
||||
public ESNode getNodeWrapper (User u) {
|
||||
if (u == null)
|
||||
return null;
|
||||
|
||||
ESUser esn = (ESUser) wrappercache.get (u);
|
||||
|
||||
if (esn == null) {
|
||||
esn = new ESUser (u.getNode(), this, u);
|
||||
wrappercache.put (u, esn);
|
||||
} else {
|
||||
// the user node may have changed (login/logout) while the ESUser was
|
||||
// lingering in the cache.
|
||||
esn.updateNodeFromUser ();
|
||||
}
|
||||
|
||||
return esn;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
|
||||
public synchronized void evaluateFile (Prototype prototype, File file) {
|
||||
try {
|
||||
FileReader fr = new FileReader (file);
|
||||
EvaluationSource es = new FileEvaluationSource (file.getPath (), null);
|
||||
updateEvaluator (prototype, fr, es);
|
||||
} catch (IOException iox) {
|
||||
app.logEvent ("Error updating function file: "+iox);
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void evaluateString (Prototype prototype, String code) {
|
||||
StringReader reader = new StringReader (code);
|
||||
StringEvaluationSource es = new StringEvaluationSource (code, null);
|
||||
updateEvaluator (prototype, reader, es);
|
||||
}
|
||||
|
||||
public synchronized void updateEvaluator (Prototype prototype, Reader reader, EvaluationSource source) {
|
||||
|
||||
// HashMap priorProps = null;
|
||||
// HashSet newProps = null;
|
||||
|
||||
try {
|
||||
|
||||
ObjectPrototype op = getPrototype (prototype.getName());
|
||||
|
||||
// extract all properties from prototype _before_ evaluation, so we can compare afterwards
|
||||
// but only do this is declaredProps is not up to date yet
|
||||
/*if (declaredPropsTimestamp != lastmod) {
|
||||
priorProps = new HashMap ();
|
||||
// remember properties before evaluation, so we can tell what's new afterwards
|
||||
try {
|
||||
for (Enumeration en=op.getAllProperties(); en.hasMoreElements(); ) {
|
||||
String prop = (String) en.nextElement ();
|
||||
priorProps.put (prop, op.getProperty (prop, prop.hashCode()));
|
||||
}
|
||||
} catch (Exception ignore) {}
|
||||
} */
|
||||
|
||||
// do the update, evaluating the file
|
||||
evaluator.evaluate(reader, op, source, false);
|
||||
|
||||
// check what's new
|
||||
/* if (declaredPropsTimestamp != lastmod) try {
|
||||
newProps = new HashSet ();
|
||||
for (Enumeration en=op.getAllProperties(); en.hasMoreElements(); ) {
|
||||
String prop = (String) en.nextElement ();
|
||||
if (priorProps.get (prop) == null || op.getProperty (prop, prop.hashCode()) != priorProps.get (prop))
|
||||
newProps.add (prop);
|
||||
}
|
||||
} catch (Exception ignore) {} */
|
||||
|
||||
} catch (Throwable e) {
|
||||
app.logEvent ("Error parsing function file "+source+": "+e);
|
||||
} finally {
|
||||
if (reader != null) {
|
||||
try {
|
||||
reader.close();
|
||||
} catch (IOException ignore) {}
|
||||
}
|
||||
|
||||
// now remove the props that were not refreshed, and set declared props to new collection
|
||||
/* if (declaredPropsTimestamp != lastmod) {
|
||||
declaredPropsTimestamp = lastmod;
|
||||
if (declaredProps != null) {
|
||||
declaredProps.removeAll (newProps);
|
||||
removeProperties (declaredProps);
|
||||
}
|
||||
declaredProps = newProps;
|
||||
// System.err.println ("DECLAREDPROPS = "+declaredProps);
|
||||
} */
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
85
src/helma/scripting/fesi/FesiScriptingEnvironment.java
Normal file
85
src/helma/scripting/fesi/FesiScriptingEnvironment.java
Normal file
|
@ -0,0 +1,85 @@
|
|||
// 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 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();
|
||||
}
|
||||
|
||||
FesiEvaluator getEvaluator (RequestEvaluator reval) {
|
||||
FesiEvaluator fesi = (FesiEvaluator) evaluators.get (reval);
|
||||
if (fesi == null) {
|
||||
fesi = new FesiEvaluator (app, reval);
|
||||
evaluators.put (reval, fesi);
|
||||
}
|
||||
return fesi;
|
||||
}
|
||||
}
|
|
@ -18,28 +18,27 @@ 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 Helma. It sets up
|
||||
* varios constructors, global functions and properties on the HopObject prototype
|
||||
* (Node objects), the user prototype, the global prototype 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 {
|
||||
|
||||
this.reval = reval;
|
||||
this.app = reval.app;
|
||||
Evaluator evaluator = reval.evaluator;
|
||||
public void initializeExtension (FesiEvaluator fesi) throws EcmaScriptException {
|
||||
this.fesi = fesi;
|
||||
Evaluator evaluator = fesi.getEvaluator ();
|
||||
GlobalObject go = evaluator.getGlobalObject();
|
||||
FunctionPrototype fp = (FunctionPrototype) evaluator.getFunctionPrototype();
|
||||
|
||||
|
@ -59,39 +58,39 @@ public class HopExtension {
|
|||
sp.putHiddenProperty ("trim", new StringTrim ("trim", 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.
|
||||
// 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
|
||||
go.putHiddenProperty("Node", node); // register the constructor for a plain Node object.
|
||||
|
@ -122,14 +121,19 @@ public class HopExtension {
|
|||
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 ("__javaobject__", esObjectPrototype);
|
||||
fesi.putPrototype ("user", esUserPrototype);
|
||||
}
|
||||
|
||||
class NodeAdd extends BuiltinFunctionObject {
|
||||
|
@ -437,7 +441,7 @@ public class HopExtension {
|
|||
if (unode == null)
|
||||
return ESNull.theNull;
|
||||
else
|
||||
return reval.getNodeWrapper (unode);
|
||||
return fesi.getNodeWrapper (unode);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -552,12 +556,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(); ) {
|
||||
|
@ -573,17 +578,29 @@ public class HopExtension {
|
|||
skin = (Skin) obj;
|
||||
}
|
||||
|
||||
// if res.skinpath is set, transform it into an array of java objects
|
||||
// (strings for directory names and INodes for internal, db-stored skinsets)
|
||||
ResponseTrans res = fesi.getResponse();
|
||||
Object[] skinpath = new Object[0];
|
||||
if (res.skinpath != null && res.skinpath instanceof ArrayPrototype) {
|
||||
ArrayPrototype array = (ArrayPrototype) res.skinpath;
|
||||
skinpath = new Object[array.size()];
|
||||
for (int i=0; i<skinpath.length; i++)
|
||||
skinpath[i] = array.getProperty(i).toJavaObject ();
|
||||
}
|
||||
|
||||
// ready... retrieve the skin and render it.
|
||||
Object javaObject = thisObject == null ? null : thisObject.toJavaObject ();
|
||||
if (skin == null)
|
||||
skin = reval.getSkin (thisObject, arguments[0].toString ());
|
||||
skin = app.getSkin (javaObject, arguments[0].toString (), skinpath);
|
||||
if (asString)
|
||||
reval.res.pushStringBuffer ();
|
||||
Object javaObj = thisObject == null ? null : thisObject.toJavaObject ();
|
||||
res.pushStringBuffer ();
|
||||
if (skin != null)
|
||||
skin.render (reval, javaObj, params);
|
||||
skin.render (fesi.getRequestEvaluator(), javaObject, params);
|
||||
else
|
||||
reval.res.write ("[Skin not found: "+arguments[0]+"]");
|
||||
res.write ("[Skin not found: "+arguments[0]+"]");
|
||||
if (asString)
|
||||
return new ESString (reval.res.popStringBuffer ());
|
||||
return new ESString (res.popStringBuffer ());
|
||||
} catch (RedirectException redir) {
|
||||
// let redirect pass through
|
||||
throw redir;
|
||||
|
@ -609,7 +626,7 @@ public class HopExtension {
|
|||
}
|
||||
if (user == null)
|
||||
return ESNull.theNull;
|
||||
return reval.getNodeWrapper (user);
|
||||
return fesi.getNodeWrapper (user);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -626,7 +643,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 ());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -663,7 +680,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);
|
||||
// }
|
||||
}
|
||||
|
@ -901,18 +918,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);
|
||||
|
@ -964,11 +969,11 @@ public class HopExtension {
|
|||
return new ESString (basicHref);
|
||||
}
|
||||
private ESString renderSkin (Skin skin, String path, Object skinElem) throws EcmaScriptException {
|
||||
reval.res.pushStringBuffer ();
|
||||
fesi.getResponse().pushStringBuffer ();
|
||||
HashMap param = new HashMap ();
|
||||
param.put ("path", path);
|
||||
skin.render (reval, skinElem, param);
|
||||
return new ESString (reval.res.popStringBuffer ().trim ());
|
||||
skin.render (fesi.getRequestEvaluator(), skinElem, param);
|
||||
return new ESString (fesi.getResponse().popStringBuffer ().trim ());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -999,164 +1004,6 @@ public class HopExtension {
|
|||
return b.toString ();
|
||||
}
|
||||
|
||||
private String getNodeChooserDD (String name, INode collection, INode target, String teaser) {
|
||||
StringBuffer buffer = new StringBuffer ("<select name=\"");
|
||||
buffer.append (name);
|
||||
buffer.append ("\">");
|
||||
if (collection.contains (target) == -1) {
|
||||
buffer.append ("<option value=>");
|
||||
buffer.append (HtmlEncoder.encodeAll (teaser));
|
||||
}
|
||||
if (collection != null) {
|
||||
int l = collection.numberOfNodes ();
|
||||
for (int i=0; i<l; i++) {
|
||||
INode next = collection.getSubnodeAt (i);
|
||||
buffer.append ("<option value=\"");
|
||||
buffer.append (next.getID ());
|
||||
if (target == next)
|
||||
buffer.append ("\" selected=\"true");
|
||||
buffer.append ("\">");
|
||||
String cname = next.getString ("name", false);
|
||||
if (cname == null) cname = next.getName ();
|
||||
buffer.append (HtmlEncoder.encodeAll (cname));
|
||||
}
|
||||
}
|
||||
buffer.append ("</select>");
|
||||
return buffer.toString ();
|
||||
}
|
||||
|
||||
private String getNodeChooserRB (String name, INode collection, INode target) {
|
||||
StringBuffer buffer = new StringBuffer ();
|
||||
if (collection != null) {
|
||||
int l = collection.numberOfNodes ();
|
||||
for (int i=0; i<l; i++) {
|
||||
INode next = collection.getSubnodeAt (i);
|
||||
buffer.append ("<input type=radio name=\"");
|
||||
buffer.append (name);
|
||||
buffer.append ("\" value=\"");
|
||||
buffer.append (next.getElementName ()+"\"");
|
||||
if (target == next)
|
||||
buffer.append (" checked");
|
||||
buffer.append (">");
|
||||
String cname = next.getString ("name", false);
|
||||
if (cname == null) cname = next.getName ();
|
||||
buffer.append (HtmlEncoder.encodeAll (cname));
|
||||
buffer.append ("<br>");
|
||||
}
|
||||
}
|
||||
return buffer.toString ();
|
||||
}
|
||||
|
||||
private String getNodeChooserCB (String name, INode collection, INode target) {
|
||||
StringBuffer buffer = new StringBuffer ();
|
||||
if (collection != null) {
|
||||
int l = collection.numberOfNodes ();
|
||||
for (int i=0; i<l; i++) {
|
||||
INode next = collection.getSubnodeAt (i);
|
||||
buffer.append ("<input type=checkbox name=\"");
|
||||
buffer.append (name);
|
||||
buffer.append ("\" value=");
|
||||
buffer.append (next.getElementName ());
|
||||
if (target.contains (next) > -1)
|
||||
buffer.append (" checked");
|
||||
buffer.append (">");
|
||||
buffer.append (HtmlEncoder.encodeAll (next.getName ()));
|
||||
buffer.append ("<br>");
|
||||
}
|
||||
}
|
||||
return buffer.toString ();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -16,13 +16,13 @@ import FESI.Interpreter.*;
|
|||
|
||||
public class NodeConstructor extends BuiltinFunctionObject {
|
||||
|
||||
RequestEvaluator reval;
|
||||
FesiEvaluator fesi;
|
||||
String typename;
|
||||
|
||||
public NodeConstructor (String name, FunctionPrototype fp, RequestEvaluator reval) {
|
||||
super(fp, reval.evaluator, name, 1);
|
||||
public NodeConstructor (String name, FunctionPrototype fp, FesiEvaluator fesi) {
|
||||
super(fp, fesi.getEvaluator (), name, 1);
|
||||
typename = name;
|
||||
this.reval = reval;
|
||||
this.fesi = fesi;
|
||||
}
|
||||
|
||||
public ESValue callFunction(ESObject thisObject, ESValue[] arguments) throws EcmaScriptException {
|
||||
|
@ -31,35 +31,33 @@ public class NodeConstructor extends BuiltinFunctionObject {
|
|||
|
||||
public ESObject doConstruct(ESObject thisObject, ESValue[] arguments) throws EcmaScriptException {
|
||||
ESNode node = null;
|
||||
Application app = fesi.getApplication ();
|
||||
if ("Node".equals (typename) || "hopobject".equalsIgnoreCase (typename)) {
|
||||
if (arguments.length == 0) {
|
||||
Node n = new Node ((String) null, (String) null, reval.app.getWrappedNodeManager ());
|
||||
node = new ESNode (reval.esNodePrototype, this.evaluator, n, reval);
|
||||
reval.objectcache.put (node.getNode (), node);
|
||||
} else {
|
||||
Node n = new Node (arguments[0].toString(), (String) null, reval.app.getWrappedNodeManager ());
|
||||
node = new ESNode (reval.esNodePrototype, this.evaluator, n, reval);
|
||||
reval.objectcache.put (node.getNode (), node);
|
||||
}
|
||||
String nodeName = null;
|
||||
if (arguments.length > 0 && arguments[0] != null)
|
||||
nodeName = arguments[0].toString();
|
||||
Node n = new Node (nodeName, (String) null, app.getWrappedNodeManager ());
|
||||
node = new ESNode (fesi.getPrototype ("hopobject"), this.evaluator, n, fesi);
|
||||
fesi.putNodeWrapper (node.getNode (), node);
|
||||
} else {
|
||||
// Typed nodes are instantiated as helma.objectmodel.db.Node from the beginning
|
||||
// even if we don't know yet if they are going to be stored in a database. The reason
|
||||
// is that we want to be able to use the specail features like subnode relations even for
|
||||
// transient nodes.
|
||||
ObjectPrototype op = reval.getPrototype (typename);
|
||||
Node n = new Node (typename, typename, reval.app.getWrappedNodeManager ());
|
||||
node = new ESNode (op, reval.evaluator, n, reval);
|
||||
ObjectPrototype op = fesi.getPrototype (typename);
|
||||
Node n = new Node (typename, typename, app.getWrappedNodeManager ());
|
||||
node = new ESNode (op, fesi.getEvaluator (), n, fesi);
|
||||
node.setPrototype (typename);
|
||||
node.getNode ().setDbMapping (reval.app.getDbMapping (typename));
|
||||
node.getNode ().setDbMapping (app.getDbMapping (typename));
|
||||
try {
|
||||
// first try calling "constructor", if that doesn't work, try calling a function
|
||||
// with the name of the type.
|
||||
// HACK: There is an incompatibility problem here, because the property
|
||||
// constructor is defined as the constructor of the object by EcmaScript.
|
||||
if (op.getProperty ("constructor", "constructor".hashCode()) instanceof ConstructedFunctionObject)
|
||||
node.doIndirectCall (reval.evaluator, node, "constructor", arguments);
|
||||
node.doIndirectCall (fesi.getEvaluator(), node, "constructor", arguments);
|
||||
else
|
||||
node.doIndirectCall (reval.evaluator, node, typename, arguments);
|
||||
node.doIndirectCall (fesi.getEvaluator(), node, typename, arguments);
|
||||
} catch (Exception ignore) {}
|
||||
}
|
||||
return node;
|
||||
|
@ -71,7 +69,7 @@ public class NodeConstructor extends BuiltinFunctionObject {
|
|||
|
||||
public ESValue getProperty(String propertyName, int hash) throws EcmaScriptException {
|
||||
if ("prototype".equals (propertyName))
|
||||
return reval.getPrototype (typename);
|
||||
return fesi.getPrototype (typename);
|
||||
return super.getProperty(propertyName, hash);
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue