/*
 * 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.io.CharArrayWriter;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.Serial;
import java.util.Collection;

import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import jakarta.servlet.jsp.tagext.TagFileInfo;
import jakarta.servlet.jsp.tagext.TagInfo;
import jakarta.servlet.jsp.tagext.TagLibraryInfo;

import org.apache.jasper.Constants;
import org.apache.jasper.JasperException;
import org.apache.jasper.JspCompilationContext;
import org.apache.tomcat.Jar;
import org.apache.tomcat.util.descriptor.DigesterFactory;
import org.apache.tomcat.util.descriptor.LocalResolver;
import org.apache.tomcat.util.descriptor.tld.TldResourcePath;
import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.Locator;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
import org.xml.sax.XMLReader;
import org.xml.sax.ext.DefaultHandler2;
import org.xml.sax.ext.EntityResolver2;
import org.xml.sax.helpers.AttributesImpl;

/**
 * Class implementing a parser for a JSP document, that is, a JSP page in XML syntax.
 */
class JspDocumentParser extends DefaultHandler2 implements TagConstants {

    private static final String LEXICAL_HANDLER_PROPERTY = "http://xml.org/sax/properties/lexical-handler";
    private static final String JSP_URI = "http://java.sun.com/JSP/Page";

    private final ParserController parserController;
    private final JspCompilationContext ctxt;
    private final PageInfo pageInfo;
    private final String path;
    private StringBuilder charBuffer;

    // Node representing the XML element currently being parsed
    private Node current;

    /*
     * Outermost (in the nesting hierarchy) node whose body is declared to be scriptless. If a node's body is declared
     * to be scriptless, all its nested nodes must be scriptless, too.
     */
    private Node scriptlessBodyNode;

    private Locator locator;

    // Mark representing the start of the current element. Note
    // that locator.getLineNumber() and locator.getColumnNumber()
    // return the line and column numbers for the character
    // immediately _following_ the current element. The underlying
    // XMl parser eats white space that is not part of character
    // data, so for Nodes that are not created from character data,
    // this is the best we can do. But when we parse character data,
    // we get an accurate starting location by starting with startMark
    // as set by the previous element, and updating it as we advance
    // through the characters.
    private Mark startMark;

    // Flag indicating whether we are inside DTD declarations
    private boolean inDTD;

    private boolean isValidating;
    private final EntityResolver2 entityResolver;

    private final ErrorDispatcher err;
    private final boolean isTagFile;
    private final boolean directivesOnly;
    private boolean isTop;

    // Nesting level of Tag dependent bodies
    private int tagDependentNesting = 0;
    // Flag set to delay incrementing tagDependentNesting until jsp:body
    // is first encountered
    private boolean tagDependentPending = false;

    /*
     * Constructor
     */
    JspDocumentParser(ParserController pc, String path, boolean isTagFile, boolean directivesOnly) {
        this.parserController = pc;
        this.ctxt = pc.getJspCompilationContext();
        this.pageInfo = pc.getCompiler().getPageInfo();
        this.err = pc.getCompiler().getErrorDispatcher();
        this.path = path;
        this.isTagFile = isTagFile;
        this.directivesOnly = directivesOnly;
        this.isTop = true;

        String blockExternalString = ctxt.getServletContext().getInitParameter(Constants.XML_BLOCK_EXTERNAL_INIT_PARAM);
        boolean blockExternal;
        if (blockExternalString == null) {
            blockExternal = true;
        } else {
            blockExternal = Boolean.parseBoolean(blockExternalString);
        }

        this.entityResolver = new LocalResolver(DigesterFactory.SERVLET_API_PUBLIC_IDS,
                DigesterFactory.SERVLET_API_SYSTEM_IDS, blockExternal);
    }

