Pretty much reworked all the Helma type management code.

This commit is contained in:
hns 2002-10-22 16:33:03 +00:00
parent ea5edf51c9
commit 7463553a95
11 changed files with 360 additions and 360 deletions

View file

@ -25,16 +25,14 @@ public final class Prototype {
String name;
Application app;
HashMap templates;
HashMap functions;
HashMap actions;
HashMap skins;
HashMap code, zippedCode;
HashMap skins, zippedSkins;
HashMap updatables;
// a map of this prototype's skins as raw strings
// a map of this prototype's skins as raw strings
// used for exposing skins to application (script) code (via app.skinfiles).
SkinMap skinMap;
DbMapping dbmap;
// lastCheck is the time the prototype's files were last checked
@ -54,12 +52,12 @@ public final class Prototype {
this.app = app;
this.name = name;
templates = new HashMap ();
functions = new HashMap ();
actions = new HashMap ();
code = new HashMap ();
zippedCode = new HashMap ();
skins = new HashMap ();
zippedSkins = new HashMap ();
updatables = new HashMap ();
skinMap = new SkinMap ();
isJavaPrototype = app.isJavaPrototype (name);
@ -96,35 +94,11 @@ public final class Prototype {
public void setDbMapping (DbMapping dbmap) {
this.dbmap = dbmap;
}
public DbMapping getDbMapping () {
return dbmap;
}
/**
* Get a template defined for this prototype. Templates
* are files that mix layout and code and were used
* before skins came along. Think of them as legacy.
*/
public Template getTemplate (String tmpname) {
return (Template) templates.get (tmpname);
}
/**
* Get a generic function file defined for this prototype.
*/
public FunctionFile getFunctionFile (String ffname) {
return (FunctionFile) functions.get (ffname);
}
/**
* Get an action file defined for this prototype. Action
* files are functions with a .hac extension
* that are accessible publicly via web interface.
*/
public ActionFile getActionFile (String afname) {
return (ActionFile) actions.get (afname);
}
/**
* Get a Skinfile for this prototype. This only works for skins
@ -132,7 +106,10 @@ public final class Prototype {
* other locations or database stored skins.
*/
public SkinFile getSkinFile (String sfname) {
return (SkinFile) skins.get (sfname);
SkinFile sf = (SkinFile) skins.get (sfname);
if (sf == null)
sf = (SkinFile) zippedSkins.get (sfname);
return sf;
}
/**
@ -141,7 +118,7 @@ public final class Prototype {
* other locations or database stored skins.
*/
public Skin getSkin (String sfname) {
SkinFile sf = (SkinFile) skins.get (sfname);
SkinFile sf = getSkinFile (sfname);
if (sf != null)
return sf.getSkin ();
else
@ -153,7 +130,7 @@ public final class Prototype {
return name;
}
Updatable[] upd = null;
/* Updatable[] upd = null;
public Updatable[] getUpdatables () {
if (upd == null) {
upd = new Updatable[updatables.size()];
@ -163,7 +140,7 @@ public final class Prototype {
}
}
return upd;
}
} */
/**
* Get the last time any script has been re-read for this prototype.
@ -190,20 +167,20 @@ public final class Prototype {
}
/**
* Signal that the prototype's scripts have been checked for
* Signal that the prototype's scripts have been checked for
* changes.
*/
public void markChecked () {
lastCheck = System.currentTimeMillis ();
}
/**
* Return a clone of this prototype's actions container. Synchronized
* to not return a map in a transient state where it is just being
* updated by the type manager.
*/
public synchronized Map getActions () {
return (Map) actions.clone();
public synchronized Map getCode () {
return (Map) code.clone();
}
/**
@ -211,46 +188,90 @@ public final class Prototype {
* to not return a map in a transient state where it is just being
* updated by the type manager.
*/
public synchronized Map getFunctions () {
return (Map) functions.clone();
public synchronized Map getZippedCode () {
return (Map) zippedCode.clone();
}
/**
* Return a clone of this prototype's templates container. Synchronized
* to not return a map in a transient state where it is just being
* updated by the type manager.
*/
public synchronized Map getTemplates () {
return (Map) templates.clone();
public synchronized void addActionFile (ActionFile action) {
File f = action.getFile ();
if (f != null) {
code.put (action.getSourceName(), action);
updatables.put (f.getName(), action);
} else {
zippedCode.put (action.getSourceName(), action);
}
}
/**
* Return a clone of this prototype's skins container. Synchronized
* to not return a map in a transient state where it is just being
* updated by the type manager.
*/
public synchronized Map getSkins () {
return (Map) skins.clone();
public synchronized void addTemplate (Template template) {
File f = template.getFile ();
if (f != null) {
code.put (template.getSourceName(), template);
updatables.put (f.getName(), template);
} else {
zippedCode.put (template.getSourceName(), template);
}
}
public synchronized void removeUpdatable (String fileName) {
updatables.remove (fileName);
markUpdated ();
public synchronized void addFunctionFile (FunctionFile funcfile) {
File f = funcfile.getFile ();
if (f != null) {
code.put (funcfile.getSourceName(), funcfile);
updatables.put (f.getName(), funcfile);
} else {
zippedCode.put (funcfile.getSourceName(), funcfile);
}
}
public synchronized void removeAction (String actionName) {
actions.remove (actionName);
markUpdated ();
public synchronized void addSkinFile (SkinFile skinfile) {
File f = skinfile.getFile ();
if (f != null) {
skins.put (skinfile.getName(), skinfile);
updatables.put (f.getName(), skinfile);
} else {
zippedSkins.put (skinfile.getName(), skinfile);
}
}
public synchronized void removeFunctionFile (String functionFileName) {
functions.remove (functionFileName);
markUpdated ();
public synchronized void removeActionFile (ActionFile action) {
File f = action.getFile ();
if (f != null) {
code.remove (action.getSourceName());
updatables.remove (f.getName());
} else {
zippedCode.remove (action.getSourceName());
}
}
public synchronized void removeTemplate (String templateName) {
templates.remove (templateName);
markUpdated ();
public synchronized void removeFunctionFile (FunctionFile funcfile) {
File f = funcfile.getFile ();
if (f != null) {
code.remove (funcfile.getSourceName());
updatables.remove (f.getName());
} else {
zippedCode.remove (funcfile.getSourceName());
}
}
public synchronized void removeTemplate (Template template) {
File f = template.getFile ();
if (f != null) {
code.remove (template.getSourceName());
updatables.remove (f.getName());
} else {
zippedCode.remove (template.getSourceName());
}
}
public synchronized void removeSkinFile (SkinFile skinfile) {
File f = skinfile.getFile ();
if (f != null) {
skins.remove (skinfile.getName());
updatables.remove (f.getName());
} else {
zippedSkins.remove (skinfile.getName());
}
}

View file

@ -108,9 +108,7 @@ public final class RequestEvaluator implements Runnable {
// used for logging
String txname = app.getName()+"/"+req.path;
// set Timer to get some profiling data
localrtx.timer.reset ();
localrtx.timer.beginEvent (requestPath+" init");
// begin transaction
localrtx.begin (txname);
String action = null;
@ -221,15 +219,12 @@ public final class RequestEvaluator implements Runnable {
throw new FrameworkException (notfound.getMessage ());
}
localrtx.timer.endEvent (txname+" init");
/////////////////////////////////////////////////////////////////////////////
// end of path resolution section
/////////////////////////////////////////////////////////////////////////////
// beginning of execution section
try {
localrtx.timer.beginEvent (txname+" execute");
// enter execution context
scriptingEngine.enterContext (globals);
@ -255,7 +250,6 @@ public final class RequestEvaluator implements Runnable {
// do the actual action invocation
scriptingEngine.invoke (currentElement, action, new Object[0], false);
localrtx.timer.endEvent (txname+" execute");
} catch (RedirectException redirect) {
// res.redirect = redirect.getMessage ();
// if there is a message set, save it on the user object for the next request
@ -296,28 +290,30 @@ public final class RequestEvaluator implements Runnable {
} catch (Exception x) {
abortTransaction (false);
app.logEvent ("### Exception in "+Thread.currentThread()+": "+x);
// Dump the profiling data to System.err
if (app.debug) {
((Transactor) Thread.currentThread ()).timer.dump (System.err);
x.printStackTrace ();
}
// If the transactor thread has been killed by the invoker thread we don't have to
// bother for the error message, just quit.
if (localrtx != rtx)
if (localrtx != rtx) {
abortTransaction (false);
break;
}
res.reset ();
// check if we tried to process the error already
if (error == null) {
abortTransaction (false);
app.errorCount += 1;
app.logEvent ("Exception in "+Thread.currentThread()+": "+x);
// Dump the profiling data to System.err
if (app.debug) {
x.printStackTrace ();
}
// set done to false so that the error will be processed
done = false;
error = x.getMessage ();
if (error == null || error.length() == 0)
error = x.toString ();
if (error == null)
error = "Unspecified error";
} else {
// error in error action. use traditional minimal error message
res.write ("<b>Error in application '"+app.getName()+"':</b> <br><br><pre>"+error+"</pre>");

View file

@ -173,7 +173,6 @@ public final class Skin {
this.start = start;
this.end = end;
int state = HANDLER;
boolean escape = false;
char quotechar = '\u0000';
@ -383,6 +382,8 @@ public final class Skin {
// System.err.println ("Getting macro from function");
// pass a clone of the parameter map so if the script changes it,
// Map param = ;
// if (parameters == null)
// parameters = new HashMap ();
Object[] arguments = { parameters == null ?
new HashMap () :
new HashMap (parameters) };

View file

@ -24,10 +24,10 @@ public final class SkinFile implements Updatable {
public SkinFile (File file, String name, Prototype proto) {
this.prototype = proto;
this.app = proto.app;
this.name = name;
this.file = file;
this.skin = null;
this.name = name;
app = proto.app;
skin = null;
}
/**
@ -37,22 +37,22 @@ public final class SkinFile implements Updatable {
*/
public SkinFile (String body, String name, Prototype proto) {
this.prototype = proto;
this.app = proto.app;
this.name = name;
this.file = null;
this.skin = new Skin (body, app);
app = proto.app;
name = name;
file = null;
skin = new Skin (body, app);
}
/**
* Create a skinfile without that doesn't belong to a prototype, or at
* Create a skinfile that doesn't belong to a prototype, or at
* least it doesn't know about its prototype and isn't managed by the prototype.
*/
public SkinFile (File file, String name, Application app) {
this.prototype = null;
this.app = app;
this.name = name;
this.file = file;
this.skin = null;
this.name = name;
prototype = null;
skin = null;
}
@ -66,7 +66,6 @@ public final class SkinFile implements Updatable {
public void update () {
if (!file.exists ()) {
// remove skin from prototype
remove ();
@ -87,19 +86,20 @@ public final class SkinFile implements Updatable {
} catch (IOException x) {
app.logEvent ("Error reading Skin "+file+": "+x);
}
lastmod = file.lastModified ();
}
public void remove () {
if (prototype != null) {
prototype.skins.remove (name);
if (file != null)
prototype.updatables.remove (file.getName());
prototype.removeSkinFile (this);
}
}
public File getFile () {
return file;
}
public Skin getSkin () {
if (skin == null)
read ();

View file

@ -226,127 +226,109 @@ public final class TypeManager {
public void updatePrototype (Prototype proto) {
if (proto == null)
return;
// System.err.println ("UPDATE PROTO: "+app.getName()+"/"+proto.getName());
// if prototype has been checked in the last second, return
// if (System.currentTimeMillis() - proto.getLastCheck() < 1000)
// return;
synchronized (proto) {
// check again because another thread may have checked the
// prototype while we were waiting for access to the synchronized section
if (System.currentTimeMillis() - proto.getLastCheck() < 1000)
return;
// check again because another thread may have checked the
// prototype while we were waiting for access to the synchronized section
if (System.currentTimeMillis() - proto.getLastCheck() < 1000)
return;
File dir = new File (appDir, proto.getName());
boolean needsUpdate = false;
HashSet updatables = null;
File dir = new File (appDir, proto.getName());
HashSet updateSet = null;
HashSet createSet = null;
// our plan is to do as little as possible, so first check if
// anything the prototype knows about has changed on disk
for (Iterator i = proto.updatables.values().iterator(); i.hasNext(); ) {
Updatable upd = (Updatable) i.next();
if (upd.needsUpdate ()) {
if (updatables == null)
updatables = new HashSet ();
needsUpdate = true;
updatables.add (upd);
// our plan is to do as little as possible, so first check if
// anything the prototype knows about has changed on disk
for (Iterator i = proto.updatables.values().iterator(); i.hasNext(); ) {
Updatable upd = (Updatable) i.next();
if (upd.needsUpdate ()) {
if (updateSet == null)
updateSet = new HashSet ();
updateSet.add (upd);
}
}
}
// next we check if files have been created or removed since last update
if (proto.getLastCheck() < dir.lastModified ()) {
String[] list = dir.list();
for (int i=0; i<list.length; i++) {
String fn = list[i];
if (!proto.updatables.containsKey (fn)) {
if (fn.endsWith (templateExtension) || fn.endsWith (scriptExtension) ||
fn.endsWith (actionExtension) || fn.endsWith (skinExtension) ||
"type.properties".equalsIgnoreCase (fn)) {
needsUpdate = true;
// updatables.add ("[new:"+proto.getName()+"/"+fn+"]");
// next we check if files have been created or removed since last update
if (proto.getLastCheck() < dir.lastModified ()) {
String[] list = dir.list();
for (int i=0; i<list.length; i++) {
String fn = list[i];
if (!proto.updatables.containsKey (fn)) {
if (fn.endsWith (templateExtension) ||
fn.endsWith (scriptExtension) ||
fn.endsWith (actionExtension) ||
fn.endsWith (skinExtension) ||
"type.properties".equalsIgnoreCase (fn))
{
if (createSet == null)
createSet = new HashSet ();
createSet.add (list[i]);
}
}
}
}
}
// if nothing needs to be updated, mark prototype as checked and return
if (!needsUpdate) {
// if nothing needs to be updated, mark prototype as checked and return
if (updateSet == null && createSet == null) {
proto.markChecked ();
return;
}
// first go through new files and create new items
if (createSet != null) {
Object[] newFiles = createSet.toArray ();
for (int i=0; i<newFiles.length; i++) {
String filename = (String) newFiles[i];
int dot = filename.lastIndexOf (".");
String tmpname = filename.substring(0, dot);
File tmpfile = new File (dir, filename);
if (filename.endsWith (templateExtension)) {
try {
Template t = new Template (tmpfile, tmpname, proto);
proto.addTemplate (t);
} catch (Throwable x) {
app.logEvent ("Error updating prototype: "+x);
}
} else if (filename.endsWith (scriptExtension)) {
try {
FunctionFile ff = new FunctionFile (tmpfile, proto);
proto.addFunctionFile (ff);
} catch (Throwable x) {
app.logEvent ("Error updating prototype: "+x);
}
} else if (filename.endsWith (actionExtension)) {
try {
ActionFile af = new ActionFile (tmpfile, tmpname, proto);
proto.addActionFile (af);
} catch (Throwable x) {
app.logEvent ("Error updating prototype: "+x);
}
} else if (filename.endsWith (skinExtension)) {
SkinFile sf = new SkinFile (tmpfile, tmpname, proto);
proto.addSkinFile (sf);
}
}
}
// next go through existing updatables
if (updateSet != null) {
for (Iterator i = updateSet.iterator(); i.hasNext(); ) {
Updatable upd = (Updatable) i.next();
try {
upd.update ();
} catch (Exception x) {
if (upd instanceof DbMapping)
app.logEvent ("Error updating db mapping for type "+proto.getName()+": "+x);
else
app.logEvent ("Error updating "+upd+" of prototye type "+proto.getName()+": "+x);
}
}
}
// mark prototype as checked and updated.
proto.markChecked ();
return;
}
// app.logEvent ("TypeManager: Updating prototypes for "+app.getName()+": "+updatables);
// first go through new files and create new items
String[] list = dir.list ();
for (int i=0; i<list.length; i++) {
String fn = list[i];
int dot = fn.lastIndexOf (".");
if (dot < 0)
continue;
if (proto.updatables.containsKey (fn) || !(fn.endsWith (templateExtension) || fn.endsWith (scriptExtension) ||
fn.endsWith (actionExtension) || fn.endsWith (skinExtension) || "type.properties".equalsIgnoreCase (fn))) {
continue;
}
String tmpname = list[i].substring(0, dot);
File tmpfile = new File (dir, list[i]);
if (list[i].endsWith (templateExtension)) {
try {
Template t = new Template (tmpfile, tmpname, proto);
proto.updatables.put (list[i], t);
proto.templates.put (tmpname, t);
} catch (Throwable x) {
app.logEvent ("Error updating prototype: "+x);
}
} else if (list[i].endsWith (scriptExtension)) {
try {
FunctionFile ff = new FunctionFile (tmpfile, tmpname, proto);
proto.updatables.put (list[i], ff);
proto.functions.put (tmpname, ff);
} catch (Throwable x) {
app.logEvent ("Error updating prototype: "+x);
}
} else if (list[i].endsWith (actionExtension)) {
try {
ActionFile af = new ActionFile (tmpfile, tmpname, proto);
proto.updatables.put (list[i], af);
proto.actions.put (tmpname, af);
} catch (Throwable x) {
app.logEvent ("Error updating prototype: "+x);
}
} else if (list[i].endsWith (skinExtension)) {
SkinFile sf = new SkinFile (tmpfile, tmpname, proto);
proto.updatables.put (list[i], sf);
proto.skins.put (tmpname, sf);
}
}
// next go through existing updatables
if (updatables != null) {
for (Iterator i = updatables.iterator(); i.hasNext(); ) {
Updatable upd = (Updatable) i.next();
try {
upd.update ();
} catch (Exception x) {
if (upd instanceof DbMapping)
app.logEvent ("Error updating db mapping for type "+proto.getName()+": "+x);
else
app.logEvent ("Error updating "+upd+" of prototye type "+proto.getName()+": "+x);
}
}
}
// mark prototype as checked and updated.
proto.markChecked ();
proto.markUpdated();
proto.markUpdated();
} // end of synchronized (proto)

View file

@ -72,20 +72,22 @@ public class ZippedAppFile implements Updatable {
}
if (fname.endsWith (".hac")) {
String name = fname.substring (0, fname.lastIndexOf ("."));
String sourceName = file.getName()+"/"+ename;
String content = getZipEntryContent (zip, entry);
// System.err.println ("["+content+"]");
ActionFile act = new ActionFile (content, name, proto);
proto.actions.put (name, act);
ActionFile act = new ActionFile (content, name, sourceName, proto);
proto.addActionFile (act);
updatables.add (act);
// mark prototype as updated
proto.markUpdated ();
}
else if (fname.endsWith (".hsp")) {
String name = fname.substring (0, fname.lastIndexOf ("."));
String sourceName = file.getName()+"/"+ename;
String content = getZipEntryContent (zip, entry);
// System.err.println ("["+content+"]");
Template tmp = new Template (content, name, proto);
proto.templates.put (name, tmp);
Template tmp = new Template (content, name, sourceName, proto);
proto.addTemplate (tmp);
updatables.add (tmp);
// mark prototype as updated
proto.markUpdated ();
@ -95,21 +97,20 @@ public class ZippedAppFile implements Updatable {
String content = getZipEntryContent (zip, entry);
// System.err.println ("["+content+"]");
SkinFile skin = new SkinFile (content, name, proto);
proto.skins.put (name, skin);
proto.addSkinFile (skin);
updatables.add (skin);
}
else if (fname.endsWith (".js")) {
String name = fname.substring (0, fname.lastIndexOf ("."));
String sourceName = file.getName()+"/"+ename;
String content = getZipEntryContent (zip, entry);
// System.err.println ("["+content+"]");
FunctionFile ff = new FunctionFile (content, name, proto);
proto.functions.put (name, ff);
FunctionFile ff = new FunctionFile (content, sourceName, proto);
proto.addFunctionFile (ff);
updatables.add (ff);
// mark prototype as updated
proto.markUpdated ();
}
else if ("type.properties".equalsIgnoreCase (fname)) {
String name = fname.substring (0, fname.lastIndexOf ("."));
DbMapping dbmap = proto.getDbMapping ();
SystemProperties props = dbmap.getProperties ();
props.addProps (file.getName(), zip.getInputStream (entry));

View file

@ -21,8 +21,7 @@ import helma.util.Updatable;
public class ActionFile implements Updatable {
String name;
String functionName;
String name, sourceName;
Prototype prototype;
Application app;
File file;
@ -34,36 +33,21 @@ public class ActionFile implements Updatable {
this.prototype = proto;
this.app = proto.getApplication ();
this.name = name;
functionName = getName()+"_action";
this.sourceName = file.getParentFile().getName()+"/"+file.getName();
this.file = file;
this.content = null;
if (file != null)
update ();
}
public ActionFile (String content, String name, Prototype proto) {
public ActionFile (String content, String name, String sourceName, Prototype proto) {
this.prototype = proto;
this.app = proto.getApplication ();
this.name = name;
functionName = getName()+"_action";
this.sourceName = sourceName;
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.
@ -74,41 +58,58 @@ public class ActionFile implements Updatable {
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 ();
}
}
public void remove () {
prototype.removeAction (name);
if (file != null)
prototype.removeUpdatable (file.getName());
prototype.removeActionFile (this);
}
public File getFile () {
return file;
}
public String getName () {
return name;
}
public String getSourceName () {
return sourceName;
}
public Reader getReader () throws FileNotFoundException {
if (content != null)
return new StringReader (content);
else if (file.length() == 0)
return new StringReader(";");
else
return new FileReader (file);
}
public String getContent () {
return content;
if (content != null)
return content;
else {
try {
FileReader reader = new FileReader (file);
char cbuf[] = new char[(int) file.length ()];
reader.read (cbuf);
reader.close ();
return new String (cbuf);
} catch (Exception filex) {
app.logEvent ("Error reading "+this+": "+filex);
return null;
}
}
}
public String getFunctionName () {
return functionName;
return name + "_action";
}
public Prototype getPrototype () {
@ -120,7 +121,7 @@ public class ActionFile implements Updatable {
}
public String toString () {
return "ActionFile["+prototype.getName()+"/"+functionName+"]";
return "ActionFile["+sourceName+"]";
}
}

View file

@ -20,22 +20,18 @@ import helma.util.Updatable;
public class FunctionFile implements Updatable {
String name;
Prototype prototype;
Application app;
File file;
String sourceName;
String content;
long lastmod;
// a set of funcion names defined by this file. We keep this to be able to
// remove them once the file should get removed
HashSet declaredProps;
long declaredPropsTimestamp;
public FunctionFile (File file, String name, Prototype proto) {
public FunctionFile (File file, Prototype proto) {
this.prototype = proto;
this.app = proto.getApplication ();
this.name = name;
this.sourceName = file.getParentFile().getName()+"/"+file.getName();
this.file = file;
update ();
}
@ -45,13 +41,12 @@ public class FunctionFile implements Updatable {
* files contained in zipped applications. The whole update mechanism is bypassed
* by immediately parsing the code.
*/
public FunctionFile (String body, String name, Prototype proto) {
public FunctionFile (String body, String sourceName, Prototype proto) {
this.prototype = proto;
this.app = proto.getApplication ();
this.name = name;
this.sourceName = sourceName;
this.file = null;
this.content = body;
update ();
}
/**
@ -64,30 +59,15 @@ public class FunctionFile implements Updatable {
public void update () {
if (file != null) {
if (!file.exists ()) {
remove ();
} else {
lastmod = file.lastModified ();
// app.typemgr.readFunctionFile (file, prototype.getName ());
// app.getScriptingEnvironment().evaluateFile (prototype, file);
}
} else {
// app.getScriptingEnvironment().evaluateString (prototype, content);
}
}
/* public void evaluate (ScriptingEnvironment env) {
if (file != null)
env.evaluateFile (prototype, file);
else
env.evaluateString (prototype, content);
}*/
public boolean hasFile () {
return file != null;
}
public File getFile () {
return file;
}
@ -96,19 +76,17 @@ public class FunctionFile implements Updatable {
return content;
}
public String getSourceName () {
return sourceName;
}
public void remove () {
prototype.removeFunctionFile (name);
if (file != null)
prototype.removeUpdatable (file.getName());
prototype.removeFunctionFile (this);
}
public String toString () {
if (file == null)
return "[Zipped script file]";
else
return prototype.getName()+"/"+file.getName();
return sourceName;
}

View file

@ -9,8 +9,6 @@ import java.util.Iterator;
import java.util.StringTokenizer;
import helma.framework.*;
import helma.framework.core.*;
// import FESI.Data.*;
// import FESI.Exceptions.*;
/**
@ -26,26 +24,36 @@ import helma.framework.core.*;
public class Template extends ActionFile {
String processedContent = null;
public Template (File file, String name, Prototype proto) {
super (file, name, proto);
functionName = name;
}
public Template (String content, String name, Prototype proto) {
super (content, name, proto);
functionName = name;
public Template (String content, String name, String sourceName, Prototype proto) {
super (content, name, sourceName, proto);
}
public String getFunctionName () {
return name;
}
public Reader getReader () {
return new StringReader(getContent());
}
public String getContent () {
if (processedContent != null)
return processedContent;
Vector partBuffer = new Vector ();
int l = content.length ();
String cstring = super.getContent();
char[] cnt = cstring.toCharArray ();
int l = cnt.length;
if (l == 0)
return "";
char cnt[] = new char[l];
content.getChars (0, l, cnt, 0);
// if last charackter is whitespace, swallow it. this is necessary for some inner templates to look ok.
if (Character.isWhitespace (cnt[l-1]))
@ -141,14 +149,12 @@ public class Template extends ActionFile {
}
// templateBody.append ("\r\nreturn null;\r\n");
return templateBody.toString ();
processedContent = templateBody.toString ();
return processedContent;
}
public void remove () {
prototype.removeTemplate (name);
if (file != null)
prototype.removeUpdatable (file.getName());
prototype.removeTemplate (this);
}

View file

@ -29,30 +29,41 @@ public class FesiActionAdapter {
Prototype prototype;
Application app;
String functionName;
String sourceName;
// this is the parsed function which can be easily applied to RequestEvaluator objects
// this is the parsed function which can be easily applied to FesiEvaluator objects
TypeUpdater pfunc, pfuncAsString;
public FesiActionAdapter (ActionFile action) {
prototype = action.getPrototype ();
app = action.getApplication ();
String content = action.getContent ();
String functionName = action.getFunctionName ();
sourceName = action.toString ();
Reader reader = null;
functionName = action.getFunctionName ();
sourceName = action.getSourceName ();
try {
reader = action.getReader ();
pfunc = parseFunction (functionName,
"arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10",
content);
reader,
sourceName);
} catch (Throwable x) {
String message = x.getMessage ();
pfunc = new ErrorFeedback (functionName, message);
} finally {
try {
reader.close();
} catch (Exception ignore) {}
}
// check if this is a template and we need to generate an "_as_string" variant
if (action instanceof Template) {
String content = "res.pushStringBuffer(); " +
action.getContent () +
"\r\nreturn res.popStringBuffer();\r\n";
try {
pfuncAsString = parseFunction (functionName+"_as_string",
"arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10",
"res.pushStringBuffer(); "+content+"\r\nreturn res.popStringBuffer();\r\n");
new StringReader(content),
sourceName);
} catch (Throwable x) {
String message = x.getMessage ();
pfunc = new ErrorFeedback (functionName+"_as_string", message);
@ -70,7 +81,7 @@ public class FesiActionAdapter {
pfuncAsString.updateEvaluator (fesi);
}
protected TypeUpdater parseFunction (String funcname, String params, String body) throws EcmaScriptException {
protected TypeUpdater parseFunction (String funcName, String params, Reader body, String sourceName) throws EcmaScriptException {
// ESObject fp = app.eval.evaluator.getFunctionPrototype();
// ConstructedFunctionObject function = null;
@ -78,15 +89,13 @@ public class FesiActionAdapter {
ASTStatementList sl = null;
FunctionEvaluationSource fes = null;
if (body == null || "".equals (body.trim()))
/* if (body == null || "".equals (body.trim()))
body = ";\r\n";
else
body = body + "\r\n";
body = body + "\r\n"; */
if (params == null) params = "";
else params = params.trim ();
String fulltext = "function "+funcname+" (" + params + ") {\n" + body + "\n}";
EcmaScript parser;
StringReader is;
@ -100,26 +109,26 @@ public class FesiActionAdapter {
fpl = (ASTFormalParameterList) parser.FormalParameterList();
is.close();
} catch (ParseException x) {
throw new EcmaScriptParseException (x, new StringEvaluationSource(fulltext, null));
throw new EcmaScriptParseException (x, new FileEvaluationSource(sourceName, null));
}
}
// this is very very very strange: without the toString, lots of obscure exceptions
// deep inside the parser...
is = new java.io.StringReader(body.toString ());
// is = new java.io.StringReader(body.toString ());
try {
parser = new EcmaScript (is);
parser = new EcmaScript (body);
sl = (ASTStatementList) parser.StatementList();
is.close();
body.close();
} catch (ParseException x) {
app.logEvent ("Error parsing file "+app.getName()+":"+sourceName+": "+x);
throw new EcmaScriptParseException (x, new StringEvaluationSource(fulltext, null));
throw new EcmaScriptParseException (x, new FileEvaluationSource(sourceName, null));
} catch (Exception x) {
app.logEvent ("Error parsing file "+app.getName()+":"+sourceName+": "+x);
throw new RuntimeException (x.getMessage ());
}
fes = new FunctionEvaluationSource (new StringEvaluationSource(fulltext, null), funcname);
return new ParsedFunction (fpl, sl, fes, fulltext, funcname);
fes = new FunctionEvaluationSource (new FileEvaluationSource(sourceName, null), funcName);
return new ParsedFunction (fpl, sl, fes, null, funcName);
}
class ParsedFunction implements TypeUpdater {

View file

@ -112,7 +112,7 @@ public final class FesiEvaluator implements ScriptingEngine {
}
/**
* Initialize the evaluator, making sure the minimum type information
* Initialize the evaluator, making sure the minimum type information
* necessary to bootstrap the rest is parsed.
*/
private void initialize () {
@ -127,7 +127,7 @@ public final class FesiEvaluator implements ScriptingEngine {
getPrototype ("global");
}
/**
/**
* Initialize a prototype without fully parsing its script files.
*/
void initPrototype (Prototype prototype) {
@ -146,7 +146,10 @@ public final class FesiEvaluator implements ScriptingEngine {
}
}
String name = prototype.getName ();
if (!"global".equalsIgnoreCase (name) && !"hopobject".equalsIgnoreCase (name) && opp == null) {
if (!"global".equalsIgnoreCase (name) &&
!"hopobject".equalsIgnoreCase (name) &&
opp == null)
{
if (app.isJavaPrototype (name))
opp = getRawPrototype ("__javaobject__");
else
@ -228,26 +231,13 @@ public final class FesiEvaluator implements ScriptingEngine {
global.putHiddenProperty (name, new NodeConstructor (name, fp, this));
} catch (EcmaScriptException ignore) {}
}
for (Iterator it = prototype.getFunctions().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.getZippedCode().values().iterator(); it.hasNext(); ) {
Object code = it.next();
evaluate (prototype, code);
}
for (Iterator it = prototype.getTemplates().values().iterator(); it.hasNext(); ) {
Template tmp = (Template) it.next ();
try {
FesiActionAdapter adp = new FesiActionAdapter (tmp);
adp.updateEvaluator (this);
} catch (EcmaScriptException ignore) {}
}
for (Iterator it = prototype.getActions().values().iterator(); it.hasNext(); ) {
ActionFile act = (ActionFile) it.next ();
try {
FesiActionAdapter adp = new FesiActionAdapter (act);
adp.updateEvaluator (this);
} catch (EcmaScriptException ignore) {}
for (Iterator it = prototype.getCode().values().iterator(); it.hasNext(); ) {
Object code = it.next();
evaluate (prototype, code);
}
}
@ -665,6 +655,8 @@ public final class FesiEvaluator implements ScriptingEngine {
public ESValue getObjectWrapper (Object e) {
if (app.getPrototypeName (e) != null)
return getElementWrapper (e);
/* else if (e instanceof Map)
return new ESMapWrapper (this, (Map) e); */
/* else if (e instanceof INode)
return new ESNode ((INode) e, this); */
else
@ -762,21 +754,34 @@ public final class FesiEvaluator implements ScriptingEngine {
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);
private synchronized void evaluate (Prototype prototype, Object code) {
if (code instanceof FunctionFile) {
FunctionFile funcfile = (FunctionFile) code;
File file = funcfile.getFile ();
if (file != null) {
try {
FileReader fr = new FileReader (file);
EvaluationSource es = new FileEvaluationSource (funcfile.getSourceName(), null);
updateEvaluator (prototype, fr, es);
} catch (IOException iox) {
app.logEvent ("Error updating function file: "+iox);
}
} else {
StringReader reader = new StringReader (funcfile.getContent());
EvaluationSource es = new FileEvaluationSource (funcfile.getSourceName(), null);
updateEvaluator (prototype, reader, es);
}
} else if (code instanceof ActionFile) {
ActionFile action = (ActionFile) code;
FesiActionAdapter fa = new FesiActionAdapter (action);
try {
fa.updateEvaluator (this);
} catch (EcmaScriptException esx) {
app.logEvent ("Error parsing "+action+": "+esx);
}
}
}
public synchronized void evaluateString (Prototype prototype, String code) {
StringReader reader = new StringReader (code);
StringEvaluationSource es = new StringEvaluationSource (code, null);
updateEvaluator (prototype, reader, es);
}
private synchronized void updateEvaluator (Prototype prototype, Reader reader, EvaluationSource source) {
try {