node.java

来自「精通tomcat书籍原代码,希望大家共同学习」· Java 代码 · 共 2,370 行 · 第 1/5 页

JAVA
2,370
字号
/*
 * 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.util.Iterator;
import java.util.List;
import java.util.Vector;
import java.util.ArrayList;

import javax.servlet.jsp.tagext.BodyTag;
import javax.servlet.jsp.tagext.DynamicAttributes;
import javax.servlet.jsp.tagext.IterationTag;
import javax.servlet.jsp.tagext.SimpleTag;
import javax.servlet.jsp.tagext.TagAttributeInfo;
import javax.servlet.jsp.tagext.TagData;
import javax.servlet.jsp.tagext.TagFileInfo;
import javax.servlet.jsp.tagext.TagInfo;
import javax.servlet.jsp.tagext.TagVariableInfo;
import javax.servlet.jsp.tagext.TryCatchFinally;
import javax.servlet.jsp.tagext.VariableInfo;

import org.apache.jasper.JasperException;
import org.apache.jasper.compiler.tagplugin.TagPluginContext;
import org.xml.sax.Attributes;


/**
 * An internal data representation of a JSP page or a JSP docuement (XML).
 * Also included here is a visitor class for tranversing nodes.
 *
 * @author Kin-man Chung
 * @author Jan Luehe
 * @author Shawn Bayern
 * @author Mark Roth
 */

abstract class Node implements TagConstants {

    private static final VariableInfo[] ZERO_VARIABLE_INFO = { };
    
    protected Attributes attrs;

    // xmlns attributes that represent tag libraries (only in XML syntax)
    protected Attributes taglibAttrs;

    /*
     * xmlns attributes that do not represent tag libraries
     * (only in XML syntax)
     */
    protected Attributes nonTaglibXmlnsAttrs;

    protected Nodes body;
    protected String text;
    protected Mark startMark;
    protected int beginJavaLine;
    protected int endJavaLine;
    protected Node parent;
    protected Nodes namedAttributeNodes; // cached for performance
    protected String qName;
    protected String localName;
    /*
     * The name of the inner class to which the codes for this node and
     * its body are generated.  For instance, for <jsp:body> in foo.jsp,
     * this is "foo_jspHelper".  This is primarily used for communicating
     * such info from Generator to Smap generator.
     */
    protected String innerClassName;

    private boolean isDummy;

    /**
     * Zero-arg Constructor.
     */
    public Node() {
	this.isDummy = true;
    }

    /**
     * Constructor.
     *
     * @param start The location of the jsp page
     * @param parent The enclosing node
     */
    public Node(Mark start, Node parent) {
	this.startMark = start;
	this.isDummy = (start == null);
	addToParent(parent);
    }

    /**
     * Constructor.
     *
     * @param qName The action's qualified name
     * @param localName The action's local name
     * @param start The location of the jsp page
     * @param parent The enclosing node
     */
    public Node(String qName, String localName, Mark start, Node parent) {
	this.qName = qName;
	this.localName = localName;
	this.startMark = start;
	this.isDummy = (start == null);
	addToParent(parent);
    }

    /**
     * Constructor for Nodes parsed from standard syntax.
     *
     * @param qName The action's qualified name
     * @param localName The action's local name
     * @param attrs The attributes for this node
     * @param start The location of the jsp page
     * @param parent The enclosing node
     */
    public Node(String qName, String localName, Attributes attrs, Mark start,
		Node parent) {
	this.qName = qName;
	this.localName = localName;
	this.attrs = attrs;
	this.startMark = start;
	this.isDummy = (start == null);
	addToParent(parent);
    }

