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 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")
 | 
			
		||||
| 
						 | 
				
			
			@ -154,8 +154,8 @@ public class RequestEvaluator implements Runnable {
 | 
			
		|||
	    // object refs to ressolve request path
 | 
			
		||||
	    Object root, currentElement;
 | 
			
		||||
	
 | 
			
		||||
	    // reset skinManager
 | 
			
		||||
	    skinmanagers = null;
 | 
			
		||||
	    // reset skinsets array and skin cache
 | 
			
		||||
	    skinsets = null;
 | 
			
		||||
	    skincache.clear ();
 | 
			
		||||
 | 
			
		||||
	    switch (reqtype) {
 | 
			
		||||
| 
						 | 
				
			
			@ -209,7 +209,6 @@ public class RequestEvaluator implements Runnable {
 | 
			
		|||
	                req.data = reqData;
 | 
			
		||||
	                resData.setData (res.getResponseData());
 | 
			
		||||
	                res.data = resData;
 | 
			
		||||
	                res.skinpath = app.getProperty ("skinpath");
 | 
			
		||||
 | 
			
		||||
	                try {
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -345,8 +344,14 @@ public class RequestEvaluator implements Runnable {
 | 
			
		|||
	                try {
 | 
			
		||||
	                    localrtx.timer.beginEvent (requestPath+" execute");
 | 
			
		||||
 | 
			
		||||
	                    int actionDot = action.lastIndexOf (".");
 | 
			
		||||
	                    boolean isAction =  actionDot == -1;
 | 
			
		||||
	                    // 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
 | 
			
		||||
	                    // calling the actual action
 | 
			
		||||
	                    try {
 | 
			
		||||
| 
						 | 
				
			
			@ -357,7 +362,16 @@ public class RequestEvaluator implements Runnable {
 | 
			
		|||
	                        // function is not defined or caused an exception, ignore
 | 
			
		||||
	                    }
 | 
			
		||||
	                    // 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
 | 
			
		||||
	                    if (res.skin != null) {
 | 
			
		||||
| 
						 | 
				
			
			@ -820,49 +834,38 @@ public class RequestEvaluator implements Runnable {
 | 
			
		|||
	    Object elem = thisObject.toJavaObject ();
 | 
			
		||||
	    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)
 | 
			
		||||
	    return null;
 | 
			
		||||
	// 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);
 | 
			
		||||
	if (skin != null) {
 | 
			
		||||
	    return skin;
 | 
			
		||||
	}
 | 
			
		||||
	// check for skin path
 | 
			
		||||
	if (res.skinpath != null) {
 | 
			
		||||
	    File f = new File (res.skinpath, proto.getName());
 | 
			
		||||
	    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 ();
 | 
			
		||||
	// check for skinsets set via res.skinpath property
 | 
			
		||||
	if (skinsets == null)
 | 
			
		||||
	    getSkinSets ();
 | 
			
		||||
	do {
 | 
			
		||||
	    for (int i=0; i<skinmanagers.length; i++) {
 | 
			
		||||
	        skin = getSkinFromNode (skinmanagers[i], proto.getName (), skinname);
 | 
			
		||||
	    for (int i=0; i<skinsets.length; i++) {
 | 
			
		||||
	        skin = getSkinInternal (skinsets[i], proto.getName (), skinname, extension);
 | 
			
		||||
	        if (skin != null) {
 | 
			
		||||
	            skincache.put (key, skin);
 | 
			
		||||
	            return skin;
 | 
			
		||||
	        }
 | 
			
		||||
	    }
 | 
			
		||||
	    // not found in node managers for this prototype.
 | 
			
		||||
	    // the next step is to look if it is defined as skin file 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 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
 | 
			
		||||
	    // 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
 | 
			
		||||
| 
						 | 
				
			
			@ -870,53 +873,68 @@ public class RequestEvaluator implements Runnable {
 | 
			
		|||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    private Skin getSkinFromNode (INode node, String prototype, String skinname) {
 | 
			
		||||
	if (prototype == null)
 | 
			
		||||
    private Skin getSkinInternal (Object skinset, String prototype, String skinname, String extension) {
 | 
			
		||||
	if (prototype == null || skinset == null)
 | 
			
		||||
	    return null;
 | 
			
		||||
	INode n = node.getNode (prototype, false);
 | 
			
		||||
	if (n != null) {
 | 
			
		||||
	    n = n.getNode (skinname, 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) {
 | 
			
		||||
	        String skin = n.getString ("skin", false);
 | 
			
		||||
	        if (skin != null) {
 | 
			
		||||
	            Skin s = (Skin) app.skincache.get (skin);
 | 
			
		||||
	            if (s == null) {
 | 
			
		||||
	                s = new Skin (skin, app);
 | 
			
		||||
	                app.skincache.put (skin, s);
 | 
			
		||||
	        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;
 | 
			
		||||
	            }
 | 
			
		||||
	            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;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Get an array of skin managers for a request path so it is retrieved ony once per request
 | 
			
		||||
     */
 | 
			
		||||
     private void getSkinManagers () {
 | 
			
		||||
 	Vector v = new Vector ();
 | 
			
		||||
	for (int i=reqPath.size()-1; i>=0; i--) try {
 | 
			
		||||
	    ESNode esn = (ESNode) reqPath.getProperty (i);
 | 
			
		||||
	    INode n = esn.getNode ();
 | 
			
		||||
	    DbMapping dbm = n.getDbMapping ();
 | 
			
		||||
	    if (dbm == null)
 | 
			
		||||
	        continue;
 | 
			
		||||
	    String[] skinmgr = dbm.getSkinManagers();
 | 
			
		||||
	    if (skinmgr == null)
 | 
			
		||||
	        continue;
 | 
			
		||||
	    for (int j=0; j<skinmgr.length; j++) {
 | 
			
		||||
	        INode sm = n.getNode (skinmgr[j], false);
 | 
			
		||||
	        if (sm != null)
 | 
			
		||||
	            v.addElement (sm);
 | 
			
		||||
     private void getSkinSets () {
 | 
			
		||||
	Vector v = new Vector ();
 | 
			
		||||
	if (res.skinpath != null && res.skinpath instanceof JSWrapper) {
 | 
			
		||||
	    try {
 | 
			
		||||
	        ArrayPrototype sp = (ArrayPrototype) ((JSWrapper) res.skinpath).getESObject ();
 | 
			
		||||
	        for (int i=0; i<sp.size(); i++) {
 | 
			
		||||
	            ESValue esv = sp.getProperty (i);
 | 
			
		||||
	            if (esv instanceof ESNode) {
 | 
			
		||||
	                // add internal, db-based skinset
 | 
			
		||||
	                INode n = ((ESNode) esv).getNode ();
 | 
			
		||||
	                v.addElement (n);
 | 
			
		||||
	            } else {
 | 
			
		||||
	                // add external, file based skinset
 | 
			
		||||
	                v.addElement (esv.toString ());
 | 
			
		||||
	            }
 | 
			
		||||
	        }
 | 
			
		||||
	    } catch (Exception x) {
 | 
			
		||||
	        app.logEvent ("Error resolving res.skinpath "+res.skinpath+": "+x);
 | 
			
		||||
	    }
 | 
			
		||||
	} catch (Exception ignore) { }
 | 
			
		||||
	skinmanagers = new INode[v.size()];
 | 
			
		||||
	v.copyInto (skinmanagers);
 | 
			
		||||
	}
 | 
			
		||||
	skinsets = new Object[v.size()];
 | 
			
		||||
	v.copyInto (skinsets);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
| 
						 | 
				
			
			@ -926,12 +944,28 @@ public class RequestEvaluator implements Runnable {
 | 
			
		|||
    public String getAction (ESObject obj, String action) {
 | 
			
		||||
	if (obj == null)
 | 
			
		||||
	    return null;
 | 
			
		||||
	String act = action == null ? "main_action" : action+"_action";
 | 
			
		||||
	try {
 | 
			
		||||
	    ESValue esv = obj.getProperty (act, act.hashCode());
 | 
			
		||||
	    if (esv != null && esv instanceof FunctionPrototype)
 | 
			
		||||
	        return act;
 | 
			
		||||
	} catch (EcmaScriptException notfound) {}
 | 
			
		||||
	// 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";
 | 
			
		||||
	    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;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1127,24 +1161,25 @@ public class RequestEvaluator implements Runnable {
 | 
			
		|||
     */
 | 
			
		||||
    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.second = second;
 | 
			
		||||
	    this.third = third;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public boolean equals (Object other) {
 | 
			
		||||
	    try {
 | 
			
		||||
	        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) {
 | 
			
		||||
	        return false;
 | 
			
		||||
	    }
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	public int hashCode () {
 | 
			
		||||
	    return first.hashCode () + second.hashCode ();
 | 
			
		||||
	    return first.hashCode () + second.hashCode () + third.hashCode ();
 | 
			
		||||
	}
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue