tomcat-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From r...@apache.org
Subject svn commit: r379417 [5/7] - in /tomcat/jasper/tc6.0.x/src/share/org/apache: el/lang/ el/parser/ el/util/ jasper/compiler/ jasper/el/ jasper/resources/ jasper/runtime/
Date Tue, 21 Feb 2006 10:57:38 GMT
Modified: tomcat/jasper/tc6.0.x/src/share/org/apache/jasper/compiler/Validator.java
URL: http://svn.apache.org/viewcvs/tomcat/jasper/tc6.0.x/src/share/org/apache/jasper/compiler/Validator.java?rev=379417&r1=379416&r2=379417&view=diff
==============================================================================
--- tomcat/jasper/tc6.0.x/src/share/org/apache/jasper/compiler/Validator.java (original)
+++ tomcat/jasper/tc6.0.x/src/share/org/apache/jasper/compiler/Validator.java Tue Feb 21 02:57:35 2006
@@ -22,7 +22,10 @@
 import java.util.Hashtable;
 import java.util.Iterator;
 
-import javax.servlet.jsp.el.FunctionMapper;
+import javax.el.ELContext;
+import javax.el.ELException;
+import javax.el.ExpressionFactory;
+import javax.el.FunctionMapper;
 import javax.servlet.jsp.tagext.FunctionInfo;
 import javax.servlet.jsp.tagext.JspFragment;
 import javax.servlet.jsp.tagext.PageData;
@@ -36,14 +39,15 @@
 import org.apache.jasper.Constants;
 import org.apache.jasper.JasperException;
 import org.apache.jasper.JspCompilationContext;
