Initial implementation of new skin path resolution schema and

public skins.

Some further work needed in both areas.
This commit is contained in:
hns 2002-03-25 18:55:38 +00:00
parent 1a777b5c5a
commit 7041bf08e7

View file

@ -83,7 +83,7 @@ public class RequestEvaluator implements Runnable {
static final int XMLRPC = 2; // via XML-RPC static final int XMLRPC = 2; // via XML-RPC
static final int INTERNAL = 3; // generic function call, e.g. by scheduler static final int INTERNAL = 3; // generic function call, e.g. by scheduler
INode[] skinmanagers; Object[] skinsets;
/** /**
* Build a RenderContext from a RequestTrans. Checks if the path is the user home node ("user") * Build a RenderContext from a RequestTrans. Checks if the path is the user home node ("user")
@ -154,8 +154,8 @@ public class RequestEvaluator implements Runnable {
// object refs to ressolve request path // object refs to ressolve request path
Object root, currentElement; Object root, currentElement;
// reset skinManager // reset skinsets array and skin cache
skinmanagers = null; skinsets = null;
skincache.clear (); skincache.clear ();
switch (reqtype) { switch (reqtype) {
@ -209,7 +209,6 @@ public class RequestEvaluator implements Runnable {
req.data = reqData; req.data = reqData;
resData.setData (res.getResponseData()); resData.setData (res.getResponseData());
res.data = resData; res.data = resData;
res.skinpath = app.getProperty ("skinpath");
try { try {
@ -345,8 +344,14 @@ public class RequestEvaluator implements Runnable {
try { try {
localrtx.timer.beginEvent (requestPath+" execute"); localrtx.timer.beginEvent (requestPath+" execute");
int actionDot = action.lastIndexOf (".");
boolean isAction = actionDot == -1;
// set the req.action property, cutting off the _action suffix // set the req.action property, cutting off the _action suffix
req.action = action.substring (0, action.length()-7); if (isAction)
req.action = action.substring (0, action.length()-7);
else
req.action = action;
// try calling onRequest() function on object before // try calling onRequest() function on object before
// calling the actual action // calling the actual action
try { try {
@ -357,7 +362,16 @@ public class RequestEvaluator implements Runnable {
// function is not defined or caused an exception, ignore // function is not defined or caused an exception, ignore
} }
// do the actual action invocation // do the actual action invocation
current.doIndirectCall (evaluator, current, action, new ESValue[0]); if (isAction)
current.doIndirectCall (evaluator, current, action, new ESValue[0]);
else {
Skin skin = getSkinInternal (app.appDir, app.getPrototype(currentElement).getName(), action.substring (0, actionDot), action.substring (actionDot+1));
if (skin != null)
skin.render (this, current.toJavaObject (), null);
else
throw new RuntimeException ("Skin "+action+" not found in "+req.path);
}
// check if the script set the name of a skin to render in res.skin // check if the script set the name of a skin to render in res.skin
if (res.skin != null) { if (res.skin != null) {
@ -820,103 +834,107 @@ public class RequestEvaluator implements Runnable {
Object elem = thisObject.toJavaObject (); Object elem = thisObject.toJavaObject ();
proto = app.getPrototype (elem); proto = app.getPrototype (elem);
} }
return getSkin (proto, skinname); return getSkin (proto, skinname, "skin");
} }
public Skin getSkin (Prototype proto, String skinname) { public Skin getSkin (Prototype proto, String skinname, String extension) {
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
SkinKey key = new SkinKey (proto.getName(), skinname); SkinKey key = new SkinKey (proto.getName(), skinname, extension);
Skin skin = (Skin) skincache.get (key); Skin skin = (Skin) skincache.get (key);
if (skin != null) { if (skin != null) {
return skin; return skin;
} }
// check for skin path // check for skinsets set via res.skinpath property
if (res.skinpath != null) { if (skinsets == null)
File f = new File (res.skinpath, proto.getName()); getSkinSets ();
f = new File (f, skinname+".skin");
if (f.exists ()) {
SkinFile sf = new SkinFile (f, skinname, proto);
skin = sf.getSkin ();
if (skin != null)
return skin;
}
}
// check for Helma-internal skinmanager nodes
if (skinmanagers == null)
getSkinManagers ();
do { do {
for (int i=0; i<skinmanagers.length; i++) { for (int i=0; i<skinsets.length; i++) {
skin = getSkinFromNode (skinmanagers[i], proto.getName (), skinname); skin = getSkinInternal (skinsets[i], proto.getName (), skinname, extension);
if (skin != null) { if (skin != null) {
skincache.put (key, skin); skincache.put (key, skin);
return skin; return skin;
} }
} }
// not found in node managers for this prototype. // skin for this prototype wasn't found in the skinsets.
// the next step is to look if it is defined as skin file for this prototype // the next step is to look if it is defined as skin file in the application directory
skin = proto.getSkin (skinname); skin = proto.getSkin (skinname);
if (skin != null) { if (skin != null) {
skincache.put (key, skin); skincache.put (key, skin);
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.getParentPrototype (); 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;
} }
private Skin getSkinFromNode (INode node, String prototype, String skinname) { private Skin getSkinInternal (Object skinset, String prototype, String skinname, String extension) {
if (prototype == null) if (prototype == null || skinset == null)
return null; return null;
INode n = node.getNode (prototype, false); // check if the skinset object is a HopObject (db based skin)
if (n != null) { // or a String (file based skin)
n = n.getNode (skinname, false); if (skinset instanceof INode) {
INode n = ((INode) skinset).getNode (prototype, false);
if (n != null) { if (n != null) {
String skin = n.getString ("skin", false); n = n.getNode (skinname, false);
if (skin != null) { if (n != null) {
Skin s = (Skin) app.skincache.get (skin); String skin = n.getString (extension, false);
if (s == null) { if (skin != null) {
s = new Skin (skin, app); Skin s = (Skin) app.skincache.get (skin);
app.skincache.put (skin, s); if (s == null) {
s = new Skin (skin, app);
app.skincache.put (skin, s);
}
return 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. // 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. // the sequence is prototype.skin-from-db, prototype.skin-from-file, parent.from-db, parent.from-file etc.
return null; return null;
} }
/** /**
* Get an array of skin managers for a request path so it is retrieved ony once per request * Get an array of skin managers for a request path so it is retrieved ony once per request
*/ */
private void getSkinManagers () { private void getSkinSets () {
Vector v = new Vector (); Vector v = new Vector ();
for (int i=reqPath.size()-1; i>=0; i--) try { if (res.skinpath != null && res.skinpath instanceof JSWrapper) {
ESNode esn = (ESNode) reqPath.getProperty (i); try {
INode n = esn.getNode (); ArrayPrototype sp = (ArrayPrototype) ((JSWrapper) res.skinpath).getESObject ();
DbMapping dbm = n.getDbMapping (); for (int i=0; i<sp.size(); i++) {
if (dbm == null) ESValue esv = sp.getProperty (i);
continue; if (esv instanceof ESNode) {
String[] skinmgr = dbm.getSkinManagers(); // add internal, db-based skinset
if (skinmgr == null) INode n = ((ESNode) esv).getNode ();
continue; v.addElement (n);
for (int j=0; j<skinmgr.length; j++) { } else {
INode sm = n.getNode (skinmgr[j], false); // add external, file based skinset
if (sm != null) v.addElement (esv.toString ());
v.addElement (sm); }
}
} catch (Exception x) {
app.logEvent ("Error resolving res.skinpath "+res.skinpath+": "+x);
} }
} catch (Exception ignore) { } }
skinmanagers = new INode[v.size()]; skinsets = new Object[v.size()];
v.copyInto (skinmanagers); v.copyInto (skinsets);
} }
/** /**
@ -926,12 +944,28 @@ public class RequestEvaluator implements Runnable {
public String getAction (ESObject obj, String action) { public String getAction (ESObject obj, String action) {
if (obj == null) if (obj == null)
return null; return null;
String act = action == null ? "main_action" : action+"_action"; // check if this is a public skin, i.e. something with an extension
try { // like "home.html"
ESValue esv = obj.getProperty (act, act.hashCode()); if (action != null && action.indexOf (".") > -1) {
if (esv != null && esv instanceof FunctionPrototype) int dot = action.lastIndexOf (".");
return act; String extension = action.substring (dot+1);
} catch (EcmaScriptException notfound) {} String contentType = app.skinExtensions.getProperty (extension);
if (contentType != null) {
res.contentType = contentType;
return action;
} else
return null;
} else {
String act = action == null ? "main_action" : action+"_action";
try {
ESObject proto = obj.getPrototype ();
if (proto != null) {
ESValue esv = proto.getProperty (act, act.hashCode());
if (esv != null && esv instanceof FunctionPrototype)
return act;
}
} catch (EcmaScriptException notfound) {}
}
return null; return null;
} }
@ -1127,24 +1161,25 @@ public class RequestEvaluator implements Runnable {
*/ */
final class SkinKey { final class SkinKey {
final String first, second; final String first, second, third;
public SkinKey (String first, String second) { public SkinKey (String first, String second, String third) {
this.first = first; this.first = first;
this.second = second; this.second = second;
this.third = third;
} }
public boolean equals (Object other) { public boolean equals (Object other) {
try { try {
SkinKey key = (SkinKey) other; SkinKey key = (SkinKey) other;
return first.equals (key.first) && second.equals (key.second); return first.equals (key.first) && second.equals (key.second) && third.equals (key.third);
} catch (Exception x) { } catch (Exception x) {
return false; return false;
} }
} }
public int hashCode () { public int hashCode () {
return first.hashCode () + second.hashCode (); return first.hashCode () + second.hashCode () + third.hashCode ();
} }
} }
} }