    /*
     * Parses a JSP document by responding to SAX events.
     *
     * @throws JasperException
     */
    public static Node.Nodes parse(ParserController pc, String path, Jar jar, Node parent, boolean isTagFile,
            boolean directivesOnly, String pageEnc, String jspConfigPageEnc, boolean isEncodingSpecifiedInProlog,
            boolean isBomPresent) throws JasperException {

        JspDocumentParser jspDocParser = new JspDocumentParser(pc, path, isTagFile, directivesOnly);
        Node.Nodes pageNodes = null;

        try {

            // Create dummy root and initialize it with given page encodings
            Node.Root dummyRoot = new Node.Root(null, parent, true,
                    pc.getJspCompilationContext().getOptions().getTempVariableNamePrefix());
            dummyRoot.setPageEncoding(pageEnc);
            dummyRoot.setJspConfigPageEncoding(jspConfigPageEnc);
            dummyRoot.setIsEncodingSpecifiedInProlog(isEncodingSpecifiedInProlog);
            dummyRoot.setIsBomPresent(isBomPresent);
            jspDocParser.current = dummyRoot;
            if (parent == null) {
                jspDocParser.addInclude(dummyRoot, jspDocParser.pageInfo.getIncludePrelude());
            } else {
                jspDocParser.isTop = false;
            }

            jspDocParser.isValidating = false;

            // Parse the input
            SAXParser saxParser = getSAXParser(false, jspDocParser);
            InputSource source = JspUtil.getInputSource(path, jar, jspDocParser.ctxt);
            try {
                saxParser.parse(source, jspDocParser);
            } catch (EnableDTDValidationException e) {
                saxParser = getSAXParser(true, jspDocParser);
                jspDocParser.isValidating = true;
                try {
                    source.getByteStream().close();
                } catch (IOException ioe) {
                    // ignore
                }
                source = JspUtil.getInputSource(path, jar, jspDocParser.ctxt);
                saxParser.parse(source, jspDocParser);
            } finally {
                try {
                    source.getByteStream().close();
                } catch (IOException ioe) {
                    // ignore
                }
            }

            if (parent == null) {
                jspDocParser.addInclude(dummyRoot, jspDocParser.pageInfo.getIncludeCoda());
            }

            // Create Node.Nodes from dummy root
            pageNodes = new Node.Nodes(dummyRoot);

        } catch (IOException ioe) {
            jspDocParser.err.jspError(ioe, "jsp.error.data.file.read", path);
        } catch (SAXParseException e) {
            jspDocParser.err.jspError(new Mark(jspDocParser.ctxt, path, e.getLineNumber(), e.getColumnNumber()), e,
                    e.getMessage());
        } catch (Exception e) {
            jspDocParser.err.jspError(e, "jsp.error.data.file.processing", path);
        }

        return pageNodes;
    }

    /*
     * Processes the given list of included files.
     *
     * This is used to implement the include-prelude and include-coda subelements of the jsp-config element in web.xml
     */
    private void addInclude(Node parent, Collection<String> files) throws SAXException {
        if (files != null) {
            for (String file : files) {
                AttributesImpl attrs = new AttributesImpl();
                attrs.addAttribute("", "file", "file", "CDATA", file);

                // Create a dummy Include directive node
                Node includeDir = new Node.IncludeDirective(attrs, null, // XXX
                        parent);
                processIncludeDirective(file, includeDir);
            }
        }
    }


    @Override
    public InputSource getExternalSubset(String name, String baseURI) throws SAXException, IOException {
        return entityResolver.getExternalSubset(name, baseURI);
    }

    @Override
    public InputSource resolveEntity(String publicId, String systemId) throws SAXException, IOException {
        return entityResolver.resolveEntity(publicId, systemId);
    }

    @Override
    public InputSource resolveEntity(String name, String publicId, String baseURI, String systemId)
            throws SAXException, IOException {
        // TODO URLs returned by the Jar abstraction may be of the form jar:jar:
        // which is not a URL that can be resolved by the JRE. This should
        // use the JarFactory to construct and return a valid InputSource.
        return entityResolver.resolveEntity(name, publicId, baseURI, systemId);
    }