+import org.apache.jasper.el.ELContextImpl;
 import org.xml.sax.Attributes;
 
 /**
- * Performs validation on the page elements.  Attributes are checked for
- * mandatory presence, entry value validity, and consistency.  As a
- * side effect, some page global value (such as those from page direcitves)
- * are stored, for later use.
- *
+ * Performs validation on the page elements. Attributes are checked for
+ * mandatory presence, entry value validity, and consistency. As a side effect,
+ * some page global value (such as those from page direcitves) are stored, for
+ * later use.
+ * 
  * @author Kin-man Chung
  * @author Jan Luehe
  * @author Shawn Bayern
@@ -56,37 +60,37 @@
      */
     static class DirectiveVisitor extends Node.Visitor {
 
-	private PageInfo pageInfo;
-	private ErrorDispatcher err;
+        private PageInfo pageInfo;
 
-	private static final JspUtil.ValidAttribute[] pageDirectiveAttrs = {
-	    new JspUtil.ValidAttribute("language"),
-	    new JspUtil.ValidAttribute("extends"),
-	    new JspUtil.ValidAttribute("import"),
-	    new JspUtil.ValidAttribute("session"),
-	    new JspUtil.ValidAttribute("buffer"),
-	    new JspUtil.ValidAttribute("autoFlush"),
-	    new JspUtil.ValidAttribute("isThreadSafe"),
-	    new JspUtil.ValidAttribute("info"),
-	    new JspUtil.ValidAttribute("errorPage"),
-	    new JspUtil.ValidAttribute("isErrorPage"),
-	    new JspUtil.ValidAttribute("contentType"),
-	    new JspUtil.ValidAttribute("pageEncoding"),
-	    new JspUtil.ValidAttribute("isELIgnored")
-	};
-
-	private boolean pageEncodingSeen = false;
-
-	/*
-	 * Constructor
-	 */
-	DirectiveVisitor(Compiler compiler) throws JasperException {
-	    this.pageInfo = compiler.getPageInfo();
-	    this.err = compiler.getErrorDispatcher();
-	    JspCompilationContext ctxt = compiler.getCompilationContext();
-	}
+        private ErrorDispatcher err;
 
-	public void visit(Node.IncludeDirective n) throws JasperException {
+        private static final JspUtil.ValidAttribute[] pageDirectiveAttrs = {
+                new JspUtil.ValidAttribute("language"),
+                new JspUtil.ValidAttribute("extends"),
+                new JspUtil.ValidAttribute("import"),
+                new JspUtil.ValidAttribute("session"),
+                new JspUtil.ValidAttribute("buffer"),
+                new JspUtil.ValidAttribute("autoFlush"),
+                new JspUtil.ValidAttribute("isThreadSafe"),
+                new JspUtil.ValidAttribute("info"),
+                new JspUtil.ValidAttribute("errorPage"),
+                new JspUtil.ValidAttribute("isErrorPage"),
+                new JspUtil.ValidAttribute("contentType"),
+                new JspUtil.ValidAttribute("pageEncoding"),
+                new JspUtil.ValidAttribute("isELIgnored") };
+
+        private boolean pageEncodingSeen = false;
+
+        /*
+         * Constructor
+         */
+        DirectiveVisitor(Compiler compiler) throws JasperException {
+            this.pageInfo = compiler.getPageInfo();
+            this.err = compiler.getErrorDispatcher();
+            JspCompilationContext ctxt = compiler.getCompilationContext();
+        }
+
+        public void visit(Node.IncludeDirective n) throws JasperException {
             // Since pageDirectiveSeen flag only applies to the Current page
             // save it here and restore it after the file is included.
             boolean pageEncodingSeenSave = pageEncodingSeen;
@@ -95,176 +99,228 @@
             pageEncodingSeen = pageEncodingSeenSave;
         }
 
-	public void visit(Node.PageDirective n) throws JasperException {    
+        public void visit(Node.PageDirective n) throws JasperException {
 
-            JspUtil.checkAttributes("Page directive", n,
-                                    pageDirectiveAttrs, err);
+            JspUtil.checkAttributes("Page directive", n, pageDirectiveAttrs,
+                    err);
 
-	    // JSP.2.10.1
-	    Attributes attrs = n.getAttributes();
-	    for (int i = 0; attrs != null && i < attrs.getLength(); i++) {
-		String attr = attrs.getQName(i);
-		String value = attrs.getValue(i);
-
-		if ("language".equals(attr)) {
-		    if (pageInfo.getLanguage(false) == null) {
-			pageInfo.setLanguage(value, n, err, true);
-		    } else if (!pageInfo.getLanguage(false).equals(value)) {
-			err.jspError(n, "jsp.error.page.conflict.language",
-				     pageInfo.getLanguage(false), value);
-		    }
-		} else if ("extends".equals(attr)) {
-		    if (pageInfo.getExtends(false) == null) {
-			pageInfo.setExtends(value, n);
-		    } else if (!pageInfo.getExtends(false).equals(value)) {
-			err.jspError(n, "jsp.error.page.conflict.extends",
-				     pageInfo.getExtends(false), value);
-		    }
-		} else if ("contentType".equals(attr)) {
-		    if (pageInfo.getContentType() == null) {
-			pageInfo.setContentType(value);
-		    } else if (!pageInfo.getContentType().equals(value)) {
-			err.jspError(n, "jsp.error.page.conflict.contenttype",
-				     pageInfo.getContentType(), value);
-		    }
-		} else if ("session".equals(attr)) {
-		    if (pageInfo.getSession() == null) {
-			pageInfo.setSession(value, n, err);
-		    } else if (!pageInfo.getSession().equals(value)) {
-			err.jspError(n, "jsp.error.page.conflict.session",
-				     pageInfo.getSession(), value);
-		    }
-		} else if ("buffer".equals(attr)) {
-		    if (pageInfo.getBufferValue() == null) {
-			pageInfo.setBufferValue(value, n, err);
-		    } else if (!pageInfo.getBufferValue().equals(value)) {
-			err.jspError(n, "jsp.error.page.conflict.buffer",
-				     pageInfo.getBufferValue(), value);
-		    }
-		} else if ("autoFlush".equals(attr)) {
-		    if (pageInfo.getAutoFlush() == null) {
-			pageInfo.setAutoFlush(value, n, err);
-		    } else if (!pageInfo.getAutoFlush().equals(value)) {
-			err.jspError(n, "jsp.error.page.conflict.autoflush",
-				     pageInfo.getAutoFlush(), value);
-		    }
-		} else if ("isThreadSafe".equals(attr)) {
-		    if (pageInfo.getIsThreadSafe() == null) {
-			pageInfo.setIsThreadSafe(value, n, err);
-		    } else if (!pageInfo.getIsThreadSafe().equals(value)) {
-			err.jspError(n, "jsp.error.page.conflict.isthreadsafe",
-				     pageInfo.getIsThreadSafe(), value);
-		    }
-		} else if ("isELIgnored".equals(attr)) {
-		    if (pageInfo.getIsELIgnored() == null) {
+            // JSP.2.10.1
+            Attributes attrs = n.getAttributes();
+            for (int i = 0; attrs != null && i < attrs.getLength(); i++) {
+                String attr = attrs.getQName(i);
+                String value = attrs.getValue(i);
+
+                if ("language".equals(attr)) {
+                    if (pageInfo.getLanguage(false) == null) {
+                        pageInfo.setLanguage(value, n, err, true);
+                    } else if (!pageInfo.getLanguage(false).equals(value)) {
+                        err.jspError(n, "jsp.error.page.conflict.language",
+                                pageInfo.getLanguage(false), value);
+                    }
+                } else if ("extends".equals(attr)) {
+                    if (pageInfo.getExtends(false) == null) {
+                        pageInfo.setExtends(value, n);
+                    } else if (!pageInfo.getExtends(false).equals(value)) {
+                        err.jspError(n, "jsp.error.page.conflict.extends",
+                                pageInfo.getExtends(false), value);
+                    }
+                } else if ("contentType".equals(attr)) {
+                    if (pageInfo.getContentType() == null) {
+                        pageInfo.setContentType(value);
+                    } else if (!pageInfo.getContentType().equals(value)) {
+                        err.jspError(n, "jsp.error.page.conflict.contenttype",
+                                pageInfo.getContentType(), value);
+                    }
+                } else if ("session".equals(attr)) {
+                    if (pageInfo.getSession() == null) {
+                        pageInfo.setSession(value, n, err);
+                    } else if (!pageInfo.getSession().equals(value)) {
+                        err.jspError(n, "jsp.error.page.conflict.session",
+                                pageInfo.getSession(), value);
+                    }
+                } else if ("buffer".equals(attr)) {
+                    if (pageInfo.getBufferValue() == null) {
+                        pageInfo.setBufferValue(value, n, err);
+                    } else if (!pageInfo.getBufferValue().equals(value)) {
+                        err.jspError(n, "jsp.error.page.conflict.buffer",
+                                pageInfo.getBufferValue(), value);
+                    }
+                } else if ("autoFlush".equals(attr)) {
+                    if (pageInfo.getAutoFlush() == null) {
+                        pageInfo.setAutoFlush(value, n, err);
+                    } else if (!pageInfo.getAutoFlush().equals(value)) {
+                        err.jspError(n, "jsp.error.page.conflict.autoflush",
+                                pageInfo.getAutoFlush(), value);
+                    }
+                } else if ("isThreadSafe".equals(attr)) {
+                    if (pageInfo.getIsThreadSafe() == null) {
+                        pageInfo.setIsThreadSafe(value, n, err);
+                    } else if (!pageInfo.getIsThreadSafe().equals(value)) {
+                        err.jspError(n, "jsp.error.page.conflict.isthreadsafe",
+                                pageInfo.getIsThreadSafe(), value);
+                    }
+                } else if ("isELIgnored".equals(attr)) {
+                    if (pageInfo.getIsELIgnored() == null) {
                         pageInfo.setIsELIgnored(value, n, err, true);
-		    } else if (!pageInfo.getIsELIgnored().equals(value)) {
-			err.jspError(n, "jsp.error.page.conflict.iselignored",
-				     pageInfo.getIsELIgnored(), value);
-		    }
-		} else if ("isErrorPage".equals(attr)) {
-		    if (pageInfo.getIsErrorPage() == null) {
-			pageInfo.setIsErrorPage(value, n, err);
-		    } else if (!pageInfo.getIsErrorPage().equals(value)) {
-			err.jspError(n, "jsp.error.page.conflict.iserrorpage",
-				     pageInfo.getIsErrorPage(), value);
-		    }
-		} else if ("errorPage".equals(attr)) {
-		    if (pageInfo.getErrorPage() == null) {
-			pageInfo.setErrorPage(value);
-		    } else if (!pageInfo.getErrorPage().equals(value)) {
-			err.jspError(n, "jsp.error.page.conflict.errorpage",
-				     pageInfo.getErrorPage(), value);
-		    }
-		} else if ("info".equals(attr)) {
-		    if (pageInfo.getInfo() == null) {
-			pageInfo.setInfo(value);
-		    } else if (!pageInfo.getInfo().equals(value)) {
-			err.jspError(n, "jsp.error.page.conflict.info",
-				     pageInfo.getInfo(), value);
-		    }
-		} else if ("pageEncoding".equals(attr)) {
-		    if (pageEncodingSeen) 
-			err.jspError(n, "jsp.error.page.multi.pageencoding");
-		    // 'pageEncoding' can occur at most once per file
-		    pageEncodingSeen = true;
-		    comparePageEncodings(value, n);
-		}
-	    }
-
-	    // Check for bad combinations
-	    if (pageInfo.getBuffer() == 0 && !pageInfo.isAutoFlush())
-		err.jspError(n, "jsp.error.page.badCombo");
-
-	    // Attributes for imports for this node have been processed by
-	    // the parsers, just add them to pageInfo.
-	    pageInfo.addImports(n.getImports());
-	}
+                    } else if (!pageInfo.getIsELIgnored().equals(value)) {
+                        err.jspError(n, "jsp.error.page.conflict.iselignored",
+                                pageInfo.getIsELIgnored(), value);
+                    }
+                } else if ("isErrorPage".equals(attr)) {
+                    if (pageInfo.getIsErrorPage() == null) {
+                        pageInfo.setIsErrorPage(value, n, err);
+                    } else if (!pageInfo.getIsErrorPage().equals(value)) {
+                        err.jspError(n, "jsp.error.page.conflict.iserrorpage",
+                                pageInfo.getIsErrorPage(), value);
+                    }
+                } else if ("errorPage".equals(attr)) {
+                    if (pageInfo.getErrorPage() == null) {
+                        pageInfo.setErrorPage(value);
+                    } else if (!pageInfo.getErrorPage().equals(value)) {
+                        err.jspError(n, "jsp.error.page.conflict.errorpage",
+                                pageInfo.getErrorPage(), value);
+                    }
+                } else if ("info".equals(attr)) {
+                    if (pageInfo.getInfo() == null) {
+                        pageInfo.setInfo(value);
+                    } else if (!pageInfo.getInfo().equals(value)) {
+                        err.jspError(n, "jsp.error.page.conflict.info",
+                                pageInfo.getInfo(), value);
+                    }
+                } else if ("pageEncoding".equals(attr)) {
+                    if (pageEncodingSeen)
+                        err.jspError(n, "jsp.error.page.multi.pageencoding");
+                    // 'pageEncoding' can occur at most once per file
+                    pageEncodingSeen = true;
+                    comparePageEncodings(value, n);
+                } else if ("deferredSyntaxAllowedAsLiteral".equals(attr)) {
+                    if (pageInfo.getDeferredSyntaxAllowedAsLiteral() == null) {
+                        pageInfo.setDeferredSyntaxAllowedAsLiteral(value, n,
+                                err, true);
+                    } else if (!pageInfo.getDeferredSyntaxAllowedAsLiteral()
+                            .equals(value)) {
+                        err
+                                .jspError(
+                                        n,
+                                        "jsp.error.page.conflict.deferredsyntaxallowedasliteral",
+                                        pageInfo
+                                                .getDeferredSyntaxAllowedAsLiteral(),
+                                        value);
+                    }
+                } else if ("trimDirectiveWhitespaces".equals(attr)) {
+                    if (pageInfo.getTrimDirectiveWhitespaces() == null) {
+                        pageInfo.setTrimDirectiveWhitespaces(value, n, err,
+                                true);
+                    } else if (!pageInfo.getTrimDirectiveWhitespaces().equals(
+                            value)) {
+                        err
+                                .jspError(
+                                        n,
+                                        "jsp.error.page.conflict.trimdirectivewhitespaces",
+                                        pageInfo.getTrimDirectiveWhitespaces(),
+                                        value);
+                    }
+                }
+            }
 
-	public void visit(Node.TagDirective n) throws JasperException {
+            // Check for bad combinations
+            if (pageInfo.getBuffer() == 0 && !pageInfo.isAutoFlush())
+                err.jspError(n, "jsp.error.page.badCombo");
+
+            // Attributes for imports for this node have been processed by
+            // the parsers, just add them to pageInfo.
+            pageInfo.addImports(n.getImports());
+        }
+
+        public void visit(Node.TagDirective n) throws JasperException {
             // Note: Most of the validation is done in TagFileProcessor
             // when it created a TagInfo object from the
             // tag file in which the directive appeared.
-        
+
             // This method does additional processing to collect page info
-            
-	    Attributes attrs = n.getAttributes();
-	    for (int i = 0; attrs != null && i < attrs.getLength(); i++) {
-		String attr = attrs.getQName(i);
-		String value = attrs.getValue(i);
-
-		if ("language".equals(attr)) {
-		    if (pageInfo.getLanguage(false) == null) {
-			pageInfo.setLanguage(value, n, err, false);
-		    } else if (!pageInfo.getLanguage(false).equals(value)) {
-			err.jspError(n, "jsp.error.tag.conflict.language",
-				     pageInfo.getLanguage(false), value);
-		    }
-		} else if ("isELIgnored".equals(attr)) {
-		    if (pageInfo.getIsELIgnored() == null) {
+
+            Attributes attrs = n.getAttributes();
+            for (int i = 0; attrs != null && i < attrs.getLength(); i++) {
+                String attr = attrs.getQName(i);
+                String value = attrs.getValue(i);
+
+                if ("language".equals(attr)) {
+                    if (pageInfo.getLanguage(false) == null) {
+                        pageInfo.setLanguage(value, n, err, false);
+                    } else if (!pageInfo.getLanguage(false).equals(value)) {
+                        err.jspError(n, "jsp.error.tag.conflict.language",
+                                pageInfo.getLanguage(false), value);
+                    }
+                } else if ("isELIgnored".equals(attr)) {
+                    if (pageInfo.getIsELIgnored() == null) {
                         pageInfo.setIsELIgnored(value, n, err, false);
-		    } else if (!pageInfo.getIsELIgnored().equals(value)) {
-			err.jspError(n, "jsp.error.tag.conflict.iselignored",
-				     pageInfo.getIsELIgnored(), value);
-		    }
-		} else if ("pageEncoding".equals(attr)) {
-		    if (pageEncodingSeen) 
-			err.jspError(n, "jsp.error.tag.multi.pageencoding");
-		    pageEncodingSeen = true;
-		    n.getRoot().setPageEncoding(value);
-		}
-	    }
-
-	    // Attributes for imports for this node have been processed by
-	    // the parsers, just add them to pageInfo.
-	    pageInfo.addImports(n.getImports());
-	}
-
-	public void visit(Node.AttributeDirective n) throws JasperException {
-	    // Do nothing, since this attribute directive has already been
-	    // validated by TagFileProcessor when it created a TagInfo object
-	    // from the tag file in which the directive appeared
-	}
-
-	public void visit(Node.VariableDirective n) throws JasperException {
-	    // Do nothing, since this variable directive has already been
-	    // validated by TagFileProcessor when it created a TagInfo object
-	    // from the tag file in which the directive appeared
-	}
+                    } else if (!pageInfo.getIsELIgnored().equals(value)) {
+                        err.jspError(n, "jsp.error.tag.conflict.iselignored",
+                                pageInfo.getIsELIgnored(), value);
+                    }
+                } else if ("pageEncoding".equals(attr)) {
+                    if (pageEncodingSeen)
+                        err.jspError(n, "jsp.error.tag.multi.pageencoding");
+                    pageEncodingSeen = true;
+                    n.getRoot().setPageEncoding(value);
+                } else if ("deferredSyntaxAllowedAsLiteral".equals(attr)) {
+                    if (pageInfo.getDeferredSyntaxAllowedAsLiteral() == null) {
+                        pageInfo.setDeferredSyntaxAllowedAsLiteral(value, n,
+                                err, false);
+                    } else if (!pageInfo.getDeferredSyntaxAllowedAsLiteral()
+                            .equals(value)) {
+                        err
+                                .jspError(
+                                        n,
+                                        "jsp.error.tag.conflict.deferredsyntaxallowedasliteral",
+                                        pageInfo
+                                                .getDeferredSyntaxAllowedAsLiteral(),
+                                        value);
+                    }
+                } else if ("trimDirectiveWhitespaces".equals(attr)) {
+                    if (pageInfo.getTrimDirectiveWhitespaces() == null) {
+                        pageInfo.setTrimDirectiveWhitespaces(value, n, err,
+                                false);
+                    } else if (!pageInfo.getTrimDirectiveWhitespaces().equals(
+                            value)) {
+                        err
+                                .jspError(
+                                        n,
+                                        "jsp.error.tag.conflict.trimdirectivewhitespaces",
+                                        pageInfo.getTrimDirectiveWhitespaces(),
+                                        value);
+                    }
+                }
+            }
+
+            // Attributes for imports for this node have been processed by
+            // the parsers, just add them to pageInfo.
+            pageInfo.addImports(n.getImports());
+        }
+
+        public void visit(Node.AttributeDirective n) throws JasperException {
+            // Do nothing, since this attribute directive has already been
+            // validated by TagFileProcessor when it created a TagInfo object
+            // from the tag file in which the directive appeared
+        }
+
+        public void visit(Node.VariableDirective n) throws JasperException {
+            // Do nothing, since this variable directive has already been
+            // validated by TagFileProcessor when it created a TagInfo object
+            // from the tag file in which the directive appeared
+        }
 
         /*
          * Compares page encodings specified in various places, and throws
          * exception in case of page encoding mismatch.
-         *
-         * @param pageDirEnc The value of the pageEncoding attribute of the
-         * page directive
-         * @param pageDir The page directive node
-         *
+         * 
+         * @param pageDirEnc The value of the pageEncoding attribute of the page
+         * directive @param pageDir The page directive node
+         * 
          * @throws JasperException in case of page encoding mismatch
          */
         private void comparePageEncodings(String pageDirEnc,
-                                          Node.PageDirective pageDir)
-                throws JasperException {
+                Node.PageDirective pageDir) throws JasperException {
 
             Node.Root root = pageDir.getRoot();
             String configEnc = root.getJspConfigPageEncoding();
@@ -272,32 +328,33 @@
             /*
              * Compare the 'pageEncoding' attribute of the page directive with
              * the encoding specified in the JSP config element whose URL
-             * pattern matches this page.
-             * Treat "UTF-16", "UTF-16BE", and "UTF-16LE" as identical.
+             * pattern matches this page. Treat "UTF-16", "UTF-16BE", and
+             * "UTF-16LE" as identical.
              */
-            if (configEnc != null && !pageDirEnc.equals(configEnc) 
-                    && (!pageDirEnc.startsWith("UTF-16")
-                        || !configEnc.startsWith("UTF-16"))) {
+            if (configEnc != null
+                    && !pageDirEnc.equals(configEnc)
+                    && (!pageDirEnc.startsWith("UTF-16") || !configEnc
+                            .startsWith("UTF-16"))) {
                 err.jspError(pageDir,
-                             "jsp.error.config_pagedir_encoding_mismatch",
-                             configEnc, pageDirEnc);
+                        "jsp.error.config_pagedir_encoding_mismatch",
+                        configEnc, pageDirEnc);
             }
 
             /*
              * Compare the 'pageEncoding' attribute of the page directive with
              * the encoding specified in the XML prolog (only for XML syntax,
              * and only if JSP document contains XML prolog with encoding
-             * declaration).
-             * Treat "UTF-16", "UTF-16BE", and "UTF-16LE" as identical.
+             * declaration). Treat "UTF-16", "UTF-16BE", and "UTF-16LE" as
+             * identical.
              */
-	    if (root.isXmlSyntax() && root.isEncodingSpecifiedInProlog()) {
-		String pageEnc = root.getPageEncoding();
-                if (!pageDirEnc.equals(pageEnc) 
-                        && (!pageDirEnc.startsWith("UTF-16")
-                            || !pageEnc.startsWith("UTF-16"))) {
+            if (root.isXmlSyntax() && root.isEncodingSpecifiedInProlog()) {
+                String pageEnc = root.getPageEncoding();
+                if (!pageDirEnc.equals(pageEnc)
+                        && (!pageDirEnc.startsWith("UTF-16") || !pageEnc
+                                .startsWith("UTF-16"))) {
                     err.jspError(pageDir,
-                                 "jsp.error.prolog_pagedir_encoding_mismatch",
-                                 pageEnc, pageDirEnc);
+                            "jsp.error.prolog_pagedir_encoding_mismatch",
+                            pageEnc, pageDirEnc);
                 }
             }
         }
@@ -308,1092 +365,1080 @@
      */
     static class ValidateVisitor extends Node.Visitor {
 
-	private PageInfo pageInfo;
-	private ErrorDispatcher err;
-	private TagInfo tagInfo;
+        private PageInfo pageInfo;
+
+        private ErrorDispatcher err;
+
+        private TagInfo tagInfo;
+
         private ClassLoader loader;
 
-	private static final JspUtil.ValidAttribute[] jspRootAttrs = {
-            new JspUtil.ValidAttribute("xsi:schemaLocation"),
-	    new JspUtil.ValidAttribute("version", true) };
-
-	private static final JspUtil.ValidAttribute[] includeDirectiveAttrs = {
-	    new JspUtil.ValidAttribute("file", true) };
-
-	private static final JspUtil.ValidAttribute[] taglibDirectiveAttrs = {
-	    new JspUtil.ValidAttribute("uri"),
-	    new JspUtil.ValidAttribute("tagdir"),
-	    new JspUtil.ValidAttribute("prefix", true) };
-
-	private static final JspUtil.ValidAttribute[] includeActionAttrs = {
-	    new JspUtil.ValidAttribute("page", true, true),
-	    new JspUtil.ValidAttribute("flush") };
-
-	private static final JspUtil.ValidAttribute[] paramActionAttrs = {
-	    new JspUtil.ValidAttribute("name", true),
-	    new JspUtil.ValidAttribute("value", true, true) };
-
-	private static final JspUtil.ValidAttribute[] forwardActionAttrs = {
-	    new JspUtil.ValidAttribute("page", true, true) };
-
-	private static final JspUtil.ValidAttribute[] getPropertyAttrs = {
-	    new JspUtil.ValidAttribute("name", true),
-	    new JspUtil.ValidAttribute("property", true) };
-
-	private static final JspUtil.ValidAttribute[] setPropertyAttrs = {
-	    new JspUtil.ValidAttribute("name", true),
-	    new JspUtil.ValidAttribute("property", true),
-	    new JspUtil.ValidAttribute("value", false, true),
-	    new JspUtil.ValidAttribute("param") };
-
-	private static final JspUtil.ValidAttribute[] useBeanAttrs = {
-	    new JspUtil.ValidAttribute("id", true),
-	    new JspUtil.ValidAttribute("scope"),
-	    new JspUtil.ValidAttribute("class"),
-	    new JspUtil.ValidAttribute("type"),
-	    new JspUtil.ValidAttribute("beanName", false, true) };
-
-	private static final JspUtil.ValidAttribute[] plugInAttrs = {
-	    new JspUtil.ValidAttribute("type",true),
-	    new JspUtil.ValidAttribute("code", true),
-	    new JspUtil.ValidAttribute("codebase"),
-	    new JspUtil.ValidAttribute("align"),
-	    new JspUtil.ValidAttribute("archive"),
-	    new JspUtil.ValidAttribute("height", false, true),
-	    new JspUtil.ValidAttribute("hspace"),
-	    new JspUtil.ValidAttribute("jreversion"),
-	    new JspUtil.ValidAttribute("name"),
-	    new JspUtil.ValidAttribute("vspace"),
-	    new JspUtil.ValidAttribute("width", false, true),
-	    new JspUtil.ValidAttribute("nspluginurl"),
-	    new JspUtil.ValidAttribute("iepluginurl") };
-            
+        private final StringBuffer buf = new StringBuffer(32);
+
+        private static final JspUtil.ValidAttribute[] jspRootAttrs = {
+                new JspUtil.ValidAttribute("xsi:schemaLocation"),
+                new JspUtil.ValidAttribute("version", true) };
+
+        private static final JspUtil.ValidAttribute[] includeDirectiveAttrs = { new JspUtil.ValidAttribute(
+                "file", true) };
+
+        private static final JspUtil.ValidAttribute[] taglibDirectiveAttrs = {
+                new JspUtil.ValidAttribute("uri"),
+                new JspUtil.ValidAttribute("tagdir"),
+                new JspUtil.ValidAttribute("prefix", true) };
+
+        private static final JspUtil.ValidAttribute[] includeActionAttrs = {
+                new JspUtil.ValidAttribute("page", true, true),
+                new JspUtil.ValidAttribute("flush") };
+
+        private static final JspUtil.ValidAttribute[] paramActionAttrs = {
+                new JspUtil.ValidAttribute("name", true),
+                new JspUtil.ValidAttribute("value", true, true) };
+
+        private static final JspUtil.ValidAttribute[] forwardActionAttrs = { new JspUtil.ValidAttribute(
+                "page", true, true) };
+
+        private static final JspUtil.ValidAttribute[] getPropertyAttrs = {
+                new JspUtil.ValidAttribute("name", true),
+                new JspUtil.ValidAttribute("property", true) };
+
+        private static final JspUtil.ValidAttribute[] setPropertyAttrs = {
+                new JspUtil.ValidAttribute("name", true),
+                new JspUtil.ValidAttribute("property", true),
+                new JspUtil.ValidAttribute("value", false, true),
+                new JspUtil.ValidAttribute("param") };
+
+        private static final JspUtil.ValidAttribute[] useBeanAttrs = {
+                new JspUtil.ValidAttribute("id", true),
+                new JspUtil.ValidAttribute("scope"),
+                new JspUtil.ValidAttribute("class"),
+                new JspUtil.ValidAttribute("type"),
+                new JspUtil.ValidAttribute("beanName", false, true) };
+
+        private static final JspUtil.ValidAttribute[] plugInAttrs = {
+                new JspUtil.ValidAttribute("type", true),
+                new JspUtil.ValidAttribute("code", true),
+                new JspUtil.ValidAttribute("codebase"),
+                new JspUtil.ValidAttribute("align"),
+                new JspUtil.ValidAttribute("archive"),
+                new JspUtil.ValidAttribute("height", false, true),
+                new JspUtil.ValidAttribute("hspace"),
+                new JspUtil.ValidAttribute("jreversion"),
+                new JspUtil.ValidAttribute("name"),
+                new JspUtil.ValidAttribute("vspace"),
+                new JspUtil.ValidAttribute("width", false, true),
+                new JspUtil.ValidAttribute("nspluginurl"),
+                new JspUtil.ValidAttribute("iepluginurl") };
+
         private static final JspUtil.ValidAttribute[] attributeAttrs = {
-            new JspUtil.ValidAttribute("name", true),
-            new JspUtil.ValidAttribute("trim") };
-            
+                new JspUtil.ValidAttribute("name", true),
+                new JspUtil.ValidAttribute("trim") };
+
         private static final JspUtil.ValidAttribute[] invokeAttrs = {
-            new JspUtil.ValidAttribute("fragment", true),
-	    new JspUtil.ValidAttribute("var"),
-	    new JspUtil.ValidAttribute("varReader"),
-	    new JspUtil.ValidAttribute("scope") };
+                new JspUtil.ValidAttribute("fragment", true),
+                new JspUtil.ValidAttribute("var"),
+                new JspUtil.ValidAttribute("varReader"),
+                new JspUtil.ValidAttribute("scope") };
 
         private static final JspUtil.ValidAttribute[] doBodyAttrs = {
-            new JspUtil.ValidAttribute("var"),
-	    new JspUtil.ValidAttribute("varReader"),
-	    new JspUtil.ValidAttribute("scope") };
-
-	private static final JspUtil.ValidAttribute[] jspOutputAttrs = {
-	    new JspUtil.ValidAttribute("omit-xml-declaration"),
-	    new JspUtil.ValidAttribute("doctype-root-element"),
-	    new JspUtil.ValidAttribute("doctype-public"),
-	    new JspUtil.ValidAttribute("doctype-system") };
-
-	/*
-	 * Constructor
-	 */
-	ValidateVisitor(Compiler compiler) {
-	    this.pageInfo = compiler.getPageInfo();
-	    this.err = compiler.getErrorDispatcher();
-	    this.tagInfo = compiler.getCompilationContext().getTagInfo();
-	    this.loader = compiler.getCompilationContext().getClassLoader();
-	}
-
-	public void visit(Node.JspRoot n) throws JasperException {
-	    JspUtil.checkAttributes("Jsp:root", n,
-				    jspRootAttrs, err);
-	    String version = n.getTextAttribute("version");
-	    if (!version.equals("1.2") && !version.equals("2.0")) {
-		err.jspError(n, "jsp.error.jsproot.version.invalid", version);
-	    }
-	    visitBody(n);
-	}
+                new JspUtil.ValidAttribute("var"),
+                new JspUtil.ValidAttribute("varReader"),
+                new JspUtil.ValidAttribute("scope") };
+
+        private static final JspUtil.ValidAttribute[] jspOutputAttrs = {
+                new JspUtil.ValidAttribute("omit-xml-declaration"),
+                new JspUtil.ValidAttribute("doctype-root-element"),
+                new JspUtil.ValidAttribute("doctype-public"),
+                new JspUtil.ValidAttribute("doctype-system") };
+
+        /*
+         * Constructor
+         */
+        ValidateVisitor(Compiler compiler) {
+            this.pageInfo = compiler.getPageInfo();
+            this.err = compiler.getErrorDispatcher();
+            this.tagInfo = compiler.getCompilationContext().getTagInfo();
+            this.loader = compiler.getCompilationContext().getClassLoader();
+        }
+
+        public void visit(Node.JspRoot n) throws JasperException {
+            JspUtil.checkAttributes("Jsp:root", n, jspRootAttrs, err);
+            String version = n.getTextAttribute("version");
+            if (!version.equals("1.2") && !version.equals("2.0")) {
+                err.jspError(n, "jsp.error.jsproot.version.invalid", version);
+            }
+            visitBody(n);
+        }
 
-	public void visit(Node.IncludeDirective n) throws JasperException {
+        public void visit(Node.IncludeDirective n) throws JasperException {
             JspUtil.checkAttributes("Include directive", n,
-                                    includeDirectiveAttrs, err);
-	    visitBody(n);
-	}
+                    includeDirectiveAttrs, err);
+            visitBody(n);
+        }
 
