Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/Java/Tomcat/java/org/apache/jasper/compiler/   (Apache Software Stiftung Version 2.4.65©)  Datei vom 10.10.2023 mit Größe 77 kB image not shown  

Quelle  Node.java   Sprache: JAVA

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

import java.util.ArrayList;
import java.util.List;

import jakarta.el.ELContext;
import jakarta.el.ELException;
import jakarta.el.ExpressionFactory;
import jakarta.servlet.jsp.tagext.BodyTag;
import jakarta.servlet.jsp.tagext.DynamicAttributes;
import jakarta.servlet.jsp.tagext.IterationTag;
import jakarta.servlet.jsp.tagext.JspIdConsumer;
import jakarta.servlet.jsp.tagext.SimpleTag;
import jakarta.servlet.jsp.tagext.TagAttributeInfo;
import jakarta.servlet.jsp.tagext.TagData;
import jakarta.servlet.jsp.tagext.TagFileInfo;
import jakarta.servlet.jsp.tagext.TagInfo;
import jakarta.servlet.jsp.tagext.TagVariableInfo;
import jakarta.servlet.jsp.tagext.TryCatchFinally;
import jakarta.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 document (XML). Also
 * included here is a visitor class for traversing 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;


    /**
     * Zero-arg Constructor.
     */

    Node() {
    }

    /**
     * Constructor.
     *
     * @param start
     *            The location of the jsp page
     * @param parent
     *            The enclosing node
     */

    Node(Mark start, Node parent) {
        this.startMark = start;
        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
     */

    Node(String qName, String localName, Attributes attrs, Mark start,
            Node parent) {
        this.qName = qName;
        this.localName = localName;
        this.attrs = attrs;
        this.startMark = start;
        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
     */

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

    Node(String qName, String localName, String text, Mark start,
            Node parent) {
        this.qName = qName;
        this.localName = localName;
        this.text = text;
        this.startMark = start;
        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:attribute
     *
     * @param name The name of the attribute
     *
     * @return The attribute value
     */

    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 sub-nodes of this node for jsp:attribute standard actions
     * with the given name.
     * <p>
     * This should always be called and only be called for nodes that accept
     * dynamic runtime attribute expressions.
     *
     * @param name The name of the attribute
     * @return the NamedAttribute node of the matching named attribute, nor null
     *         if no such node is found.
     */

    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 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);
        }
    }


    /**
     * Represents the root of a Jsp page or Jsp document
     */

    public static class Root extends Node {

        private final Root parentRoot;

        private final boolean isXmlSyntax;

        private final String variablePrefix;

        // 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;

        /*
         * Indicates whether an encoding has been explicitly specified in the
         * page's dom.
         */

        private boolean isBomPresent;

        /*
         * Sequence number for temporary variables.
         */

        private int tempSequenceNumber = 0;

        /*
         * Constructor.
         */

        Root(Mark start, Node parent, boolean isXmlSyntax, String variablePrefix) {
            super(start, parent);
            this.isXmlSyntax = isXmlSyntax;
            this.variablePrefix = variablePrefix;
            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;
        }

        @Override
        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.
         */

        public String getJspConfigPageEncoding() {
            return jspConfigPageEnc;
        }

        public void setPageEncoding(String enc) {
            pageEnc = enc;
        }

        public String getPageEncoding() {
            return pageEnc;
        }

        public void setIsDefaultPageEncoding(boolean isDefault) {
            isDefaultPageEncoding = isDefault;
        }

        public boolean isDefaultPageEncoding() {
            return isDefaultPageEncoding;
        }

        public void setIsEncodingSpecifiedInProlog(boolean isSpecified) {
            isEncodingSpecifiedInProlog = isSpecified;
        }

        public boolean isEncodingSpecifiedInProlog() {
            return isEncodingSpecifiedInProlog;
        }

        public void setIsBomPresent(boolean isBom) {
            isBomPresent = isBom;
        }

        public boolean isBomPresent() {
            return isBomPresent;
        }

        /**
         * Generates a new temporary variable name.
         *
         * @return The name to use for the temporary variable
         */

        public String nextTemporaryVariableName() {
            if (parentRoot == null) {
                return variablePrefix + (tempSequenceNumber++);
            } else {
                return parentRoot.nextTemporaryVariableName();
            }

        }
    }

    /**
     * Represents the root of a Jsp document (XML syntax)
     */

    public static class JspRoot extends Node {

        JspRoot(String qName, Attributes attrs,
                Attributes nonTaglibXmlnsAttrs, Attributes taglibAttrs,
                Mark start, Node parent) {
            super(qName, ROOT_ACTION, attrs, nonTaglibXmlnsAttrs, taglibAttrs,
                    start, parent);
        }

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

    /**
     * Represents a page directive
     */

    public static class PageDirective extends Node {

        private final List<String> imports;

        PageDirective(Attributes attrs, Mark start, Node parent) {
            this(JSP_PAGE_DIRECTIVE_ACTION, attrs, nullnull, start, parent);
        }

        PageDirective(String qName, Attributes attrs,
                Attributes nonTaglibXmlnsAttrs, Attributes taglibAttrs,
                Mark start, Node parent) {
            super(qName, PAGE_DIRECTIVE_ACTION, attrs, nonTaglibXmlnsAttrs,
                    taglibAttrs, start, parent);
            imports = new ArrayList<>();
        }

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

        /**
         * Parses the comma-separated list of class or package names in the
         * given attribute value and adds each component to this PageDirective's
         * vector of imported classes and packages.
         *
         * @param value
         *            A comma-separated string of imports.
         */

        public void addImport(String value) {
            int start = 0;
            int index;
            while ((index = value.indexOf(',', start)) != -1) {
                imports.add(validateImport(value.substring(start, index)));
                start = index + 1;
            }
            if (start == 0) {
                // No comma found
                imports.add(validateImport(value));
            } else {
                imports.add(validateImport(value.substring(start)));
            }
        }

        public List<String> getImports() {
            return imports;
        }

        /**
         * Just need enough validation to make sure nothing strange is going on.
         * The compiler will validate this thoroughly when it tries to compile
         * the resulting .java file.
         */

        private String validateImport(String importEntry) {
            // This should either be a fully-qualified class name or a package
            // name with a wildcard
            if (importEntry.indexOf(';') > -1) {
                throw new IllegalArgumentException(
                        Localizer.getMessage("jsp.error.page.invalid.import"));
            }
            return importEntry.trim();
        }
    }

    /**
     * Represents an include directive
     */

    public static class IncludeDirective extends Node {

        IncludeDirective(Attributes attrs, Mark start, Node parent) {
            this(JSP_INCLUDE_DIRECTIVE_ACTION, attrs, nullnull, start, parent);
        }

        IncludeDirective(String qName, Attributes attrs,
                Attributes nonTaglibXmlnsAttrs, Attributes taglibAttrs,
                Mark start, Node parent) {
            super(qName, INCLUDE_DIRECTIVE_ACTION, attrs, nonTaglibXmlnsAttrs,
                    taglibAttrs, start, parent);
        }

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

    /**
     * Represents a custom taglib directive
     */

    public static class TaglibDirective extends Node {

        TaglibDirective(Attributes attrs, Mark start, Node parent) {
            super(JSP_TAGLIB_DIRECTIVE_ACTION, TAGLIB_DIRECTIVE_ACTION, attrs,
                    start, parent);
        }

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

    /**
     * Represents a tag directive
     */

    public static class TagDirective extends Node {
        private final List<String> imports;

        TagDirective(Attributes attrs, Mark start, Node parent) {
            this(JSP_TAG_DIRECTIVE_ACTION, attrs, nullnull, start, parent);
        }

        TagDirective(String qName, Attributes attrs,
                Attributes nonTaglibXmlnsAttrs, Attributes taglibAttrs,
                Mark start, Node parent) {
            super(qName, TAG_DIRECTIVE_ACTION, attrs, nonTaglibXmlnsAttrs,
                    taglibAttrs, start, parent);
            imports = new ArrayList<>();
        }

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

        /**
         * Parses the comma-separated list of class or package names in the
         * given attribute value and adds each component to this PageDirective's
         * vector of imported classes and packages.
         *
         * @param value
         *            A comma-separated string of imports.
         */

        public void addImport(String value) {
            int start = 0;
            int index;
            while ((index = value.indexOf(',', start)) != -1) {
                imports.add(value.substring(start, index).trim());
                start = index + 1;
            }
            if (start == 0) {
                // No comma found
                imports.add(value.trim());
            } else {
                imports.add(value.substring(start).trim());
            }
        }

        public List<String> getImports() {
            return imports;
        }
    }

    /**
     * Represents an attribute directive
     */

    public static class AttributeDirective extends Node {

        AttributeDirective(Attributes attrs, Mark start, Node parent) {
            this(JSP_ATTRIBUTE_DIRECTIVE_ACTION, attrs, nullnull, start,
                    parent);
        }

        AttributeDirective(String qName, Attributes attrs,
                Attributes nonTaglibXmlnsAttrs, Attributes taglibAttrs,
                Mark start, Node parent) {
            super(qName, ATTRIBUTE_DIRECTIVE_ACTION, attrs,
                    nonTaglibXmlnsAttrs, taglibAttrs, start, parent);
        }

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

    /**
     * Represents a variable directive
     */

    public static class VariableDirective extends Node {

        VariableDirective(Attributes attrs, Mark start, Node parent) {
            this(JSP_VARIABLE_DIRECTIVE_ACTION, attrs, nullnull, start,
                    parent);
        }

        VariableDirective(String qName, Attributes attrs,
                Attributes nonTaglibXmlnsAttrs, Attributes taglibAttrs,
                Mark start, Node parent) {
            super(qName, VARIABLE_DIRECTIVE_ACTION, attrs, nonTaglibXmlnsAttrs,
                    taglibAttrs, start, parent);
        }

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

    /**
     * Represents a <jsp:invoke> tag file action
     */

    public static class InvokeAction extends Node {

        InvokeAction(Attributes attrs, Mark start, Node parent) {
            this(JSP_INVOKE_ACTION, attrs, nullnull, start, parent);
        }

        InvokeAction(String qName, Attributes attrs,
                Attributes nonTaglibXmlnsAttrs, Attributes taglibAttrs,
                Mark start, Node parent) {
            super(qName, INVOKE_ACTION, attrs, nonTaglibXmlnsAttrs,
                    taglibAttrs, start, parent);
        }

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

    /**
     * Represents a <jsp:doBody> tag file action
     */

    public static class DoBodyAction extends Node {

        DoBodyAction(Attributes attrs, Mark start, Node parent) {
            this(JSP_DOBODY_ACTION, attrs, nullnull, start, parent);
        }

        DoBodyAction(String qName, Attributes attrs,
                Attributes nonTaglibXmlnsAttrs, Attributes taglibAttrs,
                Mark start, Node parent) {
            super(qName, DOBODY_ACTION, attrs, nonTaglibXmlnsAttrs,
                    taglibAttrs, start, parent);
        }

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

    /**
     * Represents a Jsp comment Comments are kept for completeness.
     */

    public static class Comment extends Node {

        Comment(String text, Mark start, Node parent) {
            super(nullnull, text, start, parent);
        }

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

    /**
     * Represents an expression, declaration, or scriptlet
     */

    public abstract static class ScriptingElement extends Node {

        ScriptingElement(String qName, String localName, String text,
                Mark start, Node parent) {
            super(qName, localName, text, start, parent);
        }

        ScriptingElement(String qName, String localName,
                Attributes nonTaglibXmlnsAttrs, Attributes taglibAttrs,
                Mark start, Node parent) {
            super(qName, localName, null, nonTaglibXmlnsAttrs, taglibAttrs,
                    start, parent);
        }

        /**
         * When this node was created from a JSP page in JSP syntax, its text
         * was stored as a String in the "text" field, whereas when this node
         * was created from a JSP document, its text was stored as one or more
         * TemplateText nodes in its body. This method handles either case.
         *
         * @return The text string
         */

        @Override
        public String getText() {
            String ret = text;
            if (ret == null) {
                if (body != null) {
                    StringBuilder buf = new StringBuilder();
                    for (int i = 0; i < body.size(); i++) {
                        buf.append(body.getNode(i).getText());
                    }
                    ret = buf.toString();
                } else {
                    // Nulls cause NPEs further down the line
                    ret = "";
                }
            }
            return ret;
        }

        /**
         * For the same reason as above, the source line information in the
         * contained TemplateText node should be used.
         */

        @Override
        public Mark getStart() {
            if (text == null && body != null && body.size() > 0) {
                return body.getNode(0).getStart();
            } else {
                return super.getStart();
            }
        }
    }

    /**
     * Represents a declaration
     */

    public static class Declaration extends ScriptingElement {

        Declaration(String text, Mark start, Node parent) {
            super(JSP_DECLARATION_ACTION, DECLARATION_ACTION, text, start,
                    parent);
        }

        Declaration(String qName, Attributes nonTaglibXmlnsAttrs,
                Attributes taglibAttrs, Mark start, Node parent) {
            super(qName, DECLARATION_ACTION, nonTaglibXmlnsAttrs, taglibAttrs,
                    start, parent);
        }

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

    /**
     * Represents an expression. Expressions in attributes are embedded in the
     * attribute string and not here.
     */

    public static class Expression extends ScriptingElement {

        Expression(String text, Mark start, Node parent) {
            super(JSP_EXPRESSION_ACTION, EXPRESSION_ACTION, text, start, parent);
        }

        Expression(String qName, Attributes nonTaglibXmlnsAttrs,
                Attributes taglibAttrs, Mark start, Node parent) {
            super(qName, EXPRESSION_ACTION, nonTaglibXmlnsAttrs, taglibAttrs,
                    start, parent);
        }

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

    /**
     * Represents a scriptlet
     */

    public static class Scriptlet extends ScriptingElement {

        Scriptlet(String text, Mark start, Node parent) {
            super(JSP_SCRIPTLET_ACTION, SCRIPTLET_ACTION, text, start, parent);
        }

        Scriptlet(String qName, Attributes nonTaglibXmlnsAttrs,
                Attributes taglibAttrs, Mark start, Node parent) {
            super(qName, SCRIPTLET_ACTION, nonTaglibXmlnsAttrs, taglibAttrs,
                    start, parent);
        }

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

    /**
     * Represents an EL expression. Expressions in attributes are embedded in
     * the attribute string and not here.
     */

    public static class ELExpression extends Node {

        private ELNode.Nodes el;

        private final char type;

        ELExpression(char type, String text, Mark start, Node parent) {
            super(nullnull, text, start, parent);
            this.type = type;
        }

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

        public void setEL(ELNode.Nodes el) {
            this.el = el;
        }

        public ELNode.Nodes getEL() {
            return el;
        }

        public char getType() {
            return this.type;
        }
    }

    /**
     * Represents a param action
     */

    public static class ParamAction extends Node {

        private JspAttribute value;

        ParamAction(Attributes attrs, Mark start, Node parent) {
            this(JSP_PARAM_ACTION, attrs, nullnull, start, parent);
        }

        ParamAction(String qName, Attributes attrs,
                Attributes nonTaglibXmlnsAttrs, Attributes taglibAttrs,
                Mark start, Node parent) {
            super(qName, PARAM_ACTION, attrs, nonTaglibXmlnsAttrs, taglibAttrs,
                    start, parent);
        }

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

        public void setValue(JspAttribute value) {
            this.value = value;
        }

        public JspAttribute getValue() {
            return value;
        }
    }

    /**
     * Represents a params action
     */

    public static class ParamsAction extends Node {

        ParamsAction(Mark start, Node parent) {
            this(JSP_PARAMS_ACTION, nullnull, start, parent);
        }

        ParamsAction(String qName, Attributes nonTaglibXmlnsAttrs,
                Attributes taglibAttrs, Mark start, Node parent) {
            super(qName, PARAMS_ACTION, null, nonTaglibXmlnsAttrs, taglibAttrs,
                    start, parent);
        }

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

    /**
     * Represents a fallback action
     */

    public static class FallBackAction extends Node {

        FallBackAction(Mark start, Node parent) {
            this(JSP_FALLBACK_ACTION, nullnull, start, parent);
        }

        FallBackAction(String qName, Attributes nonTaglibXmlnsAttrs,
                Attributes taglibAttrs, Mark start, Node parent) {
            super(qName, FALLBACK_ACTION, null, nonTaglibXmlnsAttrs,
                    taglibAttrs, start, parent);
        }

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

    /**
     * Represents an include action
     */

    public static class IncludeAction extends Node {

        private JspAttribute page;

        IncludeAction(Attributes attrs, Mark start, Node parent) {
            this(JSP_INCLUDE_ACTION, attrs, nullnull, start, parent);
        }

        IncludeAction(String qName, Attributes attrs,
                Attributes nonTaglibXmlnsAttrs, Attributes taglibAttrs,
                Mark start, Node parent) {
            super(qName, INCLUDE_ACTION, attrs, nonTaglibXmlnsAttrs,
                    taglibAttrs, start, parent);
        }

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

        public void setPage(JspAttribute page) {
            this.page = page;
        }

        public JspAttribute getPage() {
            return page;
        }
    }

    /**
     * Represents a forward action
     */

    public static class ForwardAction extends Node {

        private JspAttribute page;

        ForwardAction(Attributes attrs, Mark start, Node parent) {
            this(JSP_FORWARD_ACTION, attrs, nullnull, start, parent);
        }

        ForwardAction(String qName, Attributes attrs,
                Attributes nonTaglibXmlnsAttrs, Attributes taglibAttrs,
                Mark start, Node parent) {
            super(qName, FORWARD_ACTION, attrs, nonTaglibXmlnsAttrs,
                    taglibAttrs, start, parent);
        }

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

        public void setPage(JspAttribute page) {
            this.page = page;
        }

        public JspAttribute getPage() {
            return page;
        }
    }

    /**
     * Represents a getProperty action
     */

    public static class GetProperty extends Node {

        GetProperty(Attributes attrs, Mark start, Node parent) {
            this(JSP_GET_PROPERTY_ACTION, attrs, nullnull, start, parent);
        }

        GetProperty(String qName, Attributes attrs,
                Attributes nonTaglibXmlnsAttrs, Attributes taglibAttrs,
                Mark start, Node parent) {
            super(qName, GET_PROPERTY_ACTION, attrs, nonTaglibXmlnsAttrs,
                    taglibAttrs, start, parent);
        }

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

    /**
     * Represents a setProperty action
     */

    public static class SetProperty extends Node {

        private JspAttribute value;

        SetProperty(Attributes attrs, Mark start, Node parent) {
            this(JSP_SET_PROPERTY_ACTION, attrs, nullnull, start, parent);
        }

        SetProperty(String qName, Attributes attrs,
                Attributes nonTaglibXmlnsAttrs, Attributes taglibAttrs,
                Mark start, Node parent) {
            super(qName, SET_PROPERTY_ACTION, attrs, nonTaglibXmlnsAttrs,
                    taglibAttrs, start, parent);
        }

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

        public void setValue(JspAttribute value) {
            this.value = value;
        }

        public JspAttribute getValue() {
            return value;
        }
    }

    /**
     * Represents a useBean action
     */

    public static class UseBean extends Node {

        private JspAttribute beanName;

        UseBean(Attributes attrs, Mark start, Node parent) {
            this(JSP_USE_BEAN_ACTION, attrs, nullnull, start, parent);
        }

        UseBean(String qName, Attributes attrs,
                Attributes nonTaglibXmlnsAttrs, Attributes taglibAttrs,
                Mark start, Node parent) {
            super(qName, USE_BEAN_ACTION, attrs, nonTaglibXmlnsAttrs,
                    taglibAttrs, start, parent);
        }

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

        public void setBeanName(JspAttribute beanName) {
            this.beanName = beanName;
        }

        public JspAttribute getBeanName() {
            return beanName;
        }
    }

    /**
     * Represents a plugin action
     */

    public static class PlugIn extends Node {

        private JspAttribute width;

        private JspAttribute height;

        PlugIn(Attributes attrs, Mark start, Node parent) {
            this(JSP_PLUGIN_ACTION, attrs, nullnull, start, parent);
        }

        PlugIn(String qName, Attributes attrs,
                Attributes nonTaglibXmlnsAttrs, Attributes taglibAttrs,
                Mark start, Node parent) {
            super(qName, PLUGIN_ACTION, attrs, nonTaglibXmlnsAttrs,
                    taglibAttrs, start, parent);
        }

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

        public void setHeight(JspAttribute height) {
            this.height = height;
        }

        public void setWidth(JspAttribute width) {
            this.width = width;
        }

        public JspAttribute getHeight() {
            return height;
        }

        public JspAttribute getWidth() {
            return width;
        }
    }

    /**
     * Represents an uninterpreted tag, from a Jsp document
     */

    public static class UninterpretedTag extends Node {

        private JspAttribute[] jspAttrs;

        UninterpretedTag(String qName, String localName,
                Attributes attrs, Attributes nonTaglibXmlnsAttrs,
                Attributes taglibAttrs, Mark start, Node parent) {
            super(qName, localName, attrs, nonTaglibXmlnsAttrs, taglibAttrs,
                    start, parent);
        }

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

        public void setJspAttributes(JspAttribute[] jspAttrs) {
            this.jspAttrs = jspAttrs;
        }

        public JspAttribute[] getJspAttributes() {
            return jspAttrs;
        }
    }

    /**
     * Represents a <jsp:element>.
     */

    public static class JspElement extends Node {

        private JspAttribute[] jspAttrs;

        private JspAttribute nameAttr;

        JspElement(Attributes attrs, Mark start, Node parent) {
            this(JSP_ELEMENT_ACTION, attrs, nullnull, start, parent);
        }

        JspElement(String qName, Attributes attrs,
                Attributes nonTaglibXmlnsAttrs, Attributes taglibAttrs,
                Mark start, Node parent) {
            super(qName, ELEMENT_ACTION, attrs, nonTaglibXmlnsAttrs,
                    taglibAttrs, start, parent);
        }

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

        public void setJspAttributes(JspAttribute[] jspAttrs) {
            this.jspAttrs = jspAttrs;
        }

        public JspAttribute[] getJspAttributes() {
            return jspAttrs;
        }

        /*
         * Sets the XML-style 'name' attribute
         */

        public void setNameAttribute(JspAttribute nameAttr) {
            this.nameAttr = nameAttr;
        }

        /*
         * Gets the XML-style 'name' attribute
         */

        public JspAttribute getNameAttribute() {
            return this.nameAttr;
        }
    }

    /**
     * Represents a <jsp:output>.
     */

    public static class JspOutput extends Node {

        JspOutput(String qName, Attributes attrs,
                Attributes nonTaglibXmlnsAttrs, Attributes taglibAttrs,
                Mark start, Node parent) {
            super(qName, OUTPUT_ACTION, attrs, nonTaglibXmlnsAttrs,
                    taglibAttrs, start, parent);
        }

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

    /**
     * Collected information about child elements. Used by nodes like CustomTag,
     * JspBody, and NamedAttribute. The information is set in the Collector.
     */

    public static class ChildInfo {
        private boolean scriptless; // true if the tag and its body

        // contain no scripting elements.
        private boolean hasUseBean;

        private boolean hasIncludeAction;

        private boolean hasParamAction;

        private boolean hasSetProperty;

        private boolean hasScriptingVars;

        public void setScriptless(boolean s) {
            scriptless = s;
        }

        public boolean isScriptless() {
            return scriptless;
        }

        public void setHasUseBean(boolean u) {
            hasUseBean = u;
        }

        public boolean hasUseBean() {
            return hasUseBean;
        }

        public void setHasIncludeAction(boolean i) {
            hasIncludeAction = i;
        }

        public boolean hasIncludeAction() {
            return hasIncludeAction;
        }

        public void setHasParamAction(boolean i) {
            hasParamAction = i;
        }

        public boolean hasParamAction() {
            return hasParamAction;
        }

        public void setHasSetProperty(boolean s) {
            hasSetProperty = s;
        }

        public boolean hasSetProperty() {
            return hasSetProperty;
        }

        public void setHasScriptingVars(boolean s) {
            hasScriptingVars = s;
        }

        public boolean hasScriptingVars() {
            return hasScriptingVars;
        }
    }


    public abstract static class ChildInfoBase extends Node {

        private final ChildInfo childInfo = new ChildInfo();

        ChildInfoBase(String qName, String localName, Attributes attrs,
                Attributes nonTaglibXmlnsAttrs, Attributes taglibAttrs, Mark start,
                Node parent) {
            super(qName, localName, attrs, nonTaglibXmlnsAttrs, taglibAttrs, start, parent);
        }

        public ChildInfo getChildInfo() {
            return childInfo;
        }
    }


    /**
     * Represents a custom tag
     */

    public static class CustomTag extends ChildInfoBase {

        private final String uri;

        private final String prefix;

        private JspAttribute[] jspAttrs;

        private TagData tagData;

        private String tagHandlerPoolName;

        private final TagInfo tagInfo;

        private final TagFileInfo tagFileInfo;

        private Class<?> tagHandlerClass;

        private VariableInfo[] varInfos;

        private final int customNestingLevel;

        private final boolean implementsIterationTag;

        private final boolean implementsBodyTag;

        private final boolean implementsTryCatchFinally;

        private final boolean implementsJspIdConsumer;

        private final boolean implementsSimpleTag;

        private final boolean implementsDynamicAttributes;

        private List<Object> atBeginScriptingVars;

        private List<Object> atEndScriptingVars;

        private List<Object> nestedScriptingVars;

        private Node.CustomTag customTagParent;

        private Integer numCount;

        private boolean useTagPlugin;

        private TagPluginContext tagPluginContext;

        /**
         * The following two fields are used for holding the Java scriptlets
         * that the tag plugins may generate. Meaningful only if useTagPlugin is
         * true; Could move them into TagPluginContextImpl, but we'll need to
         * cast tagPluginContext to TagPluginContextImpl all the time...
         */

        private Nodes atSTag;

        private Nodes atETag;

        /*
         * Constructor for custom action implemented by tag handler.
         */

        CustomTag(String qName, String prefix, String localName,
                String uri, Attributes attrs, Mark start, Node parent,
                TagInfo tagInfo, Class<?> tagHandlerClass) {
            this(qName, prefix, localName, uri, attrs, nullnull, start,
                    parent, tagInfo, tagHandlerClass);
        }

        /*
         * Constructor for custom action implemented by tag handler.
         */

        CustomTag(String qName, String prefix, String localName,
                String uri, Attributes attrs, Attributes nonTaglibXmlnsAttrs,
                Attributes taglibAttrs, Mark start, Node parent,
                TagInfo tagInfo, Class<?> tagHandlerClass) {
            super(qName, localName, attrs, nonTaglibXmlnsAttrs, taglibAttrs,
                    start, parent);

            this.uri = uri;
            this.prefix = prefix;
            this.tagInfo = tagInfo;
            this.tagFileInfo = null;
            this.tagHandlerClass = tagHandlerClass;
            this.customNestingLevel = makeCustomNestingLevel();

            this.implementsIterationTag = IterationTag.class
                    .isAssignableFrom(tagHandlerClass);
            this.implementsBodyTag = BodyTag.class
                    .isAssignableFrom(tagHandlerClass);
            this.implementsTryCatchFinally = TryCatchFinally.class
                    .isAssignableFrom(tagHandlerClass);
            this.implementsSimpleTag = SimpleTag.class
                    .isAssignableFrom(tagHandlerClass);
            this.implementsDynamicAttributes = DynamicAttributes.class
                    .isAssignableFrom(tagHandlerClass);
            this.implementsJspIdConsumer = JspIdConsumer.class
                    .isAssignableFrom(tagHandlerClass);
        }

        /*
         * Constructor for custom action implemented by tag file.
         */

        CustomTag(String qName, String prefix, String localName,
                String uri, Attributes attrs, Mark start, Node parent,
                TagFileInfo tagFileInfo) {
            this(qName, prefix, localName, uri, attrs, nullnull, start,
                    parent, tagFileInfo);
        }

        /*
         * Constructor for custom action implemented by tag file.
         */

        CustomTag(String qName, String prefix, String localName,
                String uri, Attributes attrs, Attributes nonTaglibXmlnsAttrs,
                Attributes taglibAttrs, Mark start, Node parent,
                TagFileInfo tagFileInfo) {

            super(qName, localName, attrs, nonTaglibXmlnsAttrs, taglibAttrs,
                    start, parent);

            this.uri = uri;
            this.prefix = prefix;
            this.tagFileInfo = tagFileInfo;
            this.tagInfo = tagFileInfo.getTagInfo();
            this.customNestingLevel = makeCustomNestingLevel();

            this.implementsIterationTag = false;
            this.implementsBodyTag = false;
            this.implementsTryCatchFinally = false;
            this.implementsSimpleTag = true;
            this.implementsJspIdConsumer = false;
            this.implementsDynamicAttributes = tagInfo.hasDynamicAttributes();
        }

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

        /**
         * @return The URI namespace that this custom action belongs to
         */

        public String getURI() {
            return this.uri;
        }

        /**
         * @return The tag prefix
         */

        public String getPrefix() {
            return prefix;
        }

        public void setJspAttributes(JspAttribute[] jspAttrs) {
            this.jspAttrs = jspAttrs;
        }

        public JspAttribute[] getJspAttributes() {
            return jspAttrs;
        }

        public void setTagData(TagData tagData) {
            this.tagData = tagData;
            this.varInfos = tagInfo.getVariableInfo(tagData);
            if (this.varInfos == null) {
                this.varInfos = ZERO_VARIABLE_INFO;
            }
        }

        public TagData getTagData() {
            return tagData;
        }

        public void setTagHandlerPoolName(String s) {
            tagHandlerPoolName = s;
        }

        public String getTagHandlerPoolName() {
            return tagHandlerPoolName;
        }

        public TagInfo getTagInfo() {
            return tagInfo;
        }

        public TagFileInfo getTagFileInfo() {
            return tagFileInfo;
        }

        /*
         * @return true if this custom action is supported by a tag file, false
         * otherwise
         */

        public boolean isTagFile() {
            return tagFileInfo != null;
        }

        public Class<?> getTagHandlerClass() {
            return tagHandlerClass;
        }

        public void setTagHandlerClass(Class<?> hc) {
            tagHandlerClass = hc;
        }

        public boolean implementsIterationTag() {
            return implementsIterationTag;
        }

        public boolean implementsBodyTag() {
            return implementsBodyTag;
        }

        public boolean implementsTryCatchFinally() {
            return implementsTryCatchFinally;
        }

        public boolean implementsJspIdConsumer() {
            return implementsJspIdConsumer;
        }

        public boolean implementsSimpleTag() {
            return implementsSimpleTag;
        }

        public boolean implementsDynamicAttributes() {
            return implementsDynamicAttributes;
        }

        public TagVariableInfo[] getTagVariableInfos() {
            return tagInfo.getTagVariableInfos();
        }

        public VariableInfo[] getVariableInfos() {
            return varInfos;
        }

        public void setCustomTagParent(Node.CustomTag n) {
            this.customTagParent = n;
        }

        public Node.CustomTag getCustomTagParent() {
            return this.customTagParent;
        }

        public void setNumCount(Integer count) {
            this.numCount = count;
        }

        public Integer getNumCount() {
            return this.numCount;
        }

        public void setScriptingVars(List<Object> vec, int scope) {
            switch (scope) {
            case VariableInfo.AT_BEGIN:
                this.atBeginScriptingVars = vec;
                break;
            case VariableInfo.AT_END:
                this.atEndScriptingVars = vec;
                break;
            case VariableInfo.NESTED:
                this.nestedScriptingVars = vec;
                break;
            default:
                throw new IllegalArgumentException(
                        Localizer.getMessage("jsp.error.page.invalid.varscope", Integer.valueOf(scope)));
            }
        }

        /*
         * Gets the scripting variables for the given scope that need to be
         * declared.
         */

        public List<Object> getScriptingVars(int scope) {
            List<Object> vec = null;

            switch (scope) {
            case VariableInfo.AT_BEGIN:
                vec = this.atBeginScriptingVars;
                break;
            case VariableInfo.AT_END:
                vec = this.atEndScriptingVars;
                break;
            case VariableInfo.NESTED:
                vec = this.nestedScriptingVars;
                break;
            default:
                throw new IllegalArgumentException(
                        Localizer.getMessage("jsp.error.page.invalid.varscope", Integer.valueOf(scope)));
            }

            return vec;
        }

        /*
         * Gets this custom tag's custom nesting level, which is given as the
         * number of times this custom tag is nested inside itself.
         */

        public int getCustomNestingLevel() {
            return customNestingLevel;
        }

        /**
         * Checks to see if the attribute of the given name is of type
         * JspFragment.
         *
         * @param name The attribute to check
         *
         * @return {@code true} if it is a JspFragment
         */

        public boolean checkIfAttributeIsJspFragment(String name) {
            boolean result = false;

            TagAttributeInfo[] attributes = tagInfo.getAttributes();
            for (TagAttributeInfo attribute : attributes) {
                if (attribute.getName().equals(name)
                        && attribute.isFragment()) {
                    result = true;
                    break;
                }
            }

            return result;
        }

        public void setUseTagPlugin(boolean use) {
            useTagPlugin = use;
        }

        public boolean useTagPlugin() {
            return useTagPlugin;
        }

        public void setTagPluginContext(TagPluginContext tagPluginContext) {
            this.tagPluginContext = tagPluginContext;
        }

        public TagPluginContext getTagPluginContext() {
            return tagPluginContext;
        }

        public void setAtSTag(Nodes sTag) {
            atSTag = sTag;
        }

        public Nodes getAtSTag() {
            return atSTag;
        }

        public void setAtETag(Nodes eTag) {
            atETag = eTag;
        }

        public Nodes getAtETag() {
            return atETag;
        }

        /*
         * Computes this custom tag's custom nesting level, which corresponds to
         * the number of times this custom tag is nested inside itself.
         *
         * Example:
         *
         * <g:h> <a:b> -- nesting level 0 <c:d> <e:f> <a:b> -- nesting level 1
         * <a:b> -- nesting level 2 </a:b> </a:b> <a:b> -- nesting level 1
         * </a:b> </e:f> </c:d> </a:b> </g:h>
         *
         * @return Custom tag's nesting level
         */

        private int makeCustomNestingLevel() {
            int n = 0;
            Node p = parent;
            while (p != null) {
                if ((p instanceof Node.CustomTag)
                        && qName.equals(((Node.CustomTag) p).qName)) {
                    n++;
                }
                p = p.parent;
            }
            return n;
        }

        /**
         * A custom action is considered to have an empty body if the following
         * holds true: - getBody() returns null, or - all immediate children are
         * jsp:attribute actions, or - the action's jsp:body is empty.
         *
         * @return {@code true} if this custom action has an empty body, and
         *         {@code false} otherwise.
         */

        public boolean hasEmptyBody() {
            boolean hasEmptyBody = true;
            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)) {
                        if (n instanceof JspBody) {
                            hasEmptyBody = (n.getBody() == null);
                        } else {
                            hasEmptyBody = false;
                        }
                        break;
                    }
                }
            }

            return hasEmptyBody;
        }
    }

    /**
     * Used as a placeholder for the evaluation code of a custom action
     * attribute (used by the tag plugin machinery only).
     */

    public static class AttributeGenerator extends Node {
        private String name; // name of the attribute

        private CustomTag tag; // The tag this attribute belongs to

        AttributeGenerator(Mark start, String name, CustomTag tag) {
            super(start, null);
            this.name = name;
            this.tag = tag;
        }

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

        public String getName() {
            return name;
        }

        public CustomTag getTag() {
            return tag;
        }
    }

    /**
     * Represents the body of a <jsp:text> element
     */

    public static class JspText extends Node {

        JspText(String qName, Attributes nonTaglibXmlnsAttrs,
                Attributes taglibAttrs, Mark start, Node parent) {
            super(qName, TEXT_ACTION, null, nonTaglibXmlnsAttrs, taglibAttrs,
                    start, parent);
        }

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

    /**
     * Represents a Named Attribute (<jsp:attribute>)
     */

    public static class NamedAttribute extends ChildInfoBase {

        // A unique temporary variable name suitable for code generation
        private String temporaryVariableName;

        // True if this node is to be trimmed, or false otherwise
        private boolean trim = true;

        // True if this attribute should be omitted from the output if
        // used with a <jsp:element>, otherwise false
        private JspAttribute omit;

        private final String name;

        private String localName;

        private String prefix;

        NamedAttribute(Attributes attrs, Mark start, Node parent) {
            this(JSP_ATTRIBUTE_ACTION, attrs, nullnull, start, parent);
        }

        NamedAttribute(String qName, Attributes attrs,
                Attributes nonTaglibXmlnsAttrs, Attributes taglibAttrs,
                Mark start, Node parent) {

            super(qName, ATTRIBUTE_ACTION, attrs, nonTaglibXmlnsAttrs,
                    taglibAttrs, start, parent);
            if ("false".equals(this.getAttributeValue("trim"))) {
                // (if null or true, leave default of true)
                trim = false;
            }
            name = this.getAttributeValue("name");
            if (name != null) {
                // Mandatory attribute "name" will be checked in Validator
                localName = name;
                int index = name.indexOf(':');
                if (index != -1) {
                    prefix = name.substring(0, index);
                    localName = name.substring(index + 1);
                }
            }
        }

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

        public String getName() {
            return this.name;
        }

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

        public String getPrefix() {
            return this.prefix;
        }

        public boolean isTrim() {
            return trim;
        }

        public void setOmit(JspAttribute omit) {
            this.omit = omit;
        }

        public JspAttribute getOmit() {
            return omit;
        }

        /**
         * @return A unique temporary variable name to store the result in.
         *         (this probably could go elsewhere, but it's convenient here)
         */

        public String getTemporaryVariableName() {
            if (temporaryVariableName == null) {
                temporaryVariableName = getRoot().nextTemporaryVariableName();
            }
            return temporaryVariableName;
        }

        /*
         * Get the attribute value from this named attribute (<jsp:attribute>).
         * Since this method is only for attributes that are not rtexpr, we can
         * assume the body of the jsp:attribute is a template text.
         */

        @Override
        public String getText() {

            class AttributeVisitor extends Visitor {
                private String attrValue = null;

                @Override
                public void visit(TemplateText txt) {
                    attrValue = txt.getText();
                }

                public String getAttrValue() {
                    return attrValue;
                }
            }

            // According to JSP 2.0, if the body of the <jsp:attribute>
            // action is empty, it is equivalent of specifying "" as the value
            // of the attribute.
            String text = "";
            if (getBody() != null) {
                AttributeVisitor attributeVisitor = new AttributeVisitor();
                try {
                    getBody().visit(attributeVisitor);
                } catch (JasperException e) {
                }
                text = attributeVisitor.getAttrValue();
            }

            return text;
        }
    }

    /**
     * Represents a JspBody node (<jsp:body>)
     */

    public static class JspBody extends ChildInfoBase {

        JspBody(Mark start, Node parent) {
            this(JSP_BODY_ACTION, nullnull, start, parent);
        }

        JspBody(String qName, Attributes nonTaglibXmlnsAttrs,
                Attributes taglibAttrs, Mark start, Node parent) {
            super(qName, BODY_ACTION, null, nonTaglibXmlnsAttrs, taglibAttrs,
                    start, parent);
        }

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

    /**
     * Represents a template text string
     */

    public static class TemplateText extends Node {

        private ArrayList<Integer> extraSmap = null;

        TemplateText(String text, Mark start, Node parent) {
            super(nullnull, text, start, parent);
        }

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

        /**
         * Trim all whitespace from the left of the template text
         */

        public void ltrim() {
            int index = 0;
            while ((index < text.length()) && (text.charAt(index) <= ' ')) {
                index++;
            }
            text = text.substring(index);
        }

        public void setText(String text) {
            this.text = text;
        }

        /**
         * Trim all whitespace from the right of the template text
         */

        public void rtrim() {
            int index = text.length();
            while ((index > 0) && (text.charAt(index - 1) <= ' ')) {
                index--;
            }
            text = text.substring(0, index);
        }

        /**
         * @return true if this template text contains whitespace only.
         */

        public boolean isAllSpace() {
            boolean isAllSpace = true;
            for (int i = 0; i < text.length(); i++) {
                if (!Character.isWhitespace(text.charAt(i))) {
                    isAllSpace = false;
                    break;
                }
            }
            return isAllSpace;
        }

        /**
         * Add a source to Java line mapping
         *
         * @param srcLine
         *            The position of the source line, relative to the line at
         *            the start of this node. The corresponding java line is
         *            assumed to be consecutive, i.e. one more than the last.
         */

        public void addSmap(int srcLine) {
            if (extraSmap == null) {
                extraSmap = new ArrayList<>();
            }
            extraSmap.add(Integer.valueOf(srcLine));
        }

        public ArrayList<Integer> getExtraSmap() {
            return extraSmap;
        }
    }

    /**
     * Represents attributes that can be request time expressions.
     *
     * Can either be a plain attribute, an attribute that represents a request
     * time expression value, or a named attribute (specified using the
     * jsp:attribute standard action).
     */


    public static class JspAttribute {

        private final String qName;

        private final String uri;

        private final String localName;

        private final String value;

        private final boolean expression;

        private final boolean dynamic;

        private final ELNode.Nodes el;

        private final TagAttributeInfo tai;

        // If true, this JspAttribute represents a <jsp:attribute>
        private final boolean namedAttribute;

        // The node in the parse tree for the NamedAttribute
        private final NamedAttribute namedAttributeNode;

        JspAttribute(TagAttributeInfo tai, String qName, String uri,
                String localName, String value, boolean expr, ELNode.Nodes el,
                boolean dyn) {
            this.qName = qName;
            this.uri = uri;
            this.localName = localName;
            this.value = value;
            this.namedAttributeNode = null;
            this.expression = expr;
            this.el = el;
            this.dynamic = dyn;
            this.namedAttribute = false;
            this.tai = tai;
        }

        /**
         * Allow node to validate itself.
         *
         * @param ef The expression factory to use to evaluate any EL
         * @param ctx The context to use to evaluate any EL
         *
         * @throws ELException If validation fails
         */

        public void validateEL(ExpressionFactory ef, ELContext ctx)
                throws ELException {
            if (this.el != null) {
                // determine exact type
                ef.createValueExpression(ctx, this.value, String.class);
            }
        }

        /**
         * Use this constructor if the JspAttribute represents a named
         * attribute. In this case, we have to store the nodes of the body of
         * the attribute.
         */

        JspAttribute(NamedAttribute na, TagAttributeInfo tai, boolean dyn) {
            this.qName = na.getName();
            this.localName = na.getLocalName();
            this.value = null;
            this.namedAttributeNode = na;
            this.expression = false;
            this.el = null;
            this.dynamic = dyn;
            this.namedAttribute = true;
            this.tai = tai;
            this.uri = null;
        }

        /**
         * @return The name of the attribute
         */

        public String getName() {
            return qName;
        }

        /**
         * @return The local name of the attribute
         */

        public String getLocalName() {
            return localName;
        }

        /**
--> --------------------

--> maximum size reached

--> --------------------

98%


¤ Diese beiden folgenden Angebotsgruppen bietet das Unternehmen0.30Angebot  Wie Sie bei der Firma Beratungs- und Dienstleistungen beauftragen können  ¤

*Eine klare Vorstellung vom Zielzustand






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung ist noch experimentell.