Enhancements for response buffer handling
What I propose here started out while thinking about ways to de-uglify res.debug(). My goals were:
- Give developers control about how the debug output is formatted and displayed.
- Allow developers to include debug output anywhere they wish, either via macro or programmatically (it is currently just appended to the main response buffer).
After trying some superficial plastic surgery, it became clear to me that this is a model case for what Tobi proposed here and was implemented as res.pushBuffer() and res.popBuffer() in Helma 1.6. (This wasn't immediately obvious because I didn't think "skin rendering" when thinking about res.debug().)
These new response methods allow to slip an existing java.lang.StringBuffer on top of the resoponse buffer stack (as opposed to res.push(), which always creates a new one), and get the StringBuffer out of the response buffer stack without converting it to a String (versus res.pop(), which does just that). In other words, the new methods allow you to get a StringBuffer in and out of the response object multiple times without the penalty of StringBuffer to String conversion.
Unfortunately, res.pushBuffer() and res.popBuffer() is not quite as powerful as it should be. The problem is that the managing of StringBuffers is left to the application, which makes it quite difficult to implement a generic res.debug().
In my eyes, we should enhance res.pushBuffer() to allow putting response buffers in a well-known, accessible location, and/or get them from there. Let's assume this location is called res.buffers. res.pushBuffer() would then optionally take a String argument:
/** * Use buffer as new response buffer, * without registering it in res.buffers. */ res.pushBuffer(java.lang.StringBuffer buffer) /** * Use the StringBuffer in res.buffers[name] as new response buffer, * creating it if it doesn't exist. */ res.pushBuffer(java.lang.String, name)
A third variant may or may not make sense:
/** * Use buffer as new response buffer and register * it as res.buffers[name], overwriting any previous buffer * with that name. */ res.pushBuffer(java.lang.StringBuffer buffer, java.lang.String name)
For programmatic access to res.buffers, it might be useful to auto-expand by automatically creating buffers that do not yet exist:
// res.buffers.debug is automatically created if it doesn't exist res.buffers.debug.append("Some debug output");
The nice thing here would be that for programmatic access we didn't even have to push/pop the buffer in question.
res.debug() could then be implemented as a method that writes to a buffer called "debug" (or "helma_debug"). Applications could simply provide their own version of res.debug(), and it would be easy to render skins to the response buffer, in addition to using res.write().
<link> tags from a central function or macro may be inadequate. By rendering these tags to a separate buffer and including that buffer in the
<head> element of the final page this problem could be solved in a simple and elegant way.