* Implement res.pushBuffer(StringBuffer) and res.popBuffer() to get

StringBuffers in and out of the res buffer stack. This is needed for
  efficiently implementing the method described in
  http://dev.helma.org/wiki/Handler+for+rendered+skins/
This commit is contained in:
hns 2007-03-27 12:53:28 +00:00
parent ac0a5f1daa
commit c04d2db80f
3 changed files with 54 additions and 26 deletions

View file

@ -471,7 +471,7 @@ public class ResponseBean implements Serializable {
* writes will be redirected to this buffer. * writes will be redirected to this buffer.
*/ */
public void push() { public void push() {
res.pushStringBuffer(); res.pushBuffer(null);
} }
/** /**
@ -481,23 +481,40 @@ public class ResponseBean implements Serializable {
* @return ... * @return ...
*/ */
public String pop() { public String pop() {
return res.popStringBuffer(); return res.popString();
} }
/** /**
* Old version for push() kept for compatibility * Old version for push() kept for compatibility
* @deprecated
*/ */
public void pushStringBuffer() { public void pushStringBuffer() {
res.pushStringBuffer(); res.pushBuffer(null);
} }
/** /**
* Old version for pop() kept for compatibility * Old version for pop() kept for compatibility
* * @deprecated
* @return ... * @return ...
*/ */
public String popStringBuffer() { public String popStringBuffer() {
return res.popStringBuffer(); return res.popString();
}
/**
* Push a string buffer on the response object. All further
* writes will be redirected to this buffer.
* @param buffer the string buffer
*/
public void pushBuffer(StringBuffer buffer) {
res.pushBuffer(buffer);
}
/**
* Pops the current response buffer without converting it to a string
*/
public StringBuffer popBuffer() {
return res.popBuffer();
} }
/** /**

View file

@ -199,10 +199,13 @@ public final class ResponseTrans extends Writer implements Serializable {
} }
/** /**
* This is called before a skin is rendered as string (renderSkinAsString) to redirect the output * This is called before a skin is rendered as string
* to a new string buffer. * (renderSkinAsString) to redirect the output to a new
* string buffer.
* @param buf the StringBuffer to use, or null
* @return the new StringBuffer instance
*/ */
public synchronized void pushStringBuffer() { public synchronized StringBuffer pushBuffer(StringBuffer buf) {
if (buffers == null) { if (buffers == null) {
buffers = new Stack(); buffers = new Stack();
} }
@ -211,33 +214,40 @@ public final class ResponseTrans extends Writer implements Serializable {
buffers.push(buffer); buffers.push(buffer);
} }
if (cachedBuffer != null) { if (buf != null) {
buffer = buf;
} else if (cachedBuffer != null) {
buffer = cachedBuffer; buffer = cachedBuffer;
cachedBuffer = null; cachedBuffer = null;
} else { } else {
buffer = new StringBuffer(64); buffer = new StringBuffer(64);
} }
return buffer;
} }
/** /**
* Returns the content of the current string buffer and switches back to the previos one. * Returns the content of the current string buffer and switches back to the previos one.
*/ */
public synchronized String popStringBuffer() { public synchronized String popString() {
StringBuffer buf = popBuffer();
String str = buf.toString();
// store stringbuffer for later reuse
buf.setLength(0);
cachedBuffer = buf;
return str;
}
public synchronized StringBuffer popBuffer() {
if (buffer == null) { if (buffer == null) {
throw new RuntimeException("Can't pop string buffer: buffer is null"); throw new RuntimeException("Can't pop string buffer: buffer is null");
} else if (buffers == null) { } else if (buffers == null) {
throw new RuntimeException("Can't pop string buffer: buffer stack is empty"); throw new RuntimeException("Can't pop string buffer: buffer stack is empty");
} }
// get local reference
String str = buffer.toString(); StringBuffer buf = buffer;
buffer.setLength(0);
cachedBuffer = buffer;
// restore the previous buffer, which may be null // restore the previous buffer, which may be null
buffer = buffers.empty() ? null : (StringBuffer) buffers.pop(); buffer = buffers.empty() ? null : (StringBuffer) buffers.pop();
return buf;
return str;
} }
/** /**

View file

@ -226,11 +226,11 @@ public final class Skin {
throws RedirectException, UnsupportedEncodingException { throws RedirectException, UnsupportedEncodingException {
String result = ""; String result = "";
ResponseTrans res = reval.getResponse(); ResponseTrans res = reval.getResponse();
res.pushStringBuffer(); res.pushBuffer(null);
try { try {
render(reval, thisObject, paramObject); render(reval, thisObject, paramObject);
} finally { } finally {
result = res.popStringBuffer(); result = res.popString();
} }
return result; return result;
} }
@ -657,14 +657,12 @@ public final class Skin {
} else { } else {
if (handler == HANDLER_RESPONSE) { if (handler == HANDLER_RESPONSE) {
// some special handling for response handler // some special handling for response handler
if ("message".equals(propName)) { if ("message".equals(propName))
value = reval.getResponse().getMessage(); value = reval.getResponse().getMessage();
} else if ("error".equals(propName)) { else if ("error".equals(propName))
value = reval.getResponse().getError(); value = reval.getResponse().getError();
} if (value != null)
if (value != null) {
return filter(reval, value, thisObject, handlerCache); return filter(reval, value, thisObject, handlerCache);
}
} }
// display error message unless silent failmode is on // display error message unless silent failmode is on
if ((handlerObject == null || !engine.hasProperty(handlerObject, propName)) if ((handlerObject == null || !engine.hasProperty(handlerObject, propName))
@ -1018,8 +1016,11 @@ public final class Skin {
} }
} }
/**
* Exception type for unhandled macros
*/
class MacroUnhandledException extends Exception { class MacroUnhandledException extends Exception {
MacroUnhandledException(String name) { MacroUnhandledException(String name) {
super(name); super(name);
} }
} }