/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.jasper.compiler;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import jakarta.el.ELException;
import jakarta.el.ExpressionFactory;
import jakarta.el.FunctionMapper;
import jakarta.servlet.jsp.JspFactory;
import jakarta.servlet.jsp.tagext.FunctionInfo;
import jakarta.servlet.jsp.tagext.PageData;
import jakarta.servlet.jsp.tagext.TagAttributeInfo;
import jakarta.servlet.jsp.tagext.TagData;
import jakarta.servlet.jsp.tagext.TagExtraInfo;
import jakarta.servlet.jsp.tagext.TagInfo;
import jakarta.servlet.jsp.tagext.TagLibraryInfo;
import jakarta.servlet.jsp.tagext.ValidationMessage;

import org.apache.jasper.JasperException;
import org.apache.jasper.compiler.ELNode.Text;
import org.apache.jasper.el.ELContextImpl;
import org.apache.tomcat.util.security.Escape;
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 directives) are stored, for
 * later use.
 *
 * @author Kin-man Chung
 * @author Jan Luehe
 * @author Shawn Bayern
 * @author Mark Roth
 */
class Validator {

    /**
     * A visitor to validate and extract page directive info
     */
    private static class DirectiveVisitor extends Node.Visitor {

        private final PageInfo pageInfo;

        private final ErrorDispatcher err;

        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("info"),
            new JspUtil.ValidAttribute("errorPage"),
            new JspUtil.ValidAttribute("isErrorPage"),
            new JspUtil.ValidAttribute("contentType"),
            new JspUtil.ValidAttribute("pageEncoding"),
            new JspUtil.ValidAttribute("isELIgnored"),
            new JspUtil.ValidAttribute("errorOnELNotFound"),
            new JspUtil.ValidAttribute("deferredSyntaxAllowedAsLiteral"),
            new JspUtil.ValidAttribute("trimDirectiveWhitespaces")
        };

        private boolean pageEncodingSeen = false;

        /*
         * Constructor
         */
        DirectiveVisitor(Compiler compiler) {
            this.pageInfo = compiler.getPageInfo();
            this.err = compiler.getErrorDispatcher();
        }

