Initial implementation of new skin path resolution schema and
public skins. Some further work needed in both areas.
This commit is contained in:
parent
1a777b5c5a
commit
7041bf08e7
1 changed files with 108 additions and 73 deletions
|
@ -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
|
||||||
|
if (isAction)
|
||||||
req.action = action.substring (0, action.length()-7);
|
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
|
||||||
|
if (isAction)
|
||||||
current.doIndirectCall (evaluator, current, action, new ESValue[0]);
|
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,49 +834,38 @@ 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
|
||||||
|
@ -870,14 +873,17 @@ public class RequestEvaluator implements Runnable {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
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)
|
||||||
|
// or a String (file based skin)
|
||||||
|
if (skinset instanceof INode) {
|
||||||
|
INode n = ((INode) skinset).getNode (prototype, false);
|
||||||
if (n != null) {
|
if (n != null) {
|
||||||
n = n.getNode (skinname, false);
|
n = n.getNode (skinname, false);
|
||||||
if (n != null) {
|
if (n != null) {
|
||||||
String skin = n.getString ("skin", false);
|
String skin = n.getString (extension, false);
|
||||||
if (skin != null) {
|
if (skin != null) {
|
||||||
Skin s = (Skin) app.skincache.get (skin);
|
Skin s = (Skin) app.skincache.get (skin);
|
||||||
if (s == null) {
|
if (s == null) {
|
||||||
|
@ -888,35 +894,47 @@ public class RequestEvaluator implements Runnable {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} 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 ignore) { }
|
}
|
||||||
skinmanagers = new INode[v.size()];
|
} catch (Exception x) {
|
||||||
v.copyInto (skinmanagers);
|
app.logEvent ("Error resolving res.skinpath "+res.skinpath+": "+x);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
skinsets = new Object[v.size()];
|
||||||
|
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;
|
||||||
|
// check if this is a public skin, i.e. something with an extension
|
||||||
|
// like "home.html"
|
||||||
|
if (action != null && action.indexOf (".") > -1) {
|
||||||
|
int dot = action.lastIndexOf (".");
|
||||||
|
String extension = action.substring (dot+1);
|
||||||
|
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";
|
String act = action == null ? "main_action" : action+"_action";
|
||||||
try {
|
try {
|
||||||
ESValue esv = obj.getProperty (act, act.hashCode());
|
ESObject proto = obj.getPrototype ();
|
||||||
|
if (proto != null) {
|
||||||
|
ESValue esv = proto.getProperty (act, act.hashCode());
|
||||||
if (esv != null && esv instanceof FunctionPrototype)
|
if (esv != null && esv instanceof FunctionPrototype)
|
||||||
return act;
|
return act;
|
||||||
|
}
|
||||||
} catch (EcmaScriptException notfound) {}
|
} 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 ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue