Hi Kin-Man!

Here's take two of the "stack based" finally.  The first version had a very
nasty bug, the stacks variables were declared by mistake as field variables,
so the JSP was not thread safe!  This version properly declares the stack
variables as local variables to the _jsp_service() method.

By the way, I wish to thank everybody for the confidence they have put
in me in the vote.  I will try hard to meet the expectations.  I consider
myself very lucky to be able to cooperate with some of the very talented 
people in Tomcat.

Thanks!


Index: 
jakarta-tomcat-jasper/jasper2/src/share/org/apache/jasper/compiler/Generator.java
===================================================================
RCS file: 
/home/cvspublic/jakarta-tomcat-jasper/jasper2/src/share/org/apache/jasper/compiler/Generator.java,v
retrieving revision 1.14
diff -c -r1.14 Generator.java
*** jakarta-tomcat-jasper/jasper2/src/share/org/apache/jasper/compiler/Generator.java  
 15 May 2002 20:42:03 -0000      1.14
--- jakarta-tomcat-jasper/jasper2/src/share/org/apache/jasper/compiler/Generator.java  
 23 May 2002 01:26:18 -0000
***************
*** 94,102 ****
      private JspCompilationContext ctxt;
      private boolean breakAtLF;
      private PageInfo pageInfo;