        @Override
        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;
            pageEncodingSeen = false;
            visitBody(n);
            pageEncodingSeen = pageEncodingSeenSave;
        }

        @Override
        public void visit(Node.PageDirective n) throws JasperException {

            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);
                    } 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 ("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 ("errorOnELNotFound".equals(attr)) {
                    if (pageInfo.getErrorOnELNotFound() == null) {
                        pageInfo.setErrorOnELNotFound(value, n, err, true);
                    } else if (!pageInfo.getErrorOnELNotFound().equals(value)) {
                        err.jspError(n, "jsp.error.page.conflict.errorOnELNotFound",
                                pageInfo.getErrorOnELNotFound(), 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;
                    String actual = comparePageEncodings(value, n);
                    n.getRoot().setPageEncoding(actual);
                } 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);
                    }
                }
            }

            // 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());
        }

        @Override
        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) {
                        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 ("errorOnELNotFound".equals(attr)) {
                    if (pageInfo.getErrorOnELNotFound() == null) {
                        pageInfo.setErrorOnELNotFound(value, n, err, false);
                    } else if (!pageInfo.getErrorOnELNotFound().equals(value)) {
                        err.jspError(n, "jsp.error.tag.conflict.errorOnELNotFound",
                                pageInfo.getErrorOnELNotFound(), value);
                    }
                } else if ("pageEncoding".equals(attr)) {
                    if (pageEncodingSeen) {
                        err.jspError(n, "jsp.error.tag.multi.pageencoding");
                    }
                    pageEncodingSeen = true;
                    compareTagEncodings(value, n);
                    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());
        }

        @Override
        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
        }

        @Override
        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
         *
         * @throws JasperException in case of page encoding mismatch
         */
        private String comparePageEncodings(String thePageDirEnc,
                Node.PageDirective pageDir) throws JasperException {

            Node.Root root = pageDir.getRoot();
            String configEnc = root.getJspConfigPageEncoding();
            String pageDirEnc = thePageDirEnc.toUpperCase(Locale.ENGLISH);

            /*
             * 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.
             */
            if (configEnc != null) {
                configEnc = configEnc.toUpperCase(Locale.ENGLISH);
                if (!pageDirEnc.equals(configEnc)
                        && (!pageDirEnc.startsWith("UTF-16") || !configEnc
                                .startsWith("UTF-16"))) {
                    err.jspError(pageDir,
                            "jsp.error.config_pagedir_encoding_mismatch",
                            configEnc, pageDirEnc);
                } else {
                    return configEnc;
                }
            }

            /*
             * 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.
             */
            if ((root.isXmlSyntax() && root.isEncodingSpecifiedInProlog()) || root.isBomPresent()) {
                String pageEnc = root.getPageEncoding().toUpperCase(Locale.ENGLISH);
                if (!pageDirEnc.equals(pageEnc)
                        && (!pageDirEnc.startsWith("UTF-16") || !pageEnc
                                .startsWith("UTF-16"))) {
                    err.jspError(pageDir,
                            "jsp.error.prolog_pagedir_encoding_mismatch",
                            pageEnc, pageDirEnc);
                } else {
                    return pageEnc;
                }
            }

            return pageDirEnc;
        }

        /*
         * Compares page encodings specified in various places, and throws
         * exception in case of page encoding mismatch.
         *
         * @param thePageDirEnc 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 compareTagEncodings(String thePageDirEnc,
                Node.TagDirective pageDir) throws JasperException {

            Node.Root root = pageDir.getRoot();
            String pageDirEnc = thePageDirEnc.toUpperCase(Locale.ENGLISH);
            /*
             * 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.
             */
            if ((root.isXmlSyntax() && root.isEncodingSpecifiedInProlog()) || root.isBomPresent()) {
                String pageEnc = root.getPageEncoding().toUpperCase(Locale.ENGLISH);
                if (!pageDirEnc.equals(pageEnc)
                        && (!pageDirEnc.startsWith("UTF-16") || !pageEnc
                                .startsWith("UTF-16"))) {
                    err.jspError(pageDir,
                            "jsp.error.prolog_pagedir_encoding_mismatch",
                            pageEnc, pageDirEnc);
                }
            }
        }

    }

    /**
     * A visitor for validating nodes other than page directives
     */
    private static class ValidateVisitor extends Node.Visitor {

        // Pattern to extract a method name from a full method signature
        private static final Pattern METHOD_NAME_PATTERN =
                Pattern.compile(".*[ \t\n\r]+(.+?)[ \t\n\r]*\\(.*", Pattern.DOTALL);

        private final PageInfo pageInfo;

        private final ErrorDispatcher err;

        private final ClassLoader loader;

        private final StringBuilder buf = new StringBuilder(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),
                new JspUtil.ValidAttribute("flush") };

        private static final JspUtil.ValidAttribute[] paramActionAttrs = {
                new JspUtil.ValidAttribute("name", true),
                new JspUtil.ValidAttribute("value", true) };

        private static final JspUtil.ValidAttribute[] forwardActionAttrs = {
                new JspUtil.ValidAttribute("page", 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),
                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) };

        private static final JspUtil.ValidAttribute[] attributeAttrs = {
                new JspUtil.ValidAttribute("name", true),
                new JspUtil.ValidAttribute("trim"),
                new JspUtil.ValidAttribute("omit")};

        private static final JspUtil.ValidAttribute[] invokeAttrs = {
                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") };

        private final ExpressionFactory expressionFactory;

        /*
         * Constructor
         */
        ValidateVisitor(Compiler compiler) {
            this.pageInfo = compiler.getPageInfo();
            this.err = compiler.getErrorDispatcher();
            this.loader = compiler.getCompilationContext().getClassLoader();
            // Get the cached EL expression factory for this context
            expressionFactory =
                    JspFactory.getDefaultFactory().getJspApplicationContext(
                    compiler.getCompilationContext().getServletContext()).
                    getExpressionFactory();
        }

        @Override
        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") &&
                    !version.equals("2.1") && !version.equals("2.2") &&
                    !version.equals("2.3") && !version.equals("3.0") &&
                    !version.equals("3.1") && !version.equals("4.0")) {
                err.jspError(n, "jsp.error.jsproot.version.invalid", version);
            }
            visitBody(n);
        }

        @Override
        public void visit(Node.IncludeDirective n) throws JasperException {
            JspUtil.checkAttributes("Include directive", n,
                    includeDirectiveAttrs, err);
            visitBody(n);
        }

        @Override
        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");
            }
        }

        @Override
        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(null, "value", null, null, n
                    .getAttributeValue("value"), n, null, false));
            visitBody(n);
        }

        @Override
        public void visit(Node.IncludeAction n) throws JasperException {
            JspUtil.checkAttributes("Include action", n, includeActionAttrs,
                    err);
            n.setPage(getJspAttribute(null, "page", null, null, n
                    .getAttributeValue("page"), n, null, false));
            visitBody(n);
        }

        @Override
        public void visit(Node.ForwardAction n) throws JasperException {
            JspUtil.checkAttributes("Forward", n, forwardActionAttrs, err);
            n.setPage(getJspAttribute(null, "page", null, null, n
                    .getAttributeValue("page"), n, null, false));
            visitBody(n);
        }

        @Override
        public void visit(Node.GetProperty n) throws JasperException {
            JspUtil.checkAttributes("GetProperty", n, getPropertyAttrs, err);
        }

        @Override
        public void visit(Node.SetProperty n) throws JasperException {
            JspUtil.checkAttributes("SetProperty", n, setPropertyAttrs, err);
            String property = n.getTextAttribute("property");
            String param = n.getTextAttribute("param");
            String value = n.getAttributeValue("value");

            n.setValue(getJspAttribute(null, "value", null, null, value,
                    n, null, false));

            boolean valueSpecified = n.getValue() != null;

            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);
        }

        @Override
        public void visit(Node.UseBean n) throws JasperException {
            JspUtil.checkAttributes("UseBean", n, useBeanAttrs, err);

            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(null, "beanName", null,
                    null, n.getAttributeValue("beanName"), n, null, false);
            n.setBeanName(jattr);
            if (className != null && jattr != null) {
                err.jspError(n, "jsp.error.usebean.notBoth");
            }

            if (className == null) {
                className = type;
            }

            beanInfo.addBean(n, name, className, scope);

            visitBody(n);
        }

        @Override
        public void visit(Node.NamedAttribute n) throws JasperException {
            JspUtil.checkAttributes("Attribute", n, attributeAttrs, err);
            n.setOmit(getJspAttribute(null, "omit", null, null, n
                    .getAttributeValue("omit"), n, null, false));
            visitBody(n);
        }

        @Override
        public void visit(Node.JspBody n) throws JasperException {
            visitBody(n);
        }

        @Override
        public void visit(Node.Declaration n) throws JasperException {
            if (pageInfo.isScriptingInvalid()) {
                err.jspError(n.getStart(), "jsp.error.no.scriptlets");
            }
        }

        @Override
        public void visit(Node.Expression n) throws JasperException {
            if (pageInfo.isScriptingInvalid()) {
                err.jspError(n.getStart(), "jsp.error.no.scriptlets");
            }
        }

        @Override
        public void visit(Node.Scriptlet n) throws JasperException {
            if (pageInfo.isScriptingInvalid()) {
                err.jspError(n.getStart(), "jsp.error.no.scriptlets");
            }
        }

        @Override
        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()) {
                    err.jspError(n, "jsp.error.el.template.deferred");
                } else {
                    return;
                }
            }

            // build expression
            StringBuilder expr = this.getBuffer();
            expr.append(n.getType()).append('{').append(n.getText())
                    .append('}');
            ELNode.Nodes el = ELParser.parse(expr.toString(), pageInfo
                    .isDeferredSyntaxAllowedAsLiteral());

            // validate/prepare expression
            prepareExpression(el, n, expr.toString());

            // store it
            n.setEL(el);
        }

        @Override
        public void visit(Node.UninterpretedTag n) throws JasperException {
            if (n.getNamedAttributeNodes().size() != 0) {
                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++) {
                    // JSP.2.2 - '#{' not allowed in template text
                    String value = attrs.getValue(i);
                    if (!pageInfo.isDeferredSyntaxAllowedAsLiteral()) {
                        if (containsDeferredSyntax(value)) {
                            err.jspError(n, "jsp.error.el.template.deferred");
                        }
                    }
                    jspAttrs[i] = getJspAttribute(null, attrs.getQName(i),
                            attrs.getURI(i), attrs.getLocalName(i), value, n,
                            null, false);
                }
                n.setJspAttributes(jspAttrs);
            }

            visitBody(n);
        }

        /*
         * Look for a #{ sequence that isn't preceded by \.
         */
        private boolean containsDeferredSyntax(String value) {
            if (value == null) {
                return false;
            }

            int i = 0;
            int len = value.length();
            boolean prevCharIsEscape = false;
            while (i < value.length()) {
                char c = value.charAt(i);
                if (c == '#' && (i+1) < len && value.charAt(i+1) == '{' && !prevCharIsEscape) {
                    return true;
                } else if (c == '\\') {
                    prevCharIsEscape = true;
                } else {
                    prevCharIsEscape = false;
                }
                i++;
            }
            return false;
        }

        @SuppressWarnings("null") // tagInfo can't be null after initial test
        @Override
        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 bodycontent 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 (TagAttributeInfo tldAttr : tldAttrs) {
                String attr = null;
                if (attrs != null) {
                    attr = attrs.getValue(tldAttr.getName());
                    if (attr == null) {
                        attr = attrs.getValue(customActionUri, tldAttr
                                .getName());
                    }
                }
                Node.NamedAttribute na = n.getNamedAttributeNode(tldAttr
                        .getName());

                if (tldAttr.isRequired() && attr == null && na == null) {
                    err.jspError(n, "jsp.error.missing_attribute", tldAttr
                            .getName(), n.getLocalName());
                }
                if (attr != null && na != null) {
                    err.jspError(n, "jsp.error.duplicate.name.jspattribute",
                            tldAttr.getName());
                }
            }

            Node.Nodes naNodes = n.getNamedAttributeNodes();
            int jspAttrsSize = naNodes.size() + attrsSize;
            Node.JspAttribute[] jspAttrs = null;
            if (jspAttrsSize > 0) {
                jspAttrs = new Node.JspAttribute[jspAttrsSize];
            }
            Hashtable<String, Object> tagDataAttrs = new Hashtable<>(attrsSize);

            checkXmlAttributes(n, jspAttrs, tagDataAttrs);
            checkNamedAttributes(n, jspAttrs, attrsSize, 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);
        }

        @Override
        public void visit(Node.JspElement n) throws JasperException {

            Attributes attrs = n.getAttributes();
            if (attrs == null) {
                err.jspError(n, "jsp.error.jspelement.missing.name");
            }
            @SuppressWarnings("null") // Exception will have been thrown above
            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(null, attrs.getQName(i),
                            attrs.getURI(i), attrs.getLocalName(i), attrs
                                    .getValue(i), n, null, false));
                } else {
                    if (jspAttrIndex < jspAttrSize) {
                        jspAttrs[jspAttrIndex++] = getJspAttribute(null,
                                attrs.getQName(i), attrs.getURI(i),
                                attrs.getLocalName(i), attrs.getValue(i), n,
                                null, 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, null,
                        false);
            }

            n.setJspAttributes(jspAttrs);

            visitBody(n);
        }

        @Override
        public void visit(Node.JspOutput n) throws JasperException {
            JspUtil.checkAttributes("jsp:output", n, jspOutputAttrs, err);

            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();

            if (omitXmlDecl != null && omitXmlDeclOld != null
                    && !omitXmlDecl.equals(omitXmlDeclOld)) {
                err.jspError(n, "jsp.error.jspoutput.conflict",
                        "omit-xml-declaration", omitXmlDeclOld, omitXmlDecl);
            }

            if (doctypeName != null && doctypeNameOld != null
                    && !doctypeName.equals(doctypeNameOld)) {
                err.jspError(n, "jsp.error.jspoutput.conflict",
                        "doctype-root-element", doctypeNameOld, doctypeName);
            }

            if (doctypePublic != null && doctypePublicOld != null
                    && !doctypePublic.equals(doctypePublicOld)) {
                err.jspError(n, "jsp.error.jspoutput.conflict",
                        "doctype-public", doctypePublicOld, doctypePublic);
            }

            if (doctypeSystem != null && doctypeSystemOld != null
                    && !doctypeSystem.equals(doctypeSystemOld)) {
                err.jspError(n, "jsp.error.jspoutput.conflict",
                        "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.doctypepublicsystem");
            }

            if (omitXmlDecl != null) {
                pageInfo.setOmitXmlDecl(omitXmlDecl);
            }
            if (doctypeName != null) {
                pageInfo.setDoctypeName(doctypeName);
            }
            if (doctypeSystem != null) {
                pageInfo.setDoctypeSystem(doctypeSystem);
            }
            if (doctypePublic != null) {
                pageInfo.setDoctypePublic(doctypePublic);
            }
        }

        @Override
        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 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");
            }
        }

        @Override
        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 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, Map<String, Object> tagDataAttrs)
                throws JasperException {

            TagInfo tagInfo = n.getTagInfo();
            TagAttributeInfo[] tldAttrs = tagInfo.getAttributes();
            Attributes attrs = n.getAttributes();

            for (int i = 0; attrs != null && i < attrs.getLength(); i++) {
                boolean found = false;

                boolean runtimeExpression = ((n.getRoot().isXmlSyntax() && attrs.getValue(i).startsWith("%="))
                        || (!n.getRoot().isXmlSyntax() && attrs.getValue(i).startsWith("<%=")));
                boolean elExpression = false;
                boolean deferred = false;
                double libraryVersion = Double.parseDouble(
                        tagInfo.getTagLibrary().getRequiredVersion());
                boolean deferredSyntaxAllowedAsLiteral =
                    pageInfo.isDeferredSyntaxAllowedAsLiteral() ||
                    libraryVersion < 2.1;

                String xmlAttributeValue = attrs.getValue(i);

                ELNode.Nodes el = null;
                if (!runtimeExpression && !pageInfo.isELIgnored()) {
                    el = ELParser.parse(xmlAttributeValue,
                            deferredSyntaxAllowedAsLiteral);
                    Iterator<ELNode> nodes = el.iterator();
                    while (nodes.hasNext()) {
                        ELNode node = nodes.next();
                        if (node instanceof ELNode.Root) {
                            if (((ELNode.Root) node).getType() == '$') {
                                if (elExpression && deferred) {
                                    err.jspError(n,
                                            "jsp.error.attribute.deferredmix");
                                }
                                elExpression = true;
                            } else if (((ELNode.Root) node).getType() == '#') {
                                if (elExpression && !deferred) {
                                    err.jspError(n,
                                            "jsp.error.attribute.deferredmix");
                                }
                                elExpression = true;
                                deferred = true;
                            }
                        }
                    }
                }

                boolean expression = runtimeExpression || elExpression;

                // When attribute is not an expression,
                // contains its textual value with \$ and \# escaping removed.
                String textAttributeValue;
                if (!elExpression && el != null) {
                    // Should be a single Text node
                    Iterator<ELNode> it = el.iterator();
                    if (it.hasNext()) {
                        textAttributeValue = ((ELNode.Text) it.next())
                                .getText();
                    } else {
                        textAttributeValue = "";
                    }
                } else {
                    textAttributeValue = xmlAttributeValue;
                }
                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()))) {

                        TagAttributeInfo tldAttr = tldAttrs[j];
                        if (tldAttr.canBeRequestTime()
                                || tldAttr.isDeferredMethod() || tldAttr.isDeferredValue()) { // JSP 2.1

                            if (!expression) {

                                String expectedType = null;
                                if (tldAttr.isDeferredMethod()) {
                                    // The String literal must be castable to what is declared as type
                                    // for the attribute
                                    String m = tldAttr.getMethodSignature();
                                    if (m != null) {
                                        m = m.trim();
                                        int rti = m.indexOf(' ');
                                        if (rti > 0) {
                                            expectedType = m.substring(0, rti).trim();
                                        }
                                    } else {
                                        expectedType = "java.lang.Object";
                                    }
                                    if ("void".equals(expectedType)) {
                                        // Can't specify a literal for a
                                        // deferred method with an expected type
                                        // of void - JSP.2.3.4
                                        err.jspError(n,
                                                "jsp.error.literal_with_void",
                                                tldAttr.getName());
                                    }
                                }
                                if (tldAttr.isDeferredValue()) {
                                    // The String literal must be castable to what is declared as type
                                    // for the attribute
                                    expectedType = tldAttr.getExpectedTypeName();
                                }
                                if (expectedType != null) {
                                    Class<?> expectedClass = String.class;
                                    try {
                                        expectedClass = JspUtil.toClass(expectedType, loader);
                                    } catch (ClassNotFoundException e) {
                                        err.jspError
                                            (n, "jsp.error.unknown_attribute_type",
                                             tldAttr.getName(), expectedType);
                                    }
                                    // Check casting - not possible for all types
                                    if (String.class.equals(expectedClass) ||
                                            expectedClass == Long.TYPE ||
                                            expectedClass == Double.TYPE ||
                                            expectedClass == Byte.TYPE ||
                                            expectedClass == Short.TYPE ||
                                            expectedClass == Integer.TYPE ||
                                            expectedClass == Float.TYPE ||
                                            Number.class.isAssignableFrom(expectedClass) ||
                                            Character.class.equals(expectedClass) ||
                                            Character.TYPE == expectedClass ||
                                            Boolean.class.equals(expectedClass) ||
                                            Boolean.TYPE == expectedClass ||
                                            expectedClass.isEnum()) {
                                        try {
                                            expressionFactory.coerceToType(textAttributeValue, expectedClass);
                                        } catch (Exception e) {
                                            err.jspError
                                                (n, "jsp.error.coerce_to_type",
                                                 tldAttr.getName(), expectedType, textAttributeValue);
                                        }
                                    }
                                }

                                jspAttrs[i] = new Node.JspAttribute(tldAttr,
                                        attrs.getQName(i), attrs.getURI(i),
                                        attrs.getLocalName(i),
                                        textAttributeValue, false, null, false);
                            } else {

                                if (deferred && !tldAttr.isDeferredMethod() && !tldAttr.isDeferredValue()) {
                                    // No deferred expressions allowed for this attribute
                                    err.jspError(n, "jsp.error.attribute.custom.non_rt_with_expr",
                                            tldAttr.getName());
                                }
                                if (!deferred && !tldAttr.canBeRequestTime()) {
                                    // Only deferred expressions are allowed for this attribute
                                    err.jspError(n, "jsp.error.attribute.custom.non_rt_with_expr",
                                            tldAttr.getName());
                                }

                                // EL or Runtime expression
                                jspAttrs[i] = getJspAttribute(tldAttr,
                                        attrs.getQName(i), attrs.getURI(i),
                                        attrs.getLocalName(i),
                                        xmlAttributeValue, n, el, false);
                            }

                        } else {
                            // Attribute does not accept any expressions.
                            // Make sure its value does not contain any.
                            if (expression) {
                                err.jspError(n, "jsp.error.attribute.custom.non_rt_with_expr",
                                                tldAttr.getName());
                            }
                            jspAttrs[i] = new Node.JspAttribute(tldAttr,
                                    attrs.getQName(i), attrs.getURI(i),
                                    attrs.getLocalName(i),
                                    textAttributeValue, false, null, false);
                        }
                        if (expression) {
                            tagDataAttrs.put(attrs.getQName(i),
                                    TagData.REQUEST_TIME_VALUE);
                        } else {
                            tagDataAttrs.put(attrs.getQName(i),
                                    textAttributeValue);
                        }
                        found = true;
                        break;
                    }
                }
                if (!found) {
                    if (tagInfo.hasDynamicAttributes()) {
                        jspAttrs[i] = getJspAttribute(null, attrs.getQName(i),
                                attrs.getURI(i), attrs.getLocalName(i),
                                xmlAttributeValue, n, el, 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,
                Map<String, Object> tagDataAttrs)
                throws JasperException {

            TagInfo tagInfo = n.getTagInfo();
            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 (TagAttributeInfo tldAttr : tldAttrs) {
                    /*
                     * 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(tldAttr.getName())
                            && (attrPrefix == null || attrPrefix.length() == 0 || attrPrefix
                            .equals(n.getPrefix()))) {
                        jspAttrs[start + i] = new Node.JspAttribute(na,
                                tldAttr, 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, null,
                                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.
         *
         * @param el EL expression, if already parsed by the caller (so that we
         *  can skip re-parsing it)
         */
        private Node.JspAttribute getJspAttribute(TagAttributeInfo tai,
                String qName, String uri, String localName, String value,
                Node n, ELNode.Nodes el, 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).

            if (value != null) {
                if (n.getRoot().isXmlSyntax() && value.startsWith("%=")) {
                    result = new Node.JspAttribute(tai, qName, uri, localName,
                            value.substring(2, value.length() - 1), true, null,
                            dynamic);
                } else if (!n.getRoot().isXmlSyntax()
                        && value.startsWith("<%=")) {
                    result = new Node.JspAttribute(tai, qName, uri, localName,
                            value.substring(3, value.length() - 2), true, null,
                            dynamic);
                } else {
                    if (!pageInfo.isELIgnored()) {
                        // The attribute can contain expressions but is not a
                        // scriptlet expression; thus, we want to run it through
                        // the expression interpreter

                        // validate expression syntax if string contains
                        // expression(s)
                        if (el == null) {
                            el = ELParser.parse(value,
                                pageInfo.isDeferredSyntaxAllowedAsLiteral());
                        }

                        if (el.containsEL()) {
                            validateFunctions(el, n);
                        } else {
                            // Get text with \$ and \# escaping removed.
                            // Should be a single Text node
                            Iterator<ELNode> it = el.iterator();
                            if (it.hasNext()) {
                                value = ((ELNode.Text) it.next()).getText();
                            } else {
                                value = "";
                            }
                            el = null;
                        }
                    }

                    if (n instanceof Node.UninterpretedTag &&
                            n.getRoot().isXmlSyntax()) {
                        // Attribute values of uninterpreted tags will have been
                        // XML un-escaped during parsing. Since these attributes
                        // are part of an uninterpreted tag the value needs to
                        // be re-escaped before being included in the output.
                        // The wrinkle is that the output of any EL must not be
                        // re-escaped as that must be output as is.
                        if (el != null) {
                            XmlEscapeNonELVisitor v = new XmlEscapeNonELVisitor(
                                    pageInfo.isDeferredSyntaxAllowedAsLiteral());
                            el.visit(v);
                            value = v.getText();
                        } else {
                            value = Escape.xml(value);
                        }
                    }

                    result = new Node.JspAttribute(tai, qName, uri, localName,
                            value, false, el, dynamic);

                    if (el != null) {
                        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 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, tai,
                            dynamic);
                }
            }

            return result;
        }


        private static class XmlEscapeNonELVisitor extends ELParser.TextBuilder {

            protected XmlEscapeNonELVisitor(
                    boolean isDeferredSyntaxAllowedAsLiteral) {
                super(isDeferredSyntaxAllowedAsLiteral);
            }

            @Override
            public void visit(Text n) throws JasperException {
                output.append(ELParser.escapeLiteralExpression(
                        Escape.xml(n.getText()),
                        isDeferredSyntaxAllowedAsLiteral));
            }
        }


        /*
         * Return an empty StringBuilder [not thread-safe]
         */
        private StringBuilder getBuffer() {
            this.buf.setLength(0);
            return this.buf;
        }

        /*
         * Checks to see if the given attribute value represents a runtime or EL
         * expression.
         */
        private boolean isExpression(Node n, String value, boolean checkDeferred) {

            boolean runtimeExpression = ((n.getRoot().isXmlSyntax() && value.startsWith("%="))
                    || (!n.getRoot().isXmlSyntax() && value.startsWith("<%=")));
            boolean elExpression = false;

            if (!runtimeExpression && !pageInfo.isELIgnored()) {
                Iterator<ELNode> nodes = ELParser.parse(value,
                        pageInfo.isDeferredSyntaxAllowedAsLiteral()).iterator();
                while (nodes.hasNext()) {
                    ELNode node = nodes.next();
                    if (node instanceof ELNode.Root) {
                        if (((ELNode.Root) node).getType() == '$') {
                            elExpression = true;
                            break;
                        } else if (checkDeferred && !pageInfo.isDeferredSyntaxAllowedAsLiteral()
                                && ((ELNode.Root) node).getType() == '#') {
                            elExpression = true;
                            break;
                        }
                    }
                }
            }

            return runtimeExpression || elExpression;

        }

        /*
         * 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
                    && n.getAttributes().getValue(attrName) != null
                    && isExpression(n, n.getAttributes().getValue(attrName), true)) {
                err.jspError(n,
                        "jsp.error.attribute.standard.non_rt_with_expr",
                        attrName, actionName);
            }
        }

        private static class NamedAttributeVisitor extends Node.Visitor {
            private boolean hasDynamicContent;

            @Override
            public void doVisit(Node n) throws JasperException {
                if (!(n instanceof Node.JspText)
                        && !(n instanceof Node.TemplateText)) {
                    hasDynamicContent = true;
                }
                visitBody(n);
            }

            public boolean hasDynamicContent() {
                return hasDynamicContent;
            }
        }

        private String findUri(String prefix, Node n) {

            for (Node p = n; p != null; p = p.getParent()) {
                Attributes attrs = p.getTaglibAttributes();
                if (attrs == null) {
                    continue;
                }
                for (int i = 0; i < attrs.getLength(); i++) {
                    String name = attrs.getQName(i);
                    int k = name.indexOf(':');
                    if (prefix == null && k < 0) {
                        // prefix not specified and a default ns found
                        return attrs.getValue(i);
                    }
                    if (prefix != null && k >= 0
                            && prefix.equals(name.substring(k + 1))) {
                        return attrs.getValue(i);
                    }
                }
            }
            return null;
        }

        /**
         * Validate functions in EL expressions
         */
        private void validateFunctions(ELNode.Nodes el, Node n)
                throws JasperException {

            class FVVisitor extends ELNode.Visitor {

                private Node n;

                FVVisitor(Node n) {
                    this.n = n;
                }

                @Override
                public void visit(ELNode.Function func) throws JasperException {
                    String prefix = func.getPrefix();
                    String function = func.getName();
                    String uri = null;

                    if (n.getRoot().isXmlSyntax()) {
                        uri = findUri(prefix, n);
                    } else if (prefix != null) {
                        uri = pageInfo.getURI(prefix);
                    }

                    if (uri == null) {
                        if (prefix == null) {
                            // This can occur when lambda expressions define
                            // functions and when functions are imported. No
                            // longer able to be sure this is an error.
                            return;
                        } else {
                            err.jspError(n, "jsp.error.attribute.invalidPrefix",
                                    prefix);
                        }
                    }
                    TagLibraryInfo taglib = pageInfo.getTaglib(uri);
                    FunctionInfo funcInfo = null;
                    if (taglib != null) {
                        funcInfo = taglib.getFunction(function);
                    }
                    if (funcInfo == null) {
                        err.jspError(n, "jsp.error.noFunction", function);
                    }
                    // Skip TLD function uniqueness check. Done by Schema ?
                    func.setUri(uri);
                    func.setFunctionInfo(funcInfo);
                    processSignature(func);
                }
            }

            el.visit(new FVVisitor(n));
        }

        private void prepareExpression(ELNode.Nodes el, Node n, String expr)
                throws JasperException {
            validateFunctions(el, n);

            // test it out
            ELContextImpl ctx = new ELContextImpl();
            ctx.setFunctionMapper(this.getFunctionMapper(el));
            ExpressionFactory ef = this.pageInfo.getExpressionFactory();
            try {
                ef.createValueExpression(ctx, expr, Object.class);
            } catch (ELException e) {
                throw new JasperException(e);
            }
        }

        private void processSignature(ELNode.Function func)
                throws JasperException {
            func.setMethodName(getMethod(func));
            func.setParameters(getParameters(func));
        }

        /**
         * Get the method name from the signature.
         */
        private String getMethod(ELNode.Function func) throws JasperException {
            FunctionInfo funcInfo = func.getFunctionInfo();
            String signature = funcInfo.getFunctionSignature();

            Matcher m = METHOD_NAME_PATTERN.matcher(signature);
            if (!m.matches()) {
                err.jspError("jsp.error.tld.fn.invalid.signature", func
                        .getPrefix(), func.getName());
            }

            return m.group(1);
        }

        /**
         * Get the parameters types from the function signature.
         *
         * @return An array of parameter class names
         */
        private String[] getParameters(ELNode.Function func)
                throws JasperException {
            FunctionInfo funcInfo = func.getFunctionInfo();
            String signature = funcInfo.getFunctionSignature();
            List<String> params = new ArrayList<>();
            // Signature is of the form
            // <return-type> S <method-name S? '('
            // < <arg-type> ( ',' <arg-type> )* )? ')'
            int start = signature.indexOf('(') + 1;
            boolean lastArg = false;
            while (true) {
                int p = signature.indexOf(',', start);
                if (p < 0) {
                    p = signature.indexOf(')', start);
                    if (p < 0) {
                        err.jspError("jsp.error.tld.fn.invalid.signature", func
                                .getPrefix(), func.getName());
                    }
                    lastArg = true;
                }
                String arg = signature.substring(start, p).trim();
                if (!arg.isEmpty()) {
                    params.add(arg);
                }
                if (lastArg) {
                    break;
                }
                start = p + 1;
            }
            return params.toArray(new String[0]);
        }

        private FunctionMapper getFunctionMapper(ELNode.Nodes el)
                throws JasperException {

            class ValidateFunctionMapper extends FunctionMapper {

                private Map<String, Method> fnmap = new HashMap<>();

                @Override
                public void mapFunction(String prefix, String localName,
                        Method method) {
                    fnmap.put(prefix + ":" + localName, method);
                }

                @Override
                public Method resolveFunction(String prefix, String localName) {
                    return this.fnmap.get(prefix + ":" + localName);
                }
            }

            class MapperELVisitor extends ELNode.Visitor {
                private ValidateFunctionMapper fmapper;

                MapperELVisitor(ValidateFunctionMapper fmapper) {
                    this.fmapper = fmapper;
                }

                @SuppressWarnings("null") // c can't be null after catch block
                @Override
                public void visit(ELNode.Function n) throws JasperException {

                    // Lambda / ImportHandler defined function
                    if (n.getFunctionInfo() == null) {
                        return;
                    }

                    Class<?> c = null;
                    Method method = null;
                    try {
                        c = loader.loadClass(n.getFunctionInfo()
                                .getFunctionClass());
                    } catch (ClassNotFoundException e) {
                        err.jspError("jsp.error.function.classnotfound", n
                                .getFunctionInfo().getFunctionClass(), n
                                .getPrefix()
                                + ':' + n.getName(), e.getMessage());
                    }
                    String paramTypes[] = n.getParameters();
                    int size = paramTypes.length;
                    Class<?> params[] = new Class[size];
                    int i = 0;
                    try {
                        for (i = 0; i < size; i++) {
                            params[i] = JspUtil.toClass(paramTypes[i], loader);
                        }
                        method = c.getDeclaredMethod(n.getMethodName(), params);
                    } catch (ClassNotFoundException e) {
                        err.jspError("jsp.error.signature.classnotfound",
                                paramTypes[i], n.getPrefix() + ':'
                                        + n.getName(), e.getMessage());
                    } catch (NoSuchMethodException e) {
                        err.jspError("jsp.error.noFunctionMethod", n
                                .getMethodName(), n.getName(), c.getName());
                    }
                    fmapper.mapFunction(n.getPrefix(), n.getName(),
                            method);
                }
            }

            ValidateFunctionMapper fmapper = new ValidateFunctionMapper();
            el.visit(new MapperELVisitor(fmapper));
            return fmapper;
        }
    } // End of ValidateVisitor

    /**
     * A visitor for validating TagExtraInfo classes of all tags
     */
    private static class TagExtraInfoVisitor extends Node.Visitor {

        private final ErrorDispatcher err;

        /*
         * Constructor
         */
        TagExtraInfoVisitor(Compiler compiler) {
            this.err = compiler.getErrorDispatcher();
        }

        @Override
        public void visit(Node.CustomTag n) throws JasperException {
            TagInfo tagInfo = n.getTagInfo();
            if (tagInfo == null) {
                err.jspError(n, "jsp.error.missing.tagInfo", n.getQName());
            }

            @SuppressWarnings("null") // tagInfo can't be null here
            ValidationMessage[] errors = tagInfo.validate(n.getTagData());
            if (errors != null && errors.length != 0) {
                StringBuilder errMsg = new StringBuilder();
                errMsg.append("<h3>");
                errMsg.append(Localizer.getMessage(
                        "jsp.error.tei.invalid.attributes", n.getQName()));
                errMsg.append("</h3>");
                for (ValidationMessage error : errors) {
                    errMsg.append("<p>");
                    if (error.getId() != null) {
                        errMsg.append(error.getId());
                        errMsg.append(": ");
                    }
                    errMsg.append(error.getMessage());
                    errMsg.append("</p>");
                }

                err.jspError(n, errMsg.toString());
            }

            visitBody(n);
        }
    }

    public static void validateDirectives(Compiler compiler, Node.Nodes page)
            throws JasperException {
        page.visit(new DirectiveVisitor(compiler));
    }

    public static void validateExDirectives(Compiler compiler, Node.Nodes page)
        throws JasperException {
        // Determine the default output content type
        PageInfo pageInfo = compiler.getPageInfo();
        String contentType = pageInfo.getContentType();

        if (contentType == null || !contentType.contains("charset=")) {
            boolean isXml = page.getRoot().isXmlSyntax();
            String defaultType;
            if (contentType == null) {
                defaultType = isXml ? "text/xml" : "text/html";
            } else {
                defaultType = contentType;
            }

            String charset = null;
            if (isXml) {
                charset = "UTF-8";
            } else {
                if (!page.getRoot().isDefaultPageEncoding()) {
                    charset = page.getRoot().getPageEncoding();
                }
            }

            if (charset != null) {
                pageInfo.setContentType(defaultType + ";charset=" + charset);
            } else {
                pageInfo.setContentType(defaultType);
            }
        }

        /*
         * Validate all other nodes. This validation step includes checking a
         * custom tag's mandatory and optional attributes against information in
         * the TLD (first validation step for custom tags according to
         * JSP.10.5).
         */
        page.visit(new ValidateVisitor(compiler));

        /*
         * Invoke TagLibraryValidator classes of all imported tags (second
         * validation step for custom tags according to JSP.10.5).
         */
        validateXmlView(new PageDataImpl(page, compiler), compiler);

        /*
         * Invoke TagExtraInfo method isValid() for all imported tags (third
         * validation step for custom tags according to JSP.10.5).
         */
        page.visit(new TagExtraInfoVisitor(compiler));

    }

    // *********************************************************************
    // Private (utility) methods

    /**
     * Validate XML view against the TagLibraryValidator classes of all imported
     * tag libraries.
     */
    private static void validateXmlView(PageData xmlView, Compiler compiler)
            throws JasperException {

        StringBuilder errMsg = null;
        ErrorDispatcher errDisp = compiler.getErrorDispatcher();

        for (Object o : compiler.getPageInfo().getTaglibs()) {

            if (!(o instanceof TagLibraryInfoImpl)) {
                continue;
            }
            TagLibraryInfoImpl tli = (TagLibraryInfoImpl) o;

            ValidationMessage[] errors = tli.validate(xmlView);
            if ((errors != null) && (errors.length != 0)) {
                if (errMsg == null) {
                    errMsg = new StringBuilder();
                }
                errMsg.append("<h3>");
                errMsg.append(Localizer.getMessage(
                        "jsp.error.tlv.invalid.page", tli.getShortName(),
                        compiler.getPageInfo().getJspFile()));
                errMsg.append("</h3>");
                for (ValidationMessage error : errors) {
                    if (error != null) {
                        errMsg.append("<p>");
                        errMsg.append(error.getId());
                        errMsg.append(": ");
                        errMsg.append(error.getMessage());
                        errMsg.append("</p>");
                    }
                }
            }
        }

        if (errMsg != null) {
            errDisp.jspError(errMsg.toString());
        }
    }
}