-	public void visit(Node.TaglibDirective n) throws JasperException {
+        public void visit(Node.TaglibDirective n) throws JasperException {
             JspUtil.checkAttributes("Taglib directive", n,
-                                    taglibDirectiveAttrs, err);
-	    // Either 'uri' or 'tagdir' attribute must be specified
-	    String uri = n.getAttributeValue("uri");
-	    String tagdir = n.getAttributeValue("tagdir");
-	    if (uri == null && tagdir == null) {
-		err.jspError(n, "jsp.error.taglibDirective.missing.location");
-	    }
-	    if (uri != null && tagdir != null) {
-		err.jspError(n, "jsp.error.taglibDirective.both_uri_and_tagdir");
-	    }
-	}
-
-	public void visit(Node.ParamAction n) throws JasperException {
-            JspUtil.checkAttributes("Param action", n,
-                                    paramActionAttrs, err);
-	    // make sure the value of the 'name' attribute is not a
-	    // request-time expression
-	    throwErrorIfExpression(n, "name", "jsp:param");
-	    n.setValue(getJspAttribute("value", null, null,
-				       n.getAttributeValue("value"),
-                                       java.lang.String.class,
-				       n, false));
+                    taglibDirectiveAttrs, err);
+            // Either 'uri' or 'tagdir' attribute must be specified
+            String uri = n.getAttributeValue("uri");
+            String tagdir = n.getAttributeValue("tagdir");
+            if (uri == null && tagdir == null) {
+                err.jspError(n, "jsp.error.taglibDirective.missing.location");
+            }
+            if (uri != null && tagdir != null) {
+                err
+                        .jspError(n,
+                                "jsp.error.taglibDirective.both_uri_and_tagdir");
+            }
+        }
+
+        public void visit(Node.ParamAction n) throws JasperException {
+            JspUtil.checkAttributes("Param action", n, paramActionAttrs, err);
+            // make sure the value of the 'name' attribute is not a
+            // request-time expression
+            throwErrorIfExpression(n, "name", "jsp:param");
+            n.setValue(getJspAttribute("value", null, null, n
+                    .getAttributeValue("value"), java.lang.String.class, n,
+                    false));
             visitBody(n);
-	}
+        }
 
