The basic operations now use the IPathElement interface instead

of INode: Path resolution in RequestEvaluator, skin rendering,
and href() function.
Application will check the rootObject property in the
app.properties file and try to create a custom root object, if set.
This commit is contained in:
hns 2001-08-13 13:10:41 +00:00
parent 1b0c4329e5
commit a2dcc29cec
7 changed files with 186 additions and 83 deletions

View file

@ -75,6 +75,11 @@ public class Application extends UnicastRemoteObject implements IRemoteApp, IRep
private DbMapping rootMapping, userRootMapping, userMapping; private DbMapping rootMapping, userRootMapping, userMapping;
// the root of the website, if a custom root object is defined.
// otherwise this is managed by the NodeManager and not cached here.
IPathElement rootObject = null;
String rootObjectClass;
boolean checkSubnodes; boolean checkSubnodes;
String charset; String charset;
@ -131,6 +136,9 @@ public class Application extends UnicastRemoteObject implements IRemoteApp, IRep
debug = "true".equalsIgnoreCase (props.getProperty ("debug")); debug = "true".equalsIgnoreCase (props.getProperty ("debug"));
checkSubnodes = !"false".equalsIgnoreCase (props.getProperty ("subnodeChecking")); checkSubnodes = !"false".equalsIgnoreCase (props.getProperty ("subnodeChecking"));
// get class name of root object if defined. Otherwise native Helma objectmodel will be used.
rootObjectClass = props.getProperty ("rootObject");
try { try {
requestTimeout = Long.parseLong (props.getProperty ("requestTimeout", "60"))*1000l; requestTimeout = Long.parseLong (props.getProperty ("requestTimeout", "60"))*1000l;
} catch (Exception ignore) { } } catch (Exception ignore) { }
@ -333,7 +341,20 @@ public class Application extends UnicastRemoteObject implements IRemoteApp, IRep
// do nothing // do nothing
} }
public INode getDataRoot () { public IPathElement getDataRoot () {
if (rootObjectClass != null) {
// create custom root element.
// NOTE: This is but a very rough first sketch of an implementation
// and needs much more care.
if (rootObject == null) try {
Class c = Class.forName (rootObjectClass);
rootObject = (IPathElement) c.newInstance ();
} catch (Throwable x) {
System.err.println ("ERROR CREATING ROOT OBJECT: "+x);
}
return rootObject;
}
// no custom root object is defined - use standard helma objectmodel
INode root = nmgr.safe.getNode ("0", rootMapping); INode root = nmgr.safe.getNode ("0", rootMapping);
root.setDbMapping (rootMapping); root.setDbMapping (rootMapping);
return root; return root;
@ -365,7 +386,7 @@ public class Application extends UnicastRemoteObject implements IRemoteApp, IRep
* Return a prototype for a given node. If the node doesn't specify a prototype, * Return a prototype for a given node. If the node doesn't specify a prototype,
* return the generic hopobject prototype. * return the generic hopobject prototype.
*/ */
public Prototype getPrototype (INode n) { public Prototype getPrototype (IPathElement n) {
String protoname = n.getPrototype (); String protoname = n.getPrototype ();
if (protoname == null) if (protoname == null)
return typemgr.getPrototype ("hopobject"); return typemgr.getPrototype ("hopobject");
@ -444,7 +465,7 @@ public class Application extends UnicastRemoteObject implements IRemoteApp, IRep
if (pw != null && pw.equals (password)) { if (pw != null && pw.equals (password)) {
// give the user her piece of persistence // give the user her piece of persistence
u.setNode (unode); u.setNode (unode);
activeUsers.put (unode.getNameOrID (), u.user); activeUsers.put (unode.getName (), u.user);
return true; return true;
} }
@ -477,29 +498,69 @@ public class Application extends UnicastRemoteObject implements IRemoteApp, IRep
return pwfile.authenticate (uname, password); return pwfile.authenticate (uname, password);
} }
public String getNodePath (INode n, String tmpname) { /* public String getNodePath (INode n, String tmpname) {
INode root = getDataRoot (); // FIXME: will fail for non-node roots
INode root = (INode) getDataRoot ();
INode users = getUserRoot (); INode users = getUserRoot ();
String siteroot = props.getProperty ("rootPrototype"); String siteroot = props.getProperty ("rootPrototype");
String href = n.getUrl (root, users, tmpname, siteroot); String href = n.getUrl (root, users, tmpname, siteroot);
return href; return href;
} } */
public String getNodeHref (INode n, String tmpname) { /**
INode root = getDataRoot (); * Return a path to be used in a URL pointing to the given element and action
*/
public String getNodeHref (IPathElement elem, String actionName) {
// FIXME: will fail for non-node roots
IPathElement root = getDataRoot ();
INode users = getUserRoot (); INode users = getUserRoot ();
// check base uri and optional root prototype from app.properties // check base uri and optional root prototype from app.properties
String base = props.getProperty ("baseURI"); String base = props.getProperty ("baseURI");
String siteroot = props.getProperty ("rootPrototype"); String rootproto = props.getProperty ("rootPrototype");
if (base != null || baseURI == null) if (base != null || baseURI == null)
setBaseURI (base); setBaseURI (base);
String href = n.getUrl (root, users, tmpname, siteroot);
// String href = n.getUrl (root, users, tmpname, siteroot);
String divider = "/";
StringBuffer b = new StringBuffer ();
IPathElement p = elem;
int loopWatch = 0;
while (p != null && p.getParentElement () != null && p != root) {
if (rootproto != null && rootproto.equals (p.getPrototype ()))
break;
b.insert (0, divider);
// users always have a canonical URL like /users/username
if ("user".equals (p.getPrototype ())) {
b.insert (0, UrlEncoder.encode (p.getElementName ()));
p = users;
break;
}
b.insert (0, UrlEncoder.encode (p.getElementName ()));
p = p.getParentElement ();
if (loopWatch++ > 20)
break;
}
if (p == users) {
b.insert (0, divider);
b.insert (0, "users");
}
String href = b.toString()+UrlEncoder.encode (actionName);
return baseURI + href; return baseURI + href;
} }
public void setBaseURI (String uri) { public void setBaseURI (String uri) {
if (uri == null) if (uri == null)
this.baseURI = "/"; this.baseURI = "/";

View file

@ -130,7 +130,7 @@ public class ESAppNode extends ESNode {
public String toString () { public String toString () {
return ("AppNode "+node.getNameOrID ()); return ("AppNode "+node.getElementName ());
} }
} }

View file

@ -412,7 +412,11 @@ public class ESNode extends ObjectPrototype {
public void clearError() { public void clearError() {
lastError = null; lastError = null;
} }
public Object toJavaObject () {
return getNode ();
}
/** /**
* An ESNode equals another object if it is an ESNode that wraps the same INode * An ESNode equals another object if it is an ESNode that wraps the same INode
* or the wrapped INode itself. FIXME: doesen't check dbmapping/type! * or the wrapped INode itself. FIXME: doesen't check dbmapping/type!

View file

@ -5,6 +5,7 @@ package helma.framework.core;
import helma.objectmodel.*; import helma.objectmodel.*;
import helma.util.*; import helma.util.*;
import helma.framework.IPathElement;
import FESI.Interpreter.*; import FESI.Interpreter.*;
import FESI.Exceptions.*; import FESI.Exceptions.*;
import FESI.Extensions.*; import FESI.Extensions.*;
@ -76,7 +77,7 @@ public class HopExtension {
reval.esNodePrototype.putHiddenProperty ("editor", new NodeEditor ("editor", evaluator, fp)); reval.esNodePrototype.putHiddenProperty ("editor", new NodeEditor ("editor", evaluator, fp));
reval.esNodePrototype.putHiddenProperty ("chooser", new NodeChooser ("chooser", evaluator, fp)); reval.esNodePrototype.putHiddenProperty ("chooser", new NodeChooser ("chooser", evaluator, fp));
reval.esNodePrototype.putHiddenProperty ("multiChooser", new MultiNodeChooser ("multiChooser", evaluator, fp)); reval.esNodePrototype.putHiddenProperty ("multiChooser", new MultiNodeChooser ("multiChooser", evaluator, fp));
reval.esNodePrototype.putHiddenProperty ("path", new NodePath ("path", evaluator, fp)); reval.esNodePrototype.putHiddenProperty ("path", new NodeHref ("path", evaluator, fp));
reval.esNodePrototype.putHiddenProperty ("href", new NodeHref ("href", evaluator, fp)); reval.esNodePrototype.putHiddenProperty ("href", new NodeHref ("href", evaluator, fp));
reval.esNodePrototype.putHiddenProperty ("setParent", new NodeSetParent ("setParent", evaluator, fp)); reval.esNodePrototype.putHiddenProperty ("setParent", new NodeSetParent ("setParent", evaluator, fp));
reval.esNodePrototype.putHiddenProperty ("invalidate", new NodeInvalidate ("invalidate", evaluator, fp)); reval.esNodePrototype.putHiddenProperty ("invalidate", new NodeInvalidate ("invalidate", evaluator, fp));
@ -574,12 +575,12 @@ public class HopExtension {
this.global = global; this.global = global;
this.asString = asString; this.asString = asString;
} }
public ESValue callFunction (ESObject thisObject, ESValue[] arguments) throws EcmaScriptException { public ESValue callFunction (ESObject thisObj, ESValue[] arguments) throws EcmaScriptException {
if (arguments.length < 1 || arguments.length > 2 || arguments[0] ==null || arguments[0] == ESNull.theNull) if (arguments.length < 1 || arguments.length > 2 || arguments[0] ==null || arguments[0] == ESNull.theNull)
throw new EcmaScriptException ("renderSkin must be called with one Skin argument and an optional parameter argument"); throw new EcmaScriptException ("renderSkin must be called with one Skin argument and an optional parameter argument");
try { try {
Skin skin = null; Skin skin = null;
ESNode handlerNode = global ? null : (ESNode) thisObject; ESObject thisObject = global ? null : thisObj;
ESObject paramObject = null; ESObject paramObject = null;
if (arguments.length > 1 && arguments[1] instanceof ESObject) if (arguments.length > 1 && arguments[1] instanceof ESObject)
paramObject = (ESObject) arguments[1]; paramObject = (ESObject) arguments[1];
@ -592,11 +593,11 @@ public class HopExtension {
} }
if (skin == null) if (skin == null)
skin = reval.getSkin (handlerNode, arguments[0].toString ()); skin = reval.getSkin (thisObject, arguments[0].toString ());
if (asString) if (asString)
reval.res.pushStringBuffer (); reval.res.pushStringBuffer ();
if (skin != null) if (skin != null)
skin.render (reval, handlerNode, paramObject); skin.render (reval, thisObject, paramObject);
else else
reval.res.write ("[Skin not found: "+arguments[0]+"]"); reval.res.write ("[Skin not found: "+arguments[0]+"]");
if (asString) if (asString)
@ -916,7 +917,7 @@ public class HopExtension {
} }
class NodePath extends BuiltinFunctionObject { /* class NodePath extends BuiltinFunctionObject {
NodePath (String name, Evaluator evaluator, FunctionPrototype fp) { NodePath (String name, Evaluator evaluator, FunctionPrototype fp) {
super (fp, evaluator, name, 1); super (fp, evaluator, name, 1);
} }
@ -925,7 +926,7 @@ public class HopExtension {
String tmpname = arguments[0].toString (); String tmpname = arguments[0].toString ();
return new ESString (app.getNodePath (n, tmpname)); return new ESString (app.getNodePath (n, tmpname));
} }
} } */
class NodeSetParent extends BuiltinFunctionObject { class NodeSetParent extends BuiltinFunctionObject {
NodeSetParent (String name, Evaluator evaluator, FunctionPrototype fp) { NodeSetParent (String name, Evaluator evaluator, FunctionPrototype fp) {
@ -943,33 +944,33 @@ public class HopExtension {
super (fp, evaluator, name, 1); super (fp, evaluator, name, 1);
} }
public ESValue callFunction (ESObject thisObject, ESValue[] arguments) throws EcmaScriptException { public ESValue callFunction (ESObject thisObject, ESValue[] arguments) throws EcmaScriptException {
INode n = ((ESNode) thisObject).getNode (); IPathElement elem = (IPathElement) thisObject.toJavaObject ();
String tmpname = arguments.length == 0 ? "" : arguments[0].toString (); String tmpname = arguments.length == 0 ? "" : arguments[0].toString ();
String basicHref =app.getNodeHref (n, tmpname); String basicHref =app.getNodeHref (elem, tmpname);
String hrefSkin = app.props.getProperty ("hrefSkin"); String hrefSkin = app.props.getProperty ("hrefSkin");
// FIXME: we should actually walk down the path from the object we called href() on // FIXME: we should actually walk down the path from the object we called href() on
// instead we move down the URL path. // instead we move down the URL path.
if (hrefSkin != null) { if (hrefSkin != null) {
// we need to post-process the href with a skin for this application // we need to post-process the href with a skin for this application
// first, look in the object href was called on. // first, look in the object href was called on.
INode sn = n; IPathElement skinElem = elem;
Skin skin = null; Skin skin = null;
while (skin == null && sn != null) { while (skin == null && skinElem != null) {
Prototype proto = app.getPrototype (sn); Prototype proto = app.getPrototype (skinElem);
if (proto != null) if (proto != null)
skin = proto.getSkin (hrefSkin); skin = proto.getSkin (hrefSkin);
if (skin == null) if (skin == null)
sn = sn.getParent (); skinElem = skinElem.getParentElement ();
} }
if (skin != null) { if (skin != null) {
ESNode esn = reval.getNodeWrapper (sn); ESObject eso = reval.getElementWrapper (skinElem);
return renderSkin (skin, basicHref, esn); return renderSkin (skin, basicHref, eso);
} }
} }
return new ESString (basicHref); return new ESString (basicHref);
} }
private ESString renderSkin (Skin skin, String path, ESNode obj) throws EcmaScriptException { private ESString renderSkin (Skin skin, String path, ESObject obj) throws EcmaScriptException {
reval.res.pushStringBuffer (); reval.res.pushStringBuffer ();
ESObject param = new ObjectPrototype (null, reval.evaluator); ESObject param = new ObjectPrototype (null, reval.evaluator);
param.putProperty ("path", new ESString (path), "path".hashCode ()); param.putProperty ("path", new ESString (path), "path".hashCode ());
@ -1040,7 +1041,7 @@ public class HopExtension {
buffer.append ("<input type=radio name=\""); buffer.append ("<input type=radio name=\"");
buffer.append (name); buffer.append (name);
buffer.append ("\" value=\""); buffer.append ("\" value=\"");
buffer.append (next.getNameOrID ()+"\""); buffer.append (next.getElementName ()+"\"");
if (target == next) if (target == next)
buffer.append (" checked"); buffer.append (" checked");
buffer.append (">"); buffer.append (">");
@ -1062,7 +1063,7 @@ public class HopExtension {
buffer.append ("<input type=checkbox name=\""); buffer.append ("<input type=checkbox name=\"");
buffer.append (name); buffer.append (name);
buffer.append ("\" value="); buffer.append ("\" value=");
buffer.append (next.getNameOrID ()); buffer.append (next.getElementName ());
if (target.contains (next) > -1) if (target.contains (next) > -1)
buffer.append (" checked"); buffer.append (" checked");
buffer.append (">"); buffer.append (">");

View file

@ -77,7 +77,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 root, userroot, currentNode; // INode root, currentNode;
INode[] skinmanagers; INode[] skinmanagers;
/** /**
@ -99,6 +99,7 @@ public class RequestEvaluator implements Runnable {
private void initEvaluator () { private void initEvaluator () {
try { try {
evaluator = new Evaluator(); evaluator = new Evaluator();
evaluator.reval = this;
global = evaluator.getGlobalObject(); global = evaluator.getGlobalObject();
for (int i=0; i<extensions.length; i++) for (int i=0; i<extensions.length; i++)
evaluator.addExtension (extensions[i]); evaluator.addExtension (extensions[i]);
@ -140,7 +141,7 @@ public class RequestEvaluator implements Runnable {
try { try {
do { do {
// app.logEvent ("got request "+reqtype); IPathElement root, currentElement;
// reset skinManager // reset skinManager
skinmanagers = null; skinmanagers = null;
@ -152,7 +153,7 @@ public class RequestEvaluator implements Runnable {
while (!done) { while (!done) {
current = null; current = null;
currentNode = null; currentElement = null;
reqPath.setSize (0); reqPath.setSize (0);
// delete path objects-via-prototype // delete path objects-via-prototype
for (Enumeration en=reqPath.getAllProperties(); en.hasMoreElements(); ) { for (Enumeration en=reqPath.getAllProperties(); en.hasMoreElements(); ) {
@ -176,7 +177,7 @@ public class RequestEvaluator implements Runnable {
ESUser esu = (ESUser) getNodeWrapper (user); ESUser esu = (ESUser) getNodeWrapper (user);
// esu.setUser (user); // esu.setUser (user);
global.putHiddenProperty ("root", getNodeWrapper (root)); global.putHiddenProperty ("root", getElementWrapper (root));
global.putHiddenProperty("user", esu); global.putHiddenProperty("user", esu);
global.putHiddenProperty ("req", new ESWrapper (req, evaluator)); global.putHiddenProperty ("req", new ESWrapper (req, evaluator));
global.putHiddenProperty ("res", new ESWrapper (res, evaluator)); global.putHiddenProperty ("res", new ESWrapper (res, evaluator));
@ -197,8 +198,8 @@ public class RequestEvaluator implements Runnable {
if (error != null) { if (error != null) {
// there was an error in the previous loop, call error handler // there was an error in the previous loop, call error handler
currentNode = root; currentElement = root;
current = getNodeWrapper (root); current = getElementWrapper (root);
reqPath.putProperty (0, current); reqPath.putProperty (0, current);
reqPath.putHiddenProperty ("root", current); reqPath.putHiddenProperty ("root", current);
Prototype p = app.getPrototype (root); Prototype p = app.getPrototype (root);
@ -208,8 +209,8 @@ public class RequestEvaluator implements Runnable {
throw new RuntimeException (error); throw new RuntimeException (error);
} else if (req.path == null || "".equals (req.path.trim ())) { } else if (req.path == null || "".equals (req.path.trim ())) {
currentNode = root; currentElement = root;
current = getNodeWrapper (root); current = getElementWrapper (root);
reqPath.putProperty (0, current); reqPath.putProperty (0, current);
reqPath.putHiddenProperty ("root", current); reqPath.putHiddenProperty ("root", current);
Prototype p = app.getPrototype (root); Prototype p = app.getPrototype (root);
@ -233,38 +234,38 @@ public class RequestEvaluator implements Runnable {
for (int i=0; i<ntokens; i++) for (int i=0; i<ntokens; i++)
pathItems[i] = st.nextToken (); pathItems[i] = st.nextToken ();
currentNode = root; currentElement = root;
current = getNodeWrapper (root); current = getElementWrapper (root);
reqPath.putProperty (0, current); reqPath.putProperty (0, current);
reqPath.putHiddenProperty ("root", current); reqPath.putHiddenProperty ("root", current);
for (int i=0; i<ntokens; i++) { for (int i=0; i<ntokens; i++) {
if (currentNode == null) if (currentElement == null)
throw new FrameworkException ("Object not found."); throw new FrameworkException ("Object not found.");
// the first token in the path needs to be treated seprerately, // the first token in the path needs to be treated seprerately,
// because "/user" is a shortcut to the current user session, while "/users" // because "/user" is a shortcut to the current user session, while "/users"
// is the mounting point for all users. // is the mounting point for all users.
if (i == 0 && "user".equalsIgnoreCase (pathItems[i])) { if (i == 0 && "user".equalsIgnoreCase (pathItems[i])) {
currentNode = user.getNode (); // currentElement = user.getNode ();
if (currentNode != null) { if (currentElement != null) {
current = getNodeWrapper (currentNode); current = getElementWrapper (currentElement);
reqPath.putProperty (1, current); reqPath.putProperty (1, current);
reqPath.putHiddenProperty ("user", current); reqPath.putHiddenProperty ("user", current);
} }
} else if (i == 0 && "users".equalsIgnoreCase (pathItems[i])) { } else if (i == 0 && "users".equalsIgnoreCase (pathItems[i])) {
currentNode = app.getUserRoot (); // currentElement = app.getUserRoot ();
isProperty = true; // isProperty = true;
if (currentNode != null) { if (currentElement != null) {
current = getNodeWrapper (currentNode); current = getElementWrapper (currentElement);
reqPath.putProperty (1, current); reqPath.putProperty (1, current);
} }
} else { } else {
if (i == ntokens-1) { if (i == ntokens-1) {
Prototype p = app.getPrototype (currentNode); Prototype p = app.getPrototype (currentElement);
if (p != null) if (p != null)
action = p.getActionOrTemplate (pathItems[i]); action = p.getActionOrTemplate (pathItems[i]);
} }
@ -273,23 +274,25 @@ public class RequestEvaluator implements Runnable {
if (pathItems[i].length () == 0) if (pathItems[i].length () == 0)
continue; continue;
if (isProperty) // get next element as property
currentNode = currentNode.getNode (pathItems[i], false); currentElement = currentElement.getChildElement (pathItems[i]);
/* if (isProperty) // get next element as property
currentElement = currentElement.getNode (pathItems[i], false);
else { else {
// try to get next element as subnode first, then fall back to property // try to get next element as subnode first, then fall back to property
INode nextNode = currentNode.getSubnode (pathItems[i]); INode nextNode = currentElement.getSubnode (pathItems[i]);
if (nextNode == null) if (nextNode == null)
nextNode = currentNode.getNode (pathItems[i], false); nextNode = currentElement.getNode (pathItems[i], false);
currentNode = nextNode; currentElement = nextNode;
} }
isProperty = false; isProperty = false; */
// add object to request path if suitable // add object to request path if suitable
if (currentNode != null) { if (currentElement != null) {
// add to reqPath array // add to reqPath array
current = getNodeWrapper (currentNode); current = getElementWrapper (currentElement);
reqPath.putProperty (reqPath.size(), current); reqPath.putProperty (reqPath.size(), current);
String pt = currentNode.getPrototype (); String pt = currentElement.getPrototype ();
if (pt != null) { if (pt != null) {
// if a prototype exists, add also by prototype name // if a prototype exists, add also by prototype name
reqPath.putHiddenProperty (pt, current); reqPath.putHiddenProperty (pt, current);
@ -300,13 +303,13 @@ public class RequestEvaluator implements Runnable {
} }
} }
if (currentNode == null) if (currentElement == null)
throw new FrameworkException ("Object not found."); throw new FrameworkException ("Object not found.");
else else
current = getNodeWrapper (currentNode); current = getElementWrapper (currentElement);
if (action == null) { if (action == null) {
Prototype p = app.getPrototype (currentNode); Prototype p = app.getPrototype (currentElement);
if (p != null) if (p != null)
action = p.getActionOrTemplate (null); action = p.getActionOrTemplate (null);
} }
@ -328,7 +331,7 @@ public class RequestEvaluator implements Runnable {
action = p.getActionOrTemplate (notFoundAction); action = p.getActionOrTemplate (notFoundAction);
if (action == null) if (action == null)
throw new FrameworkException (notfound.getMessage ()); throw new FrameworkException (notfound.getMessage ());
current = getNodeWrapper (root); current = getElementWrapper (root);
} }
localrtx.timer.endEvent (requestPath+" init"); localrtx.timer.endEvent (requestPath+" init");
@ -430,7 +433,7 @@ public class RequestEvaluator implements Runnable {
root = app.getDataRoot (); root = app.getDataRoot ();
global.putHiddenProperty ("root", getNodeWrapper (root)); global.putHiddenProperty ("root", getElementWrapper (root));
global.deleteProperty("user", "user".hashCode()); global.deleteProperty("user", "user".hashCode());
global.deleteProperty ("req", "req".hashCode()); global.deleteProperty ("req", "req".hashCode());
global.putHiddenProperty ("res", ESLoader.normalizeValue(res, evaluator)); global.putHiddenProperty ("res", ESLoader.normalizeValue(res, evaluator));
@ -439,7 +442,7 @@ public class RequestEvaluator implements Runnable {
// convert arguments // convert arguments
int l = args.size (); int l = args.size ();
current = getNodeWrapper (root); current = getElementWrapper (root);
if (method.indexOf (".") > -1) { if (method.indexOf (".") > -1) {
StringTokenizer st = new StringTokenizer (method, "."); StringTokenizer st = new StringTokenizer (method, ".");
int cnt = st.countTokens (); int cnt = st.countTokens ();
@ -491,7 +494,7 @@ public class RequestEvaluator implements Runnable {
root = app.getDataRoot (); root = app.getDataRoot ();
global.putHiddenProperty ("root", getNodeWrapper (root)); global.putHiddenProperty ("root", getElementWrapper (root));
global.deleteProperty("user", "user".hashCode()); global.deleteProperty("user", "user".hashCode());
global.deleteProperty ("req", "req".hashCode()); global.deleteProperty ("req", "req".hashCode());
global.putHiddenProperty ("res", ESLoader.normalizeValue(res, evaluator)); global.putHiddenProperty ("res", ESLoader.normalizeValue(res, evaluator));
@ -642,13 +645,13 @@ public class RequestEvaluator implements Runnable {
return result; return result;
} }
public synchronized ESValue invokeFunction (INode node, String functionName, ESValue[] args) public synchronized ESValue invokeFunction (IPathElement node, String functionName, ESValue[] args)
throws Exception { throws Exception {
ESObject obj = null; ESObject obj = null;
if (node == null) if (node == null)
obj = global; obj = global;
else else
obj = getNodeWrapper (node); obj = getElementWrapper (node);
return invokeFunction (obj, functionName, args); return invokeFunction (obj, functionName, args);
} }
@ -741,8 +744,14 @@ public class RequestEvaluator implements Runnable {
Prototype proto = null; Prototype proto = null;
if (thisObject == null) if (thisObject == null)
proto = app.typemgr.getPrototype ("global"); proto = app.typemgr.getPrototype ("global");
else else {
proto = app.getPrototype (((ESNode) thisObject).getNode ()); try {
IPathElement elem = (IPathElement) thisObject.toJavaObject ();
proto = app.getPrototype (elem);
} catch (ClassCastException wrongClass) {
throw new RuntimeException ("Can't render a skin on something that is not a path element: "+wrongClass);
}
}
return getSkin (proto, skinname); return getSkin (proto, skinname);
} }
@ -829,6 +838,21 @@ public class RequestEvaluator implements Runnable {
return (ESNode) objectcache.get (n); return (ESNode) objectcache.get (n);
} }
public ESObject getElementWrapper (IPathElement e) {
if (e instanceof INode)
return getNodeWrapper ((INode) e);
String protoname = e.getPrototype ();
ObjectPrototype op = (ObjectPrototype) prototypes.get (protoname);
return new ESGenericObject (op, evaluator, e);
}
/**
* Get a script wrapper for an implemntation of helma.objectmodel.INode
*/
public ESNode getNodeWrapper (INode n) { public ESNode getNodeWrapper (INode n) {
if (n == null) if (n == null)

View file

@ -72,12 +72,24 @@ public class Skin {
return source; return source;
} }
public void render (RequestEvaluator reval, ESNode thisNode, ESObject paramObject) throws RedirectException { public void render (RequestEvaluator reval, ESObject thisObject, ESObject paramObject) throws RedirectException {
if (parts == null) if (parts == null)
return; return;
IPathElement elem = null;
if (thisObject != null) {
try {
elem = (IPathElement) thisObject.toJavaObject ();
} catch (ClassCastException wrongClass) {
throw new RuntimeException ("Can't render a skin on something that is not a path element: "+wrongClass);
}
}
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) parts[i]).render (reval, thisNode, paramObject); ((Macro) parts[i]).render (reval, thisObject, elem, paramObject);
else else
reval.res.write (parts[i]); reval.res.write (parts[i]);
} }
@ -193,7 +205,7 @@ public class Skin {
} }
public void render (RequestEvaluator reval, ESNode thisNode, ESObject paramObject) throws RedirectException { public void render (RequestEvaluator reval, ESObject thisObject, IPathElement elem, ESObject paramObject) throws RedirectException {
if (notallowed) { if (notallowed) {
String h = handler == null ? "global" : handler; String h = handler == null ? "global" : handler;
@ -223,32 +235,33 @@ public class Skin {
if ("currentuser".equalsIgnoreCase (handler)) { if ("currentuser".equalsIgnoreCase (handler)) {
// as a special convention, we use "currentuser" to access macros in the current user object // as a special convention, we use "currentuser" to access macros in the current user object
handlerObject = reval.getNodeWrapper (reval.user.getNode ()); handlerObject = reval.getNodeWrapper (reval.user.getNode ());
} else if (thisNode != null) { } else if (elem != null) {
// not a global macro - need to find handler object // not a global macro - need to find handler object
// was called with this object - check it or its parents for matching prototype // was called with this object - check it or its parents for matching prototype
if (!handler.equalsIgnoreCase ("this") && !handler.equalsIgnoreCase (thisNode.getPrototypeName ())) { if (!handler.equalsIgnoreCase ("this") && !handler.equalsIgnoreCase (elem.getPrototype ())) {
// the handler object is not what we want // the handler object is not what we want
INode n = thisNode.getNode(); IPathElement n = elem;
// walk down parent chain to find handler object // walk down parent chain to find handler object
while (n != null) { while (n != null) {
if (handler.equalsIgnoreCase (n.getPrototype())) { if (handler.equalsIgnoreCase (n.getPrototype())) {
handlerObject = reval.getNodeWrapper (n); handlerObject = reval.getElementWrapper (n);
break; break;
} }
n = n.getParent (); n = n.getParentElement ();
} }
} else { } else {
// we already have the right handler object // we already have the right handler object
handlerObject = thisNode; handlerObject = thisObject;
} }
} }
if (handlerObject == null) { if (handlerObject == null) {
// eiter because thisNode == null or the right object wasn't found in the targetNode path // eiter because thisObject == null or the right object wasn't found in the object's parent path
// go check request path for an object with matching prototype // go check request path for an object with matching prototype
int l = reval.reqPath.size(); int l = reval.reqPath.size();
for (int i=l-1; i>=0; i--) { for (int i=l-1; i>=0; i--) {
if (handler.equalsIgnoreCase (((ESNode) reval.reqPath.getProperty(i)).getPrototypeName())) { IPathElement pathelem = (IPathElement) reval.reqPath.getProperty (i).toJavaObject ();
if (handler.equalsIgnoreCase (pathelem.getPrototype ())) {
handlerObject = (ESNode) reval.reqPath.getProperty(i); handlerObject = (ESNode) reval.reqPath.getProperty(i);
break; break;
} }

View file

@ -52,7 +52,7 @@ public class User implements Serializable {
nhandle = null; nhandle = null;
uid = null; uid = null;
} else { } else {
uid = n.getNameOrID (); uid = n.getElementName ();
nhandle = ((helma.objectmodel.db.Node) n).getHandle (); nhandle = ((helma.objectmodel.db.Node) n).getHandle ();
} }
} }