Adapted to other classes moving to the helma.scripting packages

This commit is contained in:
hns 2001-08-29 18:04:30 +00:00
parent 6353177656
commit dd3cbc45e9
6 changed files with 172 additions and 86 deletions

View file

@ -8,6 +8,7 @@ import java.lang.reflect.*;
import java.rmi.*; import java.rmi.*;
import java.rmi.server.*; import java.rmi.server.*;
import helma.framework.*; import helma.framework.*;
import helma.scripting.fesi.*;
import helma.objectmodel.*; import helma.objectmodel.*;
import helma.objectmodel.db.*; import helma.objectmodel.db.*;
import helma.xmlrpc.*; import helma.xmlrpc.*;
@ -34,7 +35,7 @@ public class Application extends UnicastRemoteObject implements IRemoteApp, IRep
private String baseURI; private String baseURI;
TypeManager typemgr; public TypeManager typemgr;
RequestEvaluator eval; RequestEvaluator eval;
protected Stack freeThreads; protected Stack freeThreads;
@ -43,8 +44,8 @@ public class Application extends UnicastRemoteObject implements IRemoteApp, IRep
boolean stopped = false; boolean stopped = false;
boolean debug; boolean debug;
Hashtable sessions; public Hashtable sessions;
Hashtable activeUsers; public Hashtable activeUsers;
Hashtable dbMappings; Hashtable dbMappings;
Hashtable dbSources; Hashtable dbSources;
@ -181,8 +182,8 @@ public class Application extends UnicastRemoteObject implements IRemoteApp, IRep
activeRequests = new Hashtable (); activeRequests = new Hashtable ();
typemgr = new TypeManager (this); typemgr = new TypeManager (this);
typemgr.check (); typemgr.createPrototypes ();
logEvent ("Started type manager for "+name); // logEvent ("Started type manager for "+name);
rootMapping = getDbMapping ("root"); rootMapping = getDbMapping ("root");
userMapping = getDbMapping ("user"); userMapping = getDbMapping ("user");
@ -196,16 +197,16 @@ public class Application extends UnicastRemoteObject implements IRemoteApp, IRep
nmgr = new NodeManager (this, dbDir.getAbsolutePath (), props); nmgr = new NodeManager (this, dbDir.getAbsolutePath (), props);
worker = new Thread (this, "Worker-"+name); // worker = new Thread (this, "Worker-"+name);
worker.setPriority (Thread.NORM_PRIORITY+2); // worker.setPriority (Thread.NORM_PRIORITY+2);
worker.start (); // worker.start ();
// logEvent ("session cleanup and scheduler thread started"); // logEvent ("session cleanup and scheduler thread started");
String xmlrpcHandlerName = props.getProperty ("xmlrpcHandlerName", this.name); String xmlrpcHandlerName = props.getProperty ("xmlrpcHandlerName", this.name);
if (xmlrpc != null) if (xmlrpc != null)
xmlrpc.addHandler (xmlrpcHandlerName, new XmlRpcInvoker (this)); xmlrpc.addHandler (xmlrpcHandlerName, new XmlRpcInvoker (this));
typemgr.start (); // typemgr.start ();
} }
@ -264,7 +265,7 @@ public class Application extends UnicastRemoteObject implements IRemoteApp, IRep
* This can be used to set the maximum number of evaluators which will be allocated. * This can be used to set the maximum number of evaluators which will be allocated.
* If evaluators are required beyound this number, an error will be thrown. * If evaluators are required beyound this number, an error will be thrown.
*/ */
protected boolean setNumberOfEvaluators (int n) { public boolean setNumberOfEvaluators (int n) {
if (n < 2 || n > 511) if (n < 2 || n > 511)
return false; return false;
int current = allThreads.size(); int current = allThreads.size();
@ -293,13 +294,20 @@ public class Application extends UnicastRemoteObject implements IRemoteApp, IRep
return true; return true;
} }
/**
* Return the number of currently active threads
*/
public int getActiveThreads () {
return 0;
}
/** /**
* Execute a request coming in from a web client. * Execute a request coming in from a web client.
*/ */
public ResponseTrans execute (RequestTrans req) { public ResponseTrans execute (RequestTrans req) {
requestCount += 1; requestCount += 1;
// long reqstart = System.currentTimeMillis ();
User u = getUser (req.session); User u = getUser (req.session);
ResponseTrans res = null; ResponseTrans res = null;
@ -342,7 +350,7 @@ public class Application extends UnicastRemoteObject implements IRemoteApp, IRep
res.waitForClose (); res.waitForClose ();
} }
} }
// System.err.println ("********************** ABSOLUTE TIME: "+(System.currentTimeMillis() - reqstart));
return res; return res;
} }
@ -697,7 +705,7 @@ public class Application extends UnicastRemoteObject implements IRemoteApp, IRep
Hashtable cloned = (Hashtable) sessions.clone (); Hashtable cloned = (Hashtable) sessions.clone ();
for (Enumeration e = cloned.elements (); e.hasMoreElements (); ) { for (Enumeration e = cloned.elements (); e.hasMoreElements (); ) {
User u = (User) e.nextElement (); User u = (User) e.nextElement ();
if (now - u.touched () > sessionTimeout * 60000) { if (now - u.lastTouched () > sessionTimeout * 60000) {
if (u.uid != null) { if (u.uid != null) {
try { try {
eval.invokeFunction (u, "onLogout", new ESValue[0]); eval.invokeFunction (u, "onLogout", new ESValue[0]);
@ -766,11 +774,11 @@ public class Application extends UnicastRemoteObject implements IRemoteApp, IRep
String protoname = m.getExtends (); String protoname = m.getExtends ();
if (protoname == null) if (protoname == null)
protoname = "hopobject"; protoname = "hopobject";
Prototype protoProto = (Prototype) typemgr.prototypes.get (protoname); Prototype parentProto = (Prototype) typemgr.prototypes.get (protoname);
if (protoProto == null) if (parentProto == null)
protoProto = (Prototype) typemgr.prototypes.get ("hopobject"); parentProto = (Prototype) typemgr.prototypes.get ("hopobject");
if (protoProto != null) if (parentProto != null)
proto.setPrototype (protoProto); proto.setParentPrototype (parentProto);
} }
} }
} catch (Exception x) { } catch (Exception x) {
@ -822,6 +830,13 @@ public class Application extends UnicastRemoteObject implements IRemoteApp, IRep
dbMappings.put (typename, dbmap); dbMappings.put (typename, dbmap);
} }
/**
* Proxy method to get a property from the applications properties.
*/
public String getProperty (String propname, String defvalue) {
return props.getProperty (propname, defvalue);
}
/** /**
* Periodically called to log thread stats for this application * Periodically called to log thread stats for this application
*/ */

View file

@ -7,7 +7,10 @@ import java.util.HashMap;
import java.util.Iterator; import java.util.Iterator;
import java.io.*; import java.io.*;
import helma.framework.*; import helma.framework.*;
import helma.scripting.*;
import helma.scripting.fesi.*;
import helma.objectmodel.*; import helma.objectmodel.*;
import helma.util.Updatable;
import FESI.Data.*; import FESI.Data.*;
import FESI.Exceptions.EcmaScriptException; import FESI.Exceptions.EcmaScriptException;
@ -25,12 +28,10 @@ public class Prototype {
String id; String id;
String name; String name;
Application app; Application app;
HashMap templates, functions, actions, skins, updatables; public HashMap templates, functions, actions, skins, updatables;
long lastUpdate; long lastUpdate;
// DbMapping dbmap; Prototype parent;
Prototype prototype;
public Prototype (String name, Application app) { public Prototype (String name, Application app) {
@ -40,11 +41,20 @@ public class Prototype {
this.app = app; this.app = app;
this.name = name; this.name = name;
lastUpdate = System.currentTimeMillis (); lastUpdate = 0; // System.currentTimeMillis ();
} }
/**
* Return the application this prototype is a part of
*/
public Application getApplication () {
return app;
}
/**
* Get an action defined for this prototype
*/
public Action getActionOrTemplate (String aname) { public Action getActionOrTemplate (String aname) {
Action retval = null; Action retval = null;
@ -56,21 +66,24 @@ public class Prototype {
if (retval == null && "true".equalsIgnoreCase (app.props.getProperty ("exposetemplates"))) if (retval == null && "true".equalsIgnoreCase (app.props.getProperty ("exposetemplates")))
retval = (Action) templates.get (aname); retval = (Action) templates.get (aname);
// if still not found, check if the action is defined for the generic node prototype // if still not found, check if the action is defined for the generic node prototype
if (retval == null && prototype != null) if (retval == null && parent != null)
retval = prototype.getActionOrTemplate (aname); retval = parent.getActionOrTemplate (aname);
return retval; return retval;
} }
public void setPrototype (Prototype prototype) { /**
* Set the parent prototype of this prototype, i.e. the prototype this one inherits from.
*/
public void setParentPrototype (Prototype parent) {
// this is not allowed for the hopobject and global prototypes // this is not allowed for the hopobject and global prototypes
if ("hopobject".equalsIgnoreCase (name) || "global".equalsIgnoreCase (name)) if ("hopobject".equalsIgnoreCase (name) || "global".equalsIgnoreCase (name))
return; return;
Prototype old = this.prototype; Prototype old = this.parent;
this.prototype = prototype; this.parent = parent;
// if prototype has changed, update ES-prototypes in request evaluators // if parent has changed, update ES-prototypes in request evaluators
if (prototype != old) { if (parent != old) {
Iterator evals = app.typemgr.getRegisteredRequestEvaluators (); Iterator evals = app.typemgr.getRegisteredRequestEvaluators ();
while (evals.hasNext ()) { while (evals.hasNext ()) {
try { try {
@ -78,8 +91,8 @@ public class Prototype {
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 = prototype == null ? ObjectPrototype opp = parent == null ?
reval.esNodePrototype : reval.getPrototype (prototype.getName ()); reval.esNodePrototype : reval.getPrototype (parent.getName ());
// don't think this is possible, but check anyway // don't think this is possible, but check anyway
if (opp == null) if (opp == null)
opp = reval.esNodePrototype; opp = reval.esNodePrototype;
@ -90,8 +103,8 @@ public class Prototype {
} }
} }
public Prototype getPrototype () { public Prototype getParentPrototype () {
return prototype; return parent;
} }
public Template getTemplate (String tmpname) { public Template getTemplate (String tmpname) {
@ -123,6 +136,18 @@ public class Prototype {
return name; return name;
} }
Updatable[] upd = null;
public Updatable[] getUpdatables () {
if (upd == null) {
upd = new Updatable[updatables.size()];
int i = 0;
for (Iterator it = updatables.values().iterator(); it.hasNext(); ) {
upd[i++] = (Updatable) it.next();
}
}
return upd;
}
public void initRequestEvaluator (RequestEvaluator reval) { public void initRequestEvaluator (RequestEvaluator reval) {
// see if we already registered with this evaluator // see if we already registered with this evaluator
@ -133,12 +158,12 @@ public class Prototype {
// get the prototype's prototype if possible and necessary // get the prototype's prototype if possible and necessary
ObjectPrototype opp = null; ObjectPrototype opp = null;
if (prototype != null) { if (parent != null) {
// see if parent prototype is already registered. if not, register it // see if parent prototype is already registered. if not, register it
opp = reval.getPrototype (prototype.getName ()); opp = reval.getPrototype (parent.getName ());
if (opp == null) { if (opp == null) {
prototype.initRequestEvaluator (reval); parent.initRequestEvaluator (reval);
opp = reval.getPrototype (prototype.getName ()); opp = reval.getPrototype (parent.getName ());
} }
} }
if (!"global".equalsIgnoreCase (name) && !"hopobject".equalsIgnoreCase (name) && opp == null) { if (!"global".equalsIgnoreCase (name) && !"hopobject".equalsIgnoreCase (name) && opp == null) {

View file

@ -6,7 +6,9 @@ package helma.framework.core;
import helma.objectmodel.*; import helma.objectmodel.*;
import helma.objectmodel.db.*; import helma.objectmodel.db.*;
import helma.framework.*; import helma.framework.*;
import helma.framework.extensions.*; import helma.scripting.*;
import helma.scripting.fesi.*;
import helma.scripting.fesi.extensions.*;
import helma.xmlrpc.fesi.*; import helma.xmlrpc.fesi.*;
import helma.util.*; import helma.util.*;
import java.util.*; import java.util.*;
@ -27,11 +29,11 @@ import FESI.Exceptions.*;
public class RequestEvaluator implements Runnable { public class RequestEvaluator implements Runnable {
Application app; public Application app;
protected boolean initialized; protected boolean initialized;
RequestTrans req; public RequestTrans req;
ResponseTrans res; public ResponseTrans res;
volatile Transactor rtx; volatile Transactor rtx;
@ -46,16 +48,16 @@ public class RequestEvaluator implements Runnable {
protected ArrayPrototype reqPath; protected ArrayPrototype reqPath;
private ESRequestData reqData; private ESRequestData reqData;
// vars for FESI EcmaScript support
public Evaluator evaluator;
public ObjectPrototype esNodePrototype;
public ObjectPrototype esUserPrototype;
public LruHashtable objectcache;
Hashtable prototypes;
// Used to cache skins within one request evaluation // Used to cache skins within one request evaluation
HashMap skincache; HashMap skincache;
// vars for FESI EcmaScript support
protected Evaluator evaluator;
protected ObjectPrototype esNodePrototype;
protected ObjectPrototype esUserPrototype;
protected LruHashtable objectcache;
protected Hashtable prototypes;
GlobalObject global; GlobalObject global;
HopExtension hopx; HopExtension hopx;
MailExtension mailx; MailExtension mailx;
@ -65,8 +67,8 @@ public class RequestEvaluator implements Runnable {
"FESI.Extensions.BasicIO", "FESI.Extensions.BasicIO",
"FESI.Extensions.FileIO", "FESI.Extensions.FileIO",
"helma.xmlrpc.fesi.FesiRpcExtension", "helma.xmlrpc.fesi.FesiRpcExtension",
"helma.framework.extensions.ImageExtension", "helma.scripting.fesi.extensions.ImageExtension",
"helma.framework.extensions.FtpExtension", "helma.scripting.fesi.extensions.FtpExtension",
"FESI.Extensions.JavaAccess", "FESI.Extensions.JavaAccess",
"FESI.Extensions.OptionalRegExp"}; "FESI.Extensions.OptionalRegExp"};
@ -106,9 +108,9 @@ public class RequestEvaluator implements Runnable {
evaluator.addExtension (extensions[i]); evaluator.addExtension (extensions[i]);
hopx = new HopExtension (); hopx = new HopExtension ();
hopx.initializeExtension (this); hopx.initializeExtension (this);
mailx = (MailExtension) evaluator.addExtension ("helma.framework.extensions.MailExtension"); mailx = (MailExtension) evaluator.addExtension ("helma.scripting.fesi.extensions.MailExtension");
mailx.setProperties (this.app.props); mailx.setProperties (this.app.props);
Database dbx = (Database) evaluator.addExtension ("helma.framework.extensions.Database"); Database dbx = (Database) evaluator.addExtension ("helma.scripting.fesi.extensions.Database");
dbx.setApplication (this.app); dbx.setApplication (this.app);
// fake a cache member like the one found in ESNodes // fake a cache member like the one found in ESNodes
@ -142,6 +144,7 @@ public class RequestEvaluator implements Runnable {
try { try {
do { do {
app.typemgr.checkPrototypes ();
IPathElement root, currentElement; IPathElement root, currentElement;
// reset skinManager // reset skinManager
skinmanagers = null; skinmanagers = null;
@ -751,7 +754,7 @@ public class RequestEvaluator implements Runnable {
if (proto == null) if (proto == null)
return null; return null;
// First check if the skin has been already used within the execution of this request // First check if the skin has been already used within the execution of this request
CompositeKey key = new CompositeKey (proto.getName(), skinname); SkinKey key = new SkinKey (proto.getName(), skinname);
Skin skin = (Skin) skincache.get (key); Skin skin = (Skin) skincache.get (key);
if (skin != null) { if (skin != null) {
return skin; return skin;
@ -775,7 +778,7 @@ public class RequestEvaluator implements Runnable {
return skin; return skin;
} }
// still not found. See if there is a parent prototype which might define the skin // still not found. See if there is a parent prototype which might define the skin
proto = proto.getPrototype (); proto = proto.getParentPrototype ();
} while (proto != null); } while (proto != null);
// looked every where, nothing to be found // looked every where, nothing to be found
return null; return null;
@ -932,18 +935,18 @@ public class RequestEvaluator implements Runnable {
prototypes.put (protoName, op); prototypes.put (protoName, op);
} }
final class CompositeKey { final class SkinKey {
final String first, second; final String first, second;
public CompositeKey (String first, String second) { public SkinKey (String first, String second) {
this.first = first; this.first = first;
this.second = second; this.second = second;
} }
public boolean equals (Object other) { public boolean equals (Object other) {
try { try {
CompositeKey key = (CompositeKey) other; SkinKey key = (SkinKey) other;
return first.equals (key.first) && second.equals (key.second); return first.equals (key.first) && second.equals (key.second);
} catch (Exception x) { } catch (Exception x) {
return false; return false;

View file

@ -4,11 +4,12 @@
package helma.framework.core; package helma.framework.core;
import java.io.*; import java.io.*;
import java.util.ArrayList; import java.util.*;
import java.util.Hashtable;
import helma.framework.*; import helma.framework.*;
import FESI.Data.*; import FESI.Data.*;
import FESI.Exceptions.*; import FESI.Exceptions.*;
import helma.scripting.*;
import helma.scripting.fesi.*;
import helma.objectmodel.INode; import helma.objectmodel.INode;
import helma.objectmodel.ConcurrencyException; import helma.objectmodel.ConcurrencyException;
import helma.util.HtmlEncoder; import helma.util.HtmlEncoder;
@ -24,13 +25,19 @@ public class Skin {
Object[] parts; Object[] parts;
Application app; Application app;
String source; String source;
ESObject sandbox; HashSet sandbox;
/**
* Create a skin without any restrictions on which macros are allowed to be called from it
*/
public Skin (String content, Application app) { public Skin (String content, Application app) {
this (content, app, null); this (content, app, null);
} }
public Skin (String content, Application app, ESObject sandbox) { /**
* Create a skin with a sandbox which contains the names of macros allowed to be called
*/
public Skin (String content, Application app, HashSet sandbox) {
this.app = app; this.app = app;
this.sandbox = sandbox; this.sandbox = sandbox;
parse (content); parse (content);
@ -110,18 +117,23 @@ public class Skin {
for (int i=0; i<parts.length; i++) { for (int i=0; i<parts.length; i++) {
if (parts[i] instanceof Macro) { if (parts[i] instanceof Macro) {
Macro m = (Macro) parts[i]; Macro m = (Macro) parts[i];
String mname = null; if (macroname.equals (m.getFullName ()))
if (m.handler == null)
mname = m.name;
else
mname = m.handler+"."+m.name;
if (macroname.equals (mname))
return true; return true;
} }
} }
return false; return false;
} }
/**
* Adds a macro to the list of allowed macros. The macro is in handler.name notation.
*/
public void allowMacro (String macroname) {
if (sandbox == null) {
sandbox = new HashSet ();
}
sandbox.add (macroname);
}
static final int HANDLER = 0; static final int HANDLER = 0;
static final int MACRO = 1; static final int MACRO = 1;
static final int PARAMNAME = 2; static final int PARAMNAME = 2;
@ -131,8 +143,8 @@ public class Skin {
String handler; String handler;
String name; String name;
String fullname;
Hashtable parameters; Hashtable parameters;
boolean notallowed = false;
public Macro (String str) { public Macro (String str) {
@ -219,24 +231,17 @@ public class Skin {
else if (state <= MACRO) else if (state <= MACRO)
name = b.toString().trim(); name = b.toString().trim();
} }
if (sandbox != null && name != null) try {
ESValue allow = handler == null ?
sandbox.getProperty ("global", "global".hashCode ()) :
sandbox.getProperty (handler, handler.hashCode ());
allow = ((ESObject) allow).getProperty (name, name.hashCode ());
if (allow == null || allow == ESUndefined.theUndefined)
notallowed = true;
} catch (Exception x) {
notallowed = true;
}
} }
/**
* Render the macro given a handler object
*/
public void render (RequestEvaluator reval, ESObject thisObject, IPathElement elem, ESObject paramObject) throws RedirectException { public void render (RequestEvaluator reval, ESObject thisObject, IPathElement elem, ESObject paramObject) throws RedirectException {
if (notallowed) { if (sandbox != null && sandbox.contains (getFullName ())) {
String h = handler == null ? "global" : handler; String h = handler == null ? "global" : handler;
reval.res.write ("[Macro "+h+"."+name+" not allowed in sandbox]"); reval.res.write ("[Macro "+getFullName()+" not allowed in sandbox]");
return; return;
} else if ("response".equalsIgnoreCase (handler)) { } else if ("response".equalsIgnoreCase (handler)) {
renderFromResponse (reval); renderFromResponse (reval);
@ -305,7 +310,7 @@ public class Skin {
if (v != ESUndefined.theUndefined && v != ESNull.theNull) if (v != ESUndefined.theUndefined && v != ESNull.theNull)
reval.res.write (v); reval.res.write (v);
} else { } else {
String msg = "[HopMacro unhandled: "+handler+"."+name+"]"; String msg = "[HopMacro unhandled: "+getFullName()+"]";
reval.res.write (" "+msg+" "); reval.res.write (" "+msg+" ");
app.logEvent (msg); app.logEvent (msg);
} }
@ -352,6 +357,10 @@ public class Skin {
} }
} }
/**
* Utility method for performing different kind of character encodings on the
* macro output.
*/
public String encode (String text, String encoding) { public String encode (String text, String encoding) {
if (encoding == null || text == null) if (encoding == null || text == null)
return text; return text;
@ -367,8 +376,22 @@ public class Skin {
} }
public String toString () { public String toString () {
return "[HopMacro: "+handler+","+name+"]"; return "[HopMacro: "+getFullName()+"]";
} }
/**
* Return the full name of the macro in handler.name notation
*/
public String getFullName () {
if (fullname == null) {
if (handler == null)
fullname = name;
else
fullname = handler+"."+name;
}
return fullname;
}
} }

View file

@ -74,10 +74,29 @@ public class User implements Serializable {
lastTouched = System.currentTimeMillis (); lastTouched = System.currentTimeMillis ();
} }
public long touched () { public long lastTouched () {
return lastTouched; return lastTouched;
} }
public long onSince () {
return onSince;
}
/**
* Get the persistent user id of a registered user. This is usually the user name, or
* null if the user is not logged in.
*/
public String getUID () {
return uid;
}
/**
* Return the transient cache node for this user.
*/
public INode getCache () {
return cache;
}
} }

View file

@ -7,6 +7,7 @@ import java.util.*;
import java.util.zip.*; import java.util.zip.*;
import java.io.*; import java.io.*;
import helma.framework.*; import helma.framework.*;
import helma.scripting.*;
import helma.util.Updatable; import helma.util.Updatable;
import helma.util.SystemProperties; import helma.util.SystemProperties;
import helma.objectmodel.db.DbMapping; import helma.objectmodel.db.DbMapping;
@ -35,7 +36,7 @@ public class ZippedAppFile 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 () || !file.exists (); return lastmod != file.lastModified ();
} }