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;
|
package helma.framework;
|
||||||
|
|
||||||
import FESI.Exceptions.EcmaScriptException;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* RedirectException is thrown internally when a response is redirected to a
|
* RedirectException is thrown internally when a response is redirected to a
|
||||||
* new URL.
|
* new URL.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class RedirectException extends EcmaScriptException {
|
public class RedirectException extends RuntimeException {
|
||||||
|
|
||||||
String url;
|
String url;
|
||||||
|
|
||||||
|
@ -18,11 +17,11 @@ public class RedirectException extends EcmaScriptException {
|
||||||
super ("Redirection Request to "+url);
|
super ("Redirection Request to "+url);
|
||||||
this.url = url;
|
this.url = url;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getMessage () {
|
public String getMessage () {
|
||||||
return url;
|
return url;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void printStackTrace(java.io.PrintStream s) {
|
public void printStackTrace(java.io.PrintStream s) {
|
||||||
// do nothing
|
// do nothing
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,8 +35,7 @@ public class Application extends UnicastRemoteObject implements IRemoteApp, IPat
|
||||||
protected NodeManager nmgr;
|
protected NodeManager nmgr;
|
||||||
|
|
||||||
// the class name of the scripting environment implementation
|
// the class name of the scripting environment implementation
|
||||||
static final String scriptEnvironmentName = "helma.scripting.fesi.Environment";
|
ScriptingEnvironment scriptingEngine;
|
||||||
ScriptingEnvironment scriptEnv;
|
|
||||||
|
|
||||||
// the root of the website, if a custom root object is defined.
|
// the root of the website, if a custom root object is defined.
|
||||||
// otherwise this is managed by the NodeManager and not cached here.
|
// 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;
|
public TypeManager typemgr;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The skin manager for this application
|
||||||
|
*/
|
||||||
|
protected SkinManager skinmgr;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Each application has one internal request evaluator for calling
|
* Each application has one internal request evaluator for calling
|
||||||
* the scheduler and other internal functions.
|
* 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.
|
* 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);
|
eval = new RequestEvaluator (this);
|
||||||
logEvent ("Starting evaluators for "+name);
|
logEvent ("Starting evaluators for "+name);
|
||||||
|
@ -249,6 +255,8 @@ public class Application extends UnicastRemoteObject implements IRemoteApp, IPat
|
||||||
typemgr.createPrototypes ();
|
typemgr.createPrototypes ();
|
||||||
// logEvent ("Started type manager for "+name);
|
// logEvent ("Started type manager for "+name);
|
||||||
|
|
||||||
|
skinmgr = new SkinManager (this);
|
||||||
|
|
||||||
rootMapping = getDbMapping ("root");
|
rootMapping = getDbMapping ("root");
|
||||||
userMapping = getDbMapping ("user");
|
userMapping = getDbMapping ("user");
|
||||||
SystemProperties p = new SystemProperties ();
|
SystemProperties p = new SystemProperties ();
|
||||||
|
@ -366,7 +374,7 @@ public class Application extends UnicastRemoteObject implements IRemoteApp, IPat
|
||||||
try {
|
try {
|
||||||
RequestEvaluator re = (RequestEvaluator) freeThreads.pop ();
|
RequestEvaluator re = (RequestEvaluator) freeThreads.pop ();
|
||||||
allThreads.removeElement (re);
|
allThreads.removeElement (re);
|
||||||
typemgr.unregisterRequestEvaluator (re);
|
// typemgr.unregisterRequestEvaluator (re);
|
||||||
re.stopThread ();
|
re.stopThread ();
|
||||||
} catch (EmptyStackException empty) {
|
} catch (EmptyStackException empty) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -520,6 +528,13 @@ public class Application extends UnicastRemoteObject implements IRemoteApp, IPat
|
||||||
return nmgr.safe;
|
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.
|
* Returns a Node representing a registered user of this application by his or her user name.
|
||||||
|
@ -552,9 +567,16 @@ public class Application extends UnicastRemoteObject implements IRemoteApp, IPat
|
||||||
* Return a collection containing all prototypes defined for this application
|
* Return a collection containing all prototypes defined for this application
|
||||||
*/
|
*/
|
||||||
public Collection getPrototypes () {
|
public Collection getPrototypes () {
|
||||||
return typemgr.prototypes.values ();
|
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
|
* 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.
|
* within the Helma scripting and rendering framework.
|
||||||
*/
|
*/
|
||||||
public String getPrototypeName (Object obj) {
|
public String getPrototypeName (Object obj) {
|
||||||
|
if (obj == null)
|
||||||
|
return "global";
|
||||||
// check if e implements the IPathElement interface
|
// check if e implements the IPathElement interface
|
||||||
if (obj instanceof IPathElement)
|
if (obj instanceof IPathElement)
|
||||||
// e implements the getPrototype() method
|
// 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
|
* The run method performs periodic tasks like executing the scheduler method and
|
||||||
* kicking out expired user sessions.
|
* kicking out expired user sessions.
|
||||||
|
@ -917,7 +949,9 @@ public class Application extends UnicastRemoteObject implements IRemoteApp, IPat
|
||||||
|
|
||||||
try {
|
try {
|
||||||
eval.invokeFunction ((INode) null, "onStart", new Object[0]);
|
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) {
|
while (Thread.currentThread () == worker) {
|
||||||
// get session timeout
|
// 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
|
* Check whether a prototype is for scripting a java class, i.e. if there's an entry
|
||||||
* for it in the class.properties file.
|
* for it in the class.properties file.
|
||||||
*/
|
*/
|
||||||
protected boolean isJavaPrototype (String typename) {
|
public boolean isJavaPrototype (String typename) {
|
||||||
for (Enumeration en = classMapping.elements(); en.hasMoreElements(); ) {
|
for (Enumeration en = classMapping.elements(); en.hasMoreElements(); ) {
|
||||||
String value = (String) en.nextElement ();
|
String value = (String) en.nextElement ();
|
||||||
if (typename.equals (value))
|
if (typename.equals (value))
|
||||||
|
@ -1129,7 +1163,9 @@ public class Application extends UnicastRemoteObject implements IRemoteApp, IPat
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public int countMaxActiveEvaluators () {
|
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;
|
RequestEvaluator ev = null;
|
||||||
try {
|
try {
|
||||||
ev = app.getEvaluator ();
|
ev = app.getEvaluator ();
|
||||||
retval = ev.invokeXmlRpc (method, argvec);
|
retval = ev.invokeXmlRpc (method, argvec.toArray());
|
||||||
} finally {
|
} finally {
|
||||||
app.releaseEvaluator (ev);
|
app.releaseEvaluator (ev);
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,11 +8,8 @@ import java.util.Iterator;
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import helma.framework.*;
|
import helma.framework.*;
|
||||||
import helma.scripting.*;
|
import helma.scripting.*;
|
||||||
import helma.scripting.fesi.*;
|
|
||||||
import helma.objectmodel.*;
|
import helma.objectmodel.*;
|
||||||
import helma.util.Updatable;
|
import helma.util.Updatable;
|
||||||
import FESI.Data.*;
|
|
||||||
import FESI.Exceptions.EcmaScriptException;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -66,12 +63,12 @@ public class Prototype {
|
||||||
|
|
||||||
// if parent has changed, update ES-prototypes in request evaluators
|
// if parent has changed, update ES-prototypes in request evaluators
|
||||||
if (parent != old) {
|
if (parent != old) {
|
||||||
Iterator evals = app.typemgr.getRegisteredRequestEvaluators ();
|
/* Iterator evals = app.typemgr.getRegisteredRequestEvaluators ();
|
||||||
while (evals.hasNext ()) {
|
while (evals.hasNext ()) {
|
||||||
try {
|
try {
|
||||||
RequestEvaluator reval = (RequestEvaluator) evals.next ();
|
RequestEvaluator reval = (RequestEvaluator) evals.next ();
|
||||||
ObjectPrototype op = reval.getPrototype (getName());
|
ObjectPrototype op = reval.getPrototype (getName());
|
||||||
// use hopobject (node) as prototype even if prototype is null -
|
// use hopobject (node) as prototype even if prototype is null -
|
||||||
// this is the case if no hopobject directory exists
|
// this is the case if no hopobject directory exists
|
||||||
ObjectPrototype opp = parent == null ?
|
ObjectPrototype opp = parent == null ?
|
||||||
reval.esNodePrototype : reval.getPrototype (parent.getName ());
|
reval.esNodePrototype : reval.getPrototype (parent.getName ());
|
||||||
|
@ -81,7 +78,7 @@ public class Prototype {
|
||||||
op.setPrototype (opp);
|
op.setPrototype (opp);
|
||||||
} catch (Exception ignore) {
|
} catch (Exception ignore) {
|
||||||
}
|
}
|
||||||
}
|
} */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -97,8 +94,8 @@ public class Prototype {
|
||||||
return (FunctionFile) functions.get (ffname);
|
return (FunctionFile) functions.get (ffname);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Action getAction (String afname) {
|
public ActionFile getActionFile (String afname) {
|
||||||
return (Action) actions.get (afname);
|
return (ActionFile) actions.get (afname);
|
||||||
}
|
}
|
||||||
|
|
||||||
public SkinFile getSkinFile (String sfname) {
|
public SkinFile getSkinFile (String sfname) {
|
||||||
|
@ -128,76 +125,11 @@ public class Prototype {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return upd;
|
return upd;
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
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 () {
|
public String toString () {
|
||||||
return "[Prototype "+ app.getName()+"/"+name+"]";
|
return "[Prototype "+ app.getName()+"/"+name+"]";
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -278,9 +278,9 @@ public class Skin {
|
||||||
if (handlerObject == null) {
|
if (handlerObject == null) {
|
||||||
// eiter because thisObject == null or the right object wasn't found in the object's parent path
|
// 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
|
// 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--) {
|
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))) {
|
if (handler.equalsIgnoreCase (app.getPrototypeName (pathelem))) {
|
||||||
handlerObject = pathelem;
|
handlerObject = pathelem;
|
||||||
break;
|
break;
|
||||||
|
@ -302,12 +302,12 @@ public class Skin {
|
||||||
// if so, the macro evaluates to the function. Otherwise,
|
// if so, the macro evaluates to the function. Otherwise,
|
||||||
// a property/field with the name is used, if defined.
|
// a property/field with the name is used, if defined.
|
||||||
Object v = null;
|
Object v = null;
|
||||||
if (reval.hasFunction (handlerObject, name+"_macro")) {
|
if (app.scriptingEngine.hasFunction (handlerObject, name+"_macro", reval)) {
|
||||||
// System.err.println ("Getting macro from function");
|
// 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 {
|
} else {
|
||||||
// System.err.println ("Getting macro from property");
|
// System.err.println ("Getting macro from property");
|
||||||
v = reval.getProperty (handlerObject, name);
|
v = app.scriptingEngine.get (handlerObject, name, reval);
|
||||||
}
|
}
|
||||||
if (v != null)
|
if (v != null)
|
||||||
writeToResponse (v.toString (), reval.res);
|
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) {
|
} else if (list[i].endsWith (app.actionExtension) && tmpfile.length () > 0) {
|
||||||
try {
|
try {
|
||||||
Action af = new Action (tmpfile, tmpname, proto);
|
ActionFile af = new ActionFile (tmpfile, tmpname, proto);
|
||||||
updatables.put (list[i], af);
|
updatables.put (list[i], af);
|
||||||
nact.put (tmpname, af);
|
nact.put (tmpname, af);
|
||||||
} catch (Throwable x) {
|
} catch (Throwable x) {
|
||||||
|
@ -257,11 +257,12 @@ public class TypeManager {
|
||||||
proto.updatables = updatables;
|
proto.updatables = updatables;
|
||||||
|
|
||||||
// init prototype on evaluators that are already initialized.
|
// init prototype on evaluators that are already initialized.
|
||||||
Iterator evals = getRegisteredRequestEvaluators ();
|
/* Iterator evals = getRegisteredRequestEvaluators ();
|
||||||
while (evals.hasNext ()) {
|
while (evals.hasNext ()) {
|
||||||
RequestEvaluator reval = (RequestEvaluator) evals.next ();
|
RequestEvaluator reval = (RequestEvaluator) evals.next ();
|
||||||
proto.initRequestEvaluator (reval);
|
proto.initRequestEvaluator (reval);
|
||||||
}
|
}*/
|
||||||
|
app.scriptingEngine.updatePrototype (proto);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -303,9 +304,9 @@ public class TypeManager {
|
||||||
|
|
||||||
if (!needsUpdate)
|
if (!needsUpdate)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
proto.lastUpdate = System.currentTimeMillis ();
|
proto.lastUpdate = System.currentTimeMillis ();
|
||||||
|
|
||||||
// let the thread know we had to do something.
|
// let the thread know we had to do something.
|
||||||
idleSeconds = 0;
|
idleSeconds = 0;
|
||||||
// app.logEvent ("TypeManager: Updating prototypes for "+app.getName()+": "+updatables);
|
// app.logEvent ("TypeManager: Updating prototypes for "+app.getName()+": "+updatables);
|
||||||
|
@ -347,7 +348,7 @@ public class TypeManager {
|
||||||
|
|
||||||
} else if (list[i].endsWith (app.actionExtension)) {
|
} else if (list[i].endsWith (app.actionExtension)) {
|
||||||
try {
|
try {
|
||||||
Action af = new Action (tmpfile, tmpname, proto);
|
ActionFile af = new ActionFile (tmpfile, tmpname, proto);
|
||||||
proto.updatables.put (list[i], af);
|
proto.updatables.put (list[i], af);
|
||||||
proto.actions.put (tmpname, af);
|
proto.actions.put (tmpname, af);
|
||||||
} catch (Throwable x) {
|
} catch (Throwable x) {
|
||||||
|
@ -362,29 +363,29 @@ public class TypeManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
// next go through existing updatables
|
// next go through existing updatables
|
||||||
if (updatables == null)
|
if (updatables != null) {
|
||||||
return;
|
for (Iterator i = updatables.iterator(); i.hasNext(); ) {
|
||||||
for (Iterator i = updatables.iterator(); i.hasNext(); ) {
|
Updatable upd = (Updatable) i.next();
|
||||||
Updatable upd = (Updatable) i.next();
|
|
||||||
|
|
||||||
if (upd.needsUpdate ()) {
|
if (upd.needsUpdate ()) {
|
||||||
if (upd instanceof DbMapping)
|
if (upd instanceof DbMapping)
|
||||||
rewire = true;
|
rewire = true;
|
||||||
try {
|
try {
|
||||||
upd.update ();
|
upd.update ();
|
||||||
} catch (Exception x) {
|
} catch (Exception x) {
|
||||||
if (upd instanceof DbMapping)
|
if (upd instanceof DbMapping)
|
||||||
app.logEvent ("Error updating db mapping for type "+name+": "+x);
|
app.logEvent ("Error updating db mapping for type "+name+": "+x);
|
||||||
else
|
else
|
||||||
app.logEvent ("Error updating "+upd+" of prototye type "+name+": "+x);
|
app.logEvent ("Error updating "+upd+" of prototye type "+name+": "+x);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
app.scriptingEngine.updatePrototype (proto);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*public void initRequestEvaluator (RequestEvaluator reval) {
|
||||||
public void initRequestEvaluator (RequestEvaluator reval) {
|
|
||||||
if (!registeredEvaluators.contains (reval))
|
if (!registeredEvaluators.contains (reval))
|
||||||
registeredEvaluators.add (reval);
|
registeredEvaluators.add (reval);
|
||||||
for (Iterator it = prototypes.values().iterator(); it.hasNext(); ) {
|
for (Iterator it = prototypes.values().iterator(); it.hasNext(); ) {
|
||||||
|
@ -404,7 +405,7 @@ public class TypeManager {
|
||||||
|
|
||||||
public int countRegisteredRequestEvaluators () {
|
public int countRegisteredRequestEvaluators () {
|
||||||
return registeredEvaluators.size ();
|
return registeredEvaluators.size ();
|
||||||
}
|
} */
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -72,16 +72,14 @@ public class ZippedAppFile implements Updatable {
|
||||||
String name = fname.substring (0, fname.lastIndexOf ("."));
|
String name = fname.substring (0, fname.lastIndexOf ("."));
|
||||||
String content = getZipEntryContent (zip, entry);
|
String content = getZipEntryContent (zip, entry);
|
||||||
// System.err.println ("["+content+"]");
|
// System.err.println ("["+content+"]");
|
||||||
Action act = new Action (null, name, proto);
|
ActionFile act = new ActionFile (content, name, proto);
|
||||||
act.update (content);
|
|
||||||
proto.actions.put (name, act);
|
proto.actions.put (name, act);
|
||||||
}
|
}
|
||||||
else if (fname.endsWith (".hsp")) {
|
else if (fname.endsWith (".hsp")) {
|
||||||
String name = fname.substring (0, fname.lastIndexOf ("."));
|
String name = fname.substring (0, fname.lastIndexOf ("."));
|
||||||
String content = getZipEntryContent (zip, entry);
|
String content = getZipEntryContent (zip, entry);
|
||||||
// System.err.println ("["+content+"]");
|
// System.err.println ("["+content+"]");
|
||||||
Template tmp = new Template (null, name, proto);
|
Template tmp = new Template (content, name, proto);
|
||||||
tmp.update (content);
|
|
||||||
proto.templates.put (name, tmp);
|
proto.templates.put (name, tmp);
|
||||||
}
|
}
|
||||||
else if (fname.endsWith (".skin")) {
|
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.*;
|
||||||
import helma.framework.core.*;
|
import helma.framework.core.*;
|
||||||
import helma.util.Updatable;
|
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.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
@ -44,8 +41,8 @@ public class FunctionFile implements Updatable {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a function file without a file, passing the code directly. This is used for
|
* Create a function file without a file, passing the code directly. This is used for
|
||||||
* files contained in zipped applications. The whole update mechanism is bypassed
|
* files contained in zipped applications. The whole update mechanism is bypassed
|
||||||
* by immediately parsing the code.
|
* by immediately parsing the code.
|
||||||
*/
|
*/
|
||||||
public FunctionFile (String body, String name, Prototype proto) {
|
public FunctionFile (String body, String name, Prototype proto) {
|
||||||
|
@ -54,20 +51,7 @@ public class FunctionFile implements Updatable {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.file = null;
|
this.file = null;
|
||||||
this.content = body;
|
this.content = body;
|
||||||
|
update ();
|
||||||
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) {}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -75,108 +59,41 @@ public class FunctionFile implements Updatable {
|
||||||
* the file has been modified or deleted.
|
* the file has been modified or deleted.
|
||||||
*/
|
*/
|
||||||
public boolean needsUpdate () {
|
public boolean needsUpdate () {
|
||||||
return lastmod != file.lastModified ();
|
return file != null && lastmod != file.lastModified ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void update () {
|
public void update () {
|
||||||
|
|
||||||
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) {
|
if (file != null) {
|
||||||
try {
|
if (!file.exists ()) {
|
||||||
FileReader fr = new FileReader (file);
|
remove ();
|
||||||
EvaluationSource es = new FileEvaluationSource (file.getPath (), null);
|
} else {
|
||||||
updateRequestEvaluator (reval, fr, es);
|
lastmod = file.lastModified ();
|
||||||
} catch (IOException iox) {
|
// app.typemgr.readFunctionFile (file, prototype.getName ());
|
||||||
app.logEvent ("Error updating function file: "+iox);
|
// app.getScriptingEnvironment().evaluateFile (prototype, file);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
StringReader reader = new StringReader (content);
|
// app.getScriptingEnvironment().evaluateString (prototype, content);
|
||||||
StringEvaluationSource es = new StringEvaluationSource (content, null);
|
|
||||||
updateRequestEvaluator (reval, reader, es);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized void updateRequestEvaluator (RequestEvaluator reval, Reader reader, EvaluationSource source) {
|
/* public void evaluate (ScriptingEnvironment env) {
|
||||||
|
if (file != null)
|
||||||
|
env.evaluateFile (prototype, file);
|
||||||
|
else
|
||||||
|
env.evaluateString (prototype, content);
|
||||||
|
}*/
|
||||||
|
public boolean hasFile () {
|
||||||
|
return file != null;
|
||||||
|
}
|
||||||
|
|
||||||
HashMap priorProps = null;
|
public File getFile () {
|
||||||
HashSet newProps = null;
|
return file;
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
public String getContent () {
|
||||||
|
return content;
|
||||||
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) {}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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) {}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -185,10 +102,10 @@ public class FunctionFile implements Updatable {
|
||||||
prototype.updatables.remove (file.getName());
|
prototype.updatables.remove (file.getName());
|
||||||
|
|
||||||
// if we did not add anything to any evaluator, we're done
|
// 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;
|
return;
|
||||||
|
|
||||||
removeProperties (declaredProps);
|
removeProperties (declaredProps); */
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -199,7 +116,7 @@ public class FunctionFile implements Updatable {
|
||||||
void removeProperties (HashSet props) {
|
void removeProperties (HashSet props) {
|
||||||
// first loop through other function files in this prototype to make a set of properties
|
// first loop through other function files in this prototype to make a set of properties
|
||||||
// owned by other files.
|
// owned by other files.
|
||||||
HashSet otherFiles = new HashSet ();
|
/* HashSet otherFiles = new HashSet ();
|
||||||
for (Iterator it=prototype.functions.values ().iterator (); it.hasNext (); ) {
|
for (Iterator it=prototype.functions.values ().iterator (); it.hasNext (); ) {
|
||||||
FunctionFile other = (FunctionFile) it.next ();
|
FunctionFile other = (FunctionFile) it.next ();
|
||||||
if (other != this && other.declaredProps != null)
|
if (other != this && other.declaredProps != null)
|
||||||
|
@ -220,7 +137,7 @@ public class FunctionFile implements Updatable {
|
||||||
// System.err.println ("REMOVING PROP: "+fname);
|
// System.err.println ("REMOVING PROP: "+fname);
|
||||||
}
|
}
|
||||||
} catch (Exception ignore) {}
|
} catch (Exception ignore) {}
|
||||||
}
|
} */
|
||||||
}
|
}
|
||||||
|
|
||||||
public String toString () {
|
public String toString () {
|
||||||
|
@ -234,40 +151,3 @@ public class FunctionFile implements Updatable {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,13 @@
|
||||||
// ScriptingEnvironment.java
|
// ScriptingEnvironment.java
|
||||||
// Copyright (c) Hannes Wallnöfer 1998-2001
|
// Copyright (c) Hannes Wallnöfer 1998-2001
|
||||||
|
|
||||||
package helma.scripting;
|
package helma.scripting;
|
||||||
|
|
||||||
|
import helma.framework.core.Application;
|
||||||
|
import helma.framework.core.Prototype;
|
||||||
|
import helma.framework.core.RequestEvaluator;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
import java.io.File;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is the interface that must be implemented to make a scripting environment
|
* 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
|
* 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.
|
* 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,14 +9,14 @@ import java.util.Iterator;
|
||||||
import java.util.StringTokenizer;
|
import java.util.StringTokenizer;
|
||||||
import helma.framework.*;
|
import helma.framework.*;
|
||||||
import helma.framework.core.*;
|
import helma.framework.core.*;
|
||||||
import FESI.Data.*;
|
// import FESI.Data.*;
|
||||||
import FESI.Exceptions.*;
|
// import FESI.Exceptions.*;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This represents a Helma template, i.e. a file with the extension .hsp
|
* This represents a Helma template, i.e. a file with the extension .hsp
|
||||||
* (Helma server page) that contains both parts that are to be evaluated
|
* (Helma server page) that contains both parts that are to be evaluated
|
||||||
* as EcmaScript and parts that are to be delivered to the client as-is.
|
* as EcmaScript and parts that are to be delivered to the client as-is.
|
||||||
* Internally, templates are regular functions.
|
* Internally, templates are regular functions.
|
||||||
* Helma templates are callable via URL, but this is just a leftover from the
|
* Helma templates are callable via URL, but this is just a leftover from the
|
||||||
* days when there were no .hac (action) files. The recommended way
|
* days when there were no .hac (action) files. The recommended way
|
||||||
|
@ -24,18 +24,24 @@ import FESI.Exceptions.*;
|
||||||
* template files to do the formatting.
|
* 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
|
// 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) {
|
public Template (File file, String name, Prototype proto) {
|
||||||
super (file, name, 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);
|
// IServer.getLogger().log ("Reading text template " + name);
|
||||||
|
|
||||||
Vector partBuffer = new Vector ();
|
Vector partBuffer = new Vector ();
|
||||||
|
@ -99,7 +105,7 @@ public class Template extends Action {
|
||||||
// append a CRLF
|
// append a CRLF
|
||||||
newLineCount++;
|
newLineCount++;
|
||||||
templateBody.append ("\\r\\n");
|
templateBody.append ("\\r\\n");
|
||||||
} else if (!"\r".equals (nextLine)){
|
} else if (!"\r".equals (nextLine)) try {
|
||||||
StringReader lineReader = new StringReader (nextLine);
|
StringReader lineReader = new StringReader (nextLine);
|
||||||
int c = lineReader.read ();
|
int c = lineReader.read ();
|
||||||
while (c > -1) {
|
while (c > -1) {
|
||||||
|
@ -109,7 +115,7 @@ public class Template extends Action {
|
||||||
templateBody.append ((char) c);
|
templateBody.append ((char) c);
|
||||||
c = lineReader.read ();
|
c = lineReader.read ();
|
||||||
}
|
}
|
||||||
}
|
} catch (IOException srx) {}
|
||||||
|
|
||||||
nextLine = st.hasMoreTokens () ? st.nextToken () : null;
|
nextLine = st.hasMoreTokens () ? st.nextToken () : null;
|
||||||
|
|
||||||
|
@ -124,7 +130,7 @@ public class Template extends Action {
|
||||||
// append the number of lines we have "swallowed" into
|
// append the number of lines we have "swallowed" into
|
||||||
// one write statement, so error messages will *approximately*
|
// one write statement, so error messages will *approximately*
|
||||||
// give correct line numbers.
|
// give correct line numbers.
|
||||||
for (int i=0; i<newLineCount; i++) {
|
for (int i=0; i<newLineCount; i++) {
|
||||||
templateBody.append ("\r\n");
|
templateBody.append ("\r\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -137,7 +143,9 @@ public class Template extends Action {
|
||||||
}
|
}
|
||||||
// templateBody.append ("\r\nreturn null;\r\n");
|
// templateBody.append ("\r\nreturn null;\r\n");
|
||||||
|
|
||||||
functionName = name;
|
return templateBody.toString ();
|
||||||
|
|
||||||
|
/*
|
||||||
String fname = name+"_as_string";
|
String fname = name+"_as_string";
|
||||||
String body = templateBody.toString ();
|
String body = templateBody.toString ();
|
||||||
|
|
||||||
|
@ -164,14 +172,15 @@ public class Template extends Action {
|
||||||
RequestEvaluator reval = (RequestEvaluator) evals.next ();
|
RequestEvaluator reval = (RequestEvaluator) evals.next ();
|
||||||
updateRequestEvaluator (reval);
|
updateRequestEvaluator (reval);
|
||||||
} catch (Exception ignore) {}
|
} catch (Exception ignore) {}
|
||||||
}
|
} */
|
||||||
}
|
}
|
||||||
|
|
||||||
void remove () {
|
protected void remove () {
|
||||||
prototype.templates.remove (name);
|
prototype.templates.remove (name);
|
||||||
prototype.updatables.remove (file.getName());
|
if (file != null)
|
||||||
|
prototype.updatables.remove (file.getName());
|
||||||
|
|
||||||
Iterator evals = app.typemgr.getRegisteredRequestEvaluators ();
|
/* Iterator evals = app.typemgr.getRegisteredRequestEvaluators ();
|
||||||
while (evals.hasNext ()) {
|
while (evals.hasNext ()) {
|
||||||
try {
|
try {
|
||||||
RequestEvaluator reval = (RequestEvaluator) evals.next ();
|
RequestEvaluator reval = (RequestEvaluator) evals.next ();
|
||||||
|
@ -187,16 +196,16 @@ public class Template extends Action {
|
||||||
op.deleteProperty (fname, fname.hashCode());
|
op.deleteProperty (fname, fname.hashCode());
|
||||||
}
|
}
|
||||||
} catch (Exception ignore) {}
|
} catch (Exception ignore) {}
|
||||||
}
|
} */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public synchronized void updateRequestEvaluator (RequestEvaluator reval) throws EcmaScriptException {
|
/* public synchronized void updateRequestEvaluator (RequestEvaluator reval) throws EcmaScriptException {
|
||||||
if (pfunc != null)
|
if (pfunc != null)
|
||||||
pfunc.updateRequestEvaluator (reval);
|
pfunc.updateRequestEvaluator (reval);
|
||||||
if (psfunc != null)
|
if (psfunc != null)
|
||||||
psfunc.updateRequestEvaluator (reval);
|
psfunc.updateRequestEvaluator (reval);
|
||||||
}
|
} */
|
||||||
|
|
||||||
class Part {
|
class Part {
|
||||||
|
|
||||||
|
@ -224,34 +233,9 @@ public class Template extends Action {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -20,11 +20,11 @@ public class ESAppNode extends ESNode {
|
||||||
private Application app;
|
private Application app;
|
||||||
private DatePrototype createtime;
|
private DatePrototype createtime;
|
||||||
|
|
||||||
public ESAppNode (INode node, RequestEvaluator eval) throws EcmaScriptException {
|
public ESAppNode (INode node, FesiEvaluator eval) throws EcmaScriptException {
|
||||||
super (eval.esNodePrototype, eval.evaluator, node, eval);
|
super (eval.getPrototype("hopobject"), eval.getEvaluator(), node, eval);
|
||||||
app = eval.app;
|
app = eval.getApplication();
|
||||||
createtime = new DatePrototype (eval.evaluator, node.created());
|
createtime = new DatePrototype (evaluator, node.created());
|
||||||
FunctionPrototype fp = (FunctionPrototype) eval.evaluator.getFunctionPrototype();
|
FunctionPrototype fp = (FunctionPrototype) evaluator.getFunctionPrototype();
|
||||||
putHiddenProperty("getThreads", new AppCountThreads ("getThreads", evaluator, fp));
|
putHiddenProperty("getThreads", new AppCountThreads ("getThreads", evaluator, fp));
|
||||||
putHiddenProperty("getMaxThreads", new AppCountEvaluators ("getMaxThreads", evaluator, fp));
|
putHiddenProperty("getMaxThreads", new AppCountEvaluators ("getMaxThreads", evaluator, fp));
|
||||||
putHiddenProperty("getFreeThreads", new AppCountFreeEvaluators ("getFreeThreads", 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 {
|
public class ESMapWrapper extends ESWrapper {
|
||||||
|
|
||||||
private Map data;
|
private Map data;
|
||||||
private RequestEvaluator reval;
|
private FesiEvaluator fesi;
|
||||||
|
|
||||||
public ESMapWrapper (RequestEvaluator reval) {
|
public ESMapWrapper (FesiEvaluator fesi) {
|
||||||
super (new Object(), reval.evaluator);
|
super (new Object(), fesi.getEvaluator ());
|
||||||
this.reval = reval;
|
this.fesi = fesi;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ESMapWrapper (RequestEvaluator reval, Map data) {
|
public ESMapWrapper (FesiEvaluator fesi, Map data) {
|
||||||
super (new Object(), reval.evaluator);
|
super (new Object(), fesi.getEvaluator ());
|
||||||
this.reval = reval;
|
this.fesi = fesi;
|
||||||
this.data = data;
|
this.data = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -63,7 +63,7 @@ public class ESMapWrapper extends ESWrapper {
|
||||||
if (val instanceof String)
|
if (val instanceof String)
|
||||||
return new ESString ((String) val);
|
return new ESString ((String) val);
|
||||||
else if (val instanceof INode)
|
else if (val instanceof INode)
|
||||||
return reval.getNodeWrapper ((INode) val);
|
return fesi.getNodeWrapper ((INode) val);
|
||||||
else if (val instanceof ESValue)
|
else if (val instanceof ESValue)
|
||||||
return (ESValue) val;
|
return (ESValue) val;
|
||||||
return ESLoader.normalizeValue(val, evaluator);
|
return ESLoader.normalizeValue(val, evaluator);
|
||||||
|
|
|
@ -35,23 +35,23 @@ public class ESNode extends ObjectPrototype {
|
||||||
NodeHandle handle;
|
NodeHandle handle;
|
||||||
DbMapping dbmap;
|
DbMapping dbmap;
|
||||||
Throwable lastError = null;
|
Throwable lastError = null;
|
||||||
RequestEvaluator eval;
|
FesiEvaluator eval;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor used to create transient cache nodes
|
* Constructor used to create transient cache nodes
|
||||||
*/
|
*/
|
||||||
public ESNode (INode node, RequestEvaluator eval) {
|
public ESNode (INode node, FesiEvaluator eval) {
|
||||||
super (eval.esNodePrototype, eval.evaluator);
|
super (eval.getPrototype("hopobject"), eval.getEvaluator());
|
||||||
this.eval = eval;
|
this.eval = eval;
|
||||||
this.node = node;
|
this.node = node;
|
||||||
cache = null;
|
cache = null;
|
||||||
cacheWrapper = null;
|
cacheWrapper = null;
|
||||||
|
|
||||||
// this is a transient node, set node handle to null
|
// this is a transient node, set node handle to null
|
||||||
handle = null;
|
handle = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ESNode (ESObject prototype, Evaluator evaluator, Object obj, RequestEvaluator eval) {
|
public ESNode (ESObject prototype, Evaluator evaluator, Object obj, FesiEvaluator eval) {
|
||||||
super (prototype, evaluator);
|
super (prototype, evaluator);
|
||||||
// eval.app.logEvent ("in ESNode constructor: "+o.getClass ());
|
// eval.app.logEvent ("in ESNode constructor: "+o.getClass ());
|
||||||
this.eval = eval;
|
this.eval = eval;
|
||||||
|
|
|
@ -27,8 +27,8 @@ public class ESUser extends ESNode {
|
||||||
/** if the user is online, this is his/her online session object */
|
/** if the user is online, this is his/her online session object */
|
||||||
public User user;
|
public User user;
|
||||||
|
|
||||||
public ESUser (INode node, RequestEvaluator eval, User user) {
|
public ESUser (INode node, FesiEvaluator eval, User user) {
|
||||||
super (eval.esUserPrototype, eval.evaluator, node, eval);
|
super (eval.getPrototype("user"), eval.getEvaluator(), node, eval);
|
||||||
this.user = user;
|
this.user = user;
|
||||||
if (user != null) {
|
if (user != null) {
|
||||||
cache = user.getCache ();
|
cache = user.getCache ();
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
// Action.java
|
// ActionFile.java
|
||||||
// Copyright (c) Hannes Wallnöfer 1998-2000
|
// Copyright (c) Hannes Wallnöfer 1998-2000
|
||||||
|
|
||||||
package helma.scripting;
|
package helma.scripting.fesi;
|
||||||
|
|
||||||
|
import helma.scripting.*;
|
||||||
import java.util.Vector;
|
import java.util.Vector;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
|
@ -20,90 +21,46 @@ import FESI.Exceptions.*;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An Action is a JavaScript function that is exposed as a URI. It is
|
* An class that updates fesi interpreters with actionfiles and templates.
|
||||||
* usually represented by a file with extension .hac (hop action file)
|
|
||||||
* that contains the pure JavaScript body of the function.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
public class Action implements Updatable {
|
public class FesiActionAdapter {
|
||||||
|
|
||||||
String name;
|
|
||||||
String functionName;
|
|
||||||
Prototype prototype;
|
Prototype prototype;
|
||||||
Application app;
|
Application app;
|
||||||
File file;
|
String sourceName;
|
||||||
long lastmod;
|
|
||||||
|
|
||||||
// this is the parsed function which can be easily applied to RequestEvaluator objects
|
// this is the parsed function which can be easily applied to RequestEvaluator objects
|
||||||
TypeUpdater pfunc;
|
TypeUpdater pfunc;
|
||||||
|
|
||||||
|
public FesiActionAdapter (ActionFile action) {
|
||||||
public Action (File file, String name, Prototype proto) {
|
prototype = action.getPrototype ();
|
||||||
this.prototype = proto;
|
app = action.getApplication ();
|
||||||
this.app = proto.getApplication ();
|
String content = action.getContent ();
|
||||||
this.name = name;
|
String functionName = action.getFunctionName ();
|
||||||
this.file = file;
|
sourceName = action.toString ();
|
||||||
if (file != null)
|
try {
|
||||||
update ();
|
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);
|
||||||
* 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 ();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* protected void update (FesiEvaluator fesi) throws Exception {
|
||||||
public void update (String content) throws Exception {
|
|
||||||
// app.logEvent ("Reading text template " + name);
|
// app.logEvent ("Reading text template " + name);
|
||||||
|
|
||||||
functionName = name+"_action";
|
FesiScriptingEnvironment scriptEnv = (FesiScriptingEnvironment) app.getScriptingEnvironment ();
|
||||||
|
Iterator evals = scriptEnv.getEvaluators().iterator();
|
||||||
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 ();
|
|
||||||
while (evals.hasNext ()) {
|
while (evals.hasNext ()) {
|
||||||
try {
|
try {
|
||||||
RequestEvaluator reval = (RequestEvaluator) evals.next ();
|
FesiEvaluator fesi = (FesiEvaluator) evals.next ();
|
||||||
updateRequestEvaluator (reval);
|
updateEvaluator (fesi);
|
||||||
} catch (Exception ignore) {}
|
} catch (Exception ignore) {}
|
||||||
}
|
}
|
||||||
}
|
} */
|
||||||
|
|
||||||
void remove () {
|
|
||||||
prototype.actions.remove (name);
|
|
||||||
prototype.updatables.remove (file.getName());
|
|
||||||
|
|
||||||
|
/* protected void remove () {
|
||||||
Iterator evals = app.typemgr.getRegisteredRequestEvaluators ();
|
Iterator evals = app.typemgr.getRegisteredRequestEvaluators ();
|
||||||
while (evals.hasNext ()) {
|
while (evals.hasNext ()) {
|
||||||
try {
|
try {
|
||||||
|
@ -116,23 +73,12 @@ public class Action implements Updatable {
|
||||||
}
|
}
|
||||||
} catch (Exception ignore) {}
|
} catch (Exception ignore) {}
|
||||||
}
|
}
|
||||||
}
|
} */
|
||||||
|
|
||||||
public String getName () {
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getFunctionName () {
|
public synchronized void updateEvaluator (FesiEvaluator fesi) throws EcmaScriptException {
|
||||||
return functionName;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String toString () {
|
|
||||||
return prototype.getName()+"/"+file.getName();
|
|
||||||
}
|
|
||||||
|
|
||||||
public synchronized void updateRequestEvaluator (RequestEvaluator reval) throws EcmaScriptException {
|
|
||||||
if (pfunc != null)
|
if (pfunc != null)
|
||||||
pfunc.updateRequestEvaluator (reval);
|
pfunc.updateEvaluator (fesi);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected TypeUpdater parseFunction (String funcname, String params, String body) throws EcmaScriptException {
|
protected TypeUpdater parseFunction (String funcname, String params, String body) throws EcmaScriptException {
|
||||||
|
@ -176,10 +122,10 @@ public class Action implements Updatable {
|
||||||
sl = (ASTStatementList) parser.StatementList();
|
sl = (ASTStatementList) parser.StatementList();
|
||||||
is.close();
|
is.close();
|
||||||
} catch (ParseException x) {
|
} 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));
|
throw new EcmaScriptParseException (x, new StringEvaluationSource(fulltext, null));
|
||||||
} catch (Exception x) {
|
} 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 ());
|
throw new RuntimeException (x.getMessage ());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -204,15 +150,15 @@ public class Action implements Updatable {
|
||||||
this.functionName = functionName;
|
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);
|
Vector vnames = vdvisitor.processVariableDeclarations(sl, fes);
|
||||||
|
|
||||||
FunctionPrototype fp = ConstructedFunctionObject.makeNewConstructedFunction (
|
FunctionPrototype fp = ConstructedFunctionObject.makeNewConstructedFunction (
|
||||||
reval.evaluator, functionName, fes,
|
fesi.evaluator, functionName, fes,
|
||||||
fullFunctionText, fpl.getArguments(), vnames, sl);
|
fullFunctionText, fpl.getArguments(), vnames, sl);
|
||||||
op.putHiddenProperty (functionName, fp);
|
op.putHiddenProperty (functionName, fp);
|
||||||
}
|
}
|
||||||
|
@ -228,12 +174,12 @@ public class Action implements Updatable {
|
||||||
errorMessage = msg;
|
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 fp = (FunctionPrototype) fesi.evaluator.getFunctionPrototype ();
|
||||||
FunctionPrototype func = new ThrowException (functionName, reval.evaluator, fp, errorMessage);
|
FunctionPrototype func = new ThrowException (functionName, fesi.evaluator, fp, errorMessage);
|
||||||
op.putHiddenProperty (functionName, func);
|
op.putHiddenProperty (functionName, func);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -254,38 +200,8 @@ public class Action implements Updatable {
|
||||||
}
|
}
|
||||||
|
|
||||||
interface TypeUpdater {
|
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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -17,29 +17,28 @@ import java.util.*;
|
||||||
import java.text.*;
|
import java.text.*;
|
||||||
import org.xml.sax.InputSource;
|
import org.xml.sax.InputSource;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is the basic Extension for FESI interpreters used in HOP. It sets up
|
* This is the basic Extension for FESI interpreters used in Helma. It sets up
|
||||||
* varios constructors, global functions and properties etc.
|
* varios constructors, global functions and properties on the HopObject prototype
|
||||||
|
* (Node objects), the user prototype, the global prototype etc.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class HopExtension {
|
public class HopExtension {
|
||||||
|
|
||||||
protected Application app;
|
protected Application app;
|
||||||
protected RequestEvaluator reval;
|
protected FesiEvaluator fesi;
|
||||||
|
|
||||||
public HopExtension () {
|
public HopExtension (Application app) {
|
||||||
super();
|
this.app = app;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called by the evaluator after the extension is loaded.
|
* Called by the evaluator after the extension is loaded.
|
||||||
*/
|
*/
|
||||||
public void initializeExtension (RequestEvaluator reval) throws EcmaScriptException {
|
public void initializeExtension (FesiEvaluator fesi) throws EcmaScriptException {
|
||||||
|
this.fesi = fesi;
|
||||||
this.reval = reval;
|
Evaluator evaluator = fesi.getEvaluator ();
|
||||||
this.app = reval.app;
|
|
||||||
Evaluator evaluator = reval.evaluator;
|
|
||||||
GlobalObject go = evaluator.getGlobalObject();
|
GlobalObject go = evaluator.getGlobalObject();
|
||||||
FunctionPrototype fp = (FunctionPrototype) evaluator.getFunctionPrototype();
|
FunctionPrototype fp = (FunctionPrototype) evaluator.getFunctionPrototype();
|
||||||
|
|
||||||
|
@ -56,42 +55,42 @@ public class HopExtension {
|
||||||
ESObject dp = evaluator.getDatePrototype ();
|
ESObject dp = evaluator.getDatePrototype ();
|
||||||
dp.putHiddenProperty ("format", new DatePrototypeFormat ("format", evaluator, fp));
|
dp.putHiddenProperty ("format", new DatePrototypeFormat ("format", evaluator, fp));
|
||||||
|
|
||||||
sp.putHiddenProperty ("trim", new StringTrim ("trim", evaluator, fp));
|
sp.putHiddenProperty ("trim", new StringTrim ("trim", evaluator, fp));
|
||||||
|
|
||||||
// generic (Java wrapper) object prototype
|
// generic (Java wrapper) object prototype
|
||||||
reval.esObjectPrototype = new ObjectPrototype (op, evaluator);
|
ObjectPrototype esObjectPrototype = new ObjectPrototype (op, evaluator);
|
||||||
// the Node prototype
|
// the Node prototype
|
||||||
reval.esNodePrototype = new ObjectPrototype(op, evaluator);
|
ObjectPrototype esNodePrototype = new ObjectPrototype(op, evaluator);
|
||||||
// the User prototype
|
// the User prototype
|
||||||
reval.esUserPrototype = new ObjectPrototype (reval.esNodePrototype, evaluator);
|
ObjectPrototype esUserPrototype = new ObjectPrototype (esNodePrototype, evaluator);
|
||||||
// the Node constructor
|
// 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
|
// register the default methods of Node objects in the Node prototype
|
||||||
reval.esNodePrototype.putHiddenProperty ("add", new NodeAdd ("add", evaluator, fp));
|
esNodePrototype.putHiddenProperty ("add", new NodeAdd ("add", evaluator, fp));
|
||||||
reval.esNodePrototype.putHiddenProperty ("addAt", new NodeAddAt ("addAt", evaluator, fp));
|
esNodePrototype.putHiddenProperty ("addAt", new NodeAddAt ("addAt", evaluator, fp));
|
||||||
reval.esNodePrototype.putHiddenProperty ("remove", new NodeRemove ("remove", evaluator, fp));
|
esNodePrototype.putHiddenProperty ("remove", new NodeRemove ("remove", evaluator, fp));
|
||||||
reval.esNodePrototype.putHiddenProperty ("link", new NodeLink ("link", evaluator, fp));
|
esNodePrototype.putHiddenProperty ("link", new NodeLink ("link", evaluator, fp));
|
||||||
reval.esNodePrototype.putHiddenProperty ("list", new NodeList ("list", evaluator, fp));
|
esNodePrototype.putHiddenProperty ("list", new NodeList ("list", evaluator, fp));
|
||||||
reval.esNodePrototype.putHiddenProperty ("set", new NodeSet ("set", evaluator, fp));
|
esNodePrototype.putHiddenProperty ("set", new NodeSet ("set", evaluator, fp));
|
||||||
reval.esNodePrototype.putHiddenProperty ("get", new NodeGet ("get", evaluator, fp));
|
esNodePrototype.putHiddenProperty ("get", new NodeGet ("get", evaluator, fp));
|
||||||
reval.esNodePrototype.putHiddenProperty ("count", new NodeCount ("count", evaluator, fp));
|
esNodePrototype.putHiddenProperty ("count", new NodeCount ("count", evaluator, fp));
|
||||||
reval.esNodePrototype.putHiddenProperty ("contains", new NodeContains ("contains", evaluator, fp));
|
esNodePrototype.putHiddenProperty ("contains", new NodeContains ("contains", evaluator, fp));
|
||||||
reval.esNodePrototype.putHiddenProperty ("size", new NodeCount ("size", evaluator, fp));
|
esNodePrototype.putHiddenProperty ("size", new NodeCount ("size", evaluator, fp));
|
||||||
reval.esNodePrototype.putHiddenProperty ("editor", new NodeEditor ("editor", evaluator, fp));
|
esNodePrototype.putHiddenProperty ("editor", new NodeEditor ("editor", evaluator, fp));
|
||||||
reval.esNodePrototype.putHiddenProperty ("path", new NodeHref ("path", evaluator, fp));
|
esNodePrototype.putHiddenProperty ("path", new NodeHref ("path", evaluator, fp));
|
||||||
reval.esNodePrototype.putHiddenProperty ("href", new NodeHref ("href", evaluator, fp));
|
esNodePrototype.putHiddenProperty ("href", new NodeHref ("href", evaluator, fp));
|
||||||
reval.esNodePrototype.putHiddenProperty ("setParent", new NodeSetParent ("setParent", evaluator, fp));
|
esNodePrototype.putHiddenProperty ("setParent", new NodeSetParent ("setParent", evaluator, fp));
|
||||||
reval.esNodePrototype.putHiddenProperty ("invalidate", new NodeInvalidate ("invalidate", evaluator, fp));
|
esNodePrototype.putHiddenProperty ("invalidate", new NodeInvalidate ("invalidate", evaluator, fp));
|
||||||
reval.esNodePrototype.putHiddenProperty ("renderSkin", new RenderSkin ("renderSkin", evaluator, fp, false, false));
|
esNodePrototype.putHiddenProperty ("renderSkin", new RenderSkin ("renderSkin", evaluator, fp, false, false));
|
||||||
reval.esNodePrototype.putHiddenProperty ("renderSkinAsString", new RenderSkin ("renderSkinAsString", evaluator, fp, false, true));
|
esNodePrototype.putHiddenProperty ("renderSkinAsString", new RenderSkin ("renderSkinAsString", evaluator, fp, false, true));
|
||||||
reval.esNodePrototype.putHiddenProperty ("clearCache", new NodeClearCache ("clearCache", evaluator, fp));
|
esNodePrototype.putHiddenProperty ("clearCache", new NodeClearCache ("clearCache", evaluator, fp));
|
||||||
|
|
||||||
// default methods for generic Java wrapper object prototype.
|
// default methods for generic Java wrapper object prototype.
|
||||||
// This is a small subset of the methods in esNodePrototype.
|
// This is a small subset of the methods in esNodePrototype.
|
||||||
reval.esObjectPrototype.putHiddenProperty ("href", new NodeHref ("href", evaluator, fp));
|
esObjectPrototype.putHiddenProperty ("href", new NodeHref ("href", evaluator, fp));
|
||||||
reval.esObjectPrototype.putHiddenProperty("renderSkin", new RenderSkin ("renderSkin", evaluator, fp, false, false));
|
esObjectPrototype.putHiddenProperty("renderSkin", new RenderSkin ("renderSkin", evaluator, fp, false, false));
|
||||||
reval.esObjectPrototype.putHiddenProperty("renderSkinAsString", new RenderSkin ("renderSkinAsString", evaluator, fp, false, true));
|
esObjectPrototype.putHiddenProperty("renderSkinAsString", new RenderSkin ("renderSkinAsString", evaluator, fp, false, true));
|
||||||
|
|
||||||
// methods that give access to properties and global user lists
|
// methods that give access to properties and global user lists
|
||||||
go.putHiddenProperty("Node", node); // register the constructor for a plain Node object.
|
go.putHiddenProperty("Node", node); // register the constructor for a plain Node object.
|
||||||
|
@ -122,14 +121,19 @@ public class HopExtension {
|
||||||
go.deleteProperty("exit", "exit".hashCode());
|
go.deleteProperty("exit", "exit".hashCode());
|
||||||
|
|
||||||
// and some methods for session management from JS...
|
// and some methods for session management from JS...
|
||||||
reval.esUserPrototype.putHiddenProperty("logon", new UserLogin ("logon", evaluator, fp));
|
esUserPrototype.putHiddenProperty("logon", new UserLogin ("logon", evaluator, fp));
|
||||||
reval.esUserPrototype.putHiddenProperty("login", new UserLogin ("login", evaluator, fp));
|
esUserPrototype.putHiddenProperty("login", new UserLogin ("login", evaluator, fp));
|
||||||
reval.esUserPrototype.putHiddenProperty("register", new UserRegister ("register", evaluator, fp));
|
esUserPrototype.putHiddenProperty("register", new UserRegister ("register", evaluator, fp));
|
||||||
reval.esUserPrototype.putHiddenProperty("logout", new UserLogout ("logout", evaluator, fp));
|
esUserPrototype.putHiddenProperty("logout", new UserLogout ("logout", evaluator, fp));
|
||||||
reval.esUserPrototype.putHiddenProperty("onSince", new UserOnSince ("onSince", evaluator, fp));
|
esUserPrototype.putHiddenProperty("onSince", new UserOnSince ("onSince", evaluator, fp));
|
||||||
reval.esUserPrototype.putHiddenProperty("lastActive", new UserLastActive ("lastActive", evaluator, fp));
|
esUserPrototype.putHiddenProperty("lastActive", new UserLastActive ("lastActive", evaluator, fp));
|
||||||
reval.esUserPrototype.putHiddenProperty("touch", new UserTouch ("touch", 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 {
|
class NodeAdd extends BuiltinFunctionObject {
|
||||||
|
@ -437,7 +441,7 @@ public class HopExtension {
|
||||||
if (unode == null)
|
if (unode == null)
|
||||||
return ESNull.theNull;
|
return ESNull.theNull;
|
||||||
else
|
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 {
|
public ESValue callFunction (ESObject thisObj, ESValue[] arguments) throws EcmaScriptException {
|
||||||
if (arguments.length < 1 || arguments.length > 2 || arguments[0] ==null || arguments[0] == ESNull.theNull)
|
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 {
|
try {
|
||||||
Skin skin = null;
|
Skin skin = null;
|
||||||
ESObject thisObject = global ? null : thisObj;
|
ESObject thisObject = global ? null : thisObj;
|
||||||
HashMap params = null;
|
HashMap params = null;
|
||||||
if (arguments.length > 1 && arguments[1] instanceof ESObject) {
|
if (arguments.length > 1 && arguments[1] instanceof ESObject) {
|
||||||
|
// create an parameter object to pass to the skin
|
||||||
ESObject paramObject = (ESObject) arguments[1];
|
ESObject paramObject = (ESObject) arguments[1];
|
||||||
params = new HashMap ();
|
params = new HashMap ();
|
||||||
for (Enumeration en=paramObject.getProperties(); en.hasMoreElements(); ) {
|
for (Enumeration en=paramObject.getProperties(); en.hasMoreElements(); ) {
|
||||||
|
@ -573,17 +578,29 @@ public class HopExtension {
|
||||||
skin = (Skin) obj;
|
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)
|
if (skin == null)
|
||||||
skin = reval.getSkin (thisObject, arguments[0].toString ());
|
skin = app.getSkin (javaObject, arguments[0].toString (), skinpath);
|
||||||
if (asString)
|
if (asString)
|
||||||
reval.res.pushStringBuffer ();
|
res.pushStringBuffer ();
|
||||||
Object javaObj = thisObject == null ? null : thisObject.toJavaObject ();
|
|
||||||
if (skin != null)
|
if (skin != null)
|
||||||
skin.render (reval, javaObj, params);
|
skin.render (fesi.getRequestEvaluator(), javaObject, params);
|
||||||
else
|
else
|
||||||
reval.res.write ("[Skin not found: "+arguments[0]+"]");
|
res.write ("[Skin not found: "+arguments[0]+"]");
|
||||||
if (asString)
|
if (asString)
|
||||||
return new ESString (reval.res.popStringBuffer ());
|
return new ESString (res.popStringBuffer ());
|
||||||
} catch (RedirectException redir) {
|
} catch (RedirectException redir) {
|
||||||
// let redirect pass through
|
// let redirect pass through
|
||||||
throw redir;
|
throw redir;
|
||||||
|
@ -602,14 +619,14 @@ public class HopExtension {
|
||||||
super (fp, evaluator, name, 1);
|
super (fp, evaluator, name, 1);
|
||||||
}
|
}
|
||||||
public ESValue callFunction (ESObject thisObject, ESValue[] arguments) throws EcmaScriptException {
|
public ESValue callFunction (ESObject thisObject, ESValue[] arguments) throws EcmaScriptException {
|
||||||
INode user = null;
|
INode user = null;
|
||||||
if (arguments.length > 0) {
|
if (arguments.length > 0) {
|
||||||
String uname = arguments[0].toString ().trim ();
|
String uname = arguments[0].toString ().trim ();
|
||||||
user = app.getUserNode (uname);
|
user = app.getUserNode (uname);
|
||||||
}
|
}
|
||||||
if (user == null)
|
if (user == null)
|
||||||
return ESNull.theNull;
|
return ESNull.theNull;
|
||||||
return reval.getNodeWrapper (user);
|
return fesi.getNodeWrapper (user);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -618,15 +635,15 @@ public class HopExtension {
|
||||||
super (fp, evaluator, name, 1);
|
super (fp, evaluator, name, 1);
|
||||||
}
|
}
|
||||||
public ESValue callFunction (ESObject thisObject, ESValue[] arguments) throws EcmaScriptException {
|
public ESValue callFunction (ESObject thisObject, ESValue[] arguments) throws EcmaScriptException {
|
||||||
User user = null;
|
User user = null;
|
||||||
if (arguments.length > 0) {
|
if (arguments.length > 0) {
|
||||||
String sid = arguments[0].toString ().trim ();
|
String sid = arguments[0].toString ().trim ();
|
||||||
user = app.getUser (sid);
|
user = app.getUser (sid);
|
||||||
}
|
}
|
||||||
if (user == null || user.getUID() == null)
|
if (user == null || user.getUID() == null)
|
||||||
return ESNull.theNull;
|
return ESNull.theNull;
|
||||||
user.touch ();
|
user.touch ();
|
||||||
return reval.getNodeWrapper (user.getNode ());
|
return fesi.getNodeWrapper (user.getNode ());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -663,7 +680,7 @@ public class HopExtension {
|
||||||
User u = (User) e.nextElement ();
|
User u = (User) e.nextElement ();
|
||||||
// Note: we previously sorted out duplicate users - now we simply enumerate all active sessions.
|
// Note: we previously sorted out duplicate users - now we simply enumerate all active sessions.
|
||||||
// if (u.uid == null || !visited.containsKey (u.uid)) {
|
// 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);
|
// 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 {
|
class NodeSetParent extends BuiltinFunctionObject {
|
||||||
NodeSetParent (String name, Evaluator evaluator, FunctionPrototype fp) {
|
NodeSetParent (String name, Evaluator evaluator, FunctionPrototype fp) {
|
||||||
super (fp, evaluator, name, 2);
|
super (fp, evaluator, name, 2);
|
||||||
|
@ -964,11 +969,11 @@ public class HopExtension {
|
||||||
return new ESString (basicHref);
|
return new ESString (basicHref);
|
||||||
}
|
}
|
||||||
private ESString renderSkin (Skin skin, String path, Object skinElem) throws EcmaScriptException {
|
private ESString renderSkin (Skin skin, String path, Object skinElem) throws EcmaScriptException {
|
||||||
reval.res.pushStringBuffer ();
|
fesi.getResponse().pushStringBuffer ();
|
||||||
HashMap param = new HashMap ();
|
HashMap param = new HashMap ();
|
||||||
param.put ("path", path);
|
param.put ("path", path);
|
||||||
skin.render (reval, skinElem, param);
|
skin.render (fesi.getRequestEvaluator(), skinElem, param);
|
||||||
return new ESString (reval.res.popStringBuffer ().trim ());
|
return new ESString (fesi.getResponse().popStringBuffer ().trim ());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -985,7 +990,7 @@ public class HopExtension {
|
||||||
double d = from <= to ? 1.0 : -1.0;
|
double d = from <= to ? 1.0 : -1.0;
|
||||||
for (double i=from; i*d<=to*d; i+=step) {
|
for (double i=from; i*d<=to*d; i+=step) {
|
||||||
if (Math.abs (i%1) < l) {
|
if (Math.abs (i%1) < l) {
|
||||||
int j = (int) i;
|
int j = (int) i;
|
||||||
b.append ("<option value=\""+j);
|
b.append ("<option value=\""+j);
|
||||||
if (i == value) b.append ("\" selected=\"true");
|
if (i == value) b.append ("\" selected=\"true");
|
||||||
b.append ("\">"+j);
|
b.append ("\">"+j);
|
||||||
|
@ -998,165 +1003,7 @@ public class HopExtension {
|
||||||
b.append ("</select>");
|
b.append ("</select>");
|
||||||
return b.toString ();
|
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 ();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -15,14 +15,14 @@ import FESI.Interpreter.*;
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class NodeConstructor extends BuiltinFunctionObject {
|
public class NodeConstructor extends BuiltinFunctionObject {
|
||||||
|
|
||||||
RequestEvaluator reval;
|
FesiEvaluator fesi;
|
||||||
String typename;
|
String typename;
|
||||||
|
|
||||||
public NodeConstructor (String name, FunctionPrototype fp, RequestEvaluator reval) {
|
public NodeConstructor (String name, FunctionPrototype fp, FesiEvaluator fesi) {
|
||||||
super(fp, reval.evaluator, name, 1);
|
super(fp, fesi.getEvaluator (), name, 1);
|
||||||
typename = name;
|
typename = name;
|
||||||
this.reval = reval;
|
this.fesi = fesi;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ESValue callFunction(ESObject thisObject, ESValue[] arguments) throws EcmaScriptException {
|
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 {
|
public ESObject doConstruct(ESObject thisObject, ESValue[] arguments) throws EcmaScriptException {
|
||||||
ESNode node = null;
|
ESNode node = null;
|
||||||
|
Application app = fesi.getApplication ();
|
||||||
if ("Node".equals (typename) || "hopobject".equalsIgnoreCase (typename)) {
|
if ("Node".equals (typename) || "hopobject".equalsIgnoreCase (typename)) {
|
||||||
if (arguments.length == 0) {
|
String nodeName = null;
|
||||||
Node n = new Node ((String) null, (String) null, reval.app.getWrappedNodeManager ());
|
if (arguments.length > 0 && arguments[0] != null)
|
||||||
node = new ESNode (reval.esNodePrototype, this.evaluator, n, reval);
|
nodeName = arguments[0].toString();
|
||||||
reval.objectcache.put (node.getNode (), node);
|
Node n = new Node (nodeName, (String) null, app.getWrappedNodeManager ());
|
||||||
} else {
|
node = new ESNode (fesi.getPrototype ("hopobject"), this.evaluator, n, fesi);
|
||||||
Node n = new Node (arguments[0].toString(), (String) null, reval.app.getWrappedNodeManager ());
|
fesi.putNodeWrapper (node.getNode (), node);
|
||||||
node = new ESNode (reval.esNodePrototype, this.evaluator, n, reval);
|
|
||||||
reval.objectcache.put (node.getNode (), node);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
// Typed nodes are instantiated as helma.objectmodel.db.Node from the beginning
|
// 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
|
// 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
|
// is that we want to be able to use the specail features like subnode relations even for
|
||||||
// transient nodes.
|
// transient nodes.
|
||||||
ObjectPrototype op = reval.getPrototype (typename);
|
ObjectPrototype op = fesi.getPrototype (typename);
|
||||||
Node n = new Node (typename, typename, reval.app.getWrappedNodeManager ());
|
Node n = new Node (typename, typename, app.getWrappedNodeManager ());
|
||||||
node = new ESNode (op, reval.evaluator, n, reval);
|
node = new ESNode (op, fesi.getEvaluator (), n, fesi);
|
||||||
node.setPrototype (typename);
|
node.setPrototype (typename);
|
||||||
node.getNode ().setDbMapping (reval.app.getDbMapping (typename));
|
node.getNode ().setDbMapping (app.getDbMapping (typename));
|
||||||
try {
|
try {
|
||||||
// first try calling "constructor", if that doesn't work, try calling a function
|
// first try calling "constructor", if that doesn't work, try calling a function
|
||||||
// with the name of the type.
|
// with the name of the type.
|
||||||
// HACK: There is an incompatibility problem here, because the property
|
// HACK: There is an incompatibility problem here, because the property
|
||||||
// constructor is defined as the constructor of the object by EcmaScript.
|
// constructor is defined as the constructor of the object by EcmaScript.
|
||||||
if (op.getProperty("constructor", "constructor".hashCode()) instanceof ConstructedFunctionObject)
|
if (op.getProperty ("constructor", "constructor".hashCode()) instanceof ConstructedFunctionObject)
|
||||||
node.doIndirectCall (reval.evaluator, node, "constructor", arguments);
|
node.doIndirectCall (fesi.getEvaluator(), node, "constructor", arguments);
|
||||||
else
|
else
|
||||||
node.doIndirectCall (reval.evaluator, node, typename, arguments);
|
node.doIndirectCall (fesi.getEvaluator(), node, typename, arguments);
|
||||||
} catch (Exception ignore) {}
|
} catch (Exception ignore) {}
|
||||||
}
|
}
|
||||||
return node;
|
return node;
|
||||||
|
@ -70,9 +68,9 @@ public class NodeConstructor extends BuiltinFunctionObject {
|
||||||
}
|
}
|
||||||
|
|
||||||
public ESValue getProperty(String propertyName, int hash) throws EcmaScriptException {
|
public ESValue getProperty(String propertyName, int hash) throws EcmaScriptException {
|
||||||
if ("prototype".equals (propertyName))
|
if ("prototype".equals (propertyName))
|
||||||
return reval.getPrototype (typename);
|
return fesi.getPrototype (typename);
|
||||||
return super.getProperty(propertyName, hash);
|
return super.getProperty(propertyName, hash);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String[] getSpecialPropertyNames() {
|
public String[] getSpecialPropertyNames() {
|
||||||
|
|
Loading…
Add table
Reference in a new issue