    /*
     * Receives notification of the start of an element.
     *
     * This method assigns the given tag attributes to one of 3 buckets:
     *
     * - "xmlns" attributes that represent (standard or custom) tag libraries. - "xmlns" attributes that do not
     * represent tag libraries. - all remaining attributes.
     *
     * For each "xmlns" attribute that represents a custom tag library, the corresponding TagLibraryInfo object is added
     * to the set of custom tag libraries.
     */
    @Override
    public void startElement(String uri, String localName, String qName, Attributes attrs) throws SAXException {

        AttributesImpl taglibAttrs = null;
        AttributesImpl nonTaglibAttrs = null;
        AttributesImpl nonTaglibXmlnsAttrs = null;

        processChars();

        checkPrefixes(uri, qName, attrs);

        if (directivesOnly && !(JSP_URI.equals(uri) && localName.startsWith(DIRECTIVE_ACTION))) {
            return;
        }

        // jsp:text must not have any subelements
        if (current instanceof Node.JspText) {
            throw new SAXParseException(Localizer.getMessage("jsp.error.text.has_subelement"), locator);
        }

        startMark = new Mark(ctxt, path, locator.getLineNumber(), locator.getColumnNumber());

        /*
         * Notice that due to a bug in the underlying SAX parser, the attributes must be enumerated in descending order.
         */
        for (int i = attrs.getLength() - 1; i >= 0; i--) {
            String attrQName = attrs.getQName(i);
            if (!attrQName.startsWith("xmlns")) {
                if (nonTaglibAttrs == null) {
                    nonTaglibAttrs = new AttributesImpl();
                }
                nonTaglibAttrs.addAttribute(attrs.getURI(i), attrs.getLocalName(i), attrs.getQName(i), attrs.getType(i),
                        attrs.getValue(i));
            } else {
                boolean isTaglib;
                if (attrQName.startsWith("xmlns:jsp")) {
                    isTaglib = true;
                } else {
                    String attrUri = attrs.getValue(i);
                    // TaglibInfo for this uri already established in
                    // startPrefixMapping
                    isTaglib = pageInfo.hasTaglib(attrUri);
                }
                if (isTaglib) {
                    if (taglibAttrs == null) {
                        taglibAttrs = new AttributesImpl();
                    }
                    taglibAttrs.addAttribute(attrs.getURI(i), attrs.getLocalName(i), attrs.getQName(i),
                            attrs.getType(i), attrs.getValue(i));
                } else {
                    if (nonTaglibXmlnsAttrs == null) {
                        nonTaglibXmlnsAttrs = new AttributesImpl();
                    }
                    nonTaglibXmlnsAttrs.addAttribute(attrs.getURI(i), attrs.getLocalName(i), attrs.getQName(i),
                            attrs.getType(i), attrs.getValue(i));
                }
            }
        }

        Node node;

        if (tagDependentPending && JSP_URI.equals(uri) && localName.equals(BODY_ACTION)) {
            tagDependentPending = false;
            tagDependentNesting++;
            current =
                    parseStandardAction(qName, localName, nonTaglibAttrs, nonTaglibXmlnsAttrs, taglibAttrs, startMark);
            return;
        }

        if (tagDependentPending && JSP_URI.equals(uri) && localName.equals(ATTRIBUTE_ACTION)) {
            current =
                    parseStandardAction(qName, localName, nonTaglibAttrs, nonTaglibXmlnsAttrs, taglibAttrs, startMark);
            return;
        }

        if (tagDependentPending) {
            tagDependentPending = false;
            tagDependentNesting++;
        }

        if (tagDependentNesting > 0) {
            node = new Node.UninterpretedTag(qName, localName, nonTaglibAttrs, nonTaglibXmlnsAttrs, taglibAttrs,
                    startMark, current);
        } else if (JSP_URI.equals(uri)) {
            node = parseStandardAction(qName, localName, nonTaglibAttrs, nonTaglibXmlnsAttrs, taglibAttrs, startMark);
        } else {
            node = parseCustomAction(qName, localName, uri, nonTaglibAttrs, nonTaglibXmlnsAttrs, taglibAttrs, startMark,
                    current);
            if (node == null) {
                node = new Node.UninterpretedTag(qName, localName, nonTaglibAttrs, nonTaglibXmlnsAttrs, taglibAttrs,
                        startMark, current);
            } else {
                // custom action
                String bodyType = getBodyType((Node.CustomTag) node);

                if (scriptlessBodyNode == null && bodyType.equalsIgnoreCase(TagInfo.BODY_CONTENT_SCRIPTLESS)) {
                    scriptlessBodyNode = node;
                } else if (TagInfo.BODY_CONTENT_TAG_DEPENDENT.equalsIgnoreCase(bodyType)) {
                    tagDependentPending = true;
                }
            }
        }

        current = node;
    }

    /*
     * Receives notification of character data inside an element.
     *
     * The SAX does not call this method with all of the template text, but may invoke this method with chunks of it.
     * This is a problem when we try to determine if the text contains only whitespaces, or when we are looking for an
     * EL expression string. Therefore, it is necessary to buffer and concatenate the chunks and process the
     * concatenated text later (at beginTag and endTag)
     *
     * @param buf The characters
     *
     * @param offset The start position in the character array
     *
     * @param len The number of characters to use from the character array
     *
     * @throws SAXException
     */
    @Override
    public void characters(char[] buf, int offset, int len) {

        if (charBuffer == null) {
            charBuffer = new StringBuilder();
        }
        charBuffer.append(buf, offset, len);
    }