-	public void visit(Node.ParamsAction n) throws JasperException {
-	    // Make sure we've got at least one nested jsp:param
+        public void visit(Node.ParamsAction n) throws JasperException {
+            // Make sure we've got at least one nested jsp:param
             Node.Nodes subElems = n.getBody();
             if (subElems == null) {
-		err.jspError(n, "jsp.error.params.emptyBody");
-	    }
+                err.jspError(n, "jsp.error.params.emptyBody");
+            }
             visitBody(n);
-	}
+        }
 
-	public void visit(Node.IncludeAction n) throws JasperException {
-            JspUtil.checkAttributes("Include action", n,
-                                    includeActionAttrs, err);
-	    n.setPage(getJspAttribute("page", null, null,
-				      n.getAttributeValue("page"), 
-                                      java.lang.String.class, n, false));
-	    visitBody(n);
+        public void visit(Node.IncludeAction n) throws JasperException {
+            JspUtil.checkAttributes("Include action", n, includeActionAttrs,
+                    err);
+            n.setPage(getJspAttribute("page", null, null, n
+                    .getAttributeValue("page"), java.lang.String.class, n,
+                    false));
+            visitBody(n);
         };
 
-	public void visit(Node.ForwardAction n) throws JasperException {
-            JspUtil.checkAttributes("Forward", n,
-                                    forwardActionAttrs, err);
-	    n.setPage(getJspAttribute("page", null, null,
-				      n.getAttributeValue("page"), 
-                                      java.lang.String.class, n, false));
-	    visitBody(n);
-	}
-
-	public void visit(Node.GetProperty n) throws JasperException {
-            JspUtil.checkAttributes("GetProperty", n,
-                                    getPropertyAttrs, err);
-	}
-
-	public void visit(Node.SetProperty n) throws JasperException {
-            JspUtil.checkAttributes("SetProperty", n,
-                                    setPropertyAttrs, err);
-	    String name = n.getTextAttribute("name");
-	    String property = n.getTextAttribute("property");
-	    String param = n.getTextAttribute("param");
-	    String value = n.getAttributeValue("value");
+        public void visit(Node.ForwardAction n) throws JasperException {
+            JspUtil.checkAttributes("Forward", n, forwardActionAttrs, err);
+            n.setPage(getJspAttribute("page", null, null, n
+                    .getAttributeValue("page"), java.lang.String.class, n,
+                    false));
+            visitBody(n);
+        }
+
+        public void visit(Node.GetProperty n) throws JasperException {
+            JspUtil.checkAttributes("GetProperty", n, getPropertyAttrs, err);
+        }
 
-            n.setValue(getJspAttribute("value", null, null, value, 
-                java.lang.Object.class, n, false));
+        public void visit(Node.SetProperty n) throws JasperException {
+            JspUtil.checkAttributes("SetProperty", n, setPropertyAttrs, err);
+            String name = n.getTextAttribute("name");
+            String property = n.getTextAttribute("property");
+            String param = n.getTextAttribute("param");
+            String value = n.getAttributeValue("value");
+
+            n.setValue(getJspAttribute("value", null, null, value,
+                    java.lang.Object.class, n, false));
 
             boolean valueSpecified = n.getValue() != null;
 
-	    if ("*".equals(property)) { 
+            if ("*".equals(property)) {
                 if (param != null || valueSpecified)
-		    err.jspError(n, "jsp.error.setProperty.invalid");
-		
-            } else if (param != null && valueSpecified) {
-		err.jspError(n, "jsp.error.setProperty.invalid");
-	    }
-            
-            visitBody(n);
-	}
+                    err.jspError(n, "jsp.error.setProperty.invalid");
 
-	public void visit(Node.UseBean n) throws JasperException {
-            JspUtil.checkAttributes("UseBean", n,
-                                    useBeanAttrs, err);
+            } else if (param != null && valueSpecified) {
+                err.jspError(n, "jsp.error.setProperty.invalid");
+            }
 
-	    String name = n.getTextAttribute ("id");
-	    String scope = n.getTextAttribute ("scope");
-	    JspUtil.checkScope(scope, n, err);
-	    String className = n.getTextAttribute ("class");
-	    String type = n.getTextAttribute ("type");
-	    BeanRepository beanInfo = pageInfo.getBeanRepository();
+            visitBody(n);
+        }
 
-	    if (className == null && type == null)
-		err.jspError(n, "jsp.error.usebean.missingType");
+        public void visit(Node.UseBean n) throws JasperException {
+            JspUtil.checkAttributes("UseBean", n, useBeanAttrs, err);
 
-	    if (beanInfo.checkVariable(name))
-		err.jspError(n, "jsp.error.usebean.duplicate");
+            String name = n.getTextAttribute("id");
+            String scope = n.getTextAttribute("scope");
+            JspUtil.checkScope(scope, n, err);
+            String className = n.getTextAttribute("class");
+            String type = n.getTextAttribute("type");
+            BeanRepository beanInfo = pageInfo.getBeanRepository();
+
+            if (className == null && type == null)
+                err.jspError(n, "jsp.error.usebean.missingType");
+
+            if (beanInfo.checkVariable(name))
+                err.jspError(n, "jsp.error.usebean.duplicate");
+
+            if ("session".equals(scope) && !pageInfo.isSession())
+                err.jspError(n, "jsp.error.usebean.noSession");
+
+            Node.JspAttribute jattr = getJspAttribute("beanName", null, null, n
+                    .getAttributeValue("beanName"), java.lang.String.class, n,
+                    false);
+            n.setBeanName(jattr);
+            if (className != null && jattr != null)
+                err.jspError(n, "jsp.error.usebean.notBoth");
 
-	    if ("session".equals(scope) && !pageInfo.isSession())
-		err.jspError(n, "jsp.error.usebean.noSession");
+            if (className == null)
+                className = type;
 
-	    Node.JspAttribute jattr
-		= getJspAttribute("beanName", null, null,
-				  n.getAttributeValue("beanName"),
-				  java.lang.String.class, n, false);
-	    n.setBeanName(jattr);
-	    if (className != null && jattr != null)
-		err.jspError(n, "jsp.error.usebean.notBoth");
+            beanInfo.addBean(n, name, className, scope);
 
-	    if (className == null)
-		className = type;
+            visitBody(n);
+        }
 
-	    beanInfo.addBean(n, name, className, scope);
+        public void visit(Node.PlugIn n) throws JasperException {
+            JspUtil.checkAttributes("Plugin", n, plugInAttrs, err);
 
-	    visitBody(n);
-	}
+            throwErrorIfExpression(n, "type", "jsp:plugin");
+            throwErrorIfExpression(n, "code", "jsp:plugin");
+            throwErrorIfExpression(n, "codebase", "jsp:plugin");
+            throwErrorIfExpression(n, "align", "jsp:plugin");
+            throwErrorIfExpression(n, "archive", "jsp:plugin");
+            throwErrorIfExpression(n, "hspace", "jsp:plugin");
+            throwErrorIfExpression(n, "jreversion", "jsp:plugin");
+            throwErrorIfExpression(n, "name", "jsp:plugin");
+            throwErrorIfExpression(n, "vspace", "jsp:plugin");
+            throwErrorIfExpression(n, "nspluginurl", "jsp:plugin");
+            throwErrorIfExpression(n, "iepluginurl", "jsp:plugin");
+
+            String type = n.getTextAttribute("type");
+            if (type == null)
+                err.jspError(n, "jsp.error.plugin.notype");
+            if (!type.equals("bean") && !type.equals("applet"))
+                err.jspError(n, "jsp.error.plugin.badtype");
+            if (n.getTextAttribute("code") == null)
+                err.jspError(n, "jsp.error.plugin.nocode");
+
+            Node.JspAttribute width = getJspAttribute("width", null, null, n
+                    .getAttributeValue("width"), java.lang.String.class, n,
+                    false);
+            n.setWidth(width);
+
+            Node.JspAttribute height = getJspAttribute("height", null, null, n
+                    .getAttributeValue("height"), java.lang.String.class, n,
+                    false);
+            n.setHeight(height);
 
-	public void visit(Node.PlugIn n) throws JasperException {
-            JspUtil.checkAttributes("Plugin", n, plugInAttrs, err);
+            visitBody(n);
+        }
 
-	    throwErrorIfExpression(n, "type", "jsp:plugin");
-	    throwErrorIfExpression(n, "code", "jsp:plugin");
-	    throwErrorIfExpression(n, "codebase", "jsp:plugin");
-	    throwErrorIfExpression(n, "align", "jsp:plugin");
-	    throwErrorIfExpression(n, "archive", "jsp:plugin");
-	    throwErrorIfExpression(n, "hspace", "jsp:plugin");
-	    throwErrorIfExpression(n, "jreversion", "jsp:plugin");
-	    throwErrorIfExpression(n, "name", "jsp:plugin");
-	    throwErrorIfExpression(n, "vspace", "jsp:plugin");
-	    throwErrorIfExpression(n, "nspluginurl", "jsp:plugin");
-	    throwErrorIfExpression(n, "iepluginurl", "jsp:plugin");
-
-	    String type = n.getTextAttribute("type");
-	    if (type == null)
-		err.jspError(n, "jsp.error.plugin.notype");
-	    if (!type.equals("bean") && !type.equals("applet"))
-		err.jspError(n, "jsp.error.plugin.badtype");
-	    if (n.getTextAttribute("code") == null)
-		err.jspError(n, "jsp.error.plugin.nocode");
-            
-	    Node.JspAttribute width
-		= getJspAttribute("width", null, null,
-				  n.getAttributeValue("width"), 
-                                  java.lang.String.class, n, false);
-	    n.setWidth( width );
-            
-	    Node.JspAttribute height
-		= getJspAttribute("height", null, null,
-				  n.getAttributeValue("height"), 
-                                  java.lang.String.class, n, false);
-	    n.setHeight( height );
-
-	    visitBody(n);
-	}
-
-	public void visit(Node.NamedAttribute n) throws JasperException {
-	    JspUtil.checkAttributes("Attribute", n,
-				    attributeAttrs, err);
+        public void visit(Node.NamedAttribute n) throws JasperException {
+            JspUtil.checkAttributes("Attribute", n, attributeAttrs, err);
             visitBody(n);
-	}
-        
-	public void visit(Node.JspBody n) throws JasperException {
+        }
+
+        public void visit(Node.JspBody n) throws JasperException {
             visitBody(n);
-	}
-        
-	public void visit(Node.Declaration n) throws JasperException {
-	    if (pageInfo.isScriptingInvalid()) {
-		err.jspError(n.getStart(), "jsp.error.no.scriptlets");
-	    }
-	}
+        }
+
+        public void visit(Node.Declaration n) throws JasperException {
+            if (pageInfo.isScriptingInvalid()) {
+                err.jspError(n.getStart(), "jsp.error.no.scriptlets");
+            }
+        }
 
         public void visit(Node.Expression n) throws JasperException {
-	    if (pageInfo.isScriptingInvalid()) {
-		err.jspError(n.getStart(), "jsp.error.no.scriptlets");
-	    }
-	}
+            if (pageInfo.isScriptingInvalid()) {
+                err.jspError(n.getStart(), "jsp.error.no.scriptlets");
+            }
+        }
 
         public void visit(Node.Scriptlet n) throws JasperException {
-	    if (pageInfo.isScriptingInvalid()) {
-		err.jspError(n.getStart(), "jsp.error.no.scriptlets");
-	    }
-	}
-
-	public void visit(Node.ELExpression n) throws JasperException {
-            if ( !pageInfo.isELIgnored() ) {
-		String expressions = "${" + new String(n.getText()) + "}";
-		ELNode.Nodes el = ELParser.parse(expressions);
-		validateFunctions(el, n);
-                JspUtil.validateExpressions(
-                    n.getStart(),
-		    expressions,
-                    java.lang.String.class, // XXX - Should template text 
-                                            // always evaluate to String?
-                    getFunctionMapper(el),
-                    err);
-		n.setEL(el);
+            if (pageInfo.isScriptingInvalid()) {
+                err.jspError(n.getStart(), "jsp.error.no.scriptlets");
             }
         }
 
-	public void visit(Node.UninterpretedTag n) throws JasperException {
+        public void visit(Node.ELExpression n) throws JasperException {
+            // exit if we are ignoring EL all together
+            if (pageInfo.isELIgnored())
+                return;
+
+            // JSP.2.2 - '#{' not allowed in template text
+            if (n.getType() == '#') {
+                if (pageInfo.isDeferredSyntaxAllowedAsLiteral())
+                    return;
+                err.jspError(n, "jsp.error.el.template.deferred");
+            }
+
+            // build expression
+            StringBuffer expr = this.getBuffer();
+            expr.append(n.getType()).append('{').append(n.getText())
+                    .append('}');
+            ELNode.Nodes el = ELParser.parse(expr.toString());
+
+            // validate/prepare expression
+            prepareExpression(el, n, expr.toString());
+
+            // store it
+            n.setEL(el);
+        }
+
+        public void visit(Node.UninterpretedTag n) throws JasperException {
             if (n.getNamedAttributeNodes().size() != 0) {
-		err.jspError(n, "jsp.error.namedAttribute.invalidUse");
+                err.jspError(n, "jsp.error.namedAttribute.invalidUse");
+            }
+
+            Attributes attrs = n.getAttributes();
+            if (attrs != null) {
+                int attrSize = attrs.getLength();
+                Node.JspAttribute[] jspAttrs = new Node.JspAttribute[attrSize];
+                for (int i = 0; i < attrSize; i++) {
+                    jspAttrs[i] = getJspAttribute(attrs.getQName(i), attrs
+                            .getURI(i), attrs.getLocalName(i), attrs
+                            .getValue(i), java.lang.Object.class, n, false);
+                }
+                n.setJspAttributes(jspAttrs);
             }
 
-	    Attributes attrs = n.getAttributes();
-	    if (attrs != null) {
-		int attrSize = attrs.getLength();
-		Node.JspAttribute[] jspAttrs = new Node.JspAttribute[attrSize];
-		for (int i=0; i < attrSize; i++) {
-		    jspAttrs[i] = getJspAttribute(attrs.getQName(i),
-						  attrs.getURI(i),
-						  attrs.getLocalName(i),
-						  attrs.getValue(i),
-						  java.lang.Object.class,
-						  n,
-						  false);
-		}
-		n.setJspAttributes(jspAttrs);
-	    }
-
-	    visitBody(n);
-        }
-
-	public void visit(Node.CustomTag n) throws JasperException {
-
-	    TagInfo tagInfo = n.getTagInfo();
-	    if (tagInfo == null) {
-		err.jspError(n, "jsp.error.missing.tagInfo", n.getQName());
-	    }
-
-	    /*
-	     * The bodyconet of a SimpleTag cannot be JSP.
-	     */
-	    if (n.implementsSimpleTag() &&
-                tagInfo.getBodyContent().equalsIgnoreCase(TagInfo.BODY_CONTENT_JSP)) {
-                err.jspError(n, "jsp.error.simpletag.badbodycontent",
-                        tagInfo.getTagClassName());
-	    }
-
-	    /*
-	     * If the tag handler declares in the TLD that it supports dynamic
-	     * attributes, it also must implement the DynamicAttributes
-	     * interface.
-	     */
-	    if (tagInfo.hasDynamicAttributes()
-		    && !n.implementsDynamicAttributes()) {
-		err.jspError(n, "jsp.error.dynamic.attributes.not.implemented",
-			     n.getQName());
-	    }
-
-	    /*
-	     * Make sure all required attributes are present, either as
-             * attributes or named attributes (<jsp:attribute>).
- 	     * Also make sure that the same attribute is not specified in
-	     * both attributes or named attributes.
-	     */
-	    TagAttributeInfo[] tldAttrs = tagInfo.getAttributes();
-	    String customActionUri = n.getURI();
-	    Attributes attrs = n.getAttributes();
-	    int attrsSize = (attrs == null) ? 0 : attrs.getLength();
-	    for (int i=0; i<tldAttrs.length; i++) {
-		String attr = null;
-		if (attrs != null) {
-		    attr = attrs.getValue(tldAttrs[i].getName());
-		    if (attr == null) {
-			attr = attrs.getValue(customActionUri,
-					      tldAttrs[i].getName());
-		    }
-		}
-		Node.NamedAttribute na =
-			n.getNamedAttributeNode(tldAttrs[i].getName());
-		
-		if (tldAttrs[i].isRequired() && attr == null && na == null) {
-		    err.jspError(n, "jsp.error.missing_attribute",
-				 tldAttrs[i].getName(), n.getLocalName());
-		}
-		if (attr != null && na != null) {
-		    err.jspError(n, "jsp.error.duplicate.name.jspattribute",
-			tldAttrs[i].getName());
-		}
-	    }
+            visitBody(n);
+        }
+
+        public void visit(Node.CustomTag n) throws JasperException {
+
+            TagInfo tagInfo = n.getTagInfo();
+            if (tagInfo == null) {
+                err.jspError(n, "jsp.error.missing.tagInfo", n.getQName());
+            }
+
+            /*
+             * The bodyconet of a SimpleTag cannot be JSP.
+             */
+            if (n.implementsSimpleTag()
+                    && tagInfo.getBodyContent().equalsIgnoreCase(
+                            TagInfo.BODY_CONTENT_JSP)) {
+                err.jspError(n, "jsp.error.simpletag.badbodycontent", tagInfo
+                        .getTagClassName());
+            }
+
+            /*
+             * If the tag handler declares in the TLD that it supports dynamic
+             * attributes, it also must implement the DynamicAttributes
+             * interface.
+             */
+            if (tagInfo.hasDynamicAttributes()
+                    && !n.implementsDynamicAttributes()) {
+                err.jspError(n, "jsp.error.dynamic.attributes.not.implemented",
+                        n.getQName());
+            }
+
+            /*
+             * Make sure all required attributes are present, either as
+             * attributes or named attributes (<jsp:attribute>). Also make sure
+             * that the same attribute is not specified in both attributes or
+             * named attributes.
+             */
+            TagAttributeInfo[] tldAttrs = tagInfo.getAttributes();
+            String customActionUri = n.getURI();
+            Attributes attrs = n.getAttributes();
+            int attrsSize = (attrs == null) ? 0 : attrs.getLength();
+            for (int i = 0; i < tldAttrs.length; i++) {
+                String attr = null;
+                if (attrs != null) {
+                    attr = attrs.getValue(tldAttrs[i].getName());
+                    if (attr == null) {
+                        attr = attrs.getValue(customActionUri, tldAttrs[i]
+                                .getName());
+                    }
+                }
+                Node.NamedAttribute na = n.getNamedAttributeNode(tldAttrs[i]
+                        .getName());
+
+                if (tldAttrs[i].isRequired() && attr == null && na == null) {
+                    err.jspError(n, "jsp.error.missing_attribute", tldAttrs[i]
+                            .getName(), n.getLocalName());
+                }
+                if (attr != null && na != null) {
+                    err.jspError(n, "jsp.error.duplicate.name.jspattribute",
+                            tldAttrs[i].getName());
+                }
+            }
 
             Node.Nodes naNodes = n.getNamedAttributeNodes();
-	    int jspAttrsSize = naNodes.size() + attrsSize;
-	    Node.JspAttribute[] jspAttrs = null;
-	    if (jspAttrsSize > 0) {
-		jspAttrs = new Node.JspAttribute[jspAttrsSize];
-	    }
-	    Hashtable tagDataAttrs = new Hashtable(attrsSize);
+            int jspAttrsSize = naNodes.size() + attrsSize;
+            Node.JspAttribute[] jspAttrs = null;
+            if (jspAttrsSize > 0) {
+                jspAttrs = new Node.JspAttribute[jspAttrsSize];
+            }
+            Hashtable tagDataAttrs = new Hashtable(attrsSize);
 
-	    checkXmlAttributes(n, jspAttrs, tagDataAttrs);
+            checkXmlAttributes(n, jspAttrs, tagDataAttrs);
             checkNamedAttributes(n, jspAttrs, attrsSize, tagDataAttrs);
 
-	    TagData tagData = new TagData(tagDataAttrs);
+            TagData tagData = new TagData(tagDataAttrs);
+
+            // JSP.C1: It is a (translation time) error for an action that
+            // has one or more variable subelements to have a TagExtraInfo
+            // class that returns a non-null object.
+            TagExtraInfo tei = tagInfo.getTagExtraInfo();
+            if (tei != null && tei.getVariableInfo(tagData) != null
+                    && tei.getVariableInfo(tagData).length > 0
+                    && tagInfo.getTagVariableInfos().length > 0) {
+                err.jspError("jsp.error.non_null_tei_and_var_subelems", n
+                        .getQName());
+            }
+
+            n.setTagData(tagData);
+            n.setJspAttributes(jspAttrs);
+
+            visitBody(n);
+        }
+
+        public void visit(Node.JspElement n) throws JasperException {
 
-	    // JSP.C1: It is a (translation time) error for an action that
-	    // has one or more variable subelements to have a TagExtraInfo
-	    // class that returns a non-null object.
-	    TagExtraInfo tei = tagInfo.getTagExtraInfo();
-	    if (tei != null
-		    && tei.getVariableInfo(tagData) != null
-		    && tei.getVariableInfo(tagData).length > 0
-		    && tagInfo.getTagVariableInfos().length > 0) {
-		err.jspError("jsp.error.non_null_tei_and_var_subelems",
-			     n.getQName());
-	    }
-
-	    n.setTagData(tagData);
-	    n.setJspAttributes(jspAttrs);
-
-	    visitBody(n);
-	}
-
-	public void visit(Node.JspElement n) throws JasperException {
-
-	    Attributes attrs = n.getAttributes();
-	    if (attrs == null) {
-		err.jspError(n, "jsp.error.jspelement.missing.name");
-	    }
-	    int xmlAttrLen = attrs.getLength();
+            Attributes attrs = n.getAttributes();
+            if (attrs == null) {
+                err.jspError(n, "jsp.error.jspelement.missing.name");
+            }
+            int xmlAttrLen = attrs.getLength();
 
             Node.Nodes namedAttrs = n.getNamedAttributeNodes();
 
-	    // XML-style 'name' attribute, which is mandatory, must not be
-	    // included in JspAttribute array
-	    int jspAttrSize = xmlAttrLen-1 + namedAttrs.size();
-
-	    Node.JspAttribute[] jspAttrs = new Node.JspAttribute[jspAttrSize];
-	    int jspAttrIndex = 0;
-
-	    // Process XML-style attributes
-	    for (int i=0; i<xmlAttrLen; i++) {
-		if ("name".equals(attrs.getLocalName(i))) {
-		    n.setNameAttribute(getJspAttribute(attrs.getQName(i),
-						       attrs.getURI(i),
-						       attrs.getLocalName(i),
-						       attrs.getValue(i),
-						       java.lang.String.class,
-						       n,
-						       false));
-		} else {
-		    if (jspAttrIndex<jspAttrSize) {
-			jspAttrs[jspAttrIndex++]
-			    = getJspAttribute(attrs.getQName(i),
-					      attrs.getURI(i),
-					      attrs.getLocalName(i),
-					      attrs.getValue(i),
-					      java.lang.Object.class,
-					      n,
-					      false);
-		    }
-		}
-	    }
-	    if (n.getNameAttribute() == null) {
-		err.jspError(n, "jsp.error.jspelement.missing.name");
-	    }
-
-	    // Process named attributes
-	    for (int i=0; i<namedAttrs.size(); i++) {
-                Node.NamedAttribute na = (Node.NamedAttribute) namedAttrs.getNode(i);
-		jspAttrs[jspAttrIndex++] = new Node.JspAttribute(na, false);
-	    }
+            // XML-style 'name' attribute, which is mandatory, must not be
+            // included in JspAttribute array
+            int jspAttrSize = xmlAttrLen - 1 + namedAttrs.size();
+
+            Node.JspAttribute[] jspAttrs = new Node.JspAttribute[jspAttrSize];
+            int jspAttrIndex = 0;
+
+            // Process XML-style attributes
+            for (int i = 0; i < xmlAttrLen; i++) {
+                if ("name".equals(attrs.getLocalName(i))) {
+                    n.setNameAttribute(getJspAttribute(attrs.getQName(i), attrs
+                            .getURI(i), attrs.getLocalName(i), attrs
+                            .getValue(i), java.lang.String.class, n, false));
+                } else {
+                    if (jspAttrIndex < jspAttrSize) {
+                        jspAttrs[jspAttrIndex++] = getJspAttribute(attrs
+                                .getQName(i), attrs.getURI(i), attrs
+                                .getLocalName(i), attrs.getValue(i),
+                                java.lang.Object.class, n, false);
+                    }
+                }
+            }
+            if (n.getNameAttribute() == null) {
+                err.jspError(n, "jsp.error.jspelement.missing.name");
+            }
+
+            // Process named attributes
+            for (int i = 0; i < namedAttrs.size(); i++) {
+                Node.NamedAttribute na = (Node.NamedAttribute) namedAttrs
+                        .getNode(i);
+                jspAttrs[jspAttrIndex++] = new Node.JspAttribute(na, false);
+            }
 
-	    n.setJspAttributes(jspAttrs);
+            n.setJspAttributes(jspAttrs);
 
-	    visitBody(n);
-	}
+            visitBody(n);
+        }
 
-	public void visit(Node.JspOutput n) throws JasperException {
+        public void visit(Node.JspOutput n) throws JasperException {
             JspUtil.checkAttributes("jsp:output", n, jspOutputAttrs, err);
 
-	    if (n.getBody() != null) {
+            if (n.getBody() != null) {
                 err.jspError(n, "jsp.error.jspoutput.nonemptybody");
-	    }
+            }
 
-	    String omitXmlDecl = n.getAttributeValue("omit-xml-declaration");
-	    String doctypeName = n.getAttributeValue("doctype-root-element");
-	    String doctypePublic = n.getAttributeValue("doctype-public");
-	    String doctypeSystem = n.getAttributeValue("doctype-system");
-
-	    String omitXmlDeclOld = pageInfo.getOmitXmlDecl();
-	    String doctypeNameOld = pageInfo.getDoctypeName();
-	    String doctypePublicOld = pageInfo.getDoctypePublic();
-	    String doctypeSystemOld = pageInfo.getDoctypeSystem();
+            String omitXmlDecl = n.getAttributeValue("omit-xml-declaration");
+            String doctypeName = n.getAttributeValue("doctype-root-element");
+            String doctypePublic = n.getAttributeValue("doctype-public");
+            String doctypeSystem = n.getAttributeValue("doctype-system");
+
+            String omitXmlDeclOld = pageInfo.getOmitXmlDecl();
+            String doctypeNameOld = pageInfo.getDoctypeName();
+            String doctypePublicOld = pageInfo.getDoctypePublic();
+            String doctypeSystemOld = pageInfo.getDoctypeSystem();
 
-	    if (omitXmlDecl != null && omitXmlDeclOld != null &&
-			!omitXmlDecl.equals(omitXmlDeclOld) ) {
+            if (omitXmlDecl != null && omitXmlDeclOld != null
+                    && !omitXmlDecl.equals(omitXmlDeclOld)) {
                 err.jspError(n, "jsp.error.jspoutput.conflict",
-			"omit-xml-declaration", omitXmlDeclOld, omitXmlDecl);
-	    }
+                        "omit-xml-declaration", omitXmlDeclOld, omitXmlDecl);
+            }
 
-	    if (doctypeName != null && doctypeNameOld != null &&
-			!doctypeName.equals(doctypeNameOld) ) {
+            if (doctypeName != null && doctypeNameOld != null
+                    && !doctypeName.equals(doctypeNameOld)) {
                 err.jspError(n, "jsp.error.jspoutput.conflict",
-			"doctype-root-element", doctypeNameOld, doctypeName);
-	    }
+                        "doctype-root-element", doctypeNameOld, doctypeName);
+            }
 
-	    if (doctypePublic != null && doctypePublicOld != null &&
-			!doctypePublic.equals(doctypePublicOld) ) {
+            if (doctypePublic != null && doctypePublicOld != null
+                    && !doctypePublic.equals(doctypePublicOld)) {
                 err.jspError(n, "jsp.error.jspoutput.conflict",
-			"doctype-public", doctypePublicOld, doctypePublic);
-	    }
+                        "doctype-public", doctypePublicOld, doctypePublic);
+            }
 
