/*
 * Copyright 1999,2004 The Apache Software Foundation.
 * 
 * Licensed 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 javax.servlet.jsp.el.FunctionMapper;
import javax.servlet.jsp.tagext.FunctionInfo;
import javax.servlet.jsp.tagext.JspFragment;
import javax.servlet.jsp.tagext.PageData;
import javax.servlet.jsp.tagext.TagAttributeInfo;
import javax.servlet.jsp.tagext.TagData;
import javax.servlet.jsp.tagext.TagExtraInfo;
import javax.servlet.jsp.tagext.TagInfo;
import javax.servlet.jsp.tagext.TagLibraryInfo;
import javax.servlet.jsp.tagext.ValidationMessage;

import org.apache.jasper.Constants;
import org.apache.jasper.JasperException;
import org.apache.jasper.JspCompilationContext;
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.
 *
 * @author Kin-man Chung
 * @author Jan Luehe
 * @author Shawn Bayern
 * @author Mark Roth
 */
class Validator {

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

	private PageInfo pageInfo;
	private 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("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;
            pageEncodingSeen = false;
            visitBody(n);
            pageEncodingSeen = pageEncodingSeenSave;
        }

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

	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 ("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
	}

        /*
         * 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 void comparePageEncodings(String pageDirEnc,
                                          Node.PageDirective pageDir)
                throws JasperException {

            Node.Root root = pageDir.getRoot();
            String configEnc = root.getJspConfigPageEncoding();

            /*
             * 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 && !pageDirEnc.equals(configEnc) 
                    && (!pageDirEnc.startsWith("UTF-16")
                        || !configEnc.startsWith("UTF-16"))) {
                err.jspError(pageDir,
                             "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.
             */
	    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);
                }
            }
        }
    }

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

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

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

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

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

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

            n.setValue(getJspAttribute("value", null, null, value, 
                java.lang.Object.class, n, 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);
	}

	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("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 (className == null)
		className = type;

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

	    visitBody(n);
	}

	public void visit(Node.PlugIn n) throws JasperException {
            JspUtil.checkAttributes("Plugin", n, plugInAttrs, err);

	    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);
            visitBody(n);
	}
        
	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.Expression n) throws JasperException {
	    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);
            }
        }

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

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

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

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

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

	    n.setJspAttributes(jspAttrs);

	    visitBody(n);
	}

	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.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 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 {

            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,
					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()) {
                            Class expectedType = String.class;
                            try {
                                String typeStr = tldAttrs[j].getTypeName();
                                if( tldAttrs[j].isFragment() ) {
                                    expectedType = JspFragment.class;
                                }
                                else if( typeStr != null ) {
                                    expectedType = JspUtil.toClass(typeStr,
								   loader);
                                }
                                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();
            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.
         * <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 {

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

                        
                        result = new Node.JspAttribute(qName, uri, localName,
						       value, false, el,
						       dynamic);
                    } else {
			value = value.replace(Constants.ESC, '$');
                        result = new Node.JspAttribute(qName, uri, localName,
						       value, false, null,
						       dynamic);
                    }
                }
            }
            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);
                }
            }

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

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

	    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 {

		Node n;

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

		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) {
			    err.jspError(n, "jsp.error.noFunctionPrefix",
				function);
			}
			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 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();
	    
	    int start = signature.indexOf(' ');
	    if (start < 0) {
		err.jspError("jsp.error.tld.fn.invalid.signature",
			     func.getPrefix(), func.getName());
	    }
	    int end = signature.indexOf('(');
	    if (end < 0) {
		err.jspError("jsp.error.tld.fn.invalid.signature.parenexpected",
			     func.getPrefix(), func.getName());
	    }
	    return signature.substring(start+1, end).trim();
	}

	/**
	 * 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();
	    ArrayList 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 (!"".equals(arg)) {
                    params.add(arg);
                }
		if (lastArg) {
		    break;
		}
		start = p+1;
	    }
	    return (String[]) params.toArray(new String[params.size()]);
	}

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

	    class ValidateFunctionMapper implements FunctionMapper {

		private HashMap fnmap = new java.util.HashMap();
		public void mapFunction(String fnQName, Method method) {
		    fnmap.put(fnQName, method);
		}

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

	    class MapperELVisitor extends ELNode.Visitor {
		ValidateFunctionMapper fmapper;

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

		public void visit(ELNode.Function n) throws JasperException {

		    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
     */
    static class TagExtraInfoVisitor extends Node.Visitor {

	private PageInfo pageInfo;
	private ErrorDispatcher err;

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

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

	    ValidationMessage[] errors = tagInfo.validate(n.getTagData());
            if (errors != null && errors.length != 0) {
		StringBuffer errMsg = new StringBuffer();
                errMsg.append("<h3>");
                errMsg.append(Localizer.getMessage("jsp.error.tei.invalid.attributes",
						   n.getQName()));
                errMsg.append("</h3>");
                for (int i=0; i<errors.length; i++) {
                    errMsg.append("<p>");
		    if (errors[i].getId() != null) {
			errMsg.append(errors[i].getId());
			errMsg.append(": ");
		    }
                    errMsg.append(errors[i].getMessage());
                    errMsg.append("</p>");
                }

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

	    visitBody(n);
	}
    }

    public static void validate(Compiler compiler,
				Node.Nodes page) throws JasperException {

	/*
	 * Visit the page/tag directives first, as they are global to the page
	 * and are position independent.
	 */
	page.visit(new DirectiveVisitor(compiler));

	// Determine the default output content type
	PageInfo pageInfo = compiler.getPageInfo();
	String contentType = pageInfo.getContentType();

	if (contentType == null || contentType.indexOf("charset=") < 0) {
	    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 {

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

	for (Iterator iter=compiler.getPageInfo().getTaglibs().iterator();
	         iter.hasNext(); ) {

	    Object o = iter.next();
	    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 StringBuffer();
		}
                errMsg.append("<h3>");
                errMsg.append(Localizer.getMessage("jsp.error.tlv.invalid.page",
						   tli.getShortName()));
                errMsg.append("</h3>");
                for (int i=0; i<errors.length; i++) {
		    if (errors[i] != null) {
			errMsg.append("<p>");
			errMsg.append(errors[i].getId());
			errMsg.append(": ");
			errMsg.append(errors[i].getMessage());
			errMsg.append("</p>");
		    }
                }
            }
        }

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