    private void processChars() throws SAXException {

        if (charBuffer == null || directivesOnly) {
            return;
        }

        /*
         * JSP.6.1.1: All textual nodes that have only white space are to be dropped from the document, except for nodes
         * in a jsp:text element, and any leading and trailing white-space-only textual nodes in a jsp:attribute whose
         * 'trim' attribute is set to FALSE, which are to be kept verbatim. <p> JSP.6.2.3 defines white space
         * characters.
         */
        boolean isAllSpace = true;
        if (!(current instanceof Node.JspText) && !(current instanceof Node.NamedAttribute)) {
            for (int i = 0; i < charBuffer.length(); i++) {
                char ch = charBuffer.charAt(i);
                if (!(ch == ' ' || ch == '\n' || ch == '\r' || ch == '\t')) {
                    isAllSpace = false;
                    break;
                }
            }
        }

        if (!isAllSpace && tagDependentPending) {
            tagDependentPending = false;
            tagDependentNesting++;
        }

        if (tagDependentNesting > 0 || pageInfo.isELIgnored() || current instanceof Node.ScriptingElement) {
            if (!charBuffer.isEmpty()) {
                @SuppressWarnings("unused")
                Node unused = new Node.TemplateText(charBuffer.toString(), startMark, current);
            }
            startMark = new Mark(ctxt, path, locator.getLineNumber(), locator.getColumnNumber());
            charBuffer = null;
            return;
        }

        if ((current instanceof Node.JspText) || (current instanceof Node.NamedAttribute) || !isAllSpace) {

            int line = startMark.getLineNumber();
            int column = startMark.getColumnNumber();

            CharArrayWriter ttext = new CharArrayWriter();
            int lastCh = 0;
            int elType;
            for (int i = 0; i < charBuffer.length(); i++) {

                int ch = charBuffer.charAt(i);
                if (ch == '\n') {
                    column = 1;
                    line++;
                } else {
                    column++;
                }
                if ((lastCh == '$' || lastCh == '#') && ch == '{') {
                    elType = lastCh;
                    if (ttext.size() > 0) {
                        @SuppressWarnings("unused")
                        Node unused = new Node.TemplateText(ttext.toString(), startMark, current);
                        ttext.reset();
                        // We subtract two from the column number to
                        // account for the '[$,#]{' that we've already parsed
                        startMark = new Mark(ctxt, path, line, column - 2);
                    }
                    // following "${" || "#{" to first unquoted "}"
                    i++;
                    boolean singleQ = false;
                    boolean doubleQ = false;
                    lastCh = 0;
                    for (;; i++) {
                        if (i >= charBuffer.length()) {
                            throw new SAXParseException(
                                    Localizer.getMessage("jsp.error.unterminated", (char) elType + "{"), locator);

                        }
                        ch = charBuffer.charAt(i);
                        if (ch == '\n') {
                            column = 1;
                            line++;
                        } else {
                            column++;
                        }
                        if (lastCh == '\\' && (singleQ || doubleQ)) {
                            ttext.write(ch);
                            lastCh = 0;
                            continue;
                        }
                        if (ch == '}') {
                            @SuppressWarnings("unused")
                            Node unused = new Node.ELExpression((char) elType, ttext.toString(), startMark, current);
                            ttext.reset();
                            startMark = new Mark(ctxt, path, line, column);
                            break;
                        }
                        if (ch == '"') {
                            doubleQ = !doubleQ;
                        } else if (ch == '\'') {
                            singleQ = !singleQ;
                        }

                        ttext.write(ch);
                        lastCh = ch;
                    }
                } else if (lastCh == '\\' && (ch == '$' || ch == '#')) {
                    if (pageInfo.isELIgnored()) {
                        ttext.write('\\');
                    }
                    ttext.write(ch);
                    ch = 0; // Not start of EL anymore
                } else {
                    if (lastCh == '$' || lastCh == '#' || lastCh == '\\') {
                        ttext.write(lastCh);
                    }
                    if (ch != '$' && ch != '#' && ch != '\\') {
                        ttext.write(ch);
                    }
                }
                lastCh = ch;
            }
            if (lastCh == '$' || lastCh == '#' || lastCh == '\\') {
                ttext.write(lastCh);
            }
            if (ttext.size() > 0) {
                @SuppressWarnings("unused")
                Node unused = new Node.TemplateText(ttext.toString(), startMark, current);
            }
        }
        startMark = new Mark(ctxt, path, locator.getLineNumber(), locator.getColumnNumber());

        charBuffer = null;
    }

    @Override
    public void endElement(String uri, String localName, String qName) throws SAXException {

        processChars();

        if (directivesOnly && !(JSP_URI.equals(uri) && localName.startsWith(DIRECTIVE_ACTION))) {
            return;
        }

        if (current instanceof Node.NamedAttribute) {
            boolean isTrim = ((Node.NamedAttribute) current).isTrim();
            Node.Nodes subElems = current.getBody();
            for (int i = 0; subElems != null && i < subElems.size(); i++) {
                Node subElem = subElems.getNode(i);
                if (!(subElem instanceof Node.TemplateText)) {
                    continue;
                }
                // Ignore any whitespace (including spaces, carriage returns,
                // line feeds, and tabs) that appear at the beginning and at
                // the end of the body of the <jsp:attribute> action, if the
                // action's 'trim' attribute is set to TRUE (default).
                // In addition, any textual nodes in the <jsp:attribute> that
                // have only white space are dropped from the document,
                // except for leading and trailing white-space-only
                // textual nodes in a <jsp:attribute> whose 'trim' attribute
                // is set to FALSE, which must be kept verbatim.
                if (i == 0) {
                    if (isTrim) {
                        ((Node.TemplateText) subElem).ltrim();
                    }
                } else if (i == subElems.size() - 1) {
                    if (isTrim) {
                        ((Node.TemplateText) subElem).rtrim();
                    }
                } else {
                    if (((Node.TemplateText) subElem).isAllSpace()) {
                        subElems.remove(subElem);
                    }
                }
            }
        } else if (current instanceof Node.ScriptingElement) {
            checkScriptingBody((Node.ScriptingElement) current);
        }

        if (isTagDependent(current)) {
            tagDependentNesting--;
        }

        if (current.equals(scriptlessBodyNode)) {
            scriptlessBodyNode = null;
        }

        if (current instanceof Node.CustomTag) {
            String bodyType = getBodyType((Node.CustomTag) current);
            if (TagInfo.BODY_CONTENT_EMPTY.equalsIgnoreCase(bodyType)) {
                // Children - if any - must be JSP attributes
                Node.Nodes children = current.getBody();
                if (children != null && children.size() > 0) {
                    for (int i = 0; i < children.size(); i++) {
                        Node child = children.getNode(i);
                        if (!(child instanceof Node.NamedAttribute)) {
                            throw new SAXParseException(
                                    Localizer.getMessage("jasper.error.emptybodycontent.nonempty", current.qName),
                                    locator);
                        }
                    }
                }
            }
        }
        if (current.getParent() != null) {
            current = current.getParent();
        }
    }