    /**
     * Constructor for Nodes parsed from XML syntax.
     *
     * @param qName The action's qualified name
     * @param localName The action's local name
     * @param attrs The action's attributes whose name does not start with
     * xmlns
     * @param nonTaglibXmlnsAttrs The action's xmlns attributes that do not
     * represent tag libraries
     * @param taglibAttrs The action's xmlns attributes that represent tag
     * libraries
     * @param start The location of the jsp page
     * @param parent The enclosing node
     */
    public Node(String qName, String localName, Attributes attrs,
		Attributes nonTaglibXmlnsAttrs, Attributes taglibAttrs,
		Mark start, Node parent) {
	this.qName = qName;
	this.localName = localName;
	this.attrs = attrs;
	this.nonTaglibXmlnsAttrs = nonTaglibXmlnsAttrs;
	this.taglibAttrs = taglibAttrs;
	this.startMark = start;
	this.isDummy = (start == null);
	addToParent(parent);
    }

    /*
     * Constructor.
     *
     * @param qName The action's qualified name
     * @param localName The action's local name
     * @param text The text associated with this node
     * @param start The location of the jsp page
     * @param parent The enclosing node
     */
    public Node(String qName, String localName, String text, Mark start,
		Node parent) {
	this.qName = qName;
	this.localName = localName;
	this.text = text;
	this.startMark = start;
	this.isDummy = (start == null);
	addToParent(parent);
    }

    public String getQName() {
	return this.qName;
    }

    public String getLocalName() {
	return this.localName;
    }

    /*
     * Gets this Node's attributes.
     *
     * In the case of a Node parsed from standard syntax, this method returns
     * all the Node's attributes.
     *
     * In the case of a Node parsed from XML syntax, this method returns only
     * those attributes whose name does not start with xmlns.
     */
    public Attributes getAttributes() {
	return this.attrs;
    }

    /*
     * Gets this Node's xmlns attributes that represent tag libraries
     * (only meaningful for Nodes parsed from XML syntax)
     */
    public Attributes getTaglibAttributes() {
	return this.taglibAttrs;
    }

    /*
     * Gets this Node's xmlns attributes that do not represent tag libraries
     * (only meaningful for Nodes parsed from XML syntax)
     */
    public Attributes getNonTaglibXmlnsAttributes() {
	return this.nonTaglibXmlnsAttrs;
    }

    public void setAttributes(Attributes attrs) {
	this.attrs = attrs;
    }

    public String getAttributeValue(String name) {
	return (attrs == null) ? null : attrs.getValue(name);
    }

    /**
     * Get the attribute that is non request time expression, either
     * from the attribute of the node, or from a jsp:attrbute 
     */
    public String getTextAttribute(String name) {

	String attr = getAttributeValue(name);
	if (attr != null) {
	    return attr;
	}

	NamedAttribute namedAttribute = getNamedAttributeNode(name);
	if (namedAttribute == null) {
	    return null;
	}

	return namedAttribute.getText();
    }

    /**
     * Searches all subnodes of this node for jsp:attribute standard
     * actions with the given name, and returns the NamedAttribute node
     * of the matching named attribute, nor null if no such node is found.
     * <p>
     * This should always be called and only be called for nodes that
     * accept dynamic runtime attribute expressions.
     */
    public NamedAttribute getNamedAttributeNode( String name ) {
        NamedAttribute result = null;
        
        // Look for the attribute in NamedAttribute children
        Nodes nodes = getNamedAttributeNodes();
        int numChildNodes = nodes.size();
        for( int i = 0; i < numChildNodes; i++ ) {
            NamedAttribute na = (NamedAttribute)nodes.getNode( i );
	    boolean found = false;
	    int index = name.indexOf(':');
	    if (index != -1) {
		// qualified name
		found = na.getName().equals(name);
	    } else {
		found = na.getLocalName().equals(name);
	    }
	    if (found) {
                result = na;
                break;
            }
        }
        
        return result;
    }

    /**
     * Searches all subnodes of this node for jsp:attribute standard
     * actions, and returns that set of nodes as a Node.Nodes object.
     *
     * @return Possibly empty Node.Nodes object containing any jsp:attribute
     * subnodes of this Node
     */
    public Node.Nodes getNamedAttributeNodes() {

	if (namedAttributeNodes != null) {
	    return namedAttributeNodes;
	}

        Node.Nodes result = new Node.Nodes();
        
        // Look for the attribute in NamedAttribute children
        Nodes nodes = getBody();
        if( nodes != null ) {
            int numChildNodes = nodes.size();
            for( int i = 0; i < numChildNodes; i++ ) {
                Node n = nodes.getNode( i );
                if( n instanceof NamedAttribute ) {
                    result.add( n );
                }
                else if (! (n instanceof Comment)) {
                    // Nothing can come before jsp:attribute, and only
                    // jsp:body can come after it.
                    break;
                }
            }
        }

	namedAttributeNodes = result;
        return result;
    }
    
