All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.jasper.compiler.PageDataImpl Maven / Gradle / Ivy

There is a newer version: 5.5.23
Show newest version
/*
 * 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 javax.servlet.jsp.tagext.PageData 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
 */

public class PageDataImpl extends PageData implements TagConstants {

    private static final String JSP_NAMESPACE = "http://java.sun.com/JSP/Page";
    private static final String JSP_VERSION = "1.2";
    private static final String CDATA_START_SECTION = "\n";

    // default "xmlns:jsp" and "version" attributes of jsp:root element
    private static AttributesImpl defaultJspRootAttrs;

    // string buffer used to build XML view
    private StringBuffer buf;

    /*
     * Static initializer which sets the "xmlns:jsp" and "version" 
     * attributes of the jsp:root element to their default values.
     */
    static {
        defaultJspRootAttrs = new AttributesImpl();
        defaultJspRootAttrs.addAttribute("", "", "xmlns:jsp", "CDATA",
                                         JSP_NAMESPACE);
        defaultJspRootAttrs.addAttribute("", "", "version", "CDATA",
                                         JSP_VERSION);
    }

    /**
     * Constructor.
     *
     * @param page the page nodes from which to generate the XML view
     */
    public PageDataImpl(Node.Nodes page) throws JasperException {

        // First pass
        FirstPassVisitor firstPassVisitor
            = new FirstPassVisitor(page.getRoot());
        page.visit(firstPassVisitor);

        // Second pass
        buf = new StringBuffer();
        SecondPassVisitor secondPassVisitor
            = new SecondPassVisitor(page.getRoot(), buf);
        page.visit(secondPassVisitor);
    }

    /**
     * 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 {

        private Node.Root root;
        private AttributesImpl rootAttrs;

        /*
         * Constructor
         */
        public FirstPassVisitor(Node.Root root) {
            this.root = root;
            this.rootAttrs = new AttributesImpl(defaultJspRootAttrs);
        }

        public void visit(Node.Root n) throws JasperException {
            visitBody(n);
            root.setAttributes(rootAttrs);
        }

        public void visit(Node.JspRoot n) throws JasperException {
            Attributes attrs = n.getAttributes();
            if (attrs == null) {
                throw new JasperException("Missing attributes in jsp:root");
            }
            int len = attrs.getLength();
            for (int i=0; i\n");
                body.visit(this);
                buf.append("\n");
            } else {
                buf.append("/>\n");
            }
        }

        /*
         * Appends the given tag, including its text body, to the XML view.
         */
        private void appendTag(String tag, Attributes attrs, char[] text)
                    throws JasperException {
            buf.append("<").append(tag);
            buf.append("\n");
            buf.append("  ").append("jsp:id").append("=\"");
            buf.append(jspId++).append("\"\n");
            if (attrs != null) {
                printAttributes(attrs);
            }
            if (text != null) {
                buf.append(">\n");
                appendText(text, false);
                buf.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.
         */
        private void appendPageDirective(Node.PageDirective pageDir) {
            Attributes attrs = pageDir.getAttributes();
            buf.append("<").append(JSP_PAGE_DIRECTIVE_TAG);
            buf.append("\n");

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

            // append remaining attributes
            int len = attrs.getLength();
            for (int i=0; i 0) {
                // Concatenate names of imported classes/packages
                boolean first = true;
                ListIterator iter = pageDir.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");
        }

        private void appendText(char[] text, boolean createJspTextElement) {
            if (createJspTextElement) {
                buf.append(JSP_TEXT_TAG_START);
                appendCDATA(text);
                buf.append(JSP_TEXT_TAG_END);
            } 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(char[] text) {
            buf.append(CDATA_START_SECTION);
            buf.append(escapeCDATA(text));
            buf.append(CDATA_END_SECTION);
        }

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

        /*
         * Appends the given attributes to the XML view.
         */
        private void printAttributes(Attributes attrs) {
            int len = attrs.getLength();
            for (int i=0; i




© 2015 - 2024 Weber Informatics LLC | Privacy Policy