    @Override
    public void setDocumentLocator(Locator locator) {
        this.locator = locator;
    }

    /*
     * See org.xml.sax.ext.LexicalHandler.
     */
    @Override
    public void comment(char[] buf, int offset, int len) throws SAXException {

        processChars(); // Flush char buffer and remove white spaces

        // ignore comments in the DTD
        if (!inDTD) {
            startMark = new Mark(ctxt, path, locator.getLineNumber(), locator.getColumnNumber());
            @SuppressWarnings("unused")
            Node unused = new Node.Comment(new String(buf, offset, len), startMark, current);
        }
    }

    /*
     * See org.xml.sax.ext.LexicalHandler.
     */
    @Override
    public void startCDATA() throws SAXException {

        processChars(); // Flush char buffer and remove white spaces
        startMark = new Mark(ctxt, path, locator.getLineNumber(), locator.getColumnNumber());
    }

    /*
     * See org.xml.sax.ext.LexicalHandler.
     */
    @Override
    public void endCDATA() throws SAXException {
        processChars(); // Flush char buffer and remove white spaces
    }

    /*
     * See org.xml.sax.ext.LexicalHandler.
     */
    @Override
    public void startEntity(String name) throws SAXException {
        // do nothing
    }

    /*
     * See org.xml.sax.ext.LexicalHandler.
     */
    @Override
    public void endEntity(String name) throws SAXException {
        // do nothing
    }

    /*
     * See org.xml.sax.ext.LexicalHandler.
     */
    @Override
    public void startDTD(String name, String publicId, String systemId) throws SAXException {
        if (!isValidating) {
            fatalError(new EnableDTDValidationException("jsp.error.enable_dtd_validation", null));
        }

        inDTD = true;
    }

    /*
     * See org.xml.sax.ext.LexicalHandler.
     */
    @Override
    public void endDTD() throws SAXException {
        inDTD = false;
    }

    @Override
    public void fatalError(SAXParseException e) throws SAXException {
        throw e;
    }

    @Override
    public void error(SAXParseException e) throws SAXException {
        throw e;
    }

    @Override
    public void startPrefixMapping(String prefix, String uri) throws SAXException {
        TagLibraryInfo taglibInfo;

        if (directivesOnly && !(JSP_URI.equals(uri))) {
            return;
        }

        try {
            taglibInfo = getTaglibInfo(prefix, uri);
        } catch (JasperException je) {
            throw new SAXParseException(Localizer.getMessage("jsp.error.could.not.add.taglibraries"), locator, je);
        }

        if (taglibInfo != null) {
            if (pageInfo.getTaglib(uri) == null) {
                pageInfo.addTaglib(uri, taglibInfo);
            }
            pageInfo.pushPrefixMapping(prefix, uri);
        } else {
            pageInfo.pushPrefixMapping(prefix, null);
        }
    }

    @Override
    public void endPrefixMapping(String prefix) throws SAXException {

        if (directivesOnly) {
            String uri = pageInfo.getURI(prefix);
            if (!JSP_URI.equals(uri)) {
                return;
            }
        }

        pageInfo.popPrefixMapping(prefix);
    }

    // *********************************************************************
    // Private utility methods

