/*
 * 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.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++) {
		    if ("version".equals(attrs.getQName(i))) {
			continue;
		    }
		    rootAttrs.addAttribute(attrs.getURI(i),
					   attrs.getLocalName(i),
					   attrs.getQName(i),
					   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");
	}
    }
}