-	    if (doctypeSystem != null && doctypeSystemOld != null &&
-			!doctypeSystem.equals(doctypeSystemOld) ) {
+            if (doctypeSystem != null && doctypeSystemOld != null
+                    && !doctypeSystem.equals(doctypeSystemOld)) {
                 err.jspError(n, "jsp.error.jspoutput.conflict",
-			"doctype-system", doctypeSystemOld, doctypeSystem);
-	    }
+                        "doctype-system", doctypeSystemOld, doctypeSystem);
+            }
 
-	    if (doctypeName == null && doctypeSystem != null ||
-		doctypeName != null && doctypeSystem == null) {
-		err.jspError(n, "jsp.error.jspoutput.doctypenamesystem");
-	    }
-
-	    if (doctypePublic != null && doctypeSystem == null) {
-		err.jspError(n, "jsp.error.jspoutput.doctypepulicsystem");
-	    }
-
-	    if (omitXmlDecl != null) {
-		pageInfo.setOmitXmlDecl(omitXmlDecl);
-	    }
-	    if (doctypeName != null) {
-		pageInfo.setDoctypeName(doctypeName);
-	    }
-	    if (doctypeSystem != null) {
-		pageInfo.setDoctypeSystem(doctypeSystem);
-	    }
-	    if (doctypePublic != null) {
-		pageInfo.setDoctypePublic(doctypePublic);
-	    }
-	}
+            if (doctypeName == null && doctypeSystem != null
+                    || doctypeName != null && doctypeSystem == null) {
+                err.jspError(n, "jsp.error.jspoutput.doctypenamesystem");
+            }
 