    private Node parseStandardAction(String qName, String localName, Attributes nonTaglibAttrs,
            Attributes nonTaglibXmlnsAttrs, Attributes taglibAttrs, Mark start) throws SAXException {

        Node node;

        switch (localName) {
            case ROOT_ACTION -> {
                if (!(current instanceof Node.Root)) {
                    throw new SAXParseException(Localizer.getMessage("jsp.error.nested_jsproot"), locator);
                }
                node = new Node.JspRoot(qName, nonTaglibAttrs, nonTaglibXmlnsAttrs, taglibAttrs, start, current);
                if (isTop) {
                    pageInfo.setHasJspRoot(true);
                }
            }
            case PAGE_DIRECTIVE_ACTION -> {
                if (isTagFile) {
                    throw new SAXParseException(Localizer.getMessage("jsp.error.action.istagfile", localName), locator);
                }
                node = new Node.PageDirective(qName, nonTaglibAttrs, nonTaglibXmlnsAttrs, taglibAttrs, start, current);
                String imports = nonTaglibAttrs.getValue("import");
                // There can only be one 'import' attribute per page directive
                if (imports != null) {
                    ((Node.PageDirective) node).addImport(imports);
                }
            }
            case INCLUDE_DIRECTIVE_ACTION -> {
                node = new Node.IncludeDirective(qName, nonTaglibAttrs, nonTaglibXmlnsAttrs, taglibAttrs, start,
                        current);
                processIncludeDirective(nonTaglibAttrs.getValue("file"), node);
            }
            case DECLARATION_ACTION -> {
                if (scriptlessBodyNode != null) {
                    // We're nested inside a node whose body is
                    // declared to be scriptless
                    throw new SAXParseException(Localizer.getMessage("jsp.error.no.scriptlets", localName), locator);
                }
                node = new Node.Declaration(qName, nonTaglibXmlnsAttrs, taglibAttrs, start, current);
            }
            case SCRIPTLET_ACTION -> {
                if (scriptlessBodyNode != null) {
                    // We're nested inside a node whose body is
                    // declared to be scriptless
                    throw new SAXParseException(Localizer.getMessage("jsp.error.no.scriptlets", localName), locator);
                }
                node = new Node.Scriptlet(qName, nonTaglibXmlnsAttrs, taglibAttrs, start, current);
            }
            case EXPRESSION_ACTION -> {
                if (scriptlessBodyNode != null) {
                    // We're nested inside a node whose body is
                    // declared to be scriptless
                    throw new SAXParseException(Localizer.getMessage("jsp.error.no.scriptlets", localName), locator);
                }
                node = new Node.Expression(qName, nonTaglibXmlnsAttrs, taglibAttrs, start, current);
            }
            case USE_BEAN_ACTION ->
                    node = new Node.UseBean(qName, nonTaglibAttrs, nonTaglibXmlnsAttrs, taglibAttrs, start, current);
            case SET_PROPERTY_ACTION ->
                    node = new Node.SetProperty(qName, nonTaglibAttrs, nonTaglibXmlnsAttrs, taglibAttrs, start, current);
            case GET_PROPERTY_ACTION ->
                    node = new Node.GetProperty(qName, nonTaglibAttrs, nonTaglibXmlnsAttrs, taglibAttrs, start, current);
            case INCLUDE_ACTION ->
                    node = new Node.IncludeAction(qName, nonTaglibAttrs, nonTaglibXmlnsAttrs, taglibAttrs, start, current);
            case FORWARD_ACTION ->
                    node = new Node.ForwardAction(qName, nonTaglibAttrs, nonTaglibXmlnsAttrs, taglibAttrs, start, current);
            case PARAM_ACTION ->
                    node = new Node.ParamAction(qName, nonTaglibAttrs, nonTaglibXmlnsAttrs, taglibAttrs, start, current);
            case TEXT_ACTION -> node = new Node.JspText(qName, nonTaglibXmlnsAttrs, taglibAttrs, start, current);
            case BODY_ACTION -> node = new Node.JspBody(qName, nonTaglibXmlnsAttrs, taglibAttrs, start, current);
            case ATTRIBUTE_ACTION ->
                    node = new Node.NamedAttribute(qName, nonTaglibAttrs, nonTaglibXmlnsAttrs, taglibAttrs, start, current);
            case OUTPUT_ACTION ->
                    node = new Node.JspOutput(qName, nonTaglibAttrs, nonTaglibXmlnsAttrs, taglibAttrs, start, current);
            case TAG_DIRECTIVE_ACTION -> {
                if (!isTagFile) {
                    throw new SAXParseException(Localizer.getMessage("jsp.error.action.isnottagfile", localName),
                            locator);
                }
                node = new Node.TagDirective(qName, nonTaglibAttrs, nonTaglibXmlnsAttrs, taglibAttrs, start, current);
                String imports = nonTaglibAttrs.getValue("import");
                // There can only be one 'import' attribute per tag directive
                if (imports != null) {
                    ((Node.TagDirective) node).addImport(imports);
                }
            }
            case ATTRIBUTE_DIRECTIVE_ACTION -> {
                if (!isTagFile) {
                    throw new SAXParseException(Localizer.getMessage("jsp.error.action.isnottagfile", localName),
                            locator);
                }
                node = new Node.AttributeDirective(qName, nonTaglibAttrs, nonTaglibXmlnsAttrs, taglibAttrs, start,
                        current);
            }
            case VARIABLE_DIRECTIVE_ACTION -> {
                if (!isTagFile) {
                    throw new SAXParseException(Localizer.getMessage("jsp.error.action.isnottagfile", localName),
                            locator);
                }
                node = new Node.VariableDirective(qName, nonTaglibAttrs, nonTaglibXmlnsAttrs, taglibAttrs, start,
                        current);
            }
            case INVOKE_ACTION -> {
                if (!isTagFile) {
                    throw new SAXParseException(Localizer.getMessage("jsp.error.action.isnottagfile", localName),
                            locator);
                }
                node = new Node.InvokeAction(qName, nonTaglibAttrs, nonTaglibXmlnsAttrs, taglibAttrs, start, current);
            }
            case DOBODY_ACTION -> {
                if (!isTagFile) {
                    throw new SAXParseException(Localizer.getMessage("jsp.error.action.isnottagfile", localName),
                            locator);
                }
                node = new Node.DoBodyAction(qName, nonTaglibAttrs, nonTaglibXmlnsAttrs, taglibAttrs, start, current);
            }
            case ELEMENT_ACTION ->
                    node = new Node.JspElement(qName, nonTaglibAttrs, nonTaglibXmlnsAttrs, taglibAttrs, start, current);
            default -> throw new SAXParseException(Localizer.getMessage("jsp.error.xml.badStandardAction", localName),
                    locator);
        }

        return node;
    }

