DO NOT REPLY TO THIS EMAIL, BUT PLEASE POST YOUR BUG 
RELATED COMMENTS THROUGH THE WEB INTERFACE AVAILABLE AT
<http://nagoya.apache.org/bugzilla/show_bug.cgi?id=26436>.
ANY REPLY MADE TO THIS MESSAGE WILL NOT BE COLLECTED AND 
INSERTED IN THE BUG DATABASE.

http://nagoya.apache.org/bugzilla/show_bug.cgi?id=26436

Jasper generates code weak against exception in doAfterTag()

           Summary: Jasper generates code weak against exception in
                    doAfterTag()
           Product: Tomcat 4
           Version: 4.1.29
          Platform: All
        OS/Version: All
            Status: NEW
          Severity: Normal
          Priority: Other
         Component: Jasper
        AssignedTo: [EMAIL PROTECTED]
        ReportedBy: [EMAIL PROTECTED]


Jasper (distributed with Tomcat 4.1.29) generates code which is not
robust to exceptions, and in some cases it breaks correct containment
of JspWriter/BodyContent in PageContext.

1. Create a custom tag handler (named ErrorTag) which may throw
   a JspException in doAfterBody().
   Bind it to <my:error> tag.

======== excerpt from ErrorTag.java
public class ErrorTag extends BodyTagSupport {
    public int doAfterBody() throws JspException {
        // Do something with bodyContent
        throw new JspException();
    }
}
========

2. Create a JSP page that has a <my:error> tag, which is enclosed by
   TryCatchFinally implementation tag. In this case, I use <c:catch>
   of JSTL Core, with <c:if> tag to expose its result.

======== excerpt from error.jsp
[[[
<c:catch var="e">
  <my:error>some content</my:error> <%-- this raises an exception --%>
</c:catch>
<c:if test="${e != null}">
  Exception!
</c:if>
]]]
========

3. Deploy them and invoke the JSP page.

Expected result is "[[[ Exception! ]]]" (whitespaces squeezed).
However, the real outcome is "[[[ ]]]".


After some investigation, I come to believe that Java source code
generated by Jasper is not robust against exceptions.

Here is the generated source code from error.jsp:
  (the part calling ErrorTag's methods; line numbers are added locally)
======== excerpt from error_jsp.java
 1:   private boolean _jspx_meth_my_error_0(javax.servlet.jsp.tagext.Tag
_jspx_th_c_catch_0, javax.servlet.jsp.PageContext pageContext, int
_jspx_push_body_count_c_catch_0)
 2:          throws Throwable {
 3:    JspWriter out = pageContext.getOut();
 4:    /* ----  my:error ---- */
 5:    lab.tag.ErrorTag _jspx_th_my_error_0 = (lab.tag.ErrorTag)
_jspx_tagPool_my_error.get(lab.tag.ErrorTag.class);
 6:    _jspx_th_my_error_0.setPageContext(pageContext);
 7:    _jspx_th_my_error_0.setParent(_jspx_th_c_catch_0);
 8:    int _jspx_eval_my_error_0 = _jspx_th_my_error_0.doStartTag();
 9:    if (_jspx_eval_my_error_0 != javax.servlet.jsp.tagext.Tag.SKIP_BODY) {
10:      if (_jspx_eval_my_error_0 !=
javax.servlet.jsp.tagext.Tag.EVAL_BODY_INCLUDE) {
11:        javax.servlet.jsp.tagext.BodyContent _bc = pageContext.pushBody();
12:        _jspx_push_body_count_c_catch_0++;
13:        out = _bc;
14:        _jspx_th_my_error_0.setBodyContent(_bc);
15:        _jspx_th_my_error_0.doInitBody();
16:      }
17:      do {
18:        out.write("some content");
19:        int evalDoAfterBody = _jspx_th_my_error_0.doAfterBody();
20:        if (evalDoAfterBody != javax.servlet.jsp.tagext.BodyTag.EVAL_BODY_AGAIN)
21:          break;
22:      } while (true);
23:      if (_jspx_eval_my_error_0 !=
javax.servlet.jsp.tagext.Tag.EVAL_BODY_INCLUDE)
24:        out = pageContext.popBody();
25:        _jspx_push_body_count_c_catch_0--;
26:    }
27:    if (_jspx_th_my_error_0.doEndTag() == javax.servlet.jsp.tagext.Tag.SKIP_PAGE)
28:      return true;
29:    _jspx_tagPool_my_error.reuse(_jspx_th_my_error_0);
30:    return false;
31:  }
========

At Line 11, pageContext.pushBody() is called, and
at Line 24, pageContext.popBody() is called.
However, if an exception is raised in doAfterBody() at Line 19,
the pushed BodyContent remains in pageContext. So, the content of
<c:if> tag is written to the BodyContent whose buffer is to be
discarded, not to the real JspWriter of the page.

I tried to fix this by modifying error_jsp.java and it looks
successful:  I enclosed the whole content of '_jspx_meth_my_error_0'
with 'try' clause, and added 'finally' clause to call popBody().  (Of
course there is more to do, such as not to pop when not yet pushed or
already popped.)

I don't know the details of Jasper and I'm not sure whether it is a
good solution in every aspect or not. I just hope this helps.

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to