You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by be...@locus.apache.org on 2000/07/03 11:11:25 UTC

cvs commit: jakarta-tomcat/src/share/org/apache/jasper/compiler TagGeneratorBase.java JspParseEventListener.java TagBeginGenerator.java TagEndGenerator.java

bergsten    00/07/03 02:11:23

  Modified:    src/share/org/apache/jasper/compiler TagGeneratorBase.java
                        JspParseEventListener.java TagBeginGenerator.java
                        TagEndGenerator.java
  Log:
  Changed all static methods and variables in TagGeneratorBase to regular
  instance variables, to avoid corrupt state in error situations and
  possibly in multi-threading race conditions. Note! A number of synchronize()
  calls can most likely be removed in this and other classes now.
  The objkects used to keep track of action element's parents and
  unique variable names are now created by JspParseEventListener and
  provided to the tag generator instances through the constructor.
  
  Replaced getAttribute() with findAttribute() in the code generated
  for synchronization of variables created by a custom action. A
  variable can be created in any scope (see JSP 1.1 errata for details).
  
  Revision  Changes    Path
  1.4       +42 -23    jakarta-tomcat/src/share/org/apache/jasper/compiler/TagGeneratorBase.java
  
  Index: TagGeneratorBase.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat/src/share/org/apache/jasper/compiler/TagGeneratorBase.java,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- TagGeneratorBase.java	1999/10/21 07:57:23	1.3
  +++ TagGeneratorBase.java	2000/07/03 09:11:17	1.4
  @@ -1,13 +1,13 @@
   /*
  - * $Header: /home/cvs/jakarta-tomcat/src/share/org/apache/jasper/compiler/TagGeneratorBase.java,v 1.3 1999/10/21 07:57:23 akv Exp $
  - * $Revision: 1.3 $
  - * $Date: 1999/10/21 07:57:23 $
  + * $Header: /home/cvs/jakarta-tomcat/src/share/org/apache/jasper/compiler/TagGeneratorBase.java,v 1.4 2000/07/03 09:11:17 bergsten Exp $
  + * $Revision: 1.4 $
  + * $Date: 2000/07/03 09:11:17 $
    *
    * ====================================================================
  - * 
  + *
    * The Apache Software License, Version 1.1
    *
  - * Copyright (c) 1999 The Apache Software Foundation.  All rights 
  + * Copyright (c) 1999 The Apache Software Foundation.  All rights
    * reserved.
    *
    * Redistribution and use in source and binary forms, with or without
  @@ -15,7 +15,7 @@
    * are met:
    *
    * 1. Redistributions of source code must retain the above copyright
  - *    notice, this list of conditions and the following disclaimer. 
  + *    notice, this list of conditions and the following disclaimer.
    *
    * 2. Redistributions in binary form must reproduce the above copyright
    *    notice, this list of conditions and the following disclaimer in
  @@ -23,15 +23,15 @@
    *    distribution.
    *
    * 3. The end-user documentation included with the redistribution, if
  - *    any, must include the following acknowlegement:  
  - *       "This product includes software developed by the 
  + *    any, must include the following acknowlegement:
  + *       "This product includes software developed by the
    *        Apache Software Foundation (http://www.apache.org/)."
    *    Alternately, this acknowlegement may appear in the software itself,
    *    if and wherever such third-party acknowlegements normally appear.
    *
    * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
    *    Foundation" must not be used to endorse or promote products derived
  - *    from this software without prior written permission. For written 
  + *    from this software without prior written permission. For written
    *    permission, please contact apache@apache.org.
    *
    * 5. Products derived from this software may not be called "Apache"
  @@ -57,7 +57,7 @@
    * information on the Apache Software Foundation, please see
    * <http://www.apache.org/>.
    *
  - */ 
  + */
   
   package org.apache.jasper.compiler;
   
  @@ -67,16 +67,18 @@
   import javax.servlet.jsp.tagext.VariableInfo;
   
   /**
  - * Common stuff for use with TagBegin and TagEndGenerators. 
  + * Common stuff for use with TagBegin and TagEndGenerators.
    *
    * @author Anil K. Vijendran
  + * @author Hans Bergsten [hans@gefionsoftware.com] (changed all statics to
  + *         regular instance vars and methods to avoid corrupt state and
  + *         multi-threading issues)
    */
   abstract class TagGeneratorBase extends GeneratorBase {
  -    static private Stack tagHandlerStack = new Stack();
  +    private Stack tagHandlerStack;
  +    private Hashtable tagVarNumbers;
   
  -    static private Hashtable tagVarNumbers = new Hashtable();
  -
  -    static class TagVariableData {
  +    class TagVariableData {
           String tagHandlerInstanceName;
           String tagEvalVarName;
           TagVariableData(String tagHandlerInstanceName, String tagEvalVarName) {
  @@ -84,22 +86,39 @@
               this.tagEvalVarName = tagEvalVarName;
           }
       }
  +
  +    /**
  +     * Sets the tag handler nesting stack for the current page.
  +     * Called when an instance is created.
  +     */
  +    protected void setTagHandlerStack(Stack tagHandlerStack) {
  +        this.tagHandlerStack = tagHandlerStack;
  +    }
  +
  +    /**
  +     * Sets the tag variable number repository for the current page.
  +     * Called when an instance is created.
  +     */
  +    protected void setTagVarNumbers(Hashtable tagVarNumbers) {
  +        this.tagVarNumbers = tagVarNumbers;
  +    }
   
  -    static protected void tagBegin(TagVariableData tvd) {
  +    protected void tagBegin(TagVariableData tvd) {
   	tagHandlerStack.push(tvd);
       }
   
  -    static protected TagVariableData tagEnd() {
  +    protected TagVariableData tagEnd() {
   	return (TagVariableData) tagHandlerStack.pop();
       }
   
  -    static protected TagVariableData topTag() {
  +    protected TagVariableData topTag() {
   	if (tagHandlerStack.empty())
   	    return null;
   	return (TagVariableData) tagHandlerStack.peek();
       }
  -	    
  -    static protected String getTagVarName(String prefix, String shortTagName) {
  +
  +    protected String getTagVarName(String prefix, String shortTagName) {
  +	// Fix: Can probably remove the synchronization now when no vars or method is static
   	synchronized (tagVarNumbers) {
   	    String tag = prefix+":"+shortTagName;
   	    String varName = prefix+"_"+shortTagName+"_";
  @@ -115,8 +134,8 @@
   	}
       }
   
  -    protected static void declareVariables(ServletWriter writer, VariableInfo[] vi, 
  -                                           boolean declare, boolean update, int scope) 
  +    protected void declareVariables(ServletWriter writer, VariableInfo[] vi,
  +                                           boolean declare, boolean update, int scope)
       {
           if (vi != null)
               for(int i = 0; i < vi.length; i++)
  @@ -125,7 +144,7 @@
                           writer.println(vi[i].getClassName()+" "+vi[i].getVarName()+" = null;");
                       if (update == true)
                           writer.println(vi[i].getVarName()+" = ("+
  -                                       vi[i].getClassName()+") pageContext.getAttribute("
  +                                       vi[i].getClassName()+") pageContext.findAttribute("
                                          +writer.quoteString(vi[i].getVarName())+");");
                   }
       }
  
  
  
  1.18      +177 -159  jakarta-tomcat/src/share/org/apache/jasper/compiler/JspParseEventListener.java
  
  Index: JspParseEventListener.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat/src/share/org/apache/jasper/compiler/JspParseEventListener.java,v
  retrieving revision 1.17
  retrieving revision 1.18
  diff -u -r1.17 -r1.18
  --- JspParseEventListener.java	2000/06/14 22:51:50	1.17
  +++ JspParseEventListener.java	2000/07/03 09:11:17	1.18
  @@ -1,13 +1,13 @@
   /*
  - * $Header: /home/cvs/jakarta-tomcat/src/share/org/apache/jasper/compiler/JspParseEventListener.java,v 1.17 2000/06/14 22:51:50 mandar Exp $
  - * $Revision: 1.17 $
  - * $Date: 2000/06/14 22:51:50 $
  + * $Header: /home/cvs/jakarta-tomcat/src/share/org/apache/jasper/compiler/JspParseEventListener.java,v 1.18 2000/07/03 09:11:17 bergsten Exp $
  + * $Revision: 1.18 $
  + * $Date: 2000/07/03 09:11:17 $
    *
    * ====================================================================
  - * 
  + *
    * The Apache Software License, Version 1.1
    *
  - * Copyright (c) 1999 The Apache Software Foundation.  All rights 
  + * Copyright (c) 1999 The Apache Software Foundation.  All rights
    * reserved.
    *
    * Redistribution and use in source and binary forms, with or without
  @@ -15,7 +15,7 @@
    * are met:
    *
    * 1. Redistributions of source code must retain the above copyright
  - *    notice, this list of conditions and the following disclaimer. 
  + *    notice, this list of conditions and the following disclaimer.
    *
    * 2. Redistributions in binary form must reproduce the above copyright
    *    notice, this list of conditions and the following disclaimer in
  @@ -23,15 +23,15 @@
    *    distribution.
    *
    * 3. The end-user documentation included with the redistribution, if
  - *    any, must include the following acknowlegement:  
  - *       "This product includes software developed by the 
  + *    any, must include the following acknowlegement:
  + *       "This product includes software developed by the
    *        Apache Software Foundation (http://www.apache.org/)."
    *    Alternately, this acknowlegement may appear in the software itself,
    *    if and wherever such third-party acknowlegements normally appear.
    *
    * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
    *    Foundation" must not be used to endorse or promote products derived
  - *    from this software without prior written permission. For written 
  + *    from this software without prior written permission. For written
    *    permission, please contact apache@apache.org.
    *
    * 5. Products derived from this software may not be called "Apache"
  @@ -57,11 +57,12 @@
    * information on the Apache Software Foundation, please see
    * <http://www.apache.org/>.
    *
  - */ 
  + */
   
   package org.apache.jasper.compiler;
   
   import java.util.Hashtable;
  +import java.util.Stack;
   import java.util.Vector;
   import java.util.Enumeration;
   import java.util.StringTokenizer;
  @@ -83,16 +84,16 @@
   import org.apache.tomcat.logging.Logger;
   
   /**
  - * JSP code generator "backend". 
  + * JSP code generator "backend".
    *
    * @author Anil K. Vijendran
    */
   public class JspParseEventListener extends BaseJspListener {
   
  -    private static CommentGenerator commentGenerator = new JakartaCommentGenerator();    
  +    private static CommentGenerator commentGenerator = new JakartaCommentGenerator();
   
       JspCompilationContext ctxt;
  -    
  +
       String jspServletBase = Constants.JSP_SERVLET_BASE;
       String serviceMethodName = Constants.SERVICE_METHOD_NAME;
       String servletContentType = Constants.SERVLET_CONTENT_TYPE;
  @@ -110,10 +111,10 @@
       Vector generators = new Vector();
   
       BeanRepository beanInfo;
  -    
  +
       int bufferSize = Constants.DEFAULT_BUFFER_SIZE;
   
  -    // a set of boolean variables to check if there are multiple attr-val 
  +    // a set of boolean variables to check if there are multiple attr-val
       // pairs for jsp directive.
       boolean languageDir = false, extendsDir = false, sessionDir = false;
       boolean bufferDir = false, threadsafeDir = false, errorpageDir = false;
  @@ -128,6 +129,11 @@
   
       TagLibraries libraries;
   
  +    // Variables shared by all TagBeginGenerator and TagEndGenerator instances
  +    // to keep track of nested tags and variable names
  +    private Stack tagHandlerStack;
  +    private Hashtable tagVarNumbers;
  +
       final void addGenerator(Generator gen) throws JasperException {
           gen.init(ctxt);
           generators.addElement(gen);
  @@ -139,22 +145,22 @@
   	}
   
   	commentGenerator = generator;
  -    }    
  -    
  +    }
  +
       /*
  -     * Package private since I want everyone to come in through 
  +     * Package private since I want everyone to come in through
        * org.apache.jasper.compiler.Main.
  -     */ 
  +     */
       JspParseEventListener(JspCompilationContext ctxt) {
   	super(ctxt.getReader(), ctxt.getWriter());
           this.ctxt = ctxt;
   	this.beanInfo = new BeanRepository(ctxt.getClassLoader());
           this.libraries = new TagLibraries(ctxt.getClassLoader());
  -        
  +
           // FIXME: Is this good enough? (I'm just taking the easy way out - akv)
           if (ctxt.getOptions().getLargeFile())
  -            dataFile = ctxt.getOutputDir() + File.separatorChar + 
  -                ctxt.getServletPackageName() + "_" + 
  +            dataFile = ctxt.getOutputDir() + File.separatorChar +
  +                ctxt.getServletPackageName() + "_" +
                   ctxt.getServletClassName() + ".dat";
       }
   
  @@ -162,7 +168,7 @@
   	for(int i = 0; i < Constants.STANDARD_IMPORTS.length; i++)
   	    imports.addElement(Constants.STANDARD_IMPORTS[i]);
       }
  -    
  +
       public void endPageProcessing() throws JasperException {
   	generateHeader();
   	writer.println();
  @@ -171,7 +177,7 @@
   	generateFooter();
           if (ctxt.getOptions().getLargeFile())
               try {
  -                ObjectOutputStream o 
  +                ObjectOutputStream o
                       = new ObjectOutputStream(new FileOutputStream(dataFile));
   
                   /*
  @@ -192,8 +198,22 @@
           ctxt.setContentType(servletContentType);
       }
   
  +    private Stack getTagHandlerStack() {
  +        if (tagHandlerStack == null) {
  +            tagHandlerStack = new Stack();
  +        }
  +        return tagHandlerStack;
  +    }
  +
  +    private Hashtable getTagVarNumbers() {
  +        if (tagVarNumbers == null) {
  +            tagVarNumbers = new Hashtable();
  +        }
  +        return tagVarNumbers;
  +    }
  +
       private void generateAll(Class phase) throws JasperException {
  -	
  +
   	for(int i = 0; i < generators.size(); i++) {
               Generator gen = (Generator) generators.elementAt(i);
               if (phase.isInstance(gen)) {
  @@ -202,7 +222,7 @@
   	}
   
       }
  -    
  +
       private void generateHeader() throws JasperException {
           String servletPackageName = ctxt.getServletPackageName();
           String servletClassName = ctxt.getServletClassName();
  @@ -211,9 +231,9 @@
   	    writer.println("package "+servletPackageName+";");
   	    writer.println();
   	}
  -	
  +
   	Enumeration e = imports.elements();
  -	while (e.hasMoreElements()) 
  +	while (e.hasMoreElements())
   	    writer.println("import "+(String) e.nextElement()+";");
   
   	writer.println();
  @@ -222,7 +242,7 @@
   
   	writer.print("public class "+servletClassName+ " extends ");
   	writer.print(extendsClass.equals("") ? jspServletBase : extendsClass);
  -	
  +
   	if (singleThreaded)
   	    interfaces.addElement("SingleThreadModel");
   
  @@ -236,7 +256,7 @@
   	}
   
   	writer.println(" {");
  -	
  +
   	writer.pushIndent();
   	writer.println();
   	generateAll(ClassDeclarationPhase.class);
  @@ -254,15 +274,15 @@
   
           writer.println("private static boolean _jspx_inited = false;");
           writer.println();
  -        
  +
           writer.println("public final void _jspx_init() throws JasperException {");
           writer.pushIndent();
   	generateAll(InitMethodPhase.class);
           writer.popIndent();
           writer.println("}");
           writer.println();
  -        
   
  +
   	writer.println("public void "+serviceMethodName+"("+
   		       "HttpServletRequest request, "+
   		       "HttpServletResponse  response)");
  @@ -272,16 +292,16 @@
   	writer.println();
           writer.println("JspFactory _jspxFactory = null;");
           writer.println("PageContext pageContext = null;");
  -        
  +
   	if (genSessionVariable)
   	    writer.println("HttpSession session = null;");
   
  -	if (ctxt.isErrorPage()) 
  +	if (ctxt.isErrorPage())
               writer.println("Throwable exception = (Throwable) request.getAttribute(\"javax.servlet.jsp.jspException\");");
   
   
  -	writer.println("ServletContext application = null;"); 
  -	writer.println("ServletConfig config = null;"); 
  +	writer.println("ServletContext application = null;");
  +	writer.println("ServletConfig config = null;");
   	writer.println("JspWriter out = null;");
           writer.println("Object page = this;");
   	writer.println("String  _value = null;");
  @@ -295,7 +315,7 @@
           writer.println("_jspx_inited = true;");
           writer.popIndent();
           writer.println("}");
  -        
  +
   	writer.println("_jspxFactory = JspFactory.getDefaultFactory();");
   	if (this.contentTypeDir == true)
   	    writer.println("response.setContentType(" +
  @@ -304,7 +324,7 @@
   	else
   	    writer.println("response.setContentType(\"" +
   			   servletContentType +
  -			   ";charset=8859_1\");");	    
  +			   ";charset=8859_1\");");
   	writer.println("pageContext = _jspxFactory.getPageContext(this, request, response,\n"
   					+ "\t\t\t"
   					+ writer.quoteString(error) + ", "
  @@ -338,33 +358,33 @@
   	writer.pushIndent();
   	/* Do stuff here for finally actions... */
           //writer.println("out.close();");
  -	writer.println("out.flush();"); 
  +	writer.println("out.flush();");
   	writer.println("_jspxFactory.releasePageContext(pageContext);");
   	writer.popIndent();
   	writer.println("}");
  -	// Close the service method: 
  +	// Close the service method:
   	writer.popIndent();
   	writer.println("}");
  -	
  +
   	// Close the class definition:
   	writer.popIndent();
   	writer.println("}");
       }
  -    
  -    
  +
  +
       public void handleComment(Mark start, Mark stop) throws JasperException {
  -        Constants.message("jsp.message.htmlcomment", 
  +        Constants.message("jsp.message.htmlcomment",
                             new Object[] { reader.getChars(start, stop) },
                             Logger.DEBUG);
       }
   
       interface PageDirectiveHandler {
  -        void handlePageDirectiveAttribute(JspParseEventListener listener, 
  +        void handlePageDirectiveAttribute(JspParseEventListener listener,
                                             String value,
                                             Mark start, Mark stop)
               throws JasperException;
       }
  -    
  +
       static final class PageDirectiveHandlerInfo {
           String attribute;
           PageDirectiveHandler handler;
  @@ -385,7 +405,7 @@
       static final String errorPageStr = "errorPage";
       static final String isErrorPageStr = "isErrorPage";
       static final String contentTypeStr = "contentType";
  -    
  +
   
       PageDirectiveHandlerInfo[] pdhis = new PageDirectiveHandlerInfo[] {
           new PageDirectiveHandlerInfo(languageStr, new LanguageHandler()),
  @@ -398,19 +418,19 @@
           new PageDirectiveHandlerInfo(infoStr, new InfoHandler()),
           new PageDirectiveHandlerInfo(isErrorPageStr, new IsErrorPageHandler()),
           new PageDirectiveHandlerInfo(contentTypeStr, new ContentTypeHandler()),
  -        new PageDirectiveHandlerInfo(errorPageStr, new ErrorPageHandler())    
  +        new PageDirectiveHandlerInfo(errorPageStr, new ErrorPageHandler())
       };
   
       // FIXME: Need to further refine these abstractions by moving the code
  -    // to handle duplicate directive instance checks to outside. 
  +    // to handle duplicate directive instance checks to outside.
   
       static final class ContentTypeHandler implements PageDirectiveHandler {
           public void handlePageDirectiveAttribute(JspParseEventListener listener,
  -                                                 String contentType, 
  -                                                 Mark start, Mark stop) 
  -            throws JasperException 
  +                                                 String contentType,
  +                                                 Mark start, Mark stop)
  +            throws JasperException
           {
  -            if (listener.contentTypeDir == true) 
  +            if (listener.contentTypeDir == true)
                   throw new CompileException(start,
   					   Constants.getString("jsp.error.page.multiple.contenttypes"));
               listener.contentTypeDir = true;
  @@ -420,12 +440,12 @@
               listener.servletContentType = contentType;
           }
       }
  -        
  +
       static final class SessionHandler implements PageDirectiveHandler {
  -        public void handlePageDirectiveAttribute(JspParseEventListener listener, 
  +        public void handlePageDirectiveAttribute(JspParseEventListener listener,
                                                    String session,
  -                                                 Mark start, Mark stop) 
  -            throws JasperException 
  +                                                 Mark start, Mark stop)
  +            throws JasperException
           {
               if (listener.sessionDir == true)
                   throw new CompileException (start,
  @@ -446,8 +466,8 @@
       static final class BufferHandler implements PageDirectiveHandler {
           public void handlePageDirectiveAttribute(JspParseEventListener listener,
                                                    String buffer,
  -                                                 Mark start, Mark stop) 
  -            throws JasperException 
  +                                                 Mark start, Mark stop)
  +            throws JasperException
           {
               if (listener.bufferDir == true)
                   throw new CompileException(start,
  @@ -455,7 +475,7 @@
               listener.bufferDir = true;
               if (buffer != null) {
                   if (buffer.equalsIgnoreCase("none"))
  -                    listener.bufferSize = 0; 
  +                    listener.bufferSize = 0;
                   else {
                       Integer i = null;
                       try {
  @@ -482,18 +502,18 @@
       static final class AutoFlushHandler implements PageDirectiveHandler {
           public void handlePageDirectiveAttribute(JspParseEventListener listener,
                                                    String autoflush,
  -                                                 Mark start, Mark stop) 
  -            throws JasperException 
  +                                                 Mark start, Mark stop)
  +            throws JasperException
           {
               if (listener.autoFlushDir == true)
                   throw new CompileException(start,
   					   Constants.getString("jsp.error.page.multiple.autoflush"));
  -            
  +
               listener.autoFlushDir = true;
               if (autoflush == null)
                   throw new CompileException(start,
   					   Constants.getString("jsp.error.page.invalid.autoflush"));
  -            
  +
               if (autoflush.equalsIgnoreCase("true"))
                   listener.autoFlush = true;
               else if (autoflush.equalsIgnoreCase("false"))
  @@ -507,43 +527,43 @@
       static final class IsThreadSafeHandler implements PageDirectiveHandler {
           public void handlePageDirectiveAttribute(JspParseEventListener listener,
                                                    String threadsafe,
  -                                                 Mark start, Mark stop) 
  -            throws JasperException 
  +                                                 Mark start, Mark stop)
  +            throws JasperException
           {
               if (listener.threadsafeDir == true)
                   throw new CompileException(start,
   					   Constants.getString("jsp.error.page.multiple.threadsafe"));
  -                                       
  +
               listener.threadsafeDir = true;
               if (threadsafe == null)
                   throw new CompileException (start,
   					    Constants.getString("jsp.error.page.invalid.threadsafe"));
  -            
  +
               if (threadsafe.equalsIgnoreCase("true"))
                   listener.singleThreaded = false;
               else if (threadsafe.equalsIgnoreCase("false"))
                   listener.singleThreaded = true;
  -            else 
  +            else
                   throw new CompileException (start,
   					    Constants.getString("jsp.error.page.invalid.threadsafe"));
           }
       }
  -    
  +
       static final class InfoHandler implements PageDirectiveHandler {
           public void handlePageDirectiveAttribute(JspParseEventListener listener,
                                                    String info,
  -                                                 Mark start, Mark stop) 
  -            throws JasperException 
  +                                                 Mark start, Mark stop)
  +            throws JasperException
           {
               if (listener.infoDir == true)
                   throw new CompileException (start,
   					    Constants.getString("jsp.error.page.multiple.info"));
  -            
  +
               listener.infoDir = true;
               if (info == null)
                   throw new CompileException(start,
   					   Constants.getString("jsp.error.page.invalid.info"));
  -            
  +
               GeneratorWrapper gen = listener. new GeneratorWrapper(new InfoGenerator(info),
                                                                     start, stop);
               listener.addGenerator(gen);
  @@ -553,18 +573,18 @@
       static final class IsErrorPageHandler implements PageDirectiveHandler {
           public void handlePageDirectiveAttribute(JspParseEventListener listener,
                                                    String iserrorpage,
  -                                                 Mark start, Mark stop) 
  -            throws JasperException 
  +                                                 Mark start, Mark stop)
  +            throws JasperException
           {
               if (listener.iserrorpageDir == true)
                   throw new CompileException (start,
   					    Constants.getString("jsp.error.page.multiple.iserrorpage"));
  -            
  +
               listener.iserrorpageDir = true;
               if (iserrorpage == null)
                   throw new CompileException(start,
   					   Constants.getString("jsp.error.page.invalid.iserrorpage"));
  -            
  +
               if (iserrorpage.equalsIgnoreCase("true"))
                   listener.ctxt.setErrorPage(true);
               else if (iserrorpage.equalsIgnoreCase("false"))
  @@ -574,35 +594,35 @@
   					   Constants.getString("jsp.error.page.invalid.iserrorpage"));
           }
       }
  -    
  +
       static final class ErrorPageHandler implements PageDirectiveHandler {
           public void handlePageDirectiveAttribute(JspParseEventListener listener,
                                                    String errorpage,
  -                                                 Mark start, Mark stop) 
  -            throws JasperException 
  +                                                 Mark start, Mark stop)
  +            throws JasperException
           {
               if (listener.errorpageDir == true)
                   throw new CompileException(start,
   					   Constants.getString("jsp.error.page.multiple.errorpage"));
  -            
  +
               listener.errorpageDir = true;
  -            if (errorpage != null) 
  +            if (errorpage != null)
                   listener.error = errorpage;
           }
       }
  -    
  +
       static final class LanguageHandler implements PageDirectiveHandler {
           public void handlePageDirectiveAttribute(JspParseEventListener listener,
                                                    String language,
  -                                                 Mark start, Mark stop) 
  -            throws JasperException 
  +                                                 Mark start, Mark stop)
  +            throws JasperException
           {
               if (listener.languageDir == true)
                   throw new CompileException(start,
   					   Constants.getString("jsp.error.page.multiple.language"));
  -            
  +
               listener.languageDir = true;
  -            if (language != null) 
  +            if (language != null)
                   if (!language.equalsIgnoreCase("java"))
                       throw new CompileException(start,
   					       Constants.getString("jsp.error.page.nomapping.language")+language);
  @@ -612,8 +632,8 @@
       static final class ImportsHandler implements PageDirectiveHandler {
           public void handlePageDirectiveAttribute(JspParseEventListener listener,
                                                    String importPkgs,
  -                                                 Mark start, Mark stop) 
  -            throws JasperException 
  +                                                 Mark start, Mark stop)
  +            throws JasperException
           {
               if (importPkgs != null) {
                   StringTokenizer tokenizer = new StringTokenizer(importPkgs, ",");
  @@ -622,18 +642,18 @@
               }
           }
       }
  -    
  +
       static final class ExtendsHandler implements PageDirectiveHandler {
           public void handlePageDirectiveAttribute(JspParseEventListener listener,
                                                    String extendsClzz,
  -                                                 Mark start, Mark stop) 
  -            throws JasperException 
  +                                                 Mark start, Mark stop)
  +            throws JasperException
           {
               if (listener.extendsDir == true)
                   throw new CompileException(start,
   					   Constants.getString("jsp.error.page.multiple.extends"));
  -            
  -            listener.extendsDir = true; 
  +
  +            listener.extendsDir = true;
               if (extendsClzz != null)  {
                   listener.extendsClass = extendsClzz;
   
  @@ -649,9 +669,9 @@
               }
           }
       }
  -    
  -    public void handleDirective(String directive, Mark start, 
  -				Mark stop, Hashtable attrs) 
  +
  +    public void handleDirective(String directive, Mark start,
  +				Mark stop, Hashtable attrs)
   	throws JasperException
       {
           Constants.message("jsp.message.handling_directive",
  @@ -667,24 +687,24 @@
                       PageDirectiveHandlerInfo pdhi = pdhis[i];
                       if (attr.equals(pdhi.attribute)) {
                           String value = (String) attrs.get(pdhi.attribute);
  -                        pdhi.handler.handlePageDirectiveAttribute(this, value, 
  +                        pdhi.handler.handlePageDirectiveAttribute(this, value,
                                                                     start, stop);
  -                    } 
  +                    }
                   }
               }
           }
   
  -        // Do some validations... 
  +        // Do some validations...
           if (bufferSize == 0 && autoFlush == false)
               throw new CompileException(start, Constants.getString(
   	    				"jsp.error.page.bad_b_and_a_combo"));
  -      
  +
   	if (directive.equals("taglib")) {
               String uri = (String) attrs.get("uri");
               String prefix = (String) attrs.get("prefix");
               try {
  -                TagLibraryInfo tl = new TagLibraryInfoImpl(ctxt, 
  -                                                               prefix, 
  +                TagLibraryInfo tl = new TagLibraryInfoImpl(ctxt,
  +                                                               prefix,
                                                                  uri);
                   libraries.addTagLibrary(prefix, tl);
               } catch (Exception ex) {
  @@ -694,15 +714,15 @@
                                                                 args));
               }
   	}
  -	
  +
   	if (directive.equals("include")) {
   	    String file = (String) attrs.get("file");
   	    String encoding = (String) attrs.get("encoding");
  -	    
  +
   	    if (file == null)
   		throw new CompileException(start,
   					   Constants.getString("jsp.error.include.missing.file"));
  -            
  +
               // jsp.error.include.bad.file needs taking care of here??
               try {
                   reader.pushFile(file, encoding);
  @@ -712,16 +732,16 @@
               }
   	}
       }
  -                        
  +
   
  -    class GeneratorWrapper 
  -        implements Generator, ClassDeclarationPhase, 
  -                   FileDeclarationPhase, ServiceMethodPhase, 
  +    class GeneratorWrapper
  +        implements Generator, ClassDeclarationPhase,
  +                   FileDeclarationPhase, ServiceMethodPhase,
                      InitMethodPhase, StaticInitializerPhase
       {
           Generator generator;
           Mark start, stop;
  -        
  +
           GeneratorWrapper(Generator generator, Mark start, Mark stop) {
               this.generator = generator;
               this.start = start;
  @@ -735,14 +755,14 @@
               return generator.generateCoordinates(phase);
           }
   
  -        public void init(JspCompilationContext ctxt) 
  -            throws JasperException 
  +        public void init(JspCompilationContext ctxt)
  +            throws JasperException
           {
               generator.init(ctxt);
           }
  -        
  -        public void generate(ServletWriter out, Class phase) 
  -				throws JasperException 
  +
  +        public void generate(ServletWriter out, Class phase)
  +				throws JasperException
   	{
               if (phase.isInstance(generator)) {
                   boolean genCoords = generator.generateCoordinates(phase);
  @@ -758,27 +778,27 @@
               }
           }
       }
  -    
  -    public void handleDeclaration(Mark start, Mark stop, Hashtable attrs) 
  -	throws JasperException 
  +
  +    public void handleDeclaration(Mark start, Mark stop, Hashtable attrs)
  +	throws JasperException
       {
           Generator gen
               = new GeneratorWrapper(new DeclarationGenerator(reader.getChars(
   	    			   start, stop)), start, stop);
   	addGenerator(gen);
       }
  -    
  -    public void handleScriptlet(Mark start, Mark stop, Hashtable attrs) 
  -	throws JasperException 
  +
  +    public void handleScriptlet(Mark start, Mark stop, Hashtable attrs)
  +	throws JasperException
       {
           Generator gen
               = new GeneratorWrapper(new ScriptletGenerator(reader.getChars(
   	    			   start, stop)), start, stop);
   	addGenerator(gen);
       }
  -    
  -    public void handleExpression(Mark start, Mark stop, Hashtable attrs) 
  -	throws JasperException 
  +
  +    public void handleExpression(Mark start, Mark stop, Hashtable attrs)
  +	throws JasperException
       {
           Generator gen
               = new GeneratorWrapper(new ExpressionGenerator(reader.getChars(
  @@ -787,7 +807,7 @@
       }
   
       public void handleBean(Mark start, Mark stop, Hashtable attrs)
  -	throws JasperException 
  +	throws JasperException
       {
           Generator gen
               = new GeneratorWrapper(new BeanGenerator(start, attrs, beanInfo,
  @@ -798,7 +818,7 @@
       }
   
       public void handleBeanEnd(Mark start, Mark stop, Hashtable attrs)
  -	throws JasperException 
  +	throws JasperException
       {
           Generator gen
               = new GeneratorWrapper(new BeanEndGenerator(),
  @@ -806,30 +826,30 @@
   	// End the block started by useBean body.
   	addGenerator(gen);
       }
  -	
  +
       public void handleGetProperty(Mark start, Mark stop, Hashtable attrs)
  -	throws JasperException 
  +	throws JasperException
       {
           Generator gen
  -            = new GeneratorWrapper(new GetPropertyGenerator(start, stop, attrs, 
  +            = new GeneratorWrapper(new GetPropertyGenerator(start, stop, attrs,
   	    			   beanInfo), start, stop);
   
   	addGenerator(gen);
       }
  -    
  +
       public void handleSetProperty(Mark start, Mark stop, Hashtable attrs)
  -	throws JasperException 
  +	throws JasperException
       {
           Generator gen
  -            = new GeneratorWrapper(new SetPropertyGenerator(start, stop, attrs, 
  +            = new GeneratorWrapper(new SetPropertyGenerator(start, stop, attrs,
   	    			   beanInfo), start, stop);
   
   	addGenerator(gen);
       }
  -    
  +
       public void handlePlugin(Mark start, Mark stop, Hashtable attrs,
  -    				Hashtable param, String fallback) 
  -	throws JasperException 
  +    				Hashtable param, String fallback)
  +	throws JasperException
       {
           Constants.message("jsp.message.handling_plugin",
                             new Object[] { attrs },
  @@ -840,17 +860,17 @@
   	addGenerator (gen);
       }
   
  -    public void handleForward(Mark start, Mark stop, Hashtable attrs, Hashtable param) 
  +    public void handleForward(Mark start, Mark stop, Hashtable attrs, Hashtable param)
   	throws JasperException
       {
           Generator gen
               = new GeneratorWrapper(new ForwardGenerator(start, attrs, param),
                                      start, stop);
  -        
  +
   	addGenerator(gen);
       }
   
  -    public void handleInclude(Mark start, Mark stop, Hashtable attrs, Hashtable param) 
  +    public void handleInclude(Mark start, Mark stop, Hashtable attrs, Hashtable param)
   	throws JasperException
       {
           Generator gen
  @@ -859,52 +879,50 @@
   
   	addGenerator(gen);
       }
  -    
  -    
  +
  +
       public void handleCharData(Mark start, Mark stop, char[] chars) throws JasperException {
           GeneratorBase cdg;
   
           if (ctxt.getOptions().getLargeFile())
               cdg = new StoredCharDataGenerator(vector, dataFile, stringId++, chars);
  -        else if(ctxt.getOptions().getMappedFile()) 
  +        else if(ctxt.getOptions().getMappedFile())
               cdg = new MappedCharDataGenerator(chars);
   	else
   	    cdg = new CharDataGenerator(chars);
  +
   
  -        
           Generator gen
               = new GeneratorWrapper(cdg,
                                      start, stop);
  -	
  +
   	addGenerator(gen);
       }
  -    
  -    public void handleTagBegin(Mark start, Mark stop, Hashtable attrs, String prefix, 
  -			       String shortTagName, TagLibraryInfo tli, 
  +
  +    public void handleTagBegin(Mark start, Mark stop, Hashtable attrs, String prefix,
  +			       String shortTagName, TagLibraryInfo tli,
   			       TagInfo ti)
   	throws JasperException
       {
  -        Generator gen
  -            = new GeneratorWrapper(new TagBeginGenerator(start, prefix, shortTagName, attrs,
  -							 tli, ti, libraries),
  -                                   start, stop);
  +        TagBeginGenerator tbg = new TagBeginGenerator(start, prefix, shortTagName, attrs,
  +	    tli, ti, libraries, getTagHandlerStack(), getTagVarNumbers());
  +        Generator gen = new GeneratorWrapper(tbg, start, stop);
   
   	addGenerator(gen);
       }
   
  -    public void handleTagEnd(Mark start, Mark stop, String prefix, 
  -			     String shortTagName, Hashtable attrs, 
  +    public void handleTagEnd(Mark start, Mark stop, String prefix,
  +			     String shortTagName, Hashtable attrs,
                                TagLibraryInfo tli, TagInfo ti)
   	throws JasperException
       {
  -        Generator gen
  -            = new GeneratorWrapper(new TagEndGenerator(prefix, shortTagName, attrs,
  -						       tli, ti, libraries),
  -                                   start, stop);
  +        TagEndGenerator teg = new TagEndGenerator(prefix, shortTagName, attrs,
  +	    tli, ti, libraries, getTagHandlerStack(), getTagVarNumbers());
  +        Generator gen = new GeneratorWrapper(teg, start, stop);
   
   	addGenerator(gen);
       }
  -    
  +
       public TagLibraries getTagLibraries() {
   	return libraries;
       }
  
  
  
  1.15      +42 -38    jakarta-tomcat/src/share/org/apache/jasper/compiler/TagBeginGenerator.java
  
  Index: TagBeginGenerator.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat/src/share/org/apache/jasper/compiler/TagBeginGenerator.java,v
  retrieving revision 1.14
  retrieving revision 1.15
  diff -u -r1.14 -r1.15
  --- TagBeginGenerator.java	2000/06/14 22:51:52	1.14
  +++ TagBeginGenerator.java	2000/07/03 09:11:17	1.15
  @@ -1,8 +1,8 @@
   /*
  - * 
  + *
    * The Apache Software License, Version 1.1
    *
  - * Copyright (c) 1999 The Apache Software Foundation.  All rights 
  + * Copyright (c) 1999 The Apache Software Foundation.  All rights
    * reserved.
    *
    * Redistribution and use in source and binary forms, with or without
  @@ -10,7 +10,7 @@
    * are met:
    *
    * 1. Redistributions of source code must retain the above copyright
  - *    notice, this list of conditions and the following disclaimer. 
  + *    notice, this list of conditions and the following disclaimer.
    *
    * 2. Redistributions in binary form must reproduce the above copyright
    *    notice, this list of conditions and the following disclaimer in
  @@ -18,15 +18,15 @@
    *    distribution.
    *
    * 3. The end-user documentation included with the redistribution, if
  - *    any, must include the following acknowlegement:  
  - *       "This product includes software developed by the 
  + *    any, must include the following acknowlegement:
  + *       "This product includes software developed by the
    *        Apache Software Foundation (http://www.apache.org/)."
    *    Alternately, this acknowlegement may appear in the software itself,
    *    if and wherever such third-party acknowlegements normally appear.
    *
    * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
    *    Foundation" must not be used to endorse or promote products derived
  - *    from this software without prior written permission. For written 
  + *    from this software without prior written permission. For written
    *    permission, please contact apache@apache.org.
    *
    * 5. Products derived from this software may not be called "Apache"
  @@ -52,10 +52,11 @@
    * information on the Apache Software Foundation, please see
    * <http://www.apache.org/>.
    *
  - */ 
  + */
   package org.apache.jasper.compiler;
   
   import java.util.Hashtable;
  +import java.util.Stack;
   import java.util.Enumeration;
   import java.lang.reflect.Method;
   
  @@ -78,8 +79,8 @@
    *
    * @author Anil K. Vijendran
    */
  -public class TagBeginGenerator 
  -    extends TagGeneratorBase 
  +public class TagBeginGenerator
  +    extends TagGeneratorBase
       implements ServiceMethodPhase
   {
       String prefix;
  @@ -93,12 +94,15 @@
       TagData tagData;
       Mark start;
       TagLibraries libraries;
  +
   
  -    
       public TagBeginGenerator(Mark start, String prefix, String shortTagName, Hashtable attrs,
  -			     TagLibraryInfo tli, TagInfo ti, TagLibraries libraries) 
  +			     TagLibraryInfo tli, TagInfo ti, TagLibraries libraries,
  +                             Stack tagHandlerStack, Hashtable tagVarNumbers)
           throws JasperException
       {
  +        setTagHandlerStack(tagHandlerStack);
  +        setTagVarNumbers(tagVarNumbers);
           this.prefix = prefix;
           this.shortTagName = shortTagName;
           this.attrs = attrs;
  @@ -123,7 +127,7 @@
                   clz = cl.loadClass(ti.getTagClassName());
               } catch (Exception ex) {
                   throw new CompileException(start,
  -					   Constants.getString("jsp.error.unable.loadclass", 
  +					   Constants.getString("jsp.error.unable.loadclass",
                                                                 new Object[] { ti.getTagClassName(),
                                                                                ex.getMessage()
                                                                 }
  @@ -133,13 +137,13 @@
               libraries.putTagCache(prefix, shortTagName, tc);
           }
       }
  -    
  +
       void validate() throws JasperException {
   
           // Sigh! I wish I didn't have to clone here.
  -        Hashtable attribs = (Hashtable) attrs.clone(); 
  +        Hashtable attribs = (Hashtable) attrs.clone();
   
  -        // First make sure all required attributes are indeed present. 
  +        // First make sure all required attributes are indeed present.
           for(int i = 0; i < attributes.length; i++)
               if (attributes[i].isRequired() && attribs.get(attributes[i].getName()) == null)
                   throw new CompileException(start,
  @@ -149,7 +153,7 @@
                                                                     shortTagName
                                                                 }
                                                                 ));
  -        // Now make sure there are no invalid attributes... 
  +        // Now make sure there are no invalid attributes...
           Enumeration e = attribs.keys();
           while (e.hasMoreElements()) {
               String attr = (String) e.nextElement();
  @@ -161,7 +165,7 @@
   			JspUtil.isExpression((String)attribs.get(attr)))
                           attribs.put(attr, TagData.REQUEST_TIME_VALUE);
   		}
  -            
  +
               if (!found)
                   throw new CompileException(start,
   					   Constants.getString("jsp.error.bad_attribute",
  @@ -177,7 +181,7 @@
   				       Constants.getString("jsp.error.invalid_attributes"));
       }
   
  -    private final void generateSetters(ServletWriter writer, String parent) 
  +    private final void generateSetters(ServletWriter writer, String parent)
           throws JasperException
       {
           writer.println(thVarName+".setPageContext(pageContext);");
  @@ -187,7 +191,7 @@
   	    for(int i = 0; i < attributes.length; i++) {
                   String attrValue = (String) attrs.get(attributes[i].getName());
                   if (attrValue != null) {
  -		    
  +
   		    if (attributes[i].canBeRequestTime()) {
   			if (JspUtil.isExpression(attrValue))
   			    attrValue = JspUtil.getExpr(attrValue);
  @@ -195,23 +199,23 @@
   			    attrValue = writer.quoteString(attrValue);
   		    } else
   			attrValue = writer.quoteString(attrValue);
  -		    
  +
   		    String attrName = attributes[i].getName();
   		    Method m = tc.getSetterMethod(attrName);
  -		    
  +
   		    if (m == null)
   			throw new CompileException
   			    (start, Constants.getString
   			     ("jsp.error.unable.to_find_method",
   			      new Object[] { attrName }));
  -		    
  +
   		    writer.println(thVarName+"."+m.getName()+"("+attrValue+");");
                   }
               }
       }
  -    
  -    public void generateServiceMethodStatements(ServletWriter writer) 
  -        throws JasperException 
  +
  +    public void generateServiceMethodStatements(ServletWriter writer)
  +        throws JasperException
       {
           TagVariableData top = topTag();
           String parent = top == null ? null : top.tagHandlerInstanceName;
  @@ -224,10 +228,10 @@
           writer.println(ti.getTagClassName()+" "+thVarName+" = new "+ti.getTagClassName()+"();");
   
           generateSetters(writer, parent);
  -        
  +
           VariableInfo[] vi = ti.getVariableInfo(tagData);
   
  -        // Just declare AT_BEGIN here... 
  +        // Just declare AT_BEGIN here...
           declareVariables(writer, vi, true, false, VariableInfo.AT_BEGIN);
   
   	writer.println("try {");
  @@ -237,15 +241,15 @@
   
           writer.println("int "+evalVar+" = "
                          +thVarName+".doStartTag();");
  -        
  +
           boolean implementsBodyTag = BodyTag.class.isAssignableFrom(tc.getTagHandlerClass());
  -        
  +
           // Need to update AT_BEGIN variables here
           declareVariables(writer, vi, false, true, VariableInfo.AT_BEGIN);
  -        
  -        // FIXME: I'm not too sure if this is the right approach. I don't like 
  -        //        throwing English language strings into the generated servlet. 
  -        //        Perhaps, I'll just define an inner classes as necessary for these 
  +
  +        // FIXME: I'm not too sure if this is the right approach. I don't like
  +        //        throwing English language strings into the generated servlet.
  +        //        Perhaps, I'll just define an inner classes as necessary for these
           //        types of exceptions? -akv
   
           if (implementsBodyTag) {
  @@ -277,10 +281,10 @@
   
   	    writer.popIndent();
   	    writer.println("}");
  -	    
  +
   	    writer.println(thVarName+".doInitBody();");
   	}
  -        
  +
   	writer.println("do {");
   	writer.pushIndent();
           // Need to declare and update NESTED variables here
  @@ -289,9 +293,9 @@
           declareVariables(writer, vi, false, true, VariableInfo.AT_BEGIN);
       }
   
  -    public void generate(ServletWriter writer, Class phase) 
  -        throws JasperException 
  +    public void generate(ServletWriter writer, Class phase)
  +        throws JasperException
       {
           generateServiceMethodStatements(writer);
  -    }    
  +    }
   }
  
  
  
  1.8       +23 -19    jakarta-tomcat/src/share/org/apache/jasper/compiler/TagEndGenerator.java
  
  Index: TagEndGenerator.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat/src/share/org/apache/jasper/compiler/TagEndGenerator.java,v
  retrieving revision 1.7
  retrieving revision 1.8
  diff -u -r1.7 -r1.8
  --- TagEndGenerator.java	2000/06/14 22:51:53	1.7
  +++ TagEndGenerator.java	2000/07/03 09:11:18	1.8
  @@ -1,7 +1,7 @@
   /*
    * The Apache Software License, Version 1.1
    *
  - * Copyright (c) 1999 The Apache Software Foundation.  All rights 
  + * Copyright (c) 1999 The Apache Software Foundation.  All rights
    * reserved.
    *
    * Redistribution and use in source and binary forms, with or without
  @@ -9,7 +9,7 @@
    * are met:
    *
    * 1. Redistributions of source code must retain the above copyright
  - *    notice, this list of conditions and the following disclaimer. 
  + *    notice, this list of conditions and the following disclaimer.
    *
    * 2. Redistributions in binary form must reproduce the above copyright
    *    notice, this list of conditions and the following disclaimer in
  @@ -17,15 +17,15 @@
    *    distribution.
    *
    * 3. The end-user documentation included with the redistribution, if
  - *    any, must include the following acknowlegement:  
  - *       "This product includes software developed by the 
  + *    any, must include the following acknowlegement:
  + *       "This product includes software developed by the
    *        Apache Software Foundation (http://www.apache.org/)."
    *    Alternately, this acknowlegement may appear in the software itself,
    *    if and wherever such third-party acknowlegements normally appear.
    *
    * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
    *    Foundation" must not be used to endorse or promote products derived
  - *    from this software without prior written permission. For written 
  + *    from this software without prior written permission. For written
    *    permission, please contact apache@apache.org.
    *
    * 5. Products derived from this software may not be called "Apache"
  @@ -51,11 +51,12 @@
    * information on the Apache Software Foundation, please see
    * <http://www.apache.org/>.
    *
  - */ 
  + */
   
   package org.apache.jasper.compiler;
   
   import java.util.Hashtable;
  +import java.util.Stack;
   
   import javax.servlet.jsp.tagext.TagLibraryInfo;
   import javax.servlet.jsp.tagext.TagInfo;
  @@ -66,12 +67,12 @@
   
   
   /**
  - * Custom tag support. 
  + * Custom tag support.
    *
    * @author Anil K. Vijendran
    */
   public class TagEndGenerator
  -    extends TagGeneratorBase 
  +    extends TagGeneratorBase
       implements ServiceMethodPhase
   {
       String prefix, shortTagName;
  @@ -80,10 +81,13 @@
       Hashtable attrs;
       TagLibraries libraries;
   
  -    public TagEndGenerator(String prefix, String shortTagName, 
  -                           Hashtable attrs, TagLibraryInfo tli, 
  -                           TagInfo ti, TagLibraries libraries) 
  +    public TagEndGenerator(String prefix, String shortTagName,
  +                           Hashtable attrs, TagLibraryInfo tli,
  +                           TagInfo ti, TagLibraries libraries,
  +                           Stack tagHandlerStack, Hashtable tagVarNumbers)
       {
  +        setTagHandlerStack(tagHandlerStack);
  +        setTagVarNumbers(tagVarNumbers);
           this.prefix = prefix;
           this.shortTagName = shortTagName;
           this.tli = tli;
  @@ -91,29 +95,29 @@
           this.attrs = attrs;
   	this.libraries = libraries;
       }
  -    
  +
       public void generate(ServletWriter writer, Class phase) {
           TagVariableData tvd = tagEnd();
           String thVarName = tvd.tagHandlerInstanceName;
           String evalVarName = tvd.tagEvalVarName;
  -        
  +
           VariableInfo[] vi = ti.getVariableInfo(new TagData(attrs));
   
           Class tagHandlerClass =
   	    libraries.getTagCache(prefix, shortTagName).getTagHandlerClass();
           boolean implementsBodyTag = BodyTag.class.isAssignableFrom(tagHandlerClass);
  -	
  +
   	writer.popIndent();
   
           if (implementsBodyTag)
               writer.println("} while ("+thVarName+".doAfterBody() == BodyTag.EVAL_BODY_TAG);");
           else
               writer.println("} while (false);");
  -        
  +
           declareVariables(writer, vi, false, true, VariableInfo.AT_BEGIN);
   
           if (implementsBodyTag) {
  -            writer.popIndent(); // try 
  +            writer.popIndent(); // try
   
               /** FIXME: REMOVE BEGIN */
               //              writer.println("} catch (Throwable t) {");
  @@ -124,11 +128,11 @@
   
               //              writer.popIndent();
               /** FIXME: REMOVE END */
  -        
  +
               writer.println("} finally {");
               writer.pushIndent();
               writer.println("if ("+evalVarName+" != Tag.EVAL_BODY_INCLUDE)");
  -            writer.pushIndent(); 
  +            writer.pushIndent();
               writer.println("out = pageContext.popBody();");
               writer.popIndent();
   
  @@ -159,7 +163,7 @@
   	writer.popIndent();
   	writer.println("}");
   
  -        // Need to declare and update AT_END variables here. 
  +        // Need to declare and update AT_END variables here.
           declareVariables(writer, vi, true, true, VariableInfo.AT_END);
       }
   }