New logic for skin handler lookup to fix the fix for bug 617. New algorithm works like this:

- resolve against the this-object prototype name, including extended prototypes
  - resolve against the res.handlers collection
  - resolve against the parent path of the this-object, including extended prototypes.

The following thread provides more context:
http://groups.google.com/group/helma/browse_frm/thread/b15805fd6f661d64
This commit is contained in:
hns 2009-06-15 13:25:36 +00:00
parent afcb459c0d
commit b48fb4e277

View file

@ -1102,44 +1102,51 @@ public final class Skin {
return handlerCache.get(handlerName); return handlerCache.get(handlerName);
} }
// if handler object wasn't found in cache retrieve it // if handler object wasn't found in cache first check this-object
if (thisObject != null) { if (thisObject != 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 this-object for matching prototype
if (handlerName.equalsIgnoreCase(app.getPrototypeName(thisObject))) { Prototype proto = app.getPrototype(thisObject);
// we already have the right handler object
// put the found handler object into the cache so we don't have to look again
if (handlerCache != null)
handlerCache.put(handlerName, thisObject);
return thisObject;
} else {
// the handler object is not what we want
Object obj = thisObject;
// walk down parent chain to find handler object, if (proto != null && proto.isInstanceOf(handlerName)) {
// limiting to 50 passes to avoid infinite loops return cacheHandler(handlerName, thisObject);
int maxloop = 50;
while (obj != null && maxloop-- > 0) {
String protoName = app.getPrototypeName(obj);
if (handlerName.equalsIgnoreCase(protoName)) {
if (handlerCache != null)
handlerCache.put(handlerName, obj);
return obj;
}
obj = app.getParentElement(obj);
}
} }
} }
// next look in res.handlers
Map macroHandlers = reval.getResponse().getMacroHandlers(); Map macroHandlers = reval.getResponse().getMacroHandlers();
Object obj = macroHandlers.get(handlerName); Object obj = macroHandlers.get(handlerName);
if (handlerCache != null && obj != null) { if (obj != null) {
handlerCache.put(handlerName, obj); return cacheHandler(handlerName, obj);
} }
return obj;
// finally walk down the this-object's parent chain
if (thisObject != null) {
obj = app.getParentElement(thisObject);
// walk down parent chain to find handler object,
// limiting to 50 passes to avoid infinite loops
int maxloop = 50;
while (obj != null && maxloop-- > 0) {
Prototype proto = app.getPrototype(obj);
if (proto != null && proto.isInstanceOf(handlerName)) {
return cacheHandler(handlerName, obj);
}
obj = app.getParentElement(obj);
}
}
return cacheHandler(handlerName, null);
} }
private Object cacheHandler(String name, Object handler) {
if (handlerCache != null) {
handlerCache.put(name, handler);
}
return handler;
}
} }
/** /**