/*
 * 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.ByteArrayInputStream;
import java.io.CharArrayWriter;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;

import jakarta.servlet.jsp.tagext.PageData;

import org.apache.jasper.JasperException;
import org.apache.tomcat.util.security.Escape;
import org.xml.sax.Attributes;
import org.xml.sax.helpers.AttributesImpl;

/**
 * An implementation of <code>jakarta.servlet.jsp.tagext.PageData</code> which builds the XML view of a given page. The
 * XML view is built in two passes: During the first pass, the FirstPassVisitor collects the attributes of the top-level
 * jsp:root and those of the jsp:root elements of any included pages, and adds them to the jsp:root element of the XML
 * view. In addition, any taglib directives are converted into xmlns: attributes and added to the jsp:root element of
 * the XML view. This pass ignores any nodes other than JspRoot and TaglibDirective. During the second pass, the
 * SecondPassVisitor produces the XML view, using the combined jsp:root attributes determined in the first pass and any
 * remaining pages nodes (this pass ignores any JspRoot and TaglibDirective nodes).
 */
class PageDataImpl extends PageData implements TagConstants {

    private static final String JSP_VERSION = "2.0";
    private static final String CDATA_START_SECTION = "<![CDATA[\n";
    private static final String CDATA_END_SECTION = "]]>\n";

    // string buffer used to build XML view
    private final StringBuilder buf;

    /**
     * @param page     the page nodes from which to generate the XML view
     * @param compiler The compiler for this page
     *
     * @throws JasperException If an error occurs
     */
    PageDataImpl(Node.Nodes page, Compiler compiler) throws JasperException {

        // First pass
        FirstPassVisitor firstPass = new FirstPassVisitor(page.getRoot(), compiler.getPageInfo());
        page.visit(firstPass);

        // Second pass
        buf = new StringBuilder();
        SecondPassVisitor secondPass = new SecondPassVisitor(page.getRoot(), buf, compiler, firstPass.getJspIdPrefix());
        page.visit(secondPass);
    }

    /**
     * Returns the input stream of the XML view.
     *
     * @return the input stream of the XML view
     */
    @Override
    public InputStream getInputStream() {
        return new ByteArrayInputStream(buf.toString().getBytes(StandardCharsets.UTF_8));
    }

    /*
     * First-pass Visitor for JspRoot nodes (representing jsp:root elements) and TaglibDirective nodes, ignoring any
     * other nodes.
     *
     * The purpose of this Visitor is to collect the attributes of the top-level jsp:root and those of the jsp:root
     * elements of any included pages, and add them to the jsp:root element of the XML view. In addition, this Visitor
     * converts any taglib directives into xmlns: attributes and adds them to the jsp:root element of the XML view.
     */
    private static class FirstPassVisitor extends Node.Visitor implements TagConstants {

        private final Node.Root root;
        private final AttributesImpl rootAttrs;
        private final PageInfo pageInfo;

        // Prefix for the 'id' attribute
        private String jspIdPrefix;

        /*
         * Constructor
         */
        FirstPassVisitor(Node.Root root, PageInfo pageInfo) {
            this.root = root;
            this.pageInfo = pageInfo;
            this.rootAttrs = new AttributesImpl();
            this.rootAttrs.addAttribute("", "", "version", "CDATA", JSP_VERSION);
            this.jspIdPrefix = "jsp";
        }

        @Override
        public void visit(Node.Root n) throws JasperException {
            visitBody(n);
            if (n == root) {
                /*
                 * Top-level page.
                 *
                 * Add xmlns:jsp="http://java.sun.com/JSP/Page" attribute only if not already present.
                 */
                if (!JSP_URI.equals(rootAttrs.getValue("xmlns:jsp"))) {
                    rootAttrs.addAttribute("", "", "xmlns:jsp", "CDATA", JSP_URI);
                }

                if (pageInfo.isJspPrefixHijacked()) {
                    /*
                     * 'jsp' prefix has been hijacked, that is, bound to a namespace other than the JSP namespace. This
                     * means that when adding an 'id' attribute to each element, we can't use the 'jsp' prefix.
                     * Therefore, create a new prefix (one that is unique across the translation unit) for use by the
                     * 'id' attribute, and bind it to the JSP namespace
                     */
                    do {
                        jspIdPrefix += "jsp";
                    } while (pageInfo.containsPrefix(jspIdPrefix));
                    rootAttrs.addAttribute("", "", "xmlns:" + jspIdPrefix, "CDATA", JSP_URI);
                }

                root.setAttributes(rootAttrs);
            }
        }