    /*
     * Checks if the XML element with the given tag name is a custom action, and returns the corresponding Node object.
     */
    private Node parseCustomAction(String qName, String localName, String uri, Attributes nonTaglibAttrs,
            Attributes nonTaglibXmlnsAttrs, Attributes taglibAttrs, Mark start, Node parent) throws SAXException {

        // Check if this is a user-defined (custom) tag
        TagLibraryInfo tagLibInfo = pageInfo.getTaglib(uri);
        if (tagLibInfo == null) {
            return null;
        }

        TagInfo tagInfo = tagLibInfo.getTag(localName);
        TagFileInfo tagFileInfo = tagLibInfo.getTagFile(localName);
        if (tagInfo == null && tagFileInfo == null) {
            throw new SAXParseException(Localizer.getMessage("jsp.error.xml.bad_tag", localName, uri), locator);
        }
        Class<?> tagHandlerClass = null;
        if (tagInfo != null) {
            String handlerClassName = tagInfo.getTagClassName();
            try {
                tagHandlerClass = ctxt.getClassLoader().loadClass(handlerClassName);
            } catch (Exception e) {
                throw new SAXParseException(
                        Localizer.getMessage("jsp.error.loadclass.taghandler", handlerClassName, qName), locator, e);
            }
        }

        String prefix = getPrefix(qName);

        Node.CustomTag ret;
        if (tagInfo != null) {
            ret = new Node.CustomTag(qName, prefix, localName, uri, nonTaglibAttrs, nonTaglibXmlnsAttrs, taglibAttrs,
                    start, parent, tagInfo, tagHandlerClass);
        } else {
            ret = new Node.CustomTag(qName, prefix, localName, uri, nonTaglibAttrs, nonTaglibXmlnsAttrs, taglibAttrs,
                    start, parent, tagFileInfo);
        }

        return ret;
    }

    /*
     * Creates the tag library associated with the given uri namespace, and returns it.
     *
     * @param prefix The prefix of the xmlns attribute
     *
     * @param uri The uri namespace (value of the xmlns attribute)
     *
     * @return The tag library associated with the given uri namespace
     */
    private TagLibraryInfo getTaglibInfo(String prefix, String uri) throws JasperException {

        TagLibraryInfo result = null;

        if (uri.startsWith(URN_JSPTAGDIR)) {
            // uri (of the form "urn:jsptagdir:path") references tag file dir
            String tagdir = uri.substring(URN_JSPTAGDIR.length());
            result = new ImplicitTagLibraryInfo(ctxt, parserController, pageInfo, prefix, tagdir, err);
        } else {
            // uri references TLD file
            boolean isPlainUri = false;
            if (uri.startsWith(URN_JSPTLD)) {
                // uri is of the form "urn:jsptld:path"
                uri = uri.substring(URN_JSPTLD.length());
            } else {
                isPlainUri = true;
            }

            TldResourcePath tldResourcePath = ctxt.getTldResourcePath(uri);
            if (tldResourcePath != null || !isPlainUri) {
                if (ctxt.getOptions().isCaching()) {
                    result = ctxt.getOptions().getCache().get(uri);
                }
                if (result == null) {
                    /*
                     * If the uri value is a plain uri, a translation error must not be generated if the uri is not
                     * found in the taglib map. Instead, any actions in the namespace defined by the uri value must be
                     * treated as uninterpreted.
                     */
                    result = new TagLibraryInfoImpl(ctxt, parserController, pageInfo, prefix, uri, tldResourcePath,
                            err);
                    if (ctxt.getOptions().isCaching()) {
                        ctxt.getOptions().getCache().put(uri, result);
                    }
                }
            }
        }

        return result;
    }

