/*
 * Copyright 1999,2004-2005 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.io.InputStream;
import java.io.ByteArrayInputStream;
import java.io.CharArrayWriter;
import java.io.UnsupportedEncodingException;
import java.util.ListIterator;
import javax.servlet.jsp.tagext.PageData;
import org.xml.sax.Attributes;
import org.xml.sax.helpers.AttributesImpl;
import org.apache.jasper.JasperException;

/**
 * An implementation of <tt>javax.servlet.jsp.tagext.PageData</tt> 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).
 *
 * @author Jan Luehe
 */
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 StringBuffer buf;

    /**
     * Constructor.
     *
     * @param page the page nodes from which to generate the XML view
     */
    public 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 StringBuffer();
	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
     */
    public InputStream getInputStream() {
	// Turn StringBuffer into InputStream
        try {
            return new ByteArrayInputStream(buf.toString().getBytes("UTF-8"));
        } catch (UnsupportedEncodingException uee) {
	    // should never happen
            throw new RuntimeException(uee.toString());
        }
    }

    /*
     * First-pass Visitor for JspRoot nodes (representing jsp:root elements)
     * and TablibDirective 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.
     */
    static class FirstPassVisitor
	        extends Node.Visitor implements TagConstants {

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

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

	/*
	 * Constructor
	 */
	public 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";
	}

	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
		     */
		    jspIdPrefix += "jsp";
		    while (pageInfo.containsPrefix(jspIdPrefix)) {
			jspIdPrefix += "jsp";
		    }
		    rootAttrs.addAttribute("", "", "xmlns:" + jspIdPrefix,
					   "CDATA", JSP_URI);
		}

		root.setAttributes(rootAttrs);
	    }
	}

	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.
	 */
	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: http://issues.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.
     */
    static class SecondPassVisitor extends Node.Visitor
        	implements TagConstants {

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

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

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

	/*
	 * Visits root node.
	 */
	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.
	 */
	public void visit(Node.JspRoot n) throws JasperException {
	    visitBody(n);
	}

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

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

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

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

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

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

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

	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(JspUtil.escapeXml(n.getText()));
	    buf.append("}");
	    if (!n.getRoot().isXmlSyntax()) {
		buf.append(JSP_TEXT_ACTION_END);
	    }
	    buf.append("\n");
	}

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

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

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

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

	public void visit(Node.ParamsAction n) throws JasperException {
	    appendTag(n);
	}

	public void visit(Node.FallBackAction n) throws JasperException {
	    appendTag(n);
	}

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

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

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

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

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

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

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

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

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

	public void visit(Node.VariableDirective n) throws JasperException {
	    appendTag(n);
	}
        
	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("</" + n.getQName() + ">\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++) {
		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++) {
		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().size() > 0) {
		// Concatenate names of imported classes/packages
		boolean first = true;
		ListIterator iter = n.getImports().listIterator();
		while (iter.hasNext()) {
		    if (first) {
			first = false;
			buf.append("  import=\"");
		    } else {
			buf.append(",");
		    }
		    buf.append(JspUtil.getExprInXml((String) iter.next()));
		}
		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++) {
		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++) {
		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++) {
		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++) {
		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");
	}
    }
}