        @Override
        public void visit(Node.JspRoot n) throws JasperException {
            addAttributes(n.getTaglibAttributes());
            addAttributes(n.getNonTaglibXmlnsAttributes());
            addAttributes(n.getAttributes());

            visitBody(n);
        }

        /*
         * Converts taglib directive into "xmlns:..." attribute of jsp:root element.
         */
        @Override
        public void visit(Node.TaglibDirective n) throws JasperException {
            Attributes attrs = n.getAttributes();
            if (attrs != null) {
                String qName = "xmlns:" + attrs.getValue("prefix");
                /*
                 * According to javadocs of org.xml.sax.helpers.AttributesImpl, the addAttribute method does not check
                 * to see if the specified attribute is already contained in the list: This is the application's
                 * responsibility!
                 */
                if (rootAttrs.getIndex(qName) == -1) {
                    String location = attrs.getValue("uri");
                    if (location != null) {
                        if (location.startsWith("/")) {
                            location = URN_JSPTLD + location;
                        }
                        rootAttrs.addAttribute("", "", qName, "CDATA", location);
                    } else {
                        location = attrs.getValue("tagdir");
                        rootAttrs.addAttribute("", "", qName, "CDATA", URN_JSPTAGDIR + location);
                    }
                }
            }
        }

        public String getJspIdPrefix() {
            return jspIdPrefix;
        }

        private void addAttributes(Attributes attrs) {
            if (attrs != null) {
                int len = attrs.getLength();

                for (int i = 0; i < len; i++) {
                    String qName = attrs.getQName(i);
                    if ("version".equals(qName)) {
                        continue;
                    }

                    // Bugzilla 35252: https://bz.apache.org/bugzilla/show_bug.cgi?id=35252
                    if (rootAttrs.getIndex(qName) == -1) {
                        rootAttrs.addAttribute(attrs.getURI(i), attrs.getLocalName(i), qName, attrs.getType(i),
                                attrs.getValue(i));
                    }
                }
            }
        }
    }


    /*
     * Second-pass Visitor responsible for producing XML view and assigning each element a unique jsp:id attribute.
     */
    private static class SecondPassVisitor extends Node.Visitor implements TagConstants {

        private final Node.Root root;
        private final StringBuilder buf;
        private final Compiler compiler;
        private final String jspIdPrefix;
        private boolean resetDefaultNS = false;

        // Current value of jsp:id attribute
        private int jspId;

        /*
         * Constructor
         */
        SecondPassVisitor(Node.Root root, StringBuilder buf, Compiler compiler, String jspIdPrefix) {
            this.root = root;
            this.buf = buf;
            this.compiler = compiler;
            this.jspIdPrefix = jspIdPrefix;
        }

        /*
         * Visits root node.
         */
        @Override
        public void visit(Node.Root n) throws JasperException {
            if (n == this.root) {
                // top-level page
                appendXmlProlog();
                appendTag(n);
            } else {
                boolean resetDefaultNSSave = resetDefaultNS;
                if (n.isXmlSyntax()) {
                    resetDefaultNS = true;
                }
                visitBody(n);
                resetDefaultNS = resetDefaultNSSave;
            }
        }

        /*
         * Visits jsp:root element of JSP page in XML syntax.
         *
         * Any nested jsp:root elements (from pages included via an include directive) are ignored.
         */
        @Override
        public void visit(Node.JspRoot n) throws JasperException {
            visitBody(n);
        }

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

        @Override
        public void visit(Node.IncludeDirective n) throws JasperException {
            // expand in place
            visitBody(n);
        }

        @Override
        public void visit(Node.Comment n) throws JasperException {
            // Comments are ignored in XML view
        }

