After hitting my head against the wall that is PageContext.pushBody() and it's near-uselessness, I have finally hacked my Tomcat 4.0.1 and added one measly method to the servlet API.
And boy is my life getting better fast. The issues are twofold: 1) pushBody() makes a BodyContent for you, pushes it, and returns it. This does nothing for folks who want to put some other sort of Writer in place, like say a PipedJspWriter to be fed from an XSLT Thread, or whatever. 2) even if pushBody() did what you want, it's pointless to invoke it from a Tag, since the JSP compiler won't set the "out" variable used to send static content etc. So I have humbly - humbly! - added pushWriter(JspWriter) to the API and altered tomcat's TagBeginGenerator and TagEndGenerator to say out = pageContext.getOut() when a BodyTag *doesn't* return EVAL_BODY_BUFFERED, and voila I finally have what I've been needing all this time. Now I can stream between Tags and take another, more general, and simpler crack at taglibs/io. And static HTML content just works, and Tags don't have to conspire with each other or mess with global state. And more, but that's for another post. I don't know the JSP standards process, but I'm hoping whoever is in charge will take this modification and the reasoning behind it under serious consideration. The attached patches are against jakarta-servletapi-4 as downloaded from the current CVS, and for jakarta-tomcat-4.0.1-src (the CVS for tomcat-4.0 seems to be older, and I didn't find a more current one). Oh, the tomcat patch also includes a fix for TagCache that is more definite about finding setters for Tag attributes. So you can use "class=" now and get more predictable behavior for attributes in general. Apologies for mixing them.
diff -c -r jakarta-servletapi-4-orig/src/share/javax/servlet/jsp/PageContext.java jakarta-servletapi-4/src/share/javax/servlet/jsp/PageContext.java *** jakarta-servletapi-4-orig/src/share/javax/servlet/jsp/PageContext.java Fri Jul 13 16:57:18 2001 --- jakarta-servletapi-4/src/share/javax/servlet/jsp/PageContext.java Sat Feb 2 13:25:29 2002 *************** *** 109,115 **** * * <p> * The following methods enable the <B>management of nested</B> JspWriter streams to ! * implement Tag Extensions: <code>pushBody()</code> and <code>popBody()</code> * * <p><B>Methods Intended for JSP authors</B> * <p> --- 109,115 ---- * * <p> * The following methods enable the <B>management of nested</B> JspWriter streams to ! * implement Tag Extensions: <code>pushBody()</code>, <code>pushWriter()</code>, and <code>popBody()</code> * * <p><B>Methods Intended for JSP authors</B> * <p> *************** *** 577,584 **** /** * Return the previous JspWriter "out" saved by the matching ! * pushBody(), and update the value of the "out" attribute in * the page scope attribute namespace of the PageConxtext * * @return the saved JspWriter. --- 577,596 ---- /** + * Push a given JspWriter, save the current "out" JspWriter, + * and update the value of the "out" attribute in the page scope + * attribute namespace of the PageContext + * + * @param w the jspwriter to use + */ + + public void pushWriter(JspWriter w) { + } + + + /** * Return the previous JspWriter "out" saved by the matching ! * pushBody() or pushWriter(), and update the value of the "out" attribute in * the page scope attribute namespace of the PageConxtext * * @return the saved JspWriter.
diff -c -r jakarta-tomcat-4.0.1-orig/jasper/src/share/org/apache/jasper/compiler/TagBeginGenerator.java jakarta-tomcat-4.0.1/jasper/src/share/org/apache/jasper/compiler/TagBeginGenerator.java *** jakarta-tomcat-4.0.1-orig/jasper/src/share/org/apache/jasper/compiler/TagBeginGenerator.java Mon Nov 12 18:02:50 2001 --- jakarta-tomcat-4.0.1/jasper/src/share/org/apache/jasper/compiler/TagBeginGenerator.java Fri Feb 1 18:31:53 2002 *************** *** 377,382 **** --- 377,388 ---- writer.popIndent(); writer.println("}"); + // a Tag might have pushed something + writer.println("else"); + writer.pushIndent(); + writer.println("out = pageContext.getOut();"); + writer.popIndent(); + writer.println(thVarName+".doInitBody();"); } diff -c -r jakarta-tomcat-4.0.1-orig/jasper/src/share/org/apache/jasper/compiler/TagCache.java jakarta-tomcat-4.0.1/jasper/src/share/org/apache/jasper/compiler/TagCache.java *** jakarta-tomcat-4.0.1-orig/jasper/src/share/org/apache/jasper/compiler/TagCache.java Mon Nov 12 18:02:50 2001 --- jakarta-tomcat-4.0.1/jasper/src/share/org/apache/jasper/compiler/TagCache.java Fri Feb 1 18:32:33 2002 *************** *** 109,114 **** --- 109,118 ---- return (Class) propertyEditorMaps.get(attrName); } + String setCap(String s) { + return "set" + Character.toUpperCase(s.charAt(0)) + s.substring(1); + } + void setTagHandlerClass(Class tagHandlerClass) throws JasperException { *************** *** 121,129 **** /* FIXME: should probably be checking for things like pageContext, bodyContent, and parent here -akv - */ if (pd[i].getWriteMethod() != null) addSetterMethod(pd[i].getName(), pd[i].getWriteMethod()); if (pd[i].getPropertyEditorClass() != null) addPropertyEditor(pd[i].getName(), pd[i].getPropertyEditorClass()); } --- 125,140 ---- /* FIXME: should probably be checking for things like pageContext, bodyContent, and parent here -akv if (pd[i].getWriteMethod() != null) addSetterMethod(pd[i].getName(), pd[i].getWriteMethod()); + + * the right way - check for setters directly, ignore non-setters +-bnl + */ + try { + Method m = tagHandlerClass.getMethod(setCap(pd[i].getName()), +new Class[] {String.class}); + addSetterMethod(pd[i].getName(), m); + } + catch (NoSuchMethodException e) {} if (pd[i].getPropertyEditorClass() != null) addPropertyEditor(pd[i].getName(), pd[i].getPropertyEditorClass()); } diff -c -r jakarta-tomcat-4.0.1-orig/jasper/src/share/org/apache/jasper/compiler/TagEndGenerator.java jakarta-tomcat-4.0.1/jasper/src/share/org/apache/jasper/compiler/TagEndGenerator.java *** jakarta-tomcat-4.0.1-orig/jasper/src/share/org/apache/jasper/compiler/TagEndGenerator.java Mon Nov 12 18:02:50 2001 --- jakarta-tomcat-4.0.1/jasper/src/share/org/apache/jasper/compiler/TagEndGenerator.java Fri Feb 1 18:31:05 2002 *************** *** 167,172 **** --- 167,173 ---- writer.pushIndent(); writer.println("return;"); writer.popIndent(); writer.popIndent(); // try + writer.println("out = pageContext.getOut();"); // doEndTag might have popped /** FIXME: REMOVE BEGIN */ // writer.println("} catch (Throwable t) {"); diff -c -r jakarta-tomcat-4.0.1-orig/jasper/src/share/org/apache/jasper/runtime/PageContextImpl.java jakarta-tomcat-4.0.1/jasper/src/share/org/apache/jasper/runtime/PageContextImpl.java *** jakarta-tomcat-4.0.1-orig/jasper/src/share/org/apache/jasper/runtime/PageContextImpl.java Mon Nov 12 18:02:50 2001 --- jakarta-tomcat-4.0.1/jasper/src/share/org/apache/jasper/runtime/PageContextImpl.java Fri Feb 1 18:09:00 2002 *************** *** 422,427 **** --- 422,432 ---- return (BodyContent) out; } + public void pushWriter(JspWriter w) { + writerStack.push(out); + out = w; + } + public JspWriter popBody() { out = (JspWriter) writerStack.pop(); return out;
-- To unsubscribe, e-mail: <mailto:[EMAIL PROTECTED]> For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>