Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  /*
   * 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;
 
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(s):
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 StringBuilder buf;

    
Constructor.

Parameters:
page the page nodes from which to generate the XML view
 
     public PageDataImpl(Node.Nodes pageCompiler compiler)
 	        throws JasperException {
 
 	// First pass
 	FirstPassVisitor firstPass = new FirstPassVisitor(page.getRoot(),
 							  compiler.getPageInfo());
 	page.visit(firstPass);
 
 	// Second pass
 	 = new StringBuilder();
 	SecondPassVisitor secondPass
 	    = new SecondPassVisitor(page.getRoot(), compiler,
 				    firstPass.getJspIdPrefix());
 	page.visit(secondPass);
     }

    
Returns the input stream of the XML view.

Returns:
the input stream of the XML view
 
     public InputStream getInputStream() {
 	// Turn StringBuilder into InputStream
         try {
             return new ByteArrayInputStream(.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 PageInfo pageInfo;
	// Prefix for the 'id' attribute
	/*
	 * Constructor
	 */
	public FirstPassVisitor(Node.Root rootPageInfo pageInfo) {
	    this. = root;
	    this. = pageInfo;
	    this. = new AttributesImpl();
	    this..addAttribute("""""version""CDATA",
	    this. = "jsp";
	}
	public void visit(Node.Root nthrows JasperException {
	    visitBody(n);
	    if (n == ) {
		/*
		 * Top-level page.
		 *
		 * Add
		 *   xmlns:jsp="http://java.sun.com/JSP/Page"
		 * attribute only if not already present.
		 */
		if (!.equals(.getValue("xmlns:jsp"))) {
		    .addAttribute("""""xmlns:jsp""CDATA",
					   );
		}
		    /*
		     * '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
		     */
		     += "jsp";
		    while (.containsPrefix()) {
			 += "jsp";
		    }
		    .addAttribute("""""xmlns:" + ,
					   "CDATA");
		}
	    }
	}
	public void visit(Node.JspRoot nthrows JasperException {
            addAttributes(n.getNonTaglibXmlnsAttributes());
	    visitBody(n);
	}
	/*
	 * Converts taglib directive into "xmlns:..." attribute of jsp:root
	 * element.
	 */
	public void visit(Node.TaglibDirective nthrows 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 (.getIndex(qName) == -1) {
		    String location = attrs.getValue("uri");
		    if (location != null) {
                        if (location.startsWith("/")) {
                            location =  + location;
                        }
			.addAttribute(""""qName"CDATA",
					       location);
		    } else {
			location = attrs.getValue("tagdir");
			.addAttribute(""""qName"CDATA",
					        + location);
		    }
		}
	    }
	}
	public String getJspIdPrefix() {
	    return ;
	}
	private void addAttributes(Attributes attrs) {
	    if (attrs != null) {
		int len = attrs.getLength();
		for (int i=0; i<leni++) {
                    String qName = attrs.getQName(i);
		    if ("version".equals(qName)) {
			continue;
		    }
                    // Bugzilla 35252: http://issues.apache.org/bugzilla/show_bug.cgi?id=35252
                    if(.getIndex(qName) == -1) {
                        .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 StringBuilder buf;
	private Compiler compiler;
	private boolean resetDefaultNS = false;
	// Current value of jsp:id attribute
	private int jspId;
	/*
	 * Constructor
	 */
				 Compiler compilerString jspIdPrefix) {
	    this. = root;
	    this. = buf;
	    this. = compiler;
	    this. = jspIdPrefix;
	}
	/*
	 * Visits root node.
	 */
	public void visit(Node.Root nthrows JasperException {
	    if (n == this.) {
		// top-level page
	    } else {
		boolean resetDefaultNSSave = ;
		if (n.isXmlSyntax()) {
		     = true;
		}
		 = 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 nthrows JasperException {
	    visitBody(n);
	}
	public void visit(Node.PageDirective nthrows JasperException {
	}
	public void visit(Node.IncludeDirective nthrows JasperException {
	    // expand in place
	    visitBody(n);
	}
	public void visit(Node.Comment nthrows JasperException {
	    // Comments are ignored in XML view
	}
	public void visit(Node.Declaration nthrows JasperException {
	    appendTag(n);
	}
	public void visit(Node.Expression nthrows JasperException {
	    appendTag(n);
	}
	public void visit(Node.Scriptlet nthrows JasperException {
	    appendTag(n);
	}
	public void visit(Node.JspElement nthrows JasperException {
	    appendTag(n);
	}
	public void visit(Node.ELExpression nthrows JasperException {
	    if (!n.getRoot().isXmlSyntax()) {
		.append(" ");
	        .append();
		.append(":id=\"");
	    }
	    .append("${");
            .append(JspUtil.escapeXml(n.getText()));
	    .append("}");
	    if (!n.getRoot().isXmlSyntax()) {
	    }
	    .append("\n");
	}
	public void visit(Node.IncludeAction nthrows JasperException {
	    appendTag(n);
	}
    
	public void visit(Node.ForwardAction nthrows JasperException {
	    appendTag(n);
	}
	public void visit(Node.GetProperty nthrows JasperException {
	    appendTag(n);
	}
	public void visit(Node.SetProperty nthrows JasperException {
	    appendTag(n);
	}
	public void visit(Node.ParamAction nthrows JasperException {
	    appendTag(n);
	}
	public void visit(Node.ParamsAction nthrows JasperException {
	    appendTag(n);
	}
	public void visit(Node.FallBackAction nthrows JasperException {
	    appendTag(n);
	}
	public void visit(Node.UseBean nthrows JasperException {
	    appendTag(n);
	}
	public void visit(Node.PlugIn nthrows JasperException {
	    appendTag(n);
	}
        public void visit(Node.NamedAttribute nthrows JasperException {
            appendTag(n);
        }
        
        public void visit(Node.JspBody nthrows JasperException {
            appendTag(n);
        }
	public void visit(Node.CustomTag nthrows JasperException {
	    boolean resetDefaultNSSave = ;
	     = resetDefaultNSSave;
	}
	public void visit(Node.UninterpretedTag nthrows JasperException {
	    boolean resetDefaultNSSave = ;
	     = resetDefaultNSSave;
	}
	public void visit(Node.JspText nthrows JasperException {
	    appendTag(n);
	}
	public void visit(Node.DoBodyAction nthrows JasperException {
	    appendTag(n);
	}
        public void visit(Node.InvokeAction nthrows JasperException {
	    appendTag(n);
	}
	public void visit(Node.TagDirective nthrows JasperException {
	}
	public void visit(Node.AttributeDirective nthrows JasperException {
	    appendTag(n);
	}
	public void visit(Node.VariableDirective nthrows JasperException {
	    appendTag(n);
	}
        
	public void visit(Node.TemplateText nthrows 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 nthrows JasperException {
	    appendTag(nfalse);
	}
	/*
	 * Appends the given tag, including its body, to the XML view,
	 * and optionally reset default namespace to "", if none specified.
	 */
	private void appendTag(Node nboolean addDefaultNS)
		throws JasperException {
	    Node.Nodes body = n.getBody();
	    String text = n.getText();
	    .append("<").append(n.getQName());
	    .append("\n");
	    printAttributes(naddDefaultNS);
	    .append("  ").append().append(":id").append("=\"");
	    .append(++).append("\"\n");
	    if (.equals(n.getLocalName()) || body != null
		        || text != null) {
		.append(">\n");
		    } else {
		    }
		}
		if (body != null) {
		    body.visit(this);
else {
		    appendText(textfalse);
		}
		.append("</" + n.getQName() + ">\n");
	    } else {
		.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.
	 */
	    boolean append = false;
	    Attributes attrs = n.getAttributes();
	    int len = (attrs == null) ? 0 : attrs.getLength();
	    for (int i=0; i<leni++) {
		String attrName = attrs.getQName(i);
		if (!"pageEncoding".equals(attrName)
		        && !"contentType".equals(attrName)) {
		    append = true;
		    break;
		}
	    }
	    if (!append) {
		return;
	    }
	    .append("<").append(n.getQName());
	    .append("\n");
	    // append jsp:id
	    .append("  ").append().append(":id").append("=\"");
	    .append(++).append("\"\n");
	    // append remaining attributes
	    for (int i=0; i<leni++) {
		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);
		.append("  ").append(attrName).append("=\"");
		.append(JspUtil.getExprInXml(value)).append("\"\n");
	    }
	    if (n.getImports().size() > 0) {
		// Concatenate names of imported classes/packages
		boolean first = true;
		while (iter.hasNext()) {
		    if (first) {
			first = false;
			.append("  import=\"");
		    } else {
			.append(",");
		    }
		    .append(JspUtil.getExprInXml((Stringiter.next()));
		}
		.append("\"\n");
	    }
	    .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() {
	    .append("\n");
	    // append jsp:id
	    .append("  ").append().append(":id").append("=\"");
	    .append(++).append("\"\n");
	    .append("  ").append("pageEncoding").append("=\"UTF-8\"\n");
	    .append("  ").append("contentType").append("=\"");
	    .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.
	 */
	        throws JasperException {
	    boolean append = false;
	    Attributes attrs = n.getAttributes();
	    int len = (attrs == null) ? 0 : attrs.getLength();
	    for (int i=0; i<leni++) {
		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() {
	    .append("\n");
	    // append jsp:id
	    .append("  ").append().append(":id").append("=\"");
	    .append(++).append("\"\n");
	    .append("  ").append("pageEncoding").append("=\"UTF-8\"\n");
	    .append("/>\n");	    
	}
	private void appendText(String textboolean createJspTextElement) {
	    if (createJspTextElement) {
		.append("\n");
		// append jsp:id
		.append("  ").append().append(":id").append("=\"");
		.append(++).append("\"\n");
		.append(">\n");
		.append("\n");
	    } else {
	    }
	}
	/*
	 * 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) {
	    .append(escapeCDATA(text));
	}
	/*
	 * 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) {
            iftext==null ) return "";
	    int len = text.length();
	    CharArrayWriter result = new CharArrayWriter(len);
	    for (int i=0; i<leni++) {
		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 nboolean addDefaultNS) {
	    /*
	     * Append "xmlns" attributes that represent tag libraries
	     */
	    Attributes attrs = n.getTaglibAttributes();
	    int len = (attrs == null) ? 0 : attrs.getLength();
	    for (int i=0; i<leni++) {
		String name = attrs.getQName(i);
		String value = attrs.getValue(i);
		.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<leni++) {
		String name = attrs.getQName(i);
		String value = attrs.getValue(i);
		.append("  ").append(name).append("=\"").append(value).append("\"\n");
		defaultNSSeen |= "xmlns".equals(name);
	    }
	    if (addDefaultNS && !defaultNSSeen) {
		.append("  xmlns=\"\"\n");
	    }
	     = false;
	    /*
	     * Append all other attributes
	     */
	    attrs = n.getAttributes();
	    len = (attrs == null) ? 0 : attrs.getLength();
	    for (int i=0; i<leni++) {
		String name = attrs.getQName(i);
		String value = attrs.getValue(i);
		.append("  ").append(name).append("=\"");
		.append(JspUtil.getExprInXml(value)).append("\"\n");
	    }
	}
	/*
	 * Appends XML prolog with encoding declaration.
	 */
	private void appendXmlProlog() {
	    .append("<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n");
	}
    }
New to GrepCode? Check out our FAQ X