        @Override
        public void visit(Node.Declaration n) throws JasperException {
            appendTag(n);
        }

        @Override
        public void visit(Node.Expression n) throws JasperException {
            appendTag(n);
        }

        @Override
        public void visit(Node.Scriptlet n) throws JasperException {
            appendTag(n);
        }

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

        @Override
        public void visit(Node.ELExpression n) throws JasperException {
            if (!n.getRoot().isXmlSyntax()) {
                buf.append('<').append(JSP_TEXT_ACTION);
                buf.append(' ');
                buf.append(jspIdPrefix);
                buf.append(":id=\"");
                buf.append(jspId++).append("\">");
            }
            buf.append("${");
            buf.append(Escape.xml(n.getText()));
            buf.append('}');
            if (!n.getRoot().isXmlSyntax()) {
                buf.append(JSP_TEXT_ACTION_END);
            }
            buf.append("\n");
        }

        @Override
        public void visit(Node.IncludeAction n) throws JasperException {
            appendTag(n);
        }

        @Override
        public void visit(Node.ForwardAction n) throws JasperException {
            appendTag(n);
        }

        @Override
        public void visit(Node.GetProperty n) throws JasperException {
            appendTag(n);
        }

        @Override
        public void visit(Node.SetProperty n) throws JasperException {
            appendTag(n);
        }

        @Override
        public void visit(Node.ParamAction n) throws JasperException {
            appendTag(n);
        }

        @Override
        public void visit(Node.UseBean n) throws JasperException {
            appendTag(n);
        }

        @Override
        public void visit(Node.NamedAttribute n) throws JasperException {
            appendTag(n);
        }

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

        @Override
        public void visit(Node.CustomTag n) throws JasperException {
            boolean resetDefaultNSSave = resetDefaultNS;
            appendTag(n, resetDefaultNS);
            resetDefaultNS = resetDefaultNSSave;
        }

        @Override
        public void visit(Node.UninterpretedTag n) throws JasperException {
            boolean resetDefaultNSSave = resetDefaultNS;
            appendTag(n, resetDefaultNS);
            resetDefaultNS = resetDefaultNSSave;
        }

        @Override
        public void visit(Node.JspText n) throws JasperException {
            appendTag(n);
        }

        @Override
        public void visit(Node.DoBodyAction n) throws JasperException {
            appendTag(n);
        }

        @Override
        public void visit(Node.InvokeAction n) throws JasperException {
            appendTag(n);
        }

        @Override
        public void visit(Node.TagDirective n) throws JasperException {
            appendTagDirective(n);
        }

        @Override
        public void visit(Node.AttributeDirective n) throws JasperException {
            appendTag(n);
        }

        @Override
        public void visit(Node.VariableDirective n) throws JasperException {
            appendTag(n);
        }

        @Override
        public void visit(Node.TemplateText n) throws JasperException {
            /*
             * If the template text came from a JSP page written in JSP syntax, create a jsp:text element for it (JSP
             * 5.3.2).
             */
            appendText(n.getText(), !n.getRoot().isXmlSyntax());
        }

        /*
         * Appends the given tag, including its body, to the XML view.
         */
        private void appendTag(Node n) throws JasperException {
            appendTag(n, false);
        }

        /*
         * Appends the given tag, including its body, to the XML view, and optionally reset default namespace to "", if
         * none specified.
         */
        private void appendTag(Node n, boolean addDefaultNS) throws JasperException {

            Node.Nodes body = n.getBody();
            String text = n.getText();

            buf.append('<').append(n.getQName());
            buf.append("\n");

            printAttributes(n, addDefaultNS);
            buf.append("  ").append(jspIdPrefix).append(":id").append("=\"");
            buf.append(jspId++).append("\"\n");

            if (ROOT_ACTION.equals(n.getLocalName()) || body != null || text != null) {
                buf.append(">\n");
                if (ROOT_ACTION.equals(n.getLocalName())) {
                    if (compiler.getCompilationContext().isTagFile()) {
                        appendTagDirective();
                    } else {
                        appendPageDirective();
                    }
                }
                if (body != null) {
                    body.visit(this);
                } else {
                    appendText(text, false);
                }
                buf.append("</").append(n.getQName()).append(">\n");
            } else {
                buf.append("/>\n");
            }
        }

