luehe 2002/07/17 14:13:38 Modified: jasper2/src/share/org/apache/jasper/compiler Generator.java Log: Fixed bug in JSP Fragment generation [PATCH by Mark Roth] Revision Changes Path 1.41 +87 -38 jakarta-tomcat-jasper/jasper2/src/share/org/apache/jasper/compiler/Generator.java Index: Generator.java =================================================================== RCS file: /home/cvs/jakarta-tomcat-jasper/jasper2/src/share/org/apache/jasper/compiler/Generator.java,v retrieving revision 1.40 retrieving revision 1.41 diff -u -r1.40 -r1.41 --- Generator.java 17 Jul 2002 20:06:58 -0000 1.40 +++ Generator.java 17 Jul 2002 21:13:38 -0000 1.41 @@ -92,7 +92,7 @@ private ServletWriter out; private MethodsBuffer methodsBuffer; - private HelperClassBuffer helperClassBuffer; + private FragmentHelperClass fragmentHelperClass; private ErrorDispatcher err; private BeanRepository beanInfo; private JspCompilationContext ctxt; @@ -707,7 +707,7 @@ private ServletWriter out; private MethodsBuffer methodsBuffer; - private HelperClassBuffer helperClassBuffer; + private FragmentHelperClass fragmentHelperClass; private int methodNesting; /** @@ -715,11 +715,11 @@ */ public GenerateVisitor(ServletWriter out, MethodsBuffer methodsBuffer, - HelperClassBuffer helperClassBuffer ) + FragmentHelperClass fragmentHelperClass ) { this.out = out; this.methodsBuffer = methodsBuffer; - this.helperClassBuffer = helperClassBuffer; + this.fragmentHelperClass = fragmentHelperClass; methodNesting = 0; handlerInfos = new Hashtable(); tagVarNumbers = new Hashtable(); @@ -2362,18 +2362,19 @@ // generate a low-overhead JspFragment that just echoes its // body. The implementation of this fragment can come from // the org.apache.jasper.runtime package as a support class. - int id = helperClassBuffer.getFragmentId(); - helperClassBuffer.openFragment( n ); + FragmentHelperClass.Fragment fragment = + fragmentHelperClass.openFragment( n ); ServletWriter outSave = out; - out = helperClassBuffer.getOut(); + out = fragment.getMethodsBuffer().getOut(); visitBody( n ); out = outSave; - helperClassBuffer.closeFragment(); + fragmentHelperClass.closeFragment( fragment ); // XXX - Need to change pageContext to jspContext if // we're not in a place where pageContext is defined (e.g. // in a fragment or in a tag file. - out.print( "new " + helperClassBuffer.getClassName() + - "( " + id + ", pageContext, " + tagHandlerVar + ")" ); + out.print( "new " + fragmentHelperClass.getClassName() + + "( " + fragment.getId() + ", pageContext, " + + tagHandlerVar + ")" ); } /** @@ -2510,9 +2511,9 @@ out.print(methodsBuffer.toString()); // Append the helper class - if( helperClassBuffer.isUsed() ) { - helperClassBuffer.generatePostamble(); - out.print(helperClassBuffer.toString()); + if( fragmentHelperClass.isUsed() ) { + fragmentHelperClass.generatePostamble(); + out.printMultiLn(fragmentHelperClass.toString()); } // generate class definition for JspxState @@ -2533,7 +2534,7 @@ methodsBuffer = new MethodsBuffer(); err = compiler.getErrorDispatcher(); ctxt = compiler.getCompilationContext(); - helperClassBuffer = new HelperClassBuffer( + fragmentHelperClass = new FragmentHelperClass( ctxt.getServletClassName() + "Helper" ); pageInfo = compiler.getPageInfo(); beanInfo = pageInfo.getBeanRepository(); @@ -2557,9 +2558,9 @@ gen.compileTagHandlerPoolList(page); } gen.generatePreamble(page); - gen.helperClassBuffer.generatePreamble(); + gen.fragmentHelperClass.generatePreamble(); page.visit(gen.new GenerateVisitor(out, gen.methodsBuffer, - gen.helperClassBuffer)); + gen.fragmentHelperClass)); gen.generatePostamble(page); } @@ -2653,19 +2654,39 @@ } /** - * Keeps a separate buffer for helper classes. + * Keeps track of the generated Fragment Helper Class */ - private static class HelperClassBuffer - extends MethodsBuffer - { + private static class FragmentHelperClass { + + private static class Fragment { + private MethodsBuffer methodsBuffer; + private int id; + + public Fragment( int id ) { + this.id = id; + methodsBuffer = new MethodsBuffer(); + } + + public MethodsBuffer getMethodsBuffer() { + return this.methodsBuffer; + } + + public int getId() { + return this.id; + } + } + // True if the helper class should be generated. private boolean used = false; - private int numFragments = 0; + private ArrayList fragments = new ArrayList(); private String className; + + // Buffer for entire helper class + private MethodsBuffer classBuffer = new MethodsBuffer(); - public HelperClassBuffer( String className ) { + public FragmentHelperClass( String className ) { this.className = className; } @@ -2677,14 +2698,13 @@ return this.used; } - public int getFragmentId() { - return this.numFragments; - } - public void generatePreamble() { + ServletWriter out = this.classBuffer.getOut(); out.println(); out.pushIndent(); - out.printil( "static class " + className ); + // Note: cannot be static, as we need to reference things like + // _jspx_meth_* + out.printil( "class " + className ); out.printil( " extends " + "org.apache.jasper.runtime.JspFragmentHelper" ); out.printil( "{" ); @@ -2698,28 +2718,53 @@ out.printil( "}" ); } - public void openFragment( Node parent ) + public Fragment openFragment( Node parent ) throws JasperException { + Fragment result = new Fragment( fragments.size() ); + fragments.add( result ); this.used = true; - out.printil( "public void invoke" + numFragments + "( " + + + ServletWriter out = result.getMethodsBuffer().getOut(); + out.pushIndent(); + out.pushIndent(); + // XXX - Returns boolean because if a tag is invoked from + // within this fragment, the Generator sometimes might + // generate code like "return true". This is ignored for now, + // meaning only the fragment is skipped. The JSR-152 + // expert group is currently discussing what to do in this case. + // See comment in closeFragment() + out.printil( "public boolean invoke" + result.getId() + "( " + "java.io.Writer out, java.util.Map params ) " ); out.pushIndent(); - out.printil( "throws javax.servlet.jsp.JspException, " + - "java.io.IOException" ); + // Note: Throwable required because methods like _jspx_meth_* + // throw Throwable. + out.printil( "throws Throwable" ); out.popIndent(); out.printil( "{" ); out.pushIndent(); generateLocalVariables( out, parent ); + + return result; } - public void closeFragment() { + public void closeFragment( Fragment fragment ) { + ServletWriter out = fragment.getMethodsBuffer().getOut(); + // XXX - See comment in openFragment() + out.printil( "return false;" ); out.popIndent(); out.printil( "}" ); - this.numFragments++; } public void generatePostamble() { + ServletWriter out = this.classBuffer.getOut(); + // Generate all fragment methods: + for( int i = 0; i < fragments.size(); i++ ) { + Fragment fragment = (Fragment)fragments.get( i ); + out.printMultiLn( fragment.getMethodsBuffer().toString() ); + } + + // Generate postamble: out.printil( "public void invoke( java.io.Writer out, " + "java.util.Map params )" ); out.pushIndent(); @@ -2744,7 +2789,7 @@ out.pushIndent(); out.printil( "switch( this.discriminator ) {" ); out.pushIndent(); - for( int i = 0; i < numFragments; i++ ) { + for( int i = 0; i < fragments.size(); i++ ) { out.printil( "case " + i + ":" ); out.pushIndent(); out.printil( "invoke" + i + "( out, params );" ); @@ -2755,7 +2800,7 @@ out.printil( "}" ); // switch out.popIndent(); out.printil( "}" ); // try - out.printil( "catch( java.io.IOException e ) {" ); + out.printil( "catch( Throwable e ) {" ); out.pushIndent(); out.printil( "throw new javax.servlet.jsp.JspException( e );" ); out.popIndent(); @@ -2775,6 +2820,10 @@ out.popIndent(); out.printil( "}" ); // helper class out.popIndent(); + } + + public String toString() { + return classBuffer.toString(); } } }
-- To unsubscribe, e-mail: <mailto:[EMAIL PROTECTED]> For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>