-	public void visit(Node.InvokeAction n) throws JasperException {
+            if (doctypePublic != null && doctypeSystem == null) {
+                err.jspError(n, "jsp.error.jspoutput.doctypepulicsystem");
+            }
+
+            if (omitXmlDecl != null) {
+                pageInfo.setOmitXmlDecl(omitXmlDecl);
+            }
+            if (doctypeName != null) {
+                pageInfo.setDoctypeName(doctypeName);
+            }
+            if (doctypeSystem != null) {
+                pageInfo.setDoctypeSystem(doctypeSystem);
+            }
+            if (doctypePublic != null) {
+                pageInfo.setDoctypePublic(doctypePublic);
+            }
+        }
+
+        public void visit(Node.InvokeAction n) throws JasperException {
 
             JspUtil.checkAttributes("Invoke", n, invokeAttrs, err);
 
-	    String scope = n.getTextAttribute ("scope");
-	    JspUtil.checkScope(scope, n, err);
+            String scope = n.getTextAttribute("scope");
+            JspUtil.checkScope(scope, n, err);
 
-	    String var = n.getTextAttribute("var");
-	    String varReader = n.getTextAttribute("varReader");
-	    if (scope != null && var == null && varReader == null) {
-		err.jspError(n, "jsp.error.missing_var_or_varReader");
-	    }
-	    if (var != null && varReader != null) {
-		err.jspError(n, "jsp.error.var_and_varReader");
-	    }
-	}
+            String var = n.getTextAttribute("var");
+            String varReader = n.getTextAttribute("varReader");
+            if (scope != null && var == null && varReader == null) {
+                err.jspError(n, "jsp.error.missing_var_or_varReader");
+            }
+            if (var != null && varReader != null) {
+                err.jspError(n, "jsp.error.var_and_varReader");
+            }
+        }
 