        /*
         * Appends the page directive with the given attributes to the XML view.
         *
         * Since the import attribute of the page directive is the only page attribute that is allowed to appear
         * multiple times within the same document, and since XML allows only single-value attributes, the values of
         * multiple import attributes must be combined into one, separated by comma.
         *
         * If the given page directive contains just 'contentType' and/or 'pageEncoding' attributes, we ignore it, as
         * we've already appended a page directive containing just these two attributes.
         */
        private void appendPageDirective(Node.PageDirective n) {
            boolean append = false;
            Attributes attrs = n.getAttributes();
            int len = (attrs == null) ? 0 : attrs.getLength();
            for (int i = 0; i < len; i++) {
                @SuppressWarnings("null") // If attrs==null, len == 0
                String attrName = attrs.getQName(i);
                if (!"pageEncoding".equals(attrName) && !"contentType".equals(attrName)) {
                    append = true;
                    break;
                }
            }
            if (!append) {
                return;
            }

            buf.append('<').append(n.getQName());
            buf.append("\n");

            // append jsp:id
            buf.append("  ").append(jspIdPrefix).append(":id").append("=\"");
            buf.append(jspId++).append("\"\n");

            // append remaining attributes
            for (int i = 0; i < len; i++) {
                @SuppressWarnings("null") // If attrs==null, len == 0
                String attrName = attrs.getQName(i);
                if ("import".equals(attrName) || "contentType".equals(attrName) || "pageEncoding".equals(attrName)) {
                    /*
                     * Page directive's 'import' attribute is considered further down, and its 'pageEncoding' and
                     * 'contentType' attributes are ignored, since we've already appended a new page directive
                     * containing just these two attributes
                     */
                    continue;
                }
                String value = attrs.getValue(i);
                buf.append("  ").append(attrName).append("=\"");
                buf.append(JspUtil.getExprInXml(value)).append("\"\n");
            }
            if (!n.getImports().isEmpty()) {
                // Concatenate names of imported classes/packages
                boolean first = true;
                for (String i : n.getImports()) {
                    if (first) {
                        first = false;
                        buf.append("  import=\"");
                    } else {
                        buf.append(',');
                    }
                    buf.append(JspUtil.getExprInXml(i));
                }
                buf.append("\"\n");
            }
            buf.append("/>\n");
        }

        /*
         * Appends a page directive with 'pageEncoding' and 'contentType' attributes.
         *
         * The value of the 'pageEncoding' attribute is hard-coded to UTF-8, whereas the value of the 'contentType'
         * attribute, which is identical to what the container will pass to ServletResponse.setContentType(), is derived
         * from the pageInfo.
         */
        private void appendPageDirective() {
            buf.append('<').append(JSP_PAGE_DIRECTIVE_ACTION);
            buf.append("\n");

            // append jsp:id
            buf.append("  ").append(jspIdPrefix).append(":id").append("=\"");
            buf.append(jspId++).append("\"\n");
            buf.append("  ").append("pageEncoding").append("=\"UTF-8\"\n");
            buf.append("  ").append("contentType").append("=\"");
            buf.append(compiler.getPageInfo().getContentType()).append("\"\n");
            buf.append("/>\n");
        }

        /*
         * Appends the tag directive with the given attributes to the XML view.
         *
         * If the given tag directive contains just a 'pageEncoding' attributes, we ignore it, as we've already appended
         * a tag directive containing just this attributes.
         */
        private void appendTagDirective(Node.TagDirective n) throws JasperException {

            boolean append = false;
            Attributes attrs = n.getAttributes();
            int len = (attrs == null) ? 0 : attrs.getLength();
            for (int i = 0; i < len; i++) {
                @SuppressWarnings("null") // If attrs==null, len == 0
                String attrName = attrs.getQName(i);
                if (!"pageEncoding".equals(attrName)) {
                    append = true;
                    break;
                }
            }
            if (!append) {
                return;
            }

            appendTag(n);
        }

