* Refactor Macro.render() method into two distict methods in order to invoke

invoke macros without rendering the result to the response (useful for
  nested macros).
This commit is contained in:
hns 2007-03-23 16:32:19 +00:00
parent dd899e67b9
commit 731ec80ac1

View file

@ -317,14 +317,11 @@ public final class Skin {
sandbox.add(macroname); sandbox.add(macroname);
} }
private Object renderMacro(Object value, RequestEvaluator reval, private Object invokeMacro(Object value, RequestEvaluator reval,
Object thisObj, Map handlerCache) Object thisObj, Map handlerCache)
throws UnsupportedEncodingException { throws Exception {
if (value instanceof Macro) { if (value instanceof Macro) {
ResponseTrans res = reval.getResponse(); return ((Macro) value).invokeAsMacro(reval, thisObj, handlerCache, null);
res.pushStringBuffer();
((Macro) value).render(reval, thisObj, handlerCache);
return res.popStringBuffer();
} else { } else {
return value; return value;
} }
@ -602,14 +599,13 @@ public final class Skin {
namedParams.put(name, value); namedParams.put(name, value);
} }
/** private Object invokeAsMacro(RequestEvaluator reval, Object thisObject,
* Render the macro given a handler object Map handlerCache, StandardParams stdParams)
*/ throws Exception {
public void render(RequestEvaluator reval, Object thisObject, Map handlerCache)
throws RedirectException, UnsupportedEncodingException {
// immediately return for comment macros // immediately return for comment macros
if (isCommentMacro) { if (isCommentMacro) {
return; return null;
} }
if ((sandbox != null) && !sandbox.contains(name)) { if ((sandbox != null) && !sandbox.contains(name)) {
@ -617,8 +613,7 @@ public final class Skin {
} }
Object handlerObject = null; Object handlerObject = null;
Object value = null;
try {
if (handler != HANDLER_GLOBAL) { if (handler != HANDLER_GLOBAL) {
handlerObject = resolveHandler(thisObject, reval, handlerCache); handlerObject = resolveHandler(thisObject, reval, handlerCache);
@ -640,12 +635,12 @@ public final class Skin {
Object[] arguments = prepareArguments(0, reval, thisObject, handlerCache); Object[] arguments = prepareArguments(0, reval, thisObject, handlerCache);
// get reference to rendered named params for after invocation // get reference to rendered named params for after invocation
Map params = (Map) arguments[0]; Map params = (Map) arguments[0];
Object value = reval.invokeDirectFunction(handlerObject, value = reval.invokeDirectFunction(handlerObject,
funcName, funcName,
arguments); arguments);
// create new renderParams to override defaults in case the macro changed anything // update StandardParams to override defaults in case the macro changed anything
StandardParams stdParams = new StandardParams(params); if (stdParams != null) stdParams.readFrom(params);
// if macro has a filter chain and didn't return anything, use output // if macro has a filter chain and didn't return anything, use output
// as filter argument. // as filter argument.
@ -656,18 +651,57 @@ public final class Skin {
} }
} }
return filter(reval, value, thisObject, handlerCache);
} else {
if (handler == HANDLER_RESPONSE) {
// some special handling for response handler
if ("message".equals(propName)) {
value = reval.getResponse().getMessage();
} else if ("error".equals(propName)) {
value = reval.getResponse().getError();
}
if (value != null) {
return filter(reval, value, thisObject, handlerCache);
}
}
// display error message unless silent failmode is on
if ((handlerObject == null || !reval.scriptingEngine.hasProperty(handlerObject, propName)) &&
standardParams.verboseFailmode(handlerObject, reval)) {
throw new MacroUnhandledException(name);
}
value = reval.scriptingEngine.getProperty(handlerObject, propName);
return filter(reval, value, thisObject, handlerCache);
}
} else if (standardParams.verboseFailmode(handlerObject, reval)) {
throw new MacroUnhandledException(name);
}
return filter(reval, null, thisObject, handlerCache);
}
/**
* Render the macro given a handler object
*/
public void render(RequestEvaluator reval, Object thisObject, Map handlerCache)
throws RedirectException, UnsupportedEncodingException {
StringBuffer buffer = reval.getResponse().getBuffer();
// remember length of response buffer before calling macro
int bufLength = buffer.length();
try {
StandardParams stdParams = standardParams.render(reval, thisObject, handlerCache);
Object value = invokeAsMacro(reval, thisObject, handlerCache, stdParams);
// check if macro wrote out to response buffer // check if macro wrote out to response buffer
if (buffer.length() == bufLength) { if (buffer.length() == bufLength) {
// If the macro function didn't write anything to the response itself, // If the macro function didn't write anything to the response itself,
// we interpret its return value as macro output. // we interpret its return value as macro output.
writeResponse(value, reval, thisObject, handlerCache, stdParams, true); writeResponse(value, reval, stdParams, true);
} else { } else {
// if an encoding is specified, re-encode the macro's output // if an encoding is specified, re-encode the macro's output
if (encoding != ENCODE_NONE) { if (encoding != ENCODE_NONE) {
String output = buffer.substring(bufLength); String output = buffer.substring(bufLength);
buffer.setLength(bufLength); buffer.setLength(bufLength);
writeResponse(output, reval, thisObject, handlerCache, stdParams, false); writeResponse(output, reval, stdParams, false);
} else { } else {
// insert prefix, // insert prefix,
if (stdParams.prefix != null) { if (stdParams.prefix != null) {
@ -682,52 +716,19 @@ public final class Skin {
// Append macro return value even if it wrote something to the response, // Append macro return value even if it wrote something to the response,
// but don't render default value in case it returned nothing. // but don't render default value in case it returned nothing.
// We do this for the sake of consistency. // We do this for the sake of consistency.
writeResponse(value, reval, thisObject, handlerCache, stdParams, false); writeResponse(value, reval, stdParams, false);
}
} else {
if (handler == HANDLER_RESPONSE) {
// some special handling for response handler
Object value = null;
if ("message".equals(propName)) {
value = reval.getResponse().getMessage();
} else if ("error".equals(propName)) {
value = reval.getResponse().getError();
}
if (value != null) {
writeResponse(value, reval, thisObject, handlerCache, standardParams, true);
return;
}
}
// display error message unless silent failmode is on
if (handlerObject == null || !reval.scriptingEngine.hasProperty(handlerObject, propName)) {
if (standardParams.verboseFailmode(handlerObject, reval)) {
String msg = "[Macro unhandled: " + name + "]";
reval.getResponse().write(" " + msg + " ");
app.logEvent(msg);
} else {
writeResponse(null, reval, thisObject, handlerCache, standardParams, true);
}
} else {
Object value = reval.scriptingEngine.getProperty(handlerObject, propName);
writeResponse(value, reval, thisObject, handlerCache, standardParams, true);
}
} }
} else {
if (standardParams.verboseFailmode(handlerObject, reval)) {
String msg = "[Macro unhandled: " + name + "]";
reval.getResponse().write(" " + msg + " ");
app.logEvent(msg);
} else {
writeResponse(null, reval, thisObject, handlerCache, standardParams, true);
}
}
} catch (RedirectException redir) { } catch (RedirectException redir) {
throw redir; throw redir;
} catch (ConcurrencyException concur) { } catch (ConcurrencyException concur) {
throw concur; throw concur;
} catch (TimeoutException timeout) { } catch (TimeoutException timeout) {
throw timeout; throw timeout;
} catch (MacroUnhandledException unhandled) {
String msg = "Macro unhandled: " + unhandled.getMessage();
reval.getResponse().write(" [" + msg + "] ");
app.logError(msg);
} catch (Exception x) { } catch (Exception x) {
String msg = x.getMessage(); String msg = x.getMessage();
if ((msg == null) || (msg.length() < 10)) { if ((msg == null) || (msg.length() < 10)) {
@ -740,7 +741,18 @@ public final class Skin {
} }
} }
private Object invokeFilter(RequestEvaluator reval, Object returnValue, private Object filter(RequestEvaluator reval, Object returnValue,
Object thisObject, Map handlerCache)
throws Exception {
// invoke filter chain if defined
if (filterChain != null) {
return filterChain.invokeAsFilter(reval, returnValue, thisObject, handlerCache);
} else {
return returnValue;
}
}
private Object invokeAsFilter(RequestEvaluator reval, Object returnValue,
Object thisObject, Map handlerCache) Object thisObject, Map handlerCache)
throws Exception { throws Exception {
@ -762,10 +774,8 @@ public final class Skin {
Object retval = reval.invokeDirectFunction(handlerObject, Object retval = reval.invokeDirectFunction(handlerObject,
funcName, funcName,
arguments); arguments);
if (filterChain == null) {
return retval; return filter(reval, retval, thisObject, handlerCache);
}
return filterChain.invokeFilter(reval, retval, thisObject, handlerCache);
} else { } else {
throw new RuntimeException("Undefined Filter " + name); throw new RuntimeException("Undefined Filter " + name);
} }
@ -773,7 +783,7 @@ public final class Skin {
private Object[] prepareArguments(int offset, RequestEvaluator reval, private Object[] prepareArguments(int offset, RequestEvaluator reval,
Object thisObject, Map handlerCache) Object thisObject, Map handlerCache)
throws UnsupportedEncodingException { throws Exception {
int nPosArgs = (positionalParams == null) ? 0 : positionalParams.size(); int nPosArgs = (positionalParams == null) ? 0 : positionalParams.size();
Object[] arguments = new Object[offset + 1 + nPosArgs]; Object[] arguments = new Object[offset + 1 + nPosArgs];
@ -784,7 +794,7 @@ public final class Skin {
for (Iterator it = namedParams.entrySet().iterator(); it.hasNext(); ) { for (Iterator it = namedParams.entrySet().iterator(); it.hasNext(); ) {
Map.Entry entry = (Map.Entry) it.next(); Map.Entry entry = (Map.Entry) it.next();
Object value = entry.getValue(); Object value = entry.getValue();
map.put(entry.getKey(), renderMacro(value, reval, thisObject, handlerCache)); map.put(entry.getKey(), invokeMacro(value, reval, thisObject, handlerCache));
} }
arguments[offset] = map; arguments[offset] = map;
} else { } else {
@ -795,7 +805,7 @@ public final class Skin {
for (int i = 0; i < nPosArgs; i++) { for (int i = 0; i < nPosArgs; i++) {
Object param = positionalParams.get(i); Object param = positionalParams.get(i);
if (param instanceof Macro) if (param instanceof Macro)
arguments[offset + 1 + i] = renderMacro(param, reval, thisObject, handlerCache); arguments[offset + 1 + i] = invokeMacro(param, reval, thisObject, handlerCache);
else else
arguments[offset + 1 + i] = param; arguments[offset + 1 + i] = param;
} }
@ -879,17 +889,11 @@ public final class Skin {
* Utility method for writing text out to the response object. * Utility method for writing text out to the response object.
*/ */
void writeResponse(Object value, RequestEvaluator reval, void writeResponse(Object value, RequestEvaluator reval,
Object thisObject, Map handlerCache,
StandardParams stdParams, boolean useDefault) StandardParams stdParams, boolean useDefault)
throws Exception { throws Exception {
String text; String text;
StringBuffer buffer = reval.getResponse().getBuffer(); StringBuffer buffer = reval.getResponse().getBuffer();
// invoke filter chain if defined
if (filterChain != null) {
value = filterChain.invokeFilter(reval, value, thisObject, handlerCache);
}
if (value == null || "".equals(value)) { if (value == null || "".equals(value)) {
if (useDefault) { if (useDefault) {
text = (String) stdParams.defaultValue; text = (String) stdParams.defaultValue;
@ -967,6 +971,10 @@ public final class Skin {
StandardParams() {} StandardParams() {}
StandardParams(Map map) { StandardParams(Map map) {
readFrom(map);
}
void readFrom(Map map) {
prefix = map.get("prefix"); prefix = map.get("prefix");
suffix = map.get("suffix"); suffix = map.get("suffix");
defaultValue = map.get("default"); defaultValue = map.get("default");
@ -993,15 +1001,21 @@ public final class Skin {
} }
StandardParams render(RequestEvaluator reval, Object thisObj, Map handlerCache) StandardParams render(RequestEvaluator reval, Object thisObj, Map handlerCache)
throws UnsupportedEncodingException { throws Exception {
if (!containsMacros()) if (!containsMacros())
return this; return this;
StandardParams stdParams = new StandardParams(); StandardParams stdParams = new StandardParams();
stdParams.prefix = renderMacro(prefix, reval, thisObj, handlerCache); stdParams.prefix = invokeMacro(prefix, reval, thisObj, handlerCache);
stdParams.suffix = renderMacro(suffix, reval, thisObj, handlerCache); stdParams.suffix = invokeMacro(suffix, reval, thisObj, handlerCache);
stdParams.defaultValue = renderMacro(defaultValue, reval, thisObj, handlerCache); stdParams.defaultValue = invokeMacro(defaultValue, reval, thisObj, handlerCache);
return stdParams; return stdParams;
} }
} }
} }
class MacroUnhandledException extends Exception {
MacroUnhandledException(String name) {
super(name);
}
}