-	public void visit(Node.DoBodyAction n) throws JasperException {
+        public void visit(Node.DoBodyAction n) throws JasperException {
 
             JspUtil.checkAttributes("DoBody", n, doBodyAttrs, err);
 
-	    String scope = n.getTextAttribute ("scope");
-	    JspUtil.checkScope(scope, n, err);
+            String scope = n.getTextAttribute("scope");
+            JspUtil.checkScope(scope, n, err);
+
+            String var = n.getTextAttribute("var");
+            String varReader = n.getTextAttribute("varReader");
+            if (scope != null && var == null && varReader == null) {
+                err.jspError(n, "jsp.error.missing_var_or_varReader");
+            }
+            if (var != null && varReader != null) {
+                err.jspError(n, "jsp.error.var_and_varReader");
+            }
+        }
+
+        /*
+         * Make sure the given custom action does not have any invalid
+         * attributes.
+         * 
+         * A custom action and its declared attributes always belong to the same
+         * namespace, which is identified by the prefix name of the custom tag
+         * invocation. For example, in this invocation:
+         * 
+         * <my:test a="1" b="2" c="3"/>, the action
+         * 
+         * "test" and its attributes "a", "b", and "c" all belong to the
+         * namespace identified by the prefix "my". The above invocation would
+         * be equivalent to:
+         * 
+         * <my:test my:a="1" my:b="2" my:c="3"/>
+         * 
+         * An action attribute may have a prefix different from that of the
+         * action invocation only if the underlying tag handler supports dynamic
+         * attributes, in which case the attribute with the different prefix is
+         * considered a dynamic attribute.
+         */
+        private void checkXmlAttributes(Node.CustomTag n,
+                Node.JspAttribute[] jspAttrs, Hashtable tagDataAttrs)
+                throws JasperException {
+
+            TagInfo tagInfo = n.getTagInfo();
+            if (tagInfo == null) {
+                err.jspError(n, "jsp.error.missing.tagInfo", n.getQName());
+            }
+            TagAttributeInfo[] tldAttrs = tagInfo.getAttributes();
+            Attributes attrs = n.getAttributes();
 
-	    String var = n.getTextAttribute("var");
-	    String varReader = n.getTextAttribute("varReader");
-	    if (scope != null && var == null && varReader == null) {
-		err.jspError(n, "jsp.error.missing_var_or_varReader");
-	    }
-	    if (var != null && varReader != null) {
-		err.jspError(n, "jsp.error.var_and_varReader");
-	    }
-	}
-
-	/*
-	 * Make sure the given custom action does not have any invalid
-	 * attributes.
-	 *
-	 * A custom action and its declared attributes always belong to the
-	 * same namespace, which is identified by the prefix name of the
-	 * custom tag invocation. For example, in this invocation:
-	 *
-	 *     <my:test a="1" b="2" c="3"/>, the action
-	 *
-	 * "test" and its attributes "a", "b", and "c" all belong to the
-	 * namespace identified by the prefix "my". The above invocation would
-	 * be equivalent to:
-	 *
-	 *     <my:test my:a="1" my:b="2" my:c="3"/>
-	 *
-	 * An action attribute may have a prefix different from that of the
-	 * action invocation only if the underlying tag handler supports
-	 * dynamic attributes, in which case the attribute with the different
-	 * prefix is considered a dynamic attribute.
-	 */
-	private void checkXmlAttributes(Node.CustomTag n,
-					Node.JspAttribute[] jspAttrs,
-					Hashtable tagDataAttrs)
-	        throws JasperException {
-
-	    TagInfo tagInfo = n.getTagInfo();
-	    if (tagInfo == null) {
-		err.jspError(n, "jsp.error.missing.tagInfo", n.getQName());
-	    }
-	    TagAttributeInfo[] tldAttrs = tagInfo.getAttributes();
-	    Attributes attrs = n.getAttributes();
-
-	    for (int i=0; attrs != null && i<attrs.getLength(); i++) {
-		boolean found = false;
-		for (int j=0; tldAttrs != null && j<tldAttrs.length; j++) {
-		    if (attrs.getLocalName(i).equals(tldAttrs[j].getName())
-			    && (attrs.getURI(i) == null
-				|| attrs.getURI(i).length() == 0
-				|| attrs.getURI(i).equals(n.getURI()))) {
-			if (tldAttrs[j].canBeRequestTime()) {
+            for (int i = 0; attrs != null && i < attrs.getLength(); i++) {
+                boolean found = false;
+                for (int j = 0; tldAttrs != null && j < tldAttrs.length; j++) {
+                    if (attrs.getLocalName(i).equals(tldAttrs[j].getName())
+                            && (attrs.getURI(i) == null
+                                    || attrs.getURI(i).length() == 0 || attrs
+                                    .getURI(i).equals(n.getURI()))) {
+                        if (tldAttrs[j].canBeRequestTime()) {
                             Class expectedType = String.class;
                             try {
                                 String typeStr = tldAttrs[j].getTypeName();
-                                if( tldAttrs[j].isFragment() ) {
+                                if (tldAttrs[j].isFragment()) {
                                     expectedType = JspFragment.class;
-                                }
-                                else if( typeStr != null ) {
+                                } else if (typeStr != null) {
                                     expectedType = JspUtil.toClass(typeStr,
-								   loader);
+                                            loader);
                                 }
-                                jspAttrs[i]
-                                    = getJspAttribute(attrs.getQName(i),
-                                                      attrs.getURI(i),
-                                                      attrs.getLocalName(i),
-                                                      attrs.getValue(i),
-                                                      expectedType,
-                                                      n,
-                                                      false);
+                                jspAttrs[i] = getJspAttribute(
+                                        attrs.getQName(i), attrs.getURI(i),
+                                        attrs.getLocalName(i), attrs
+                                                .getValue(i), expectedType, n,
+                                        false);
                             } catch (ClassNotFoundException e) {
-                                err.jspError(n, 
-                                    "jsp.error.unknown_attribute_type",
-                                    tldAttrs[j].getName(), 
-                                    tldAttrs[j].getTypeName() );
-                            }
-			} else {
-			    // Attribute does not accept any expressions.
-			    // Make sure its value does not contain any.
-			    if (isExpression(n, attrs.getValue(i))) {
                                 err.jspError(n,
-				        "jsp.error.attribute.custom.non_rt_with_expr",
-					     tldAttrs[j].getName());
-			    }
-			    jspAttrs[i]
-				= new Node.JspAttribute(attrs.getQName(i),
-							attrs.getURI(i),
-							attrs.getLocalName(i),
-							attrs.getValue(i),
-							false,
-							null,
-							false);
-			}
-			if (jspAttrs[i].isExpression()) {
-			    tagDataAttrs.put(attrs.getQName(i),
-					     TagData.REQUEST_TIME_VALUE);
-			} else {
-			    tagDataAttrs.put(attrs.getQName(i),
-					     attrs.getValue(i));
-			}
-			found = true;
-			break;
-		    }
-		}
-		if (!found) {
-		    if (tagInfo.hasDynamicAttributes()) {
-			jspAttrs[i] = getJspAttribute(attrs.getQName(i),
-						      attrs.getURI(i),
-						      attrs.getLocalName(i),
-						      attrs.getValue(i),
-						      java.lang.Object.class,
-                                                      n,
-						      true);
-		    } else {
-			err.jspError(n, "jsp.error.bad_attribute",
-				     attrs.getQName(i), n.getLocalName());
-		    }
-		}
-	    }
-	}
-
-	/*
-	 * Make sure the given custom action does not have any invalid named
-	 * attributes
-	 */
-	private void checkNamedAttributes(Node.CustomTag n,
-					  Node.JspAttribute[] jspAttrs,
-					  int start,
-					  Hashtable tagDataAttrs)
-	        throws JasperException {
-
-	    TagInfo tagInfo = n.getTagInfo();
-	    if (tagInfo == null) {
-		err.jspError(n, "jsp.error.missing.tagInfo", n.getQName());
-	    }
-	    TagAttributeInfo[] tldAttrs = tagInfo.getAttributes();
+                                        "jsp.error.unknown_attribute_type",
+                                        tldAttrs[j].getName(), tldAttrs[j]
+                                                .getTypeName());
+                            }
+                        } else {
+                            // Attribute does not accept any expressions.
+                            // Make sure its value does not contain any.
+                            if (isExpression(n, attrs.getValue(i))) {
+                                err
+                                        .jspError(
+                                                n,
+                                                "jsp.error.attribute.custom.non_rt_with_expr",
+                                                tldAttrs[j].getName());
+                            }
+                            jspAttrs[i] = new Node.JspAttribute(attrs
+                                    .getQName(i), attrs.getURI(i), attrs
+                                    .getLocalName(i), attrs.getValue(i), false,
+                                    null, false);
+                        }
+                        if (jspAttrs[i].isExpression()) {
+                            tagDataAttrs.put(attrs.getQName(i),
+                                    TagData.REQUEST_TIME_VALUE);
+                        } else {
+                            tagDataAttrs.put(attrs.getQName(i), attrs
+                                    .getValue(i));
+                        }
+                        found = true;
+                        break;
+                    }
+                }
+                if (!found) {
+                    if (tagInfo.hasDynamicAttributes()) {
+                        jspAttrs[i] = getJspAttribute(attrs.getQName(i), attrs
+                                .getURI(i), attrs.getLocalName(i), attrs
+                                .getValue(i), java.lang.Object.class, n, true);
+                    } else {
+                        err.jspError(n, "jsp.error.bad_attribute", attrs
+                                .getQName(i), n.getLocalName());
+                    }
+                }
+            }
+        }
+
+        /*
+         * Make sure the given custom action does not have any invalid named
+         * attributes
+         */
+        private void checkNamedAttributes(Node.CustomTag n,
+                Node.JspAttribute[] jspAttrs, int start, Hashtable tagDataAttrs)
+                throws JasperException {
+
+            TagInfo tagInfo = n.getTagInfo();
+            if (tagInfo == null) {
+                err.jspError(n, "jsp.error.missing.tagInfo", n.getQName());
+            }
+            TagAttributeInfo[] tldAttrs = tagInfo.getAttributes();
             Node.Nodes naNodes = n.getNamedAttributeNodes();
 
-	    for (int i=0; i<naNodes.size(); i++) {
-                Node.NamedAttribute na = (Node.NamedAttribute)
-		    naNodes.getNode(i);
-		boolean found = false;
-		for (int j=0; j<tldAttrs.length; j++) {
-		    /*
-		     * See above comment about namespace matches. For named
-		     * attributes, we use the prefix instead of URI as the
-		     * match criterion, because in the case of a JSP document,
-		     * we'd have to keep track of which namespaces are in scope
-		     * when parsing a named attribute, in order to determine
-		     * the URI that the prefix of the named attribute's name
-		     * matches to.
-		     */
-		    String attrPrefix = na.getPrefix();
-		    if (na.getLocalName().equals(tldAttrs[j].getName())
-			    && (attrPrefix == null || attrPrefix.length() == 0
-				|| attrPrefix.equals(n.getPrefix()))) {
-			jspAttrs[start + i] = new Node.JspAttribute(na, false);
-			NamedAttributeVisitor nav = null;
-			if (na.getBody() != null) {
-			    nav = new NamedAttributeVisitor();
-			    na.getBody().visit(nav);
-			}
-			if (nav != null && nav.hasDynamicContent()) {
-			    tagDataAttrs.put(na.getName(),
-					     TagData.REQUEST_TIME_VALUE);
-			} else {
-			    tagDataAttrs.put(na.getName(), na.getText());    
-			}
-			found = true;
-			break;
-		    }
-		}
-		if (!found) {
-		    if (tagInfo.hasDynamicAttributes()) {
-			jspAttrs[start + i] = new Node.JspAttribute(na, true);
-		    } else {
-			err.jspError(n, "jsp.error.bad_attribute",
-				     na.getName(), n.getLocalName());
-		    }
-		}
-	    }
-	}
-
-	/**
-	 * Preprocess attributes that can be expressions.  Expression
-	 * delimiters are stripped.
+            for (int i = 0; i < naNodes.size(); i++) {
+                Node.NamedAttribute na = (Node.NamedAttribute) naNodes
+                        .getNode(i);
+                boolean found = false;
+                for (int j = 0; j < tldAttrs.length; j++) {
+                    /*
+                     * See above comment about namespace matches. For named
+                     * attributes, we use the prefix instead of URI as the match
+                     * criterion, because in the case of a JSP document, we'd
+                     * have to keep track of which namespaces are in scope when
+                     * parsing a named attribute, in order to determine the URI
+                     * that the prefix of the named attribute's name matches to.
+                     */
+                    String attrPrefix = na.getPrefix();
+                    if (na.getLocalName().equals(tldAttrs[j].getName())
+                            && (attrPrefix == null || attrPrefix.length() == 0 || attrPrefix
+                                    .equals(n.getPrefix()))) {
+                        jspAttrs[start + i] = new Node.JspAttribute(na, false);
+                        NamedAttributeVisitor nav = null;
+                        if (na.getBody() != null) {
+                            nav = new NamedAttributeVisitor();
+                            na.getBody().visit(nav);
+                        }
+                        if (nav != null && nav.hasDynamicContent()) {
+                            tagDataAttrs.put(na.getName(),
+                                    TagData.REQUEST_TIME_VALUE);
+                        } else {
+                            tagDataAttrs.put(na.getName(), na.getText());
+                        }
+                        found = true;
+                        break;
+                    }
+                }
+                if (!found) {
+                    if (tagInfo.hasDynamicAttributes()) {
+                        jspAttrs[start + i] = new Node.JspAttribute(na, true);
+                    } else {
+                        err.jspError(n, "jsp.error.bad_attribute",
+                                na.getName(), n.getLocalName());
+                    }
+                }
+            }
+        }
+
+        /**
+         * Preprocess attributes that can be expressions. Expression delimiters
+         * are stripped.
          * <p>
-         * If value is null, checks if there are any
-         * NamedAttribute subelements in the tree node, and if so,
-         * constructs a JspAttribute out of a child NamedAttribute node.
-	 */
-	private Node.JspAttribute getJspAttribute(String qName,
-						  String uri,
-						  String localName,
-						  String value,
-                                                  Class expectedType,
-                                                  Node n,
-						  boolean dynamic)
-                throws JasperException {
+         * If value is null, checks if there are any NamedAttribute subelements
+         * in the tree node, and if so, constructs a JspAttribute out of a child
+         * NamedAttribute node.
+         */
+        private Node.JspAttribute getJspAttribute(String qName, String uri,
+                String localName, String value, Class expectedType, Node n,
+                boolean dynamic) throws JasperException {
 
             Node.JspAttribute result = null;
 
-	    // XXX Is it an error to see "%=foo%" in non-Xml page?
-	    // (We won't see "<%=foo%> in xml page because '<' is not a
-	    // valid attribute value in xml).
+            // XXX Is it an error to see "%=foo%" in non-Xml page?
+            // (We won't see "<%=foo%> in xml page because '<' is not a
+            // valid attribute value in xml).
 
             if (value != null) {
                 if (n.getRoot().isXmlSyntax() && value.startsWith("%=")) {
-                    result = new Node.JspAttribute(
-                                        qName,
-					uri,
-					localName,
-					value.substring(2, value.length()-1),
-					true,
-					null,
-					dynamic);
-                }
-                else if(!n.getRoot().isXmlSyntax() && value.startsWith("<%=")) {
-                    result = new Node.JspAttribute(
-                                        qName,
-					uri,
-					localName,
-					value.substring(3, value.length()-2),
-					true,
-					null,
-					dynamic);
-                }
-                else {
+                    result = new Node.JspAttribute(qName, uri, localName, value
+                            .substring(2, value.length() - 1), true, null,
+                            dynamic);
+                } else if (!n.getRoot().isXmlSyntax()
+                        && value.startsWith("<%=")) {
+                    result = new Node.JspAttribute(qName, uri, localName, value
+                            .substring(3, value.length() - 2), true, null,
+                            dynamic);
+                } else {
                     // The attribute can contain expressions but is not a
-                    // scriptlet expression; thus, we want to run it through 
+                    // scriptlet expression; thus, we want to run it through
                     // the expression interpreter
 
                     // validate expression syntax if string contains
                     // expression(s)
                     ELNode.Nodes el = ELParser.parse(value);
                     if (el.containsEL() && !pageInfo.isELIgnored()) {
-	                validateFunctions(el, n);
-                        JspUtil.validateExpressions(
-                            n.getStart(),
-                            value, 
-                            expectedType, 
-                            getFunctionMapper(el),
-                            this.err);
+                        validateFunctions(el, n);
 
-                        
                         result = new Node.JspAttribute(qName, uri, localName,
-						       value, false, el,
-						       dynamic);
+                                value, false, el, dynamic);
+
+                        ELContextImpl ctx = new ELContextImpl();
+                        ctx.setFunctionMapper(getFunctionMapper(el));
+
+                        try {
+                            result.validateEL(this.pageInfo
+                                    .getExpressionFactory(), ctx);
+                        } catch (ELException e) {
+                            this.err.jspError(n.getStart(),
+                                    "jsp.error.invalid.expression", value, e
+                                            .toString());
+                        }
+
                     } else {
-			value = value.replace(Constants.ESC, '$');
+                        value = value.replace(Constants.ESC, '$');
                         result = new Node.JspAttribute(qName, uri, localName,
-						       value, false, null,
-						       dynamic);
+                                value, false, null, dynamic);
                     }
                 }
-            }
-            else {
-                // Value is null.  Check for any NamedAttribute subnodes
+            } else {
+                // Value is null. Check for any NamedAttribute subnodes
                 // that might contain the value for this attribute.
                 // Otherwise, the attribute wasn't found so we return null.
 
-                Node.NamedAttribute namedAttributeNode =
-                    n.getNamedAttributeNode( qName );
-                if( namedAttributeNode != null ) {
-                    result = new Node.JspAttribute(namedAttributeNode,
-						   dynamic);
+                Node.NamedAttribute namedAttributeNode = n
+                        .getNamedAttributeNode(qName);
+                if (namedAttributeNode != null) {
+                    result = new Node.JspAttribute(namedAttributeNode, dynamic);
                 }
             }
 
             return result;
         }
 
-	/*
-	 * Checks to see if the given attribute value represents a runtime or
-	 * EL expression.
-	 */
-	private boolean isExpression(Node n, String value) {
-	    if ((n.getRoot().isXmlSyntax() && value.startsWith("%="))
-		    || (!n.getRoot().isXmlSyntax() && value.startsWith("<%="))
-   		    || (value.indexOf("${") != -1 && !pageInfo.isELIgnored()))
-		return true;
-	    else
-		return false;
-	}
-
-	/*
-	 * Throws exception if the value of the attribute with the given
-	 * name in the given node is given as an RT or EL expression, but the
-	 * spec requires a static value.
-	 */
-	private void throwErrorIfExpression(Node n, String attrName,
-					    String actionName)
-	            throws JasperException {
-	    if (n.getAttributes() != null

[... 766 lines stripped ...]


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org


Mime
View raw message