    /*
     * Ensures that the given body only contains nodes that are instances of TemplateText.
     *
     * This check is performed only for the body of a scripting (that is: declaration, scriptlet, or expression)
     * element, after the end tag of a scripting element has been reached.
     */
    private void checkScriptingBody(Node.ScriptingElement scriptingElem) throws SAXException {
        Node.Nodes body = scriptingElem.getBody();
        if (body != null) {
            int size = body.size();
            for (int i = 0; i < size; i++) {
                Node n = body.getNode(i);
                if (!(n instanceof Node.TemplateText)) {
                    String elemType = SCRIPTLET_ACTION;
                    if (scriptingElem instanceof Node.Declaration) {
                        elemType = DECLARATION_ACTION;
                    }
                    if (scriptingElem instanceof Node.Expression) {
                        elemType = EXPRESSION_ACTION;
                    }
                    String msg = Localizer.getMessage("jsp.error.parse.xml.scripting.invalid.body", elemType);
                    throw new SAXParseException(msg, locator);
                }
            }
        }
    }

    /*
     * Parses the given file included via an include directive.
     *
     * @param fname The path to the included resource, as specified by the 'file' attribute of the include directive
     *
     * @param parent The Node representing the include directive
     */
    private void processIncludeDirective(String fname, Node parent) throws SAXException {

        if (fname == null) {
            return;
        }

        try {
            parserController.parse(fname, parent, null);
        } catch (FileNotFoundException fnfe) {
            throw new SAXParseException(Localizer.getMessage("jsp.error.file.not.found", fname), locator, fnfe);
        } catch (Exception e) {
            throw new SAXParseException(e.getMessage(), locator, e);
        }
    }

    /*
     * Checks an element's given URI, qname, and attributes to see if any of them hijack the 'jsp' prefix, that is, bind
     * it to a namespace other than http://java.sun.com/JSP/Page.
     *
     * @param uri The element's URI
     *
     * @param qName The element's qname
     *
     * @param attrs The element's attributes
     */
    private void checkPrefixes(String uri, String qName, Attributes attrs) {

        checkPrefix(uri, qName);

        int len = attrs.getLength();
        for (int i = 0; i < len; i++) {
            checkPrefix(attrs.getURI(i), attrs.getQName(i));
        }
    }

    /*
     * Checks the given URI and qname to see if they hijack the 'jsp' prefix, which would be the case if qName contained
     * the 'jsp' prefix and uri was different from http://java.sun.com/JSP/Page.
     *
     * @param uri The URI to check
     *
     * @param qName The qname to check
     */
    private void checkPrefix(String uri, String qName) {

        String prefix = getPrefix(qName);
        if (!prefix.isEmpty()) {
            pageInfo.addPrefix(prefix);
            if ("jsp".equals(prefix) && !JSP_URI.equals(uri)) {
                pageInfo.setIsJspPrefixHijacked(true);
            }
        }
    }

    private String getPrefix(String qName) {
        int index = qName.indexOf(':');
        if (index != -1) {
            return qName.substring(0, index);
        }
        return "";
    }

    /*
     * Gets SAXParser.
     *
     * @param validating Indicates whether the requested SAXParser should be validating
     *
     * @param jspDocParser The JSP document parser
     *
     * @return The SAXParser
     */
    private static SAXParser getSAXParser(boolean validating, JspDocumentParser jspDocParser) throws Exception {

        Thread currentThread = Thread.currentThread();
        ClassLoader original = currentThread.getContextClassLoader();
        try {
            currentThread.setContextClassLoader(JspDocumentParser.class.getClassLoader());

            SAXParserFactory factory = SAXParserFactory.newInstance();

            factory.setNamespaceAware(true);
            // Preserve xmlns attributes
            factory.setFeature("http://xml.org/sax/features/namespace-prefixes", true);

            factory.setValidating(validating);
            if (validating) {
                // Enable DTD validation
                factory.setFeature("http://xml.org/sax/features/validation", true);
                // Enable schema validation
                factory.setFeature("http://apache.org/xml/features/validation/schema", true);
            }

            // Configure the parser
            SAXParser saxParser = factory.newSAXParser();
            XMLReader xmlReader = saxParser.getXMLReader();
            xmlReader.setProperty(LEXICAL_HANDLER_PROPERTY, jspDocParser);
            xmlReader.setErrorHandler(jspDocParser);

            return saxParser;
        } finally {
            currentThread.setContextClassLoader(original);
        }
    }

    /*
     * Exception indicating that a DOCTYPE declaration is present, but validation is turned off.
     */
    private static class EnableDTDValidationException extends SAXParseException {

        @Serial
        private static final long serialVersionUID = 1L;

        EnableDTDValidationException(String message, Locator loc) {
            super(message, loc);
        }

        @Override
        public synchronized Throwable fillInStackTrace() {
            // This class does not provide a stack trace
            return this;
        }
    }

    private static String getBodyType(Node.CustomTag custom) {

        if (custom.getTagInfo() != null) {
            return custom.getTagInfo().getBodyContent();
        }

        return custom.getTagFileInfo().getTagInfo().getBodyContent();
    }

    private boolean isTagDependent(Node n) {

        if (n instanceof Node.CustomTag) {
            String bodyType = getBodyType((Node.CustomTag) n);
            return TagInfo.BODY_CONTENT_TAG_DEPENDENT.equalsIgnoreCase(bodyType);
        }
        return false;
    }
}