        /*
         * Appends a tag directive containing a single 'pageEncoding' attribute whose value is hard-coded to UTF-8.
         */
        private void appendTagDirective() {
            buf.append('<').append(JSP_TAG_DIRECTIVE_ACTION);
            buf.append("\n");

            // append jsp:id
            buf.append("  ").append(jspIdPrefix).append(":id").append("=\"");
            buf.append(jspId++).append("\"\n");
            buf.append("  ").append("pageEncoding").append("=\"UTF-8\"\n");
            buf.append("/>\n");
        }

        private void appendText(String text, boolean createJspTextElement) {
            if (createJspTextElement) {
                buf.append('<').append(JSP_TEXT_ACTION);
                buf.append("\n");

                // append jsp:id
                buf.append("  ").append(jspIdPrefix).append(":id").append("=\"");
                buf.append(jspId++).append("\"\n");
                buf.append(">\n");

                appendCDATA(text);
                buf.append(JSP_TEXT_ACTION_END);
                buf.append("\n");
            } else {
                appendCDATA(text);
            }
        }

        /*
         * Appends the given text as a CDATA section to the XML view, unless the text has already been marked as CDATA.
         */
        private void appendCDATA(String text) {
            buf.append(CDATA_START_SECTION);
            buf.append(escapeCDATA(text));
            buf.append(CDATA_END_SECTION);
        }

        /*
         * Escapes any occurrences of "]]>" (by replacing them with "]]&gt;") within the given text, so it can be
         * included in a CDATA section.
         */
        private String escapeCDATA(String text) {
            if (text == null) {
                return "";
            }
            int len = text.length();
            CharArrayWriter result = new CharArrayWriter(len);
            for (int i = 0; i < len; i++) {
                if (((i + 2) < len) && (text.charAt(i) == ']') && (text.charAt(i + 1) == ']') &&
                        (text.charAt(i + 2) == '>')) {
                    // match found
                    result.write(']');
                    result.write(']');
                    result.write('&');
                    result.write('g');
                    result.write('t');
                    result.write(';');
                    i += 2;
                } else {
                    result.write(text.charAt(i));
                }
            }
            return result.toString();
        }

        /*
         * Appends the attributes of the given Node to the XML view.
         */
        private void printAttributes(Node n, boolean addDefaultNS) {

            /*
             * Append "xmlns" attributes that represent tag libraries
             */
            Attributes attrs = n.getTaglibAttributes();
            int len = (attrs == null) ? 0 : attrs.getLength();
            for (int i = 0; i < len; i++) {
                @SuppressWarnings("null") // If attrs==null, len == 0
                String name = attrs.getQName(i);
                String value = attrs.getValue(i);
                buf.append("  ").append(name).append("=\"").append(value).append("\"\n");
            }

            /*
             * Append "xmlns" attributes that do not represent tag libraries
             */
            attrs = n.getNonTaglibXmlnsAttributes();
            len = (attrs == null) ? 0 : attrs.getLength();
            boolean defaultNSSeen = false;
            for (int i = 0; i < len; i++) {
                @SuppressWarnings("null") // If attrs==null, len == 0
                String name = attrs.getQName(i);
                String value = attrs.getValue(i);
                buf.append("  ").append(name).append("=\"").append(value).append("\"\n");
                defaultNSSeen |= "xmlns".equals(name);
            }
            if (addDefaultNS && !defaultNSSeen) {
                buf.append("  xmlns=\"\"\n");
            }
            resetDefaultNS = false;

            /*
             * Append all other attributes
             */
            attrs = n.getAttributes();
            len = (attrs == null) ? 0 : attrs.getLength();
            for (int i = 0; i < len; i++) {
                @SuppressWarnings("null") // If attrs==null, len == 0
                String name = attrs.getQName(i);
                String value = attrs.getValue(i);
                buf.append("  ").append(name).append("=\"");
                buf.append(JspUtil.getExprInXml(value)).append("\"\n");
            }
        }

        /*
         * Appends XML prolog with encoding declaration.
         */
        private void appendXmlProlog() {
            buf.append("<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n");
        }
    }
}