    public Nodes getBody() {
	return body;
    }

    public void setBody(Nodes body) {
	this.body = body;
    }

    public String getText() {
	return text;
    }

    public Mark getStart() {
	return startMark;
    }

    public Node getParent() {
	return parent;
    }

    public int getBeginJavaLine() {
	return beginJavaLine;
    }

    public void setBeginJavaLine(int begin) {
	beginJavaLine = begin;
    }

    public int getEndJavaLine() {
	return endJavaLine;
    }

    public void setEndJavaLine(int end) {
	endJavaLine = end;
    }

    public boolean isDummy() {
	return isDummy;
    }

    public Node.Root getRoot() {
	Node n = this;
	while (!(n instanceof Node.Root)) {
	    n = n.getParent();
	}
	return (Node.Root) n;
    }

    public String getInnerClassName() {
        return innerClassName;
    }

    public void setInnerClassName(String icn) {
        innerClassName = icn;
    }

    /**
     * Selects and invokes a method in the visitor class based on the node
     * type.  This is abstract and should be overrode by the extending classes.
     * @param v The visitor class
     */
    abstract void accept(Visitor v) throws JasperException;


    //*********************************************************************
    // Private utility methods

    /*
     * Adds this Node to the body of the given parent.
     */
    private void addToParent(Node parent) {
	if (parent != null) {
	    this.parent = parent;
	    Nodes parentBody = parent.getBody();
	    if (parentBody == null) {
		parentBody = new Nodes();
		parent.setBody(parentBody);
	    }
	    parentBody.add(this);
	}
    }


    /*********************************************************************
     * Child classes
     */
    
    /**
     * Represents the root of a Jsp page or Jsp document
     */
    public static class Root extends Node {

	private Root parentRoot;
	private boolean isXmlSyntax;

	// Source encoding of the page containing this Root
	private String pageEnc;
	
	// Page encoding specified in JSP config element
	private String jspConfigPageEnc;

	/*
	 * Flag indicating if the default page encoding is being used (only
	 * applicable with standard syntax).
	 *
	 * True if the page does not provide a page directive with a
	 * 'contentType' attribute (or the 'contentType' attribute doesn't
	 * have a CHARSET value), the page does not provide a page directive
	 * with a 'pageEncoding' attribute, and there is no JSP configuration
	 * element page-encoding whose URL pattern matches the page.
	 */
	private boolean isDefaultPageEncoding;

	/*
	 * Indicates whether an encoding has been explicitly specified in the
	 * page's XML prolog (only used for pages in XML syntax).
	 * This information is used to decide whether a translation error must
	 * be reported for encoding conflicts.
	 */
	private boolean isEncodingSpecifiedInProlog;

	/*
	 * Constructor.
	 */
	Root(Mark start, Node parent, boolean isXmlSyntax) {
	    super(start, parent);
	    this.isXmlSyntax = isXmlSyntax;
	    this.qName = JSP_ROOT_ACTION;
	    this.localName = ROOT_ACTION;

	    // Figure out and set the parent root
	    Node r = parent;
	    while ((r != null) && !(r instanceof Node.Root))
		r = r.getParent();
	    parentRoot = (Node.Root) r;
	}

	public void accept(Visitor v) throws JasperException {
	    v.visit(this);
	}

	public boolean isXmlSyntax() {
	    return isXmlSyntax;
	}

	/*
	 * Sets the encoding specified in the JSP config element whose URL
	 * pattern matches the page containing this Root.
	 */
	public void setJspConfigPageEncoding(String enc) {
	    jspConfigPageEnc = enc;
	}

	/*
	 * Gets the encoding specified in the JSP config element whose URL
	 * pattern matches the page containing this Root.
	 */

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?