!     private FinallyApplyer finallies;
!     private int tryBit;
!     private Stack tryStack;
  
      /**
       * @param s the input string
--- 94,100 ----
      private JspCompilationContext ctxt;
      private boolean breakAtLF;
      private PageInfo pageInfo;
!     private int maxTagNesting;
  
      /**
       * @param s the input string
***************
*** 227,232 ****
--- 225,240 ----
              out.println();
          }
  
+       // Class fields declarations
+       
+       maxTagNesting = pageInfo.getMaxTagNesting();
+       if (maxTagNesting >= 0) {
+               out.printil("private static final int RELEASE_ACTION         = 0;");
+               out.printil("private static final int POP_AND_RELEASE_ACTION = 1;");
+               out.println();
+               out.println();
+       }
+ 
        // Constructor (empty so far) here
  
        // Method used to get compile time include file dependencies
***************
*** 238,255 ****
          out.println();
          out.println();
  
-         out.printil("private void addTagToVector(java.util.Vector tags, int index, 
Object tag) {");
-         out.pushIndent();
-         out.printil("if (index + 1 > tags.size())");
-         out.pushIndent();
-         out.printil("tags.setSize(index + 1);");
-         out.popIndent();
-         out.printil("tags.setElementAt(tag, index);");
-         out.popIndent();
-         out.printil("}");
-         out.println();
-         out.println();
- 
        // Now the service method
        out.printin("public void ");
        out.print  (serviceMethodName);
--- 246,251 ----
***************
*** 272,279 ****
        out.printil("ServletConfig config = null;");
        out.printil("JspWriter out = null;");
        out.printil("Object page = this;");
!         out.printil("java.util.BitSet bitmask = new java.util.BitSet();");
!         out.printil("java.util.Vector tags = new java.util.Vector();");
  
        out.printil("try {");
        out.pushIndent();
--- 268,287 ----
        out.printil("ServletConfig config = null;");
        out.printil("JspWriter out = null;");
        out.printil("Object page = this;");
!     
!       // pseudo "Finally" state stack objects
!         if (maxTagNesting >= 0) {
!             String depth = Integer.toString(maxTagNesting + 1);
!             out.printil("int   finallyStackIndex = -1;");
!             out.printin("int[] finallyStackActions = new int[");
!             out.print(depth);
!             out.println("];");
!             out.printin("javax.servlet.jsp.tagext.Tag[] finallyStackTags = new 
javax.servlet.jsp.tagext.Tag[");
!             out.print(depth);
!             out.println("];");
!             out.println();
!             out.println();
!         }
  
        out.printil("try {");
        out.pushIndent();
***************
*** 982,997 ****
                  out.pushIndent();
              } else {
                  out.printil("// try {");
!                 out.printin("bitmask.set(");
!                 Integer tryBitVal = new Integer(tryBit++);
!                 tryStack.push(tryBitVal);
!                 out.print(tryBitVal.toString());
!                 out.println(");");
!                 out.printin("addTagToVector(tags, ");
!                 out.print(tryBitVal.toString());
!                 out.print(", ");
                  out.print(tagHandlerVar);
!                 out.println(");");
              }
            out.printin("int ");
            out.print(tagEvalVar);
--- 990,999 ----
                  out.pushIndent();
              } else {
                  out.printil("// try {");
!                 out.printil("finallyStackActions[++finallyStackIndex] = 
RELEASE_ACTION;");
!                 out.printin("finallyStackTags[finallyStackIndex] = ");
                  out.print(tagHandlerVar);
!                 out.println(";");
              }
            out.printin("int ");
            out.print(tagEvalVar);
***************
*** 1015,1030 ****
                
                if (isBodyTag) {
                      out.printil("// try {");
-                     out.printin("bitmask.set(");
-                     Integer tryBitVal = new Integer(tryBit++);
-                     tryStack.push(tryBitVal);
-                     out.print(tryBitVal.toString());
-                     out.println(");");
-                     out.printin("addTagToVector(tags, ");
-                     out.print(tryBitVal.toString());
-                     out.print(", new Integer(");
-                     out.print(tagEvalVar);
-                     out.println("));");
                    out.printin("if (");
                    out.print(tagEvalVar);
                    out.println(" != javax.servlet.jsp.tagext.Tag.EVAL_BODY_INCLUDE) 
{");
--- 1017,1022 ----
***************
*** 1032,1037 ****
--- 1024,1032 ----
                    out.pushIndent();
                    
                    out.printil("out = pageContext.pushBody();");
+                   if (!implementsTryCatchFinally) {
+                       out.printil("finallyStackActions[finallyStackIndex] = 
+POP_AND_RELEASE_ACTION;");
+                   }
                    out.printin(tagHandlerVar);
                    
out.println(".setBodyContent((javax.servlet.jsp.tagext.BodyContent) out);");
                    out.printin(tagHandlerVar);
***************
*** 1086,1113 ****
  
            if (n.getBody() != null) {
                if (implementsBodyTag) {
-                     Integer tryBitVal = (Integer)tryStack.pop();
                      out.printil("// } finally {");
!                     out.printin("bitmask.clear(");
!                     out.print(tryBitVal.toString());
!                     out.println(");");
! 
                    out.printin("if (");
                    out.print(tagEvalVar);
                    out.println(" != javax.servlet.jsp.tagext.Tag.EVAL_BODY_INCLUDE)");
                    out.pushIndent();
                    out.printil("out = pageContext.popBody();");
                    out.popIndent();
- 
-                     finallies.beginPartMethod(tryBitVal.intValue());
-                     finallies.print("      if (");
-                     finallies.print("((Integer)tags.elementAt(");
-                     finallies.print(tryBitVal.toString());
-                     finallies.print(")).intValue()");
-                     finallies.println(" != 
javax.servlet.jsp.tagext.Tag.EVAL_BODY_INCLUDE)");
-                     finallies.println("        out = pageContext.popBody();");
- 
-                     finallies.endPartMethod();
                      out.printil("// }");
                }
  
--- 1081,1096 ----
  
            if (n.getBody() != null) {
                if (implementsBodyTag) {
                      out.printil("// } finally {");
!                   if (!implementsTryCatchFinally) {
!                       out.printil("finallyStackActions[finallyStackIndex] = 
RELEASE_ACTION;");
!                   }
                    out.printin("if (");
                    out.print(tagEvalVar);
                    out.println(" != javax.servlet.jsp.tagext.Tag.EVAL_BODY_INCLUDE)");
                    out.pushIndent();
                    out.printil("out = pageContext.popBody();");
                    out.popIndent();
                      out.printil("// }");
                }
  
***************
*** 1139,1158 ****
                  out.popIndent();
                  out.printil("}");
              } else {
-                 Integer tryBitVal = (Integer)tryStack.pop();
                  out.printil("// } finally {");
!                 out.printin("bitmask.clear(");
!                 out.print(tryBitVal.toString());
!                 out.println(");");
                  out.printin(tagHandlerVar);
                  out.println(".release();");
                  out.printil("// }");
-                 finallies.beginPartMethod(tryBitVal.intValue());
-                 finallies.printin("((javax.servlet.jsp.tagext.Tag)tags.elementAt(");
-                 finallies.print(tryBitVal.toString());
-                 finallies.print("))");
-                 finallies.println(".release();");
-                 finallies.endPartMethod();
            }
  
            // Declare and update AT_END variables
--- 1122,1132 ----
                  out.popIndent();
                  out.printil("}");
              } else {
                  out.printil("// } finally {");
!                 out.printil("finallyStackIndex--;");
                  out.printin(tagHandlerVar);
                  out.println(".release();");
                  out.printil("// }");
            }
  
            // Declare and update AT_END variables
***************
*** 1419,1424 ****
--- 1393,1409 ----
          out.popIndent();
          out.printil("} catch (Throwable t) {");
          out.pushIndent();
+         if (maxTagNesting >= 0) {
+             out.printil("while (finallyStackIndex >= 0) {");
+             out.pushIndent();
+             out.printil("if (POP_AND_RELEASE_ACTION == 
+finallyStackActions[finallyStackIndex])");
+             out.pushIndent();
+             out.printil("out = pageContext.popBody();");
+             out.popIndent();
+             out.printil("finallyStackTags[finallyStackIndex--].release();");
+             out.popIndent();
+             out.printil("}");
+         }
          out.printil("if (out != null && out.getBufferSize() != 0)");
          out.pushIndent();
          out.printil("out.clearBuffer();");
***************
*** 1427,1446 ****
          out.popIndent();
          out.printil("} finally {");
          out.pushIndent();
- 
-         // Do stuff here for finally actions...
- 
-         out.printil("try {");
-         out.pushIndent();
-         out.printil("finallies(bitmask, out, tags, pageContext);");
-         out.popIndent();
-         out.printil("} catch (javax.servlet.jsp.JspException e) {");
-         out.pushIndent();
-         out.printil("if (pageContext != null) pageContext.handlePageException(e);");
-         out.popIndent();
-         out.printil("}");
          out.printil("if (_jspxFactory != null) 
_jspxFactory.releasePageContext(pageContext);");
- 
          out.popIndent();
          out.printil("}");
  
--- 1412,1418 ----
***************
*** 1448,1457 ****
          out.popIndent();
          out.printil("}");
  
-         // Call the final method
-         finallies.done();
-         out.printil(finallies.toString());
- 
          // Close the class definition
          out.popIndent();
          out.printil("}");
--- 1420,1425 ----
***************
*** 1467,1474 ****
        pageInfo = compiler.getPageInfo();
        beanInfo = pageInfo.getBeanRepository();
        breakAtLF = ctxt.getOptions().getMappedFile();
-         finallies = new FinallyApplyer();
-         tryStack = new Stack();
      }
  
      /**
--- 1435,1440 ----
***************
*** 1563,1617 ****
            return tagHandlerClass;
        }
      }
- 
-     private static class FinallyApplyer {
-         private PrintStream finalOutput;
-         private ByteArrayOutputStream rawOutput;
- 
-         FinallyApplyer() {
-             rawOutput = new ByteArrayOutputStream();
-             finalOutput = new PrintStream(rawOutput, true);
- 
-             finalOutput.println();
-             finalOutput.println("  private void finallies(java.util.BitSet bitmask, 
JspWriter out, java.util.Vector tags, PageContext pageContext)");
-             finalOutput.println("  throws javax.servlet.jsp.JspException {");
-         }
- 
-         public void done() {
-             finalOutput.println("  }");
-         }
- 
-         public void beginPartMethod(int bit) {
-             finalOutput.print("    if (bitmask.get(");
-             finalOutput.print(bit);
-             finalOutput.println(")) {");
-         }
- 
-         public void endPartMethod() {
-             finalOutput.println("    }");
-             finalOutput.println();
-         }
- 
-         public void println(String aLine) {
-             if (null != aLine) {
-                 finalOutput.print(aLine);
-             }
-             finalOutput.println();
-         }
- 
-         public void printin(String partLine) {
-             finalOutput.print("      ");
-             finalOutput.print(partLine);
-         }
- 
-         public void print(String partLine) {
-             finalOutput.print(partLine);
-         }
- 
-         public String toString() {
-             return rawOutput.toString();
-         }
-     }
- 
  }
  
--- 1529,1533 ----

-- 
Denis Benoit
[EMAIL PROTECTED]


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

Reply via email to