horwat 01/04/26 16:17:41 Modified: jasper/src/share/org/apache/jasper/compiler DelegatingListener.java JspParseEventListener.java ParseEventListener.java Parser.java ParserXJspSaxHandler.java TagBeginGenerator.java TagEndGenerator.java Log: Implementation of the following JSP 1.2 PFD2 changes: JSP.E.1.5 Empty Action Clarification When an action has no body, the methods related to body manipulation are not invoked. Whitespace is considered significant, except in the xml version of the jsp page. The following methods will NOT be invoked on an empty body: - setBodyContent() - doInitBody() - doAfterBody() Revision Changes Path 1.8 +9 -9 jakarta-tomcat-4.0/jasper/src/share/org/apache/jasper/compiler/DelegatingListener.java Index: DelegatingListener.java =================================================================== RCS file: /home/cvs/jakarta-tomcat-4.0/jasper/src/share/org/apache/jasper/compiler/DelegatingListener.java,v retrieving revision 1.7 retrieving revision 1.8 diff -u -r1.7 -r1.8 --- DelegatingListener.java 2001/04/13 21:51:33 1.7 +++ DelegatingListener.java 2001/04/26 23:17:40 1.8 @@ -1,7 +1,7 @@ /* - * $Header: /home/cvs/jakarta-tomcat-4.0/jasper/src/share/org/apache/jasper/compiler/DelegatingListener.java,v 1.7 2001/04/13 21:51:33 horwat Exp $ - * $Revision: 1.7 $ - * $Date: 2001/04/13 21:51:33 $ + * $Header: /home/cvs/jakarta-tomcat-4.0/jasper/src/share/org/apache/jasper/compiler/DelegatingListener.java,v 1.8 2001/04/26 23:17:40 horwat Exp $ + * $Revision: 1.8 $ + * $Date: 2001/04/26 23:17:40 $ * * ==================================================================== * @@ -207,20 +207,20 @@ delegate.handleInclude(start, stop, attrs, param, isXml); } - public void handleTagBegin(Mark start,Mark stop,Attributes attrs,String prefix,String shortTagName,TagLibraryInfo tli,TagInfo ti) throws JasperException + public void handleTagBegin(Mark start,Mark stop,Attributes attrs,String prefix,String shortTagName,TagLibraryInfo tli,TagInfo ti, boolean hasBody) throws JasperException { - handleTagBegin(start, stop, attrs, prefix, shortTagName, tli, ti, false); + handleTagBegin(start, stop, attrs, prefix, shortTagName, tli, ti, hasBody, false); } - public void handleTagBegin(Mark start,Mark stop,Attributes attrs,String prefix,String shortTagName,TagLibraryInfo tli,TagInfo ti, boolean isXml) throws JasperException + public void handleTagBegin(Mark start,Mark stop,Attributes attrs,String prefix,String shortTagName,TagLibraryInfo tli,TagInfo ti, boolean hasBody, boolean isXml) throws JasperException { doAction(this.tmplStart, this.tmplStop); - delegate.handleTagBegin(start, stop, attrs, prefix, shortTagName, tli, ti, isXml); + delegate.handleTagBegin(start, stop, attrs, prefix, shortTagName, tli, ti, hasBody, isXml); } - public void handleTagEnd(Mark start,Mark stop,String prefix,String shortTagName,Attributes attrs,TagLibraryInfo tli,TagInfo ti) throws JasperException + public void handleTagEnd(Mark start,Mark stop,String prefix,String shortTagName,Attributes attrs,TagLibraryInfo tli,TagInfo ti, boolean hasBody) throws JasperException { doAction(this.tmplStart, this.tmplStop); - delegate.handleTagEnd(start, stop, prefix, shortTagName, attrs, tli, ti); + delegate.handleTagEnd(start, stop, prefix, shortTagName, attrs, tli, ti, hasBody); } public TagLibraries getTagLibraries() { 1.28 +9 -9 jakarta-tomcat-4.0/jasper/src/share/org/apache/jasper/compiler/JspParseEventListener.java Index: JspParseEventListener.java =================================================================== RCS file: /home/cvs/jakarta-tomcat-4.0/jasper/src/share/org/apache/jasper/compiler/JspParseEventListener.java,v retrieving revision 1.27 retrieving revision 1.28 diff -u -r1.27 -r1.28 --- JspParseEventListener.java 2001/04/25 19:33:55 1.27 +++ JspParseEventListener.java 2001/04/26 23:17:40 1.28 @@ -1,7 +1,7 @@ /* - * $Header: /home/cvs/jakarta-tomcat-4.0/jasper/src/share/org/apache/jasper/compiler/JspParseEventListener.java,v 1.27 2001/04/25 19:33:55 horwat Exp $ - * $Revision: 1.27 $ - * $Date: 2001/04/25 19:33:55 $ + * $Header: /home/cvs/jakarta-tomcat-4.0/jasper/src/share/org/apache/jasper/compiler/JspParseEventListener.java,v 1.28 2001/04/26 23:17:40 horwat Exp $ + * $Revision: 1.28 $ + * $Date: 2001/04/26 23:17:40 $ * * ==================================================================== * @@ -1007,23 +1007,23 @@ public void handleTagBegin(Mark start, Mark stop, Attributes attrs, String prefix, String shortTagName, TagLibraryInfo tli, - TagInfo ti) + TagInfo ti, boolean hasBody) throws JasperException { handleTagBegin(start, stop, attrs, prefix, shortTagName, tli, ti, - false); + hasBody, false); } public void handleTagBegin(Mark start, Mark stop, Attributes attrs, String prefix, String shortTagName, TagLibraryInfo tli, - TagInfo ti, boolean isXml) + TagInfo ti, boolean hasBody, boolean isXml) throws JasperException { TagBeginGenerator tbg = new TagBeginGenerator(start, prefix, shortTagName, attrs, tli, ti, libraries, getTagHandlerStack(), - getTagVarNumbers(), isXml); + getTagVarNumbers(), hasBody, isXml); Generator gen = new GeneratorWrapper(tbg, start, stop); addGenerator(gen); xo.append(prefix+":"+shortTagName, attrs); @@ -1031,11 +1031,11 @@ public void handleTagEnd(Mark start, Mark stop, String prefix, String shortTagName, Attributes attrs, - TagLibraryInfo tli, TagInfo ti) + TagLibraryInfo tli, TagInfo ti, boolean hasBody) throws JasperException { TagEndGenerator teg = new TagEndGenerator(prefix, shortTagName, attrs, - tli, ti, libraries, getTagHandlerStack(), getTagVarNumbers()); + tli, ti, libraries, getTagHandlerStack(), getTagVarNumbers(), hasBody); Generator gen = new GeneratorWrapper(teg, start, stop); addGenerator(gen); 1.7 +6 -6 jakarta-tomcat-4.0/jasper/src/share/org/apache/jasper/compiler/ParseEventListener.java Index: ParseEventListener.java =================================================================== RCS file: /home/cvs/jakarta-tomcat-4.0/jasper/src/share/org/apache/jasper/compiler/ParseEventListener.java,v retrieving revision 1.6 retrieving revision 1.7 diff -u -r1.6 -r1.7 --- ParseEventListener.java 2000/12/05 11:05:20 1.6 +++ ParseEventListener.java 2001/04/26 23:17:40 1.7 @@ -1,7 +1,7 @@ /* - * $Header: /home/cvs/jakarta-tomcat-4.0/jasper/src/share/org/apache/jasper/compiler/ParseEventListener.java,v 1.6 2000/12/05 11:05:20 pierred Exp $ - * $Revision: 1.6 $ - * $Date: 2000/12/05 11:05:20 $ + * $Header: /home/cvs/jakarta-tomcat-4.0/jasper/src/share/org/apache/jasper/compiler/ParseEventListener.java,v 1.7 2001/04/26 23:17:40 horwat Exp $ + * $Revision: 1.7 $ + * $Date: 2001/04/26 23:17:40 $ * * ==================================================================== * @@ -135,14 +135,14 @@ * stop: can be null if the body contained JSP tags... */ void handleTagBegin(Mark start, Mark stop, Attributes attrs, String prefix, String shortTagName, - TagLibraryInfo tli, TagInfo ti) + TagLibraryInfo tli, TagInfo ti, boolean hasBody) throws JasperException; void handleTagBegin(Mark start, Mark stop, Attributes attrs, String prefix, String shortTagName, - TagLibraryInfo tli, TagInfo ti, boolean isXml) + TagLibraryInfo tli, TagInfo ti, boolean hasBody, boolean isXml) throws JasperException; void handleTagEnd(Mark start, Mark stop, String prefix, String shortTagName, - Attributes attrs, TagLibraryInfo tli, TagInfo ti) + Attributes attrs, TagLibraryInfo tli, TagInfo ti, boolean hasBody) throws JasperException; void handleForward(Mark start, Mark stop, Attributes attrs, Hashtable param) 1.9 +18 -5 jakarta-tomcat-4.0/jasper/src/share/org/apache/jasper/compiler/Parser.java Index: Parser.java =================================================================== RCS file: /home/cvs/jakarta-tomcat-4.0/jasper/src/share/org/apache/jasper/compiler/Parser.java,v retrieving revision 1.8 retrieving revision 1.9 diff -u -r1.8 -r1.9 --- Parser.java 2001/04/13 21:51:34 1.8 +++ Parser.java 2001/04/26 23:17:40 1.9 @@ -828,6 +828,10 @@ Mark bodyStart = null; Mark bodyStop = null; + // Get information about the body content. When the body content is + // empty, methods that manipulate the body are NOT invoked + boolean hasBody = false; + if (reader.matches(CLOSE_1) @@ -839,9 +843,9 @@ listener.setTemplateInfo(parser.tmplStart, parser.tmplStop); listener.handleTagBegin(start, reader.mark(), attrs, prefix, - shortTagName, tli, ti); + shortTagName, tli, ti, hasBody); listener.handleTagEnd(start, reader.mark(), prefix, - shortTagName, attrs, tli, ti); + shortTagName, attrs, tli, ti, hasBody); } else { // Body can be either // - JSP tags @@ -850,12 +854,21 @@ reader.advance(CLOSE.length()); bodyStart = reader.mark(); listener.setTemplateInfo(parser.tmplStart, parser.tmplStop); + + String tagEnd = "</"+tag+">"; + // Watch out: skipUntil() is case sensitive + bodyStop = reader.skipUntil(tagEnd.toLowerCase()); + if (bodyStop != null) { + String bodyString = new String(reader.getChars(bodyStart, bodyStop)); + hasBody = (bodyString.length() > 0); + } + reader.reset(bodyStart); + listener.handleTagBegin(start, bodyStart, attrs, prefix, - shortTagName, tli, ti); + shortTagName, tli, ti, hasBody); if (bc.equalsIgnoreCase(TagInfo.BODY_CONTENT_TAG_DEPENDENT) || bc.equalsIgnoreCase(TagInfo.BODY_CONTENT_JSP)) { - String tagEnd = "</"+tag+">"; // Parse until the end of the tag body. // Then skip the tag end... if (bc.equalsIgnoreCase(TagInfo.BODY_CONTENT_TAG_DEPENDENT)) @@ -875,7 +888,7 @@ } listener.setTemplateInfo(parser.tmplStart, parser.tmplStop); listener.handleTagEnd(parser.tmplStop, reader.mark(), prefix, - shortTagName, attrs, tli, ti); + shortTagName, attrs, tli, ti, hasBody); } else throw new ParseException(start, "Internal Error: Invalid BODY_CONTENT type"); 1.11 +45 -3 jakarta-tomcat-4.0/jasper/src/share/org/apache/jasper/compiler/ParserXJspSaxHandler.java Index: ParserXJspSaxHandler.java =================================================================== RCS file: /home/cvs/jakarta-tomcat-4.0/jasper/src/share/org/apache/jasper/compiler/ParserXJspSaxHandler.java,v retrieving revision 1.10 retrieving revision 1.11 diff -u -r1.10 -r1.11 --- ParserXJspSaxHandler.java 2001/04/25 19:33:56 1.10 +++ ParserXJspSaxHandler.java 2001/04/26 23:17:40 1.11 @@ -231,6 +231,19 @@ return; } + // If previous node is a custom tag, call its + // begin tag handler + if (!name.equals("jsp:root")) { + Node prevNode = (Node)stack.peek(); + if (prevNode instanceof NodeTag) { + try { + processCustomTagBeginDoIt((NodeTag) prevNode, true); + } catch (Exception ex) { + throw new SAXException(ex); + } + } + } + // Simply push the new 'node' on the stack, and it will be // processed on the 'endElement' event. stack.push(node); @@ -397,6 +410,19 @@ } } + // Need to delay calling the begin handler until we know whether + // the custom tag has a body or not. Must read ahead. + private void processCustomTagBeginDoIt(NodeTag node, boolean hasBody) + throws JasperException + { + if (!node.isBeginDone()) { + jspHandler.handleTagBegin(node.start, node.start, node.attrs, + node.prefix, node.shortTagName, node.tli, + node.ti, hasBody, true); + node.setBeginDone(true); + } + } + private void processCustomTagBegin(String prefix, String shortTagName) throws ParseException, JasperException { @@ -415,20 +441,26 @@ "Unable to locate TagInfo for " + prefix + ":" + shortTagName); } node = new NodeTag(node, prefix, shortTagName, tli, ti); + stack.push(node); - jspHandler.handleTagBegin(node.start, node.start, node.attrs, - prefix, shortTagName, tli, ti, true); } private void processCustomTagEnd(NodeTag node, Mark stop) throws ParseException, JasperException { String bc = node.ti.getBodyContent(); + + String charString = node.getText().toString(); + boolean hasBody = (charString.trim().length() > 0); + + // call begin tag processing with body info + processCustomTagBeginDoIt(node, hasBody); + if (node.getText() != null && bc.equalsIgnoreCase(TagInfo.BODY_CONTENT_EMPTY)) { throw new ParseException(node.start, "Body is supposed to be empty for " + node.rawName); } jspHandler.handleTagEnd(node.start, stop, node.prefix, - node.shortTagName, node.attrs, node.tli, node.ti); + node.shortTagName, node.attrs, node.tli, node.ti, hasBody); } //********************************************************************* @@ -663,6 +695,7 @@ String shortTagName; TagLibraryInfo tli; TagInfo ti; + boolean beginDone; NodeTag(Node node, String prefix, String shortTagName, TagLibraryInfo tli, TagInfo ti) @@ -672,6 +705,15 @@ this.shortTagName = shortTagName; this.tli = tli; this.ti = ti; + beginDone = false; + } + + boolean isBeginDone() { + return beginDone; + } + + void setBeginDone(boolean beginDone) { + this.beginDone = beginDone; } } 1.13 +20 -16 jakarta-tomcat-4.0/jasper/src/share/org/apache/jasper/compiler/TagBeginGenerator.java Index: TagBeginGenerator.java =================================================================== RCS file: /home/cvs/jakarta-tomcat-4.0/jasper/src/share/org/apache/jasper/compiler/TagBeginGenerator.java,v retrieving revision 1.12 retrieving revision 1.13 diff -u -r1.12 -r1.13 --- TagBeginGenerator.java 2001/04/26 01:15:11 1.12 +++ TagBeginGenerator.java 2001/04/26 23:17:40 1.13 @@ -99,13 +99,14 @@ TagData tagData; Mark start; TagLibraries libraries; + boolean hasBody; boolean isXml; public TagBeginGenerator(Mark start, String prefix, String shortTagName, Attributes attrs, TagLibraryInfo tli, TagInfo ti, TagLibraries libraries, Stack tagHandlerStack, Hashtable tagVarNumbers, - boolean isXml) + boolean hasBody, boolean isXml) throws JasperException { setTagHandlerStack(tagHandlerStack); @@ -120,6 +121,7 @@ this.thVarName = "_jspx_th_"+baseVarName; this.start = start; this.libraries = libraries; + this.hasBody = hasBody; this.isXml = isXml; } @@ -358,27 +360,29 @@ writer.popIndent(); } - writer.println("if ("+evalVar+" != Tag.SKIP_BODY) {"); - writer.pushIndent(); + if (hasBody) { + writer.println("if ("+evalVar+" != Tag.SKIP_BODY) {"); + writer.pushIndent(); - if (implementsBodyTag) { - writer.println("try {"); - writer.pushIndent(); + if (implementsBodyTag) { + writer.println("try {"); + writer.pushIndent(); - writer.println("if ("+evalVar+" != Tag.EVAL_BODY_INCLUDE) {"); - writer.pushIndent(); + writer.println("if ("+evalVar+" != Tag.EVAL_BODY_INCLUDE) {"); + writer.pushIndent(); - writer.println("out = pageContext.pushBody();"); - writer.println(thVarName+".setBodyContent((BodyContent) out);"); + writer.println("out = pageContext.pushBody();"); + writer.println(thVarName+".setBodyContent((BodyContent) out);"); - writer.popIndent(); - writer.println("}"); + writer.popIndent(); + writer.println("}"); - writer.println(thVarName+".doInitBody();"); - } + writer.println(thVarName+".doInitBody();"); + } - writer.println("do {"); - writer.pushIndent(); + writer.println("do {"); + writer.pushIndent(); + } // Need to declare and update NESTED variables here declareVariables(writer, vi, tvi, tagData, true, true, VariableInfo.NESTED); // Need to update AT_BEGIN variables here 1.6 +36 -29 jakarta-tomcat-4.0/jasper/src/share/org/apache/jasper/compiler/TagEndGenerator.java Index: TagEndGenerator.java =================================================================== RCS file: /home/cvs/jakarta-tomcat-4.0/jasper/src/share/org/apache/jasper/compiler/TagEndGenerator.java,v retrieving revision 1.5 retrieving revision 1.6 diff -u -r1.5 -r1.6 --- TagEndGenerator.java 2000/11/01 20:25:08 1.5 +++ TagEndGenerator.java 2001/04/26 23:17:40 1.6 @@ -85,11 +85,13 @@ TagInfo ti; Attributes attrs; TagLibraries libraries; + boolean hasBody; public TagEndGenerator(String prefix, String shortTagName, Attributes attrs, TagLibraryInfo tli, TagInfo ti, TagLibraries libraries, - Stack tagHandlerStack, Hashtable tagVarNumbers) + Stack tagHandlerStack, Hashtable tagVarNumbers, + boolean hasBody) { setTagHandlerStack(tagHandlerStack); setTagVarNumbers(tagVarNumbers); @@ -99,6 +101,7 @@ this.ti = ti; this.attrs = attrs; this.libraries = libraries; + this.hasBody = hasBody; } public void generate(ServletWriter writer, Class phase) { @@ -122,39 +125,43 @@ writer.popIndent(); - if (implementsIterationTag) - writer.println("} while ("+thVarName+".doAfterBody() == BodyTag.EVAL_BODY_AGAIN);"); - else - writer.println("} while (false);"); + if (hasBody) { + if (implementsIterationTag) + writer.println("} while ("+thVarName+".doAfterBody() == BodyTag.EVAL_BODY_AGAIN);"); + else + writer.println("} while (false);"); + } declareVariables(writer, vi, tvi, tagData, false, true, VariableInfo.AT_BEGIN); - - if (implementsBodyTag) { - writer.popIndent(); // try - /** FIXME: REMOVE BEGIN */ - // writer.println("} catch (Throwable t) {"); - // writer.pushIndent(); - - // writer.println("System.err.println(\"Caught: \");"); - // writer.println("t.printStackTrace();"); - - // writer.popIndent(); - /** FIXME: REMOVE END */ - - writer.println("} finally {"); - writer.pushIndent(); - writer.println("if ("+evalVarName+" != Tag.EVAL_BODY_INCLUDE)"); - writer.pushIndent(); - writer.println("out = pageContext.popBody();"); - writer.popIndent(); + if (hasBody) { + if (implementsBodyTag) { + writer.popIndent(); // try + + /** FIXME: REMOVE BEGIN */ + // writer.println("} catch (Throwable t) {"); + // writer.pushIndent(); + + // writer.println("System.err.println(\"Caught: \");"); + // writer.println("t.printStackTrace();"); + + // writer.popIndent(); + /** FIXME: REMOVE END */ + + writer.println("} finally {"); + writer.pushIndent(); + writer.println("if ("+evalVarName+" != Tag.EVAL_BODY_INCLUDE)"); + writer.pushIndent(); + writer.println("out = pageContext.popBody();"); + writer.popIndent(); + + writer.popIndent(); + writer.println("}"); + } - writer.popIndent(); - writer.println("}"); + writer.popIndent(); // EVAL_BODY + writer.println("}"); } - - writer.popIndent(); // EVAL_BODY - writer.println("}"); writer.println("if ("+thVarName+".doEndTag() == Tag.SKIP_PAGE)"); writer.pushIndent(); writer.println("return;"); writer.popIndent();