Save This Page
Home » apache-tomcat-6.0.16-src » org.apache » jasper » compiler » [javadoc | source]
    1   /*
    2    * Licensed to the Apache Software Foundation (ASF) under one or more
    3    * contributor license agreements.  See the NOTICE file distributed with
    4    * this work for additional information regarding copyright ownership.
    5    * The ASF licenses this file to You under the Apache License, Version 2.0
    6    * (the "License"); you may not use this file except in compliance with
    7    * the License.  You may obtain a copy of the License at
    8    * 
    9    *      http://www.apache.org/licenses/LICENSE-2.0
   10    * 
   11    * Unless required by applicable law or agreed to in writing, software
   12    * distributed under the License is distributed on an "AS IS" BASIS,
   13    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   14    * See the License for the specific language governing permissions and
   15    * limitations under the License.
   16    */
   17   
   18   package org.apache.jasper.compiler;
   19   
   20   import java.util.Iterator;
   21   import java.util.List;
   22   import java.util.Vector;
   23   import java.util.ArrayList;
   24   
   25   import javax.el.ELContext;
   26   import javax.el.ELException;
   27   import javax.el.ExpressionFactory;
   28   import javax.el.ValueExpression;
   29   import javax.servlet.jsp.tagext.BodyTag;
   30   import javax.servlet.jsp.tagext.DynamicAttributes;
   31   import javax.servlet.jsp.tagext.IterationTag;
   32   import javax.servlet.jsp.tagext.JspIdConsumer;
   33   import javax.servlet.jsp.tagext.SimpleTag;
   34   import javax.servlet.jsp.tagext.TagAttributeInfo;
   35   import javax.servlet.jsp.tagext.TagData;
   36   import javax.servlet.jsp.tagext.TagFileInfo;
   37   import javax.servlet.jsp.tagext.TagInfo;
   38   import javax.servlet.jsp.tagext.TagVariableInfo;
   39   import javax.servlet.jsp.tagext.TryCatchFinally;
   40   import javax.servlet.jsp.tagext.VariableInfo;
   41   
   42   import org.apache.jasper.JasperException;
   43   import org.apache.jasper.compiler.tagplugin.TagPluginContext;
   44   import org.xml.sax.Attributes;
   45   
   46   /**
   47    * An internal data representation of a JSP page or a JSP docuement (XML). Also
   48    * included here is a visitor class for tranversing nodes.
   49    * 
   50    * @author Kin-man Chung
   51    * @author Jan Luehe
   52    * @author Shawn Bayern
   53    * @author Mark Roth
   54    */
   55   
   56   abstract class Node implements TagConstants {
   57   
   58       private static final VariableInfo[] ZERO_VARIABLE_INFO = {};
   59   
   60       protected Attributes attrs;
   61   
   62       // xmlns attributes that represent tag libraries (only in XML syntax)
   63       protected Attributes taglibAttrs;
   64   
   65       /*
   66        * xmlns attributes that do not represent tag libraries (only in XML syntax)
   67        */
   68       protected Attributes nonTaglibXmlnsAttrs;
   69   
   70       protected Nodes body;
   71   
   72       protected String text;
   73   
   74       protected Mark startMark;
   75   
   76       protected int beginJavaLine;
   77   
   78       protected int endJavaLine;
   79   
   80       protected Node parent;
   81   
   82       protected Nodes namedAttributeNodes; // cached for performance
   83   
   84       protected String qName;
   85   
   86       protected String localName;
   87   
   88       /*
   89        * The name of the inner class to which the codes for this node and its body
   90        * are generated. For instance, for <jsp:body> in foo.jsp, this is
   91        * "foo_jspHelper". This is primarily used for communicating such info from
   92        * Generator to Smap generator.
   93        */
   94       protected String innerClassName;
   95   
   96       private boolean isDummy;
   97   
   98       /**
   99        * Zero-arg Constructor.
  100        */
  101       public Node() {
  102           this.isDummy = true;
  103       }
  104   
  105       /**
  106        * Constructor.
  107        * 
  108        * @param start
  109        *            The location of the jsp page
  110        * @param parent
  111        *            The enclosing node
  112        */
  113       public Node(Mark start, Node parent) {
  114           this.startMark = start;
  115           this.isDummy = (start == null);
  116           addToParent(parent);
  117       }
  118   
  119       /**
  120        * Constructor.
  121        * 
  122        * @param qName
  123        *            The action's qualified name
  124        * @param localName
  125        *            The action's local name
  126        * @param start
  127        *            The location of the jsp page
  128        * @param parent
  129        *            The enclosing node
  130        */
  131       public Node(String qName, String localName, Mark start, Node parent) {
  132           this.qName = qName;
  133           this.localName = localName;
  134           this.startMark = start;
  135           this.isDummy = (start == null);
  136           addToParent(parent);
  137       }
  138   
  139       /**
  140        * Constructor for Nodes parsed from standard syntax.
  141        * 
  142        * @param qName
  143        *            The action's qualified name
  144        * @param localName
  145        *            The action's local name
  146        * @param attrs
  147        *            The attributes for this node
  148        * @param start
  149        *            The location of the jsp page
  150        * @param parent
  151        *            The enclosing node
  152        */
  153       public Node(String qName, String localName, Attributes attrs, Mark start,
  154               Node parent) {
  155           this.qName = qName;
  156           this.localName = localName;
  157           this.attrs = attrs;
  158           this.startMark = start;
  159           this.isDummy = (start == null);
  160           addToParent(parent);
  161       }
  162   
  163       /**
  164        * Constructor for Nodes parsed from XML syntax.
  165        * 
  166        * @param qName
  167        *            The action's qualified name
  168        * @param localName
  169        *            The action's local name
  170        * @param attrs
  171        *            The action's attributes whose name does not start with xmlns
  172        * @param nonTaglibXmlnsAttrs
  173        *            The action's xmlns attributes that do not represent tag
  174        *            libraries
  175        * @param taglibAttrs
  176        *            The action's xmlns attributes that represent tag libraries
  177        * @param start
  178        *            The location of the jsp page
  179        * @param parent
  180        *            The enclosing node
  181        */
  182       public Node(String qName, String localName, Attributes attrs,
  183               Attributes nonTaglibXmlnsAttrs, Attributes taglibAttrs, Mark start,
  184               Node parent) {
  185           this.qName = qName;
  186           this.localName = localName;
  187           this.attrs = attrs;
  188           this.nonTaglibXmlnsAttrs = nonTaglibXmlnsAttrs;
  189           this.taglibAttrs = taglibAttrs;
  190           this.startMark = start;
  191           this.isDummy = (start == null);
  192           addToParent(parent);
  193       }
  194   
  195       /*
  196        * Constructor.
  197        * 
  198        * @param qName The action's qualified name @param localName The action's
  199        * local name @param text The text associated with this node @param start
  200        * The location of the jsp page @param parent The enclosing node
  201        */
  202       public Node(String qName, String localName, String text, Mark start,
  203               Node parent) {
  204           this.qName = qName;
  205           this.localName = localName;
  206           this.text = text;
  207           this.startMark = start;
  208           this.isDummy = (start == null);
  209           addToParent(parent);
  210       }
  211   
  212       public String getQName() {
  213           return this.qName;
  214       }
  215   
  216       public String getLocalName() {
  217           return this.localName;
  218       }
  219   
  220       /*
  221        * Gets this Node's attributes.
  222        * 
  223        * In the case of a Node parsed from standard syntax, this method returns
  224        * all the Node's attributes.
  225        * 
  226        * In the case of a Node parsed from XML syntax, this method returns only
  227        * those attributes whose name does not start with xmlns.
  228        */
  229       public Attributes getAttributes() {
  230           return this.attrs;
  231       }
  232   
  233       /*
  234        * Gets this Node's xmlns attributes that represent tag libraries (only
  235        * meaningful for Nodes parsed from XML syntax)
  236        */
  237       public Attributes getTaglibAttributes() {
  238           return this.taglibAttrs;
  239       }
  240   
  241       /*
  242        * Gets this Node's xmlns attributes that do not represent tag libraries
  243        * (only meaningful for Nodes parsed from XML syntax)
  244        */
  245       public Attributes getNonTaglibXmlnsAttributes() {
  246           return this.nonTaglibXmlnsAttrs;
  247       }
  248   
  249       public void setAttributes(Attributes attrs) {
  250           this.attrs = attrs;
  251       }
  252   
  253       public String getAttributeValue(String name) {
  254           return (attrs == null) ? null : attrs.getValue(name);
  255       }
  256   
  257       /**
  258        * Get the attribute that is non request time expression, either from the
  259        * attribute of the node, or from a jsp:attrbute
  260        */
  261       public String getTextAttribute(String name) {
  262   
  263           String attr = getAttributeValue(name);
  264           if (attr != null) {
  265               return attr;
  266           }
  267   
  268           NamedAttribute namedAttribute = getNamedAttributeNode(name);
  269           if (namedAttribute == null) {
  270               return null;
  271           }
  272   
  273           return namedAttribute.getText();
  274       }
  275   
  276       /**
  277        * Searches all subnodes of this node for jsp:attribute standard actions
  278        * with the given name, and returns the NamedAttribute node of the matching
  279        * named attribute, nor null if no such node is found.
  280        * <p>
  281        * This should always be called and only be called for nodes that accept
  282        * dynamic runtime attribute expressions.
  283        */
  284       public NamedAttribute getNamedAttributeNode(String name) {
  285           NamedAttribute result = null;
  286   
  287           // Look for the attribute in NamedAttribute children
  288           Nodes nodes = getNamedAttributeNodes();
  289           int numChildNodes = nodes.size();
  290           for (int i = 0; i < numChildNodes; i++) {
  291               NamedAttribute na = (NamedAttribute) nodes.getNode(i);
  292               boolean found = false;
  293               int index = name.indexOf(':');
  294               if (index != -1) {
  295                   // qualified name
  296                   found = na.getName().equals(name);
  297               } else {
  298                   found = na.getLocalName().equals(name);
  299               }
  300               if (found) {
  301                   result = na;
  302                   break;
  303               }
  304           }
  305   
  306           return result;
  307       }
  308   
  309       /**
  310        * Searches all subnodes of this node for jsp:attribute standard actions,
  311        * and returns that set of nodes as a Node.Nodes object.
  312        * 
  313        * @return Possibly empty Node.Nodes object containing any jsp:attribute
  314        *         subnodes of this Node
  315        */
  316       public Node.Nodes getNamedAttributeNodes() {
  317   
  318           if (namedAttributeNodes != null) {
  319               return namedAttributeNodes;
  320           }
  321   
  322           Node.Nodes result = new Node.Nodes();
  323   
  324           // Look for the attribute in NamedAttribute children
  325           Nodes nodes = getBody();
  326           if (nodes != null) {
  327               int numChildNodes = nodes.size();
  328               for (int i = 0; i < numChildNodes; i++) {
  329                   Node n = nodes.getNode(i);
  330                   if (n instanceof NamedAttribute) {
  331                       result.add(n);
  332                   } else if (!(n instanceof Comment)) {
  333                       // Nothing can come before jsp:attribute, and only
  334                       // jsp:body can come after it.
  335                       break;
  336                   }
  337               }
  338           }
  339   
  340           namedAttributeNodes = result;
  341           return result;
  342       }
  343   
  344       public Nodes getBody() {
  345           return body;
  346       }
  347   
  348       public void setBody(Nodes body) {
  349           this.body = body;
  350       }
  351   
  352       public String getText() {
  353           return text;
  354       }
  355   
  356       public Mark getStart() {
  357           return startMark;
  358       }
  359   
  360       public Node getParent() {
  361           return parent;
  362       }
  363   
  364       public int getBeginJavaLine() {
  365           return beginJavaLine;
  366       }
  367   
  368       public void setBeginJavaLine(int begin) {
  369           beginJavaLine = begin;
  370       }
  371   
  372       public int getEndJavaLine() {
  373           return endJavaLine;
  374       }
  375   
  376       public void setEndJavaLine(int end) {
  377           endJavaLine = end;
  378       }
  379   
  380       public boolean isDummy() {
  381           return isDummy;
  382       }
  383   
  384       public Node.Root getRoot() {
  385           Node n = this;
  386           while (!(n instanceof Node.Root)) {
  387               n = n.getParent();
  388           }
  389           return (Node.Root) n;
  390       }
  391   
  392       public String getInnerClassName() {
  393           return innerClassName;
  394       }
  395   
  396       public void setInnerClassName(String icn) {
  397           innerClassName = icn;
  398       }
  399   
  400       /**
  401        * Selects and invokes a method in the visitor class based on the node type.
  402        * This is abstract and should be overrode by the extending classes.
  403        * 
  404        * @param v
  405        *            The visitor class
  406        */
  407       abstract void accept(Visitor v) throws JasperException;
  408   
  409       // *********************************************************************
  410       // Private utility methods
  411   
  412       /*
  413        * Adds this Node to the body of the given parent.
  414        */
  415       private void addToParent(Node parent) {
  416           if (parent != null) {
  417               this.parent = parent;
  418               Nodes parentBody = parent.getBody();
  419               if (parentBody == null) {
  420                   parentBody = new Nodes();
  421                   parent.setBody(parentBody);
  422               }
  423               parentBody.add(this);
  424           }
  425       }
  426   
  427       /***************************************************************************
  428        * Child classes
  429        */
  430   
  431       /**
  432        * Represents the root of a Jsp page or Jsp document
  433        */
  434       public static class Root extends Node {
  435   
  436           private Root parentRoot;
  437   
  438           private boolean isXmlSyntax;
  439   
  440           // Source encoding of the page containing this Root
  441           private String pageEnc;
  442   
  443           // Page encoding specified in JSP config element
  444           private String jspConfigPageEnc;
  445   
  446           /*
  447            * Flag indicating if the default page encoding is being used (only
  448            * applicable with standard syntax).
  449            * 
  450            * True if the page does not provide a page directive with a
  451            * 'contentType' attribute (or the 'contentType' attribute doesn't have
  452            * a CHARSET value), the page does not provide a page directive with a
  453            * 'pageEncoding' attribute, and there is no JSP configuration element
  454            * page-encoding whose URL pattern matches the page.
  455            */
  456           private boolean isDefaultPageEncoding;
  457   
  458           /*
  459            * Indicates whether an encoding has been explicitly specified in the
  460            * page's XML prolog (only used for pages in XML syntax). This
  461            * information is used to decide whether a translation error must be
  462            * reported for encoding conflicts.
  463            */
  464           private boolean isEncodingSpecifiedInProlog;
  465   
  466           /*
  467            * Indicates whether an encoding has been explicitly specified in the
  468            * page's bom.
  469            */
  470           private boolean isBomPresent;
  471   
  472           /*
  473            * Constructor.
  474            */
  475           Root(Mark start, Node parent, boolean isXmlSyntax) {
  476               super(start, parent);
  477               this.isXmlSyntax = isXmlSyntax;
  478               this.qName = JSP_ROOT_ACTION;
  479               this.localName = ROOT_ACTION;
  480   
  481               // Figure out and set the parent root
  482               Node r = parent;
  483               while ((r != null) && !(r instanceof Node.Root))
  484                   r = r.getParent();
  485               parentRoot = (Node.Root) r;
  486           }
  487   
  488           public void accept(Visitor v) throws JasperException {
  489               v.visit(this);
  490           }
  491   
  492           public boolean isXmlSyntax() {
  493               return isXmlSyntax;
  494           }
  495   
  496           /*
  497            * Sets the encoding specified in the JSP config element whose URL
  498            * pattern matches the page containing this Root.
  499            */
  500           public void setJspConfigPageEncoding(String enc) {
  501               jspConfigPageEnc = enc;
  502           }
  503   
  504           /*
  505            * Gets the encoding specified in the JSP config element whose URL
  506            * pattern matches the page containing this Root.
  507            */
  508           public String getJspConfigPageEncoding() {
  509               return jspConfigPageEnc;
  510           }
  511   
  512           public void setPageEncoding(String enc) {
  513               pageEnc = enc;
  514           }
  515   
  516           public String getPageEncoding() {
  517               return pageEnc;
  518           }
  519   
  520           public void setIsDefaultPageEncoding(boolean isDefault) {
  521               isDefaultPageEncoding = isDefault;
  522           }
  523   
  524           public boolean isDefaultPageEncoding() {
  525               return isDefaultPageEncoding;
  526           }
  527   
  528           public void setIsEncodingSpecifiedInProlog(boolean isSpecified) {
  529               isEncodingSpecifiedInProlog = isSpecified;
  530           }
  531   
  532           public boolean isEncodingSpecifiedInProlog() {
  533               return isEncodingSpecifiedInProlog;
  534           }
  535   
  536           public void setIsBomPresent(boolean isBom) {
  537               isBomPresent = isBom;
  538           }
  539   
  540           public boolean isBomPresent() {
  541               return isBomPresent;
  542           }
  543   
  544           /**
  545            * @return The enclosing root to this Root. Usually represents the page
  546            *         that includes this one.
  547            */
  548           public Root getParentRoot() {
  549               return parentRoot;
  550           }
  551       }
  552   
  553       /**
  554        * Represents the root of a Jsp document (XML syntax)
  555        */
  556       public static class JspRoot extends Node {
  557   
  558           public JspRoot(String qName, Attributes attrs,
  559                   Attributes nonTaglibXmlnsAttrs, Attributes taglibAttrs,
  560                   Mark start, Node parent) {
  561               super(qName, ROOT_ACTION, attrs, nonTaglibXmlnsAttrs, taglibAttrs,
  562                       start, parent);
  563           }
  564   
  565           public void accept(Visitor v) throws JasperException {
  566               v.visit(this);
  567           }
  568       }
  569   
  570       /**
  571        * Represents a page directive
  572        */
  573       public static class PageDirective extends Node {
  574   
  575           private Vector imports;
  576   
  577           public PageDirective(Attributes attrs, Mark start, Node parent) {
  578               this(JSP_PAGE_DIRECTIVE_ACTION, attrs, null, null, start, parent);
  579           }
  580   
  581           public PageDirective(String qName, Attributes attrs,
  582                   Attributes nonTaglibXmlnsAttrs, Attributes taglibAttrs,
  583                   Mark start, Node parent) {
  584               super(qName, PAGE_DIRECTIVE_ACTION, attrs, nonTaglibXmlnsAttrs,
  585                       taglibAttrs, start, parent);
  586               imports = new Vector();
  587           }
  588   
  589           public void accept(Visitor v) throws JasperException {
  590               v.visit(this);
  591           }
  592   
  593           /**
  594            * Parses the comma-separated list of class or package names in the
  595            * given attribute value and adds each component to this PageDirective's
  596            * vector of imported classes and packages.
  597            * 
  598            * @param value
  599            *            A comma-separated string of imports.
  600            */
  601           public void addImport(String value) {
  602               int start = 0;
  603               int index;
  604               while ((index = value.indexOf(',', start)) != -1) {
  605                   imports.add(value.substring(start, index).trim());
  606                   start = index + 1;
  607               }
  608               if (start == 0) {
  609                   // No comma found
  610                   imports.add(value.trim());
  611               } else {
  612                   imports.add(value.substring(start).trim());
  613               }
  614           }
  615   
  616           public List getImports() {
  617               return imports;
  618           }
  619       }
  620   
  621       /**
  622        * Represents an include directive
  623        */
  624       public static class IncludeDirective extends Node {
  625   
  626           public IncludeDirective(Attributes attrs, Mark start, Node parent) {
  627               this(JSP_INCLUDE_DIRECTIVE_ACTION, attrs, null, null, start, parent);
  628           }
  629   
  630           public IncludeDirective(String qName, Attributes attrs,
  631                   Attributes nonTaglibXmlnsAttrs, Attributes taglibAttrs,
  632                   Mark start, Node parent) {
  633               super(qName, INCLUDE_DIRECTIVE_ACTION, attrs, nonTaglibXmlnsAttrs,
  634                       taglibAttrs, start, parent);
  635           }
  636   
  637           public void accept(Visitor v) throws JasperException {
  638               v.visit(this);
  639           }
  640       }
  641   
  642       /**
  643        * Represents a custom taglib directive
  644        */
  645       public static class TaglibDirective extends Node {
  646   
  647           public TaglibDirective(Attributes attrs, Mark start, Node parent) {
  648               super(JSP_TAGLIB_DIRECTIVE_ACTION, TAGLIB_DIRECTIVE_ACTION, attrs,
  649                       start, parent);
  650           }
  651   
  652           public void accept(Visitor v) throws JasperException {
  653               v.visit(this);
  654           }
  655       }
  656   
  657       /**
  658        * Represents a tag directive
  659        */
  660       public static class TagDirective extends Node {
  661           private Vector imports;
  662   
  663           public TagDirective(Attributes attrs, Mark start, Node parent) {
  664               this(JSP_TAG_DIRECTIVE_ACTION, attrs, null, null, start, parent);
  665           }
  666   
  667           public TagDirective(String qName, Attributes attrs,
  668                   Attributes nonTaglibXmlnsAttrs, Attributes taglibAttrs,
  669                   Mark start, Node parent) {
  670               super(qName, TAG_DIRECTIVE_ACTION, attrs, nonTaglibXmlnsAttrs,
  671                       taglibAttrs, start, parent);
  672               imports = new Vector();
  673           }
  674   
  675           public void accept(Visitor v) throws JasperException {
  676               v.visit(this);
  677           }
  678   
  679           /**
  680            * Parses the comma-separated list of class or package names in the
  681            * given attribute value and adds each component to this PageDirective's
  682            * vector of imported classes and packages.
  683            * 
  684            * @param value
  685            *            A comma-separated string of imports.
  686            */
  687           public void addImport(String value) {
  688               int start = 0;
  689               int index;
  690               while ((index = value.indexOf(',', start)) != -1) {
  691                   imports.add(value.substring(start, index).trim());
  692                   start = index + 1;
  693               }
  694               if (start == 0) {
  695                   // No comma found
  696                   imports.add(value.trim());
  697               } else {
  698                   imports.add(value.substring(start).trim());
  699               }
  700           }
  701   
  702           public List getImports() {
  703               return imports;
  704           }
  705       }
  706   
  707       /**
  708        * Represents an attribute directive
  709        */
  710       public static class AttributeDirective extends Node {
  711   
  712           public AttributeDirective(Attributes attrs, Mark start, Node parent) {
  713               this(JSP_ATTRIBUTE_DIRECTIVE_ACTION, attrs, null, null, start,
  714                       parent);
  715           }
  716   
  717           public AttributeDirective(String qName, Attributes attrs,
  718                   Attributes nonTaglibXmlnsAttrs, Attributes taglibAttrs,
  719                   Mark start, Node parent) {
  720               super(qName, ATTRIBUTE_DIRECTIVE_ACTION, attrs,
  721                       nonTaglibXmlnsAttrs, taglibAttrs, start, parent);
  722           }
  723   
  724           public void accept(Visitor v) throws JasperException {
  725               v.visit(this);
  726           }
  727       }
  728   
  729       /**
  730        * Represents a variable directive
  731        */
  732       public static class VariableDirective extends Node {
  733   
  734           public VariableDirective(Attributes attrs, Mark start, Node parent) {
  735               this(JSP_VARIABLE_DIRECTIVE_ACTION, attrs, null, null, start,
  736                       parent);
  737           }
  738   
  739           public VariableDirective(String qName, Attributes attrs,
  740                   Attributes nonTaglibXmlnsAttrs, Attributes taglibAttrs,
  741                   Mark start, Node parent) {
  742               super(qName, VARIABLE_DIRECTIVE_ACTION, attrs, nonTaglibXmlnsAttrs,
  743                       taglibAttrs, start, parent);
  744           }
  745   
  746           public void accept(Visitor v) throws JasperException {
  747               v.visit(this);
  748           }
  749       }
  750   
  751       /**
  752        * Represents a <jsp:invoke> tag file action
  753        */
  754       public static class InvokeAction extends Node {
  755   
  756           public InvokeAction(Attributes attrs, Mark start, Node parent) {
  757               this(JSP_INVOKE_ACTION, attrs, null, null, start, parent);
  758           }
  759   
  760           public InvokeAction(String qName, Attributes attrs,
  761                   Attributes nonTaglibXmlnsAttrs, Attributes taglibAttrs,
  762                   Mark start, Node parent) {
  763               super(qName, INVOKE_ACTION, attrs, nonTaglibXmlnsAttrs,
  764                       taglibAttrs, start, parent);
  765           }
  766   
  767           public void accept(Visitor v) throws JasperException {
  768               v.visit(this);
  769           }
  770       }
  771   
  772       /**
  773        * Represents a <jsp:doBody> tag file action
  774        */
  775       public static class DoBodyAction extends Node {
  776   
  777           public DoBodyAction(Attributes attrs, Mark start, Node parent) {
  778               this(JSP_DOBODY_ACTION, attrs, null, null, start, parent);
  779           }
  780   
  781           public DoBodyAction(String qName, Attributes attrs,
  782                   Attributes nonTaglibXmlnsAttrs, Attributes taglibAttrs,
  783                   Mark start, Node parent) {
  784               super(qName, DOBODY_ACTION, attrs, nonTaglibXmlnsAttrs,
  785                       taglibAttrs, start, parent);
  786           }
  787   
  788           public void accept(Visitor v) throws JasperException {
  789               v.visit(this);
  790           }
  791       }
  792   
  793       /**
  794        * Represents a Jsp comment Comments are kept for completeness.
  795        */
  796       public static class Comment extends Node {
  797   
  798           public Comment(String text, Mark start, Node parent) {
  799               super(null, null, text, start, parent);
  800           }
  801   
  802           public void accept(Visitor v) throws JasperException {
  803               v.visit(this);
  804           }
  805       }
  806   
  807       /**
  808        * Represents an expression, declaration, or scriptlet
  809        */
  810       public static abstract class ScriptingElement extends Node {
  811   
  812           public ScriptingElement(String qName, String localName, String text,
  813                   Mark start, Node parent) {
  814               super(qName, localName, text, start, parent);
  815           }
  816   
  817           public ScriptingElement(String qName, String localName,
  818                   Attributes nonTaglibXmlnsAttrs, Attributes taglibAttrs,
  819                   Mark start, Node parent) {
  820               super(qName, localName, null, nonTaglibXmlnsAttrs, taglibAttrs,
  821                       start, parent);
  822           }
  823   
  824           /**
  825            * When this node was created from a JSP page in JSP syntax, its text
  826            * was stored as a String in the "text" field, whereas when this node
  827            * was created from a JSP document, its text was stored as one or more
  828            * TemplateText nodes in its body. This method handles either case.
  829            * 
  830            * @return The text string
  831            */
  832           public String getText() {
  833               String ret = text;
  834               if (ret == null) {
  835                   if (body != null) {
  836                       StringBuffer buf = new StringBuffer();
  837                       for (int i = 0; i < body.size(); i++) {
  838                           buf.append(body.getNode(i).getText());
  839                       }
  840                       ret = buf.toString();
  841                   } else {
  842                       // Nulls cause NPEs further down the line
  843                       ret = "";
  844                   }
  845               }
  846               return ret;
  847           }
  848   
  849           /**
  850            * For the same reason as above, the source line information in the
  851            * contained TemplateText node should be used.
  852            */
  853           public Mark getStart() {
  854               if (text == null && body != null && body.size() > 0) {
  855                   return body.getNode(0).getStart();
  856               } else {
  857                   return super.getStart();
  858               }
  859           }
  860       }
  861   
  862       /**
  863        * Represents a declaration
  864        */
  865       public static class Declaration extends ScriptingElement {
  866   
  867           public Declaration(String text, Mark start, Node parent) {
  868               super(JSP_DECLARATION_ACTION, DECLARATION_ACTION, text, start,
  869                       parent);
  870           }
  871   
  872           public Declaration(String qName, Attributes nonTaglibXmlnsAttrs,
  873                   Attributes taglibAttrs, Mark start, Node parent) {
  874               super(qName, DECLARATION_ACTION, nonTaglibXmlnsAttrs, taglibAttrs,
  875                       start, parent);
  876           }
  877   
  878           public void accept(Visitor v) throws JasperException {
  879               v.visit(this);
  880           }
  881       }
  882   
  883       /**
  884        * Represents an expression. Expressions in attributes are embedded in the
  885        * attribute string and not here.
  886        */
  887       public static class Expression extends ScriptingElement {
  888   
  889           public Expression(String text, Mark start, Node parent) {
  890               super(JSP_EXPRESSION_ACTION, EXPRESSION_ACTION, text, start, parent);
  891           }
  892   
  893           public Expression(String qName, Attributes nonTaglibXmlnsAttrs,
  894                   Attributes taglibAttrs, Mark start, Node parent) {
  895               super(qName, EXPRESSION_ACTION, nonTaglibXmlnsAttrs, taglibAttrs,
  896                       start, parent);
  897           }
  898   
  899           public void accept(Visitor v) throws JasperException {
  900               v.visit(this);
  901           }
  902       }
  903   
  904       /**
  905        * Represents a scriptlet
  906        */
  907       public static class Scriptlet extends ScriptingElement {
  908   
  909           public Scriptlet(String text, Mark start, Node parent) {
  910               super(JSP_SCRIPTLET_ACTION, SCRIPTLET_ACTION, text, start, parent);
  911           }
  912   
  913           public Scriptlet(String qName, Attributes nonTaglibXmlnsAttrs,
  914                   Attributes taglibAttrs, Mark start, Node parent) {
  915               super(qName, SCRIPTLET_ACTION, nonTaglibXmlnsAttrs, taglibAttrs,
  916                       start, parent);
  917           }
  918   
  919           public void accept(Visitor v) throws JasperException {
  920               v.visit(this);
  921           }
  922       }
  923   
  924       /**
  925        * Represents an EL expression. Expressions in attributes are embedded in
  926        * the attribute string and not here.
  927        */
  928       public static class ELExpression extends Node {
  929   
  930           private ELNode.Nodes el;
  931   
  932           private final char type;
  933   
  934           public ELExpression(char type, String text, Mark start, Node parent) {
  935               super(null, null, text, start, parent);
  936               this.type = type;
  937           }
  938   
  939           public void accept(Visitor v) throws JasperException {
  940               v.visit(this);
  941           }
  942   
  943           public void setEL(ELNode.Nodes el) {
  944               this.el = el;
  945           }
  946   
  947           public ELNode.Nodes getEL() {
  948               return el;
  949           }
  950   
  951           public char getType() {
  952               return this.type;
  953           }
  954       }
  955   
  956       /**
  957        * Represents a param action
  958        */
  959       public static class ParamAction extends Node {
  960   
  961           JspAttribute value;
  962   
  963           public ParamAction(Attributes attrs, Mark start, Node parent) {
  964               this(JSP_PARAM_ACTION, attrs, null, null, start, parent);
  965           }
  966   
  967           public ParamAction(String qName, Attributes attrs,
  968                   Attributes nonTaglibXmlnsAttrs, Attributes taglibAttrs,
  969                   Mark start, Node parent) {
  970               super(qName, PARAM_ACTION, attrs, nonTaglibXmlnsAttrs, taglibAttrs,
  971                       start, parent);
  972           }
  973   
  974           public void accept(Visitor v) throws JasperException {
  975               v.visit(this);
  976           }
  977   
  978           public void setValue(JspAttribute value) {
  979               this.value = value;
  980           }
  981   
  982           public JspAttribute getValue() {
  983               return value;
  984           }
  985       }
  986   
  987       /**
  988        * Represents a params action
  989        */
  990       public static class ParamsAction extends Node {
  991   
  992           public ParamsAction(Mark start, Node parent) {
  993               this(JSP_PARAMS_ACTION, null, null, start, parent);
  994           }
  995   
  996           public ParamsAction(String qName, Attributes nonTaglibXmlnsAttrs,
  997                   Attributes taglibAttrs, Mark start, Node parent) {
  998               super(qName, PARAMS_ACTION, null, nonTaglibXmlnsAttrs, taglibAttrs,
  999                       start, parent);
 1000           }
 1001   
 1002           public void accept(Visitor v) throws JasperException {
 1003               v.visit(this);
 1004           }
 1005       }
 1006   
 1007       /**
 1008        * Represents a fallback action
 1009        */
 1010       public static class FallBackAction extends Node {
 1011   
 1012           public FallBackAction(Mark start, Node parent) {
 1013               this(JSP_FALLBACK_ACTION, null, null, start, parent);
 1014           }
 1015   
 1016           public FallBackAction(String qName, Attributes nonTaglibXmlnsAttrs,
 1017                   Attributes taglibAttrs, Mark start, Node parent) {
 1018               super(qName, FALLBACK_ACTION, null, nonTaglibXmlnsAttrs,
 1019                       taglibAttrs, start, parent);
 1020           }
 1021   
 1022           public void accept(Visitor v) throws JasperException {
 1023               v.visit(this);
 1024           }
 1025       }
 1026   
 1027       /**
 1028        * Represents an include action
 1029        */
 1030       public static class IncludeAction extends Node {
 1031   
 1032           private JspAttribute page;
 1033   
 1034           public IncludeAction(Attributes attrs, Mark start, Node parent) {
 1035               this(JSP_INCLUDE_ACTION, attrs, null, null, start, parent);
 1036           }
 1037   
 1038           public IncludeAction(String qName, Attributes attrs,
 1039                   Attributes nonTaglibXmlnsAttrs, Attributes taglibAttrs,
 1040                   Mark start, Node parent) {
 1041               super(qName, INCLUDE_ACTION, attrs, nonTaglibXmlnsAttrs,
 1042                       taglibAttrs, start, parent);
 1043           }
 1044   
 1045           public void accept(Visitor v) throws JasperException {
 1046               v.visit(this);
 1047           }
 1048   
 1049           public void setPage(JspAttribute page) {
 1050               this.page = page;
 1051           }
 1052   
 1053           public JspAttribute getPage() {
 1054               return page;
 1055           }
 1056       }
 1057   
 1058       /**
 1059        * Represents a forward action
 1060        */
 1061       public static class ForwardAction extends Node {
 1062   
 1063           private JspAttribute page;
 1064   
 1065           public ForwardAction(Attributes attrs, Mark start, Node parent) {
 1066               this(JSP_FORWARD_ACTION, attrs, null, null, start, parent);
 1067           }
 1068   
 1069           public ForwardAction(String qName, Attributes attrs,
 1070                   Attributes nonTaglibXmlnsAttrs, Attributes taglibAttrs,
 1071                   Mark start, Node parent) {
 1072               super(qName, FORWARD_ACTION, attrs, nonTaglibXmlnsAttrs,
 1073                       taglibAttrs, start, parent);
 1074           }
 1075   
 1076           public void accept(Visitor v) throws JasperException {
 1077               v.visit(this);
 1078           }
 1079   
 1080           public void setPage(JspAttribute page) {
 1081               this.page = page;
 1082           }
 1083   
 1084           public JspAttribute getPage() {
 1085               return page;
 1086           }
 1087       }
 1088   
 1089       /**
 1090        * Represents a getProperty action
 1091        */
 1092       public static class GetProperty extends Node {
 1093   
 1094           public GetProperty(Attributes attrs, Mark start, Node parent) {
 1095               this(JSP_GET_PROPERTY_ACTION, attrs, null, null, start, parent);
 1096           }
 1097   
 1098           public GetProperty(String qName, Attributes attrs,
 1099                   Attributes nonTaglibXmlnsAttrs, Attributes taglibAttrs,
 1100                   Mark start, Node parent) {
 1101               super(qName, GET_PROPERTY_ACTION, attrs, nonTaglibXmlnsAttrs,
 1102                       taglibAttrs, start, parent);
 1103           }
 1104   
 1105           public void accept(Visitor v) throws JasperException {
 1106               v.visit(this);
 1107           }
 1108       }
 1109   
 1110       /**
 1111        * Represents a setProperty action
 1112        */
 1113       public static class SetProperty extends Node {
 1114   
 1115           private JspAttribute value;
 1116   
 1117           public SetProperty(Attributes attrs, Mark start, Node parent) {
 1118               this(JSP_SET_PROPERTY_ACTION, attrs, null, null, start, parent);
 1119           }
 1120   
 1121           public SetProperty(String qName, Attributes attrs,
 1122                   Attributes nonTaglibXmlnsAttrs, Attributes taglibAttrs,
 1123                   Mark start, Node parent) {
 1124               super(qName, SET_PROPERTY_ACTION, attrs, nonTaglibXmlnsAttrs,
 1125                       taglibAttrs, start, parent);
 1126           }
 1127   
 1128           public void accept(Visitor v) throws JasperException {
 1129               v.visit(this);
 1130           }
 1131   
 1132           public void setValue(JspAttribute value) {
 1133               this.value = value;
 1134           }
 1135   
 1136           public JspAttribute getValue() {
 1137               return value;
 1138           }
 1139       }
 1140   
 1141       /**
 1142        * Represents a useBean action
 1143        */
 1144       public static class UseBean extends Node {
 1145   
 1146           JspAttribute beanName;
 1147   
 1148           public UseBean(Attributes attrs, Mark start, Node parent) {
 1149               this(JSP_USE_BEAN_ACTION, attrs, null, null, start, parent);
 1150           }
 1151   
 1152           public UseBean(String qName, Attributes attrs,
 1153                   Attributes nonTaglibXmlnsAttrs, Attributes taglibAttrs,
 1154                   Mark start, Node parent) {
 1155               super(qName, USE_BEAN_ACTION, attrs, nonTaglibXmlnsAttrs,
 1156                       taglibAttrs, start, parent);
 1157           }
 1158   
 1159           public void accept(Visitor v) throws JasperException {
 1160               v.visit(this);
 1161           }
 1162   
 1163           public void setBeanName(JspAttribute beanName) {
 1164               this.beanName = beanName;
 1165           }
 1166   
 1167           public JspAttribute getBeanName() {
 1168               return beanName;
 1169           }
 1170       }
 1171   
 1172       /**
 1173        * Represents a plugin action
 1174        */
 1175       public static class PlugIn extends Node {
 1176   
 1177           private JspAttribute width;
 1178   
 1179           private JspAttribute height;
 1180   
 1181           public PlugIn(Attributes attrs, Mark start, Node parent) {
 1182               this(JSP_PLUGIN_ACTION, attrs, null, null, start, parent);
 1183           }
 1184   
 1185           public PlugIn(String qName, Attributes attrs,
 1186                   Attributes nonTaglibXmlnsAttrs, Attributes taglibAttrs,
 1187                   Mark start, Node parent) {
 1188               super(qName, PLUGIN_ACTION, attrs, nonTaglibXmlnsAttrs,
 1189                       taglibAttrs, start, parent);
 1190           }
 1191   
 1192           public void accept(Visitor v) throws JasperException {
 1193               v.visit(this);
 1194           }
 1195   
 1196           public void setHeight(JspAttribute height) {
 1197               this.height = height;
 1198           }
 1199   
 1200           public void setWidth(JspAttribute width) {
 1201               this.width = width;
 1202           }
 1203   
 1204           public JspAttribute getHeight() {
 1205               return height;
 1206           }
 1207   
 1208           public JspAttribute getWidth() {
 1209               return width;
 1210           }
 1211       }
 1212   
 1213       /**
 1214        * Represents an uninterpreted tag, from a Jsp document
 1215        */
 1216       public static class UninterpretedTag extends Node {
 1217   
 1218           private JspAttribute[] jspAttrs;
 1219   
 1220           public UninterpretedTag(String qName, String localName,
 1221                   Attributes attrs, Attributes nonTaglibXmlnsAttrs,
 1222                   Attributes taglibAttrs, Mark start, Node parent) {
 1223               super(qName, localName, attrs, nonTaglibXmlnsAttrs, taglibAttrs,
 1224                       start, parent);
 1225           }
 1226   
 1227           public void accept(Visitor v) throws JasperException {
 1228               v.visit(this);
 1229           }
 1230   
 1231           public void setJspAttributes(JspAttribute[] jspAttrs) {
 1232               this.jspAttrs = jspAttrs;
 1233           }
 1234   
 1235           public JspAttribute[] getJspAttributes() {
 1236               return jspAttrs;
 1237           }
 1238       }
 1239   
 1240       /**
 1241        * Represents a <jsp:element>.
 1242        */
 1243       public static class JspElement extends Node {
 1244   
 1245           private JspAttribute[] jspAttrs;
 1246   
 1247           private JspAttribute nameAttr;
 1248   
 1249           public JspElement(Attributes attrs, Mark start, Node parent) {
 1250               this(JSP_ELEMENT_ACTION, attrs, null, null, start, parent);
 1251           }
 1252   
 1253           public JspElement(String qName, Attributes attrs,
 1254                   Attributes nonTaglibXmlnsAttrs, Attributes taglibAttrs,
 1255                   Mark start, Node parent) {
 1256               super(qName, ELEMENT_ACTION, attrs, nonTaglibXmlnsAttrs,
 1257                       taglibAttrs, start, parent);
 1258           }
 1259   
 1260           public void accept(Visitor v) throws JasperException {
 1261               v.visit(this);
 1262           }
 1263   
 1264           public void setJspAttributes(JspAttribute[] jspAttrs) {
 1265               this.jspAttrs = jspAttrs;
 1266           }
 1267   
 1268           public JspAttribute[] getJspAttributes() {
 1269               return jspAttrs;
 1270           }
 1271   
 1272           /*
 1273            * Sets the XML-style 'name' attribute
 1274            */
 1275           public void setNameAttribute(JspAttribute nameAttr) {
 1276               this.nameAttr = nameAttr;
 1277           }
 1278   
 1279           /*
 1280            * Gets the XML-style 'name' attribute
 1281            */
 1282           public JspAttribute getNameAttribute() {
 1283               return this.nameAttr;
 1284           }
 1285       }
 1286   
 1287       /**
 1288        * Represents a <jsp:output>.
 1289        */
 1290       public static class JspOutput extends Node {
 1291   
 1292           public JspOutput(String qName, Attributes attrs,
 1293                   Attributes nonTaglibXmlnsAttrs, Attributes taglibAttrs,
 1294                   Mark start, Node parent) {
 1295               super(qName, OUTPUT_ACTION, attrs, nonTaglibXmlnsAttrs,
 1296                       taglibAttrs, start, parent);
 1297           }
 1298   
 1299           public void accept(Visitor v) throws JasperException {
 1300               v.visit(this);
 1301           }
 1302       }
 1303   
 1304       /**
 1305        * Collected information about child elements. Used by nodes like CustomTag,
 1306        * JspBody, and NamedAttribute. The information is set in the Collector.
 1307        */
 1308       public static class ChildInfo {
 1309           private boolean scriptless; // true if the tag and its body
 1310   
 1311           // contain no scripting elements.
 1312           private boolean hasUseBean;
 1313   
 1314           private boolean hasIncludeAction;
 1315   
 1316           private boolean hasParamAction;
 1317   
 1318           private boolean hasSetProperty;
 1319   
 1320           private boolean hasScriptingVars;
 1321   
 1322           public void setScriptless(boolean s) {
 1323               scriptless = s;
 1324           }
 1325   
 1326           public boolean isScriptless() {
 1327               return scriptless;
 1328           }
 1329   
 1330           public void setHasUseBean(boolean u) {
 1331               hasUseBean = u;
 1332           }
 1333   
 1334           public boolean hasUseBean() {
 1335               return hasUseBean;
 1336           }
 1337   
 1338           public void setHasIncludeAction(boolean i) {
 1339               hasIncludeAction = i;
 1340           }
 1341   
 1342           public boolean hasIncludeAction() {
 1343               return hasIncludeAction;
 1344           }
 1345   
 1346           public void setHasParamAction(boolean i) {
 1347               hasParamAction = i;
 1348           }
 1349   
 1350           public boolean hasParamAction() {
 1351               return hasParamAction;
 1352           }
 1353   
 1354           public void setHasSetProperty(boolean s) {
 1355               hasSetProperty = s;
 1356           }
 1357   
 1358           public boolean hasSetProperty() {
 1359               return hasSetProperty;
 1360           }
 1361   
 1362           public void setHasScriptingVars(boolean s) {
 1363               hasScriptingVars = s;
 1364           }
 1365   
 1366           public boolean hasScriptingVars() {
 1367               return hasScriptingVars;
 1368           }
 1369       }
 1370   
 1371       /**
 1372        * Represents a custom tag
 1373        */
 1374       public static class CustomTag extends Node {
 1375   
 1376           private String uri;
 1377   
 1378           private String prefix;
 1379   
 1380           private JspAttribute[] jspAttrs;
 1381   
 1382           private TagData tagData;
 1383   
 1384           private String tagHandlerPoolName;
 1385   
 1386           private TagInfo tagInfo;
 1387   
 1388           private TagFileInfo tagFileInfo;
 1389   
 1390           private Class tagHandlerClass;
 1391   
 1392           private VariableInfo[] varInfos;
 1393   
 1394           private int customNestingLevel;
 1395   
 1396           private ChildInfo childInfo;
 1397   
 1398           private boolean implementsIterationTag;
 1399   
 1400           private boolean implementsBodyTag;
 1401   
 1402           private boolean implementsTryCatchFinally;
 1403   
 1404           private boolean implementsJspIdConsumer;
 1405   
 1406           private boolean implementsSimpleTag;
 1407   
 1408           private boolean implementsDynamicAttributes;
 1409   
 1410           private Vector atBeginScriptingVars;
 1411   
 1412           private Vector atEndScriptingVars;
 1413   
 1414           private Vector nestedScriptingVars;
 1415   
 1416           private Node.CustomTag customTagParent;
 1417   
 1418           private Integer numCount;
 1419   
 1420           private boolean useTagPlugin;
 1421   
 1422           private TagPluginContext tagPluginContext;
 1423   
 1424           /**
 1425            * The following two fields are used for holding the Java scriptlets
 1426            * that the tag plugins may generate. Meaningful only if useTagPlugin is
 1427            * true; Could move them into TagPluginContextImpl, but we'll need to
 1428            * cast tagPluginContext to TagPluginContextImpl all the time...
 1429            */
 1430           private Nodes atSTag;
 1431   
 1432           private Nodes atETag;
 1433   
 1434           /*
 1435            * Constructor for custom action implemented by tag handler.
 1436            */
 1437           public CustomTag(String qName, String prefix, String localName,
 1438                   String uri, Attributes attrs, Mark start, Node parent,
 1439                   TagInfo tagInfo, Class tagHandlerClass) {
 1440               this(qName, prefix, localName, uri, attrs, null, null, start,
 1441                       parent, tagInfo, tagHandlerClass);
 1442           }
 1443   
 1444           /*
 1445            * Constructor for custom action implemented by tag handler.
 1446            */
 1447           public CustomTag(String qName, String prefix, String localName,
 1448                   String uri, Attributes attrs, Attributes nonTaglibXmlnsAttrs,
 1449                   Attributes taglibAttrs, Mark start, Node parent,
 1450                   TagInfo tagInfo, Class tagHandlerClass) {
 1451               super(qName, localName, attrs, nonTaglibXmlnsAttrs, taglibAttrs,
 1452                       start, parent);
 1453   
 1454               this.uri = uri;
 1455               this.prefix = prefix;
 1456               this.tagInfo = tagInfo;
 1457               this.tagHandlerClass = tagHandlerClass;
 1458               this.customNestingLevel = makeCustomNestingLevel();
 1459               this.childInfo = new ChildInfo();
 1460   
 1461               this.implementsIterationTag = IterationTag.class
 1462                       .isAssignableFrom(tagHandlerClass);
 1463               this.implementsBodyTag = BodyTag.class
 1464                       .isAssignableFrom(tagHandlerClass);
 1465               this.implementsTryCatchFinally = TryCatchFinally.class
 1466                       .isAssignableFrom(tagHandlerClass);
 1467               this.implementsSimpleTag = SimpleTag.class
 1468                       .isAssignableFrom(tagHandlerClass);
 1469               this.implementsDynamicAttributes = DynamicAttributes.class
 1470                       .isAssignableFrom(tagHandlerClass);
 1471               this.implementsJspIdConsumer = JspIdConsumer.class
 1472                       .isAssignableFrom(tagHandlerClass);
 1473           }
 1474   
 1475           /*
 1476            * Constructor for custom action implemented by tag file.
 1477            */
 1478           public CustomTag(String qName, String prefix, String localName,
 1479                   String uri, Attributes attrs, Mark start, Node parent,
 1480                   TagFileInfo tagFileInfo) {
 1481               this(qName, prefix, localName, uri, attrs, null, null, start,
 1482                       parent, tagFileInfo);
 1483           }
 1484   
 1485           /*
 1486            * Constructor for custom action implemented by tag file.
 1487            */
 1488           public CustomTag(String qName, String prefix, String localName,
 1489                   String uri, Attributes attrs, Attributes nonTaglibXmlnsAttrs,
 1490                   Attributes taglibAttrs, Mark start, Node parent,
 1491                   TagFileInfo tagFileInfo) {
 1492   
 1493               super(qName, localName, attrs, nonTaglibXmlnsAttrs, taglibAttrs,
 1494                       start, parent);
 1495   
 1496               this.uri = uri;
 1497               this.prefix = prefix;
 1498               this.tagFileInfo = tagFileInfo;
 1499               this.tagInfo = tagFileInfo.getTagInfo();
 1500               this.customNestingLevel = makeCustomNestingLevel();
 1501               this.childInfo = new ChildInfo();
 1502   
 1503               this.implementsIterationTag = false;
 1504               this.implementsBodyTag = false;
 1505               this.implementsTryCatchFinally = false;
 1506               this.implementsSimpleTag = true;
 1507               this.implementsJspIdConsumer = false;
 1508               this.implementsDynamicAttributes = tagInfo.hasDynamicAttributes();
 1509           }
 1510   
 1511           public void accept(Visitor v) throws JasperException {
 1512               v.visit(this);
 1513           }
 1514   
 1515           /**
 1516            * @return The URI namespace that this custom action belongs to
 1517            */
 1518           public String getURI() {
 1519               return this.uri;
 1520           }
 1521   
 1522           /**
 1523            * @return The tag prefix
 1524            */
 1525           public String getPrefix() {
 1526               return prefix;
 1527           }
 1528   
 1529           public void setJspAttributes(JspAttribute[] jspAttrs) {
 1530               this.jspAttrs = jspAttrs;
 1531           }
 1532   
 1533           public TagAttributeInfo getTagAttributeInfo(String name) {
 1534               TagInfo info = this.getTagInfo();
 1535               if (info == null)
 1536                   return null;
 1537               TagAttributeInfo[] tai = info.getAttributes();
 1538               for (int i = 0; i < tai.length; i++) {
 1539                   if (tai[i].getName().equals(name)) {
 1540                       return tai[i];
 1541                   }
 1542               }
 1543               return null;
 1544           }
 1545   
 1546           public JspAttribute[] getJspAttributes() {
 1547               return jspAttrs;
 1548           }
 1549   
 1550           public ChildInfo getChildInfo() {
 1551               return childInfo;
 1552           }
 1553   
 1554           public void setTagData(TagData tagData) {
 1555               this.tagData = tagData;
 1556               this.varInfos = tagInfo.getVariableInfo(tagData);
 1557               if (this.varInfos == null) {
 1558                   this.varInfos = ZERO_VARIABLE_INFO;
 1559               }
 1560           }
 1561   
 1562           public TagData getTagData() {
 1563               return tagData;
 1564           }
 1565   
 1566           public void setTagHandlerPoolName(String s) {
 1567               tagHandlerPoolName = s;
 1568           }
 1569   
 1570           public String getTagHandlerPoolName() {
 1571               return tagHandlerPoolName;
 1572           }
 1573   
 1574           public TagInfo getTagInfo() {
 1575               return tagInfo;
 1576           }
 1577   
 1578           public TagFileInfo getTagFileInfo() {
 1579               return tagFileInfo;
 1580           }
 1581   
 1582           /*
 1583            * @return true if this custom action is supported by a tag file, false
 1584            * otherwise
 1585            */
 1586           public boolean isTagFile() {
 1587               return tagFileInfo != null;
 1588           }
 1589   
 1590           public Class getTagHandlerClass() {
 1591               return tagHandlerClass;
 1592           }
 1593   
 1594           public void setTagHandlerClass(Class hc) {
 1595               tagHandlerClass = hc;
 1596           }
 1597   
 1598           public boolean implementsIterationTag() {
 1599               return implementsIterationTag;
 1600           }
 1601   
 1602           public boolean implementsBodyTag() {
 1603               return implementsBodyTag;
 1604           }
 1605   
 1606           public boolean implementsTryCatchFinally() {
 1607               return implementsTryCatchFinally;
 1608           }
 1609   
 1610           public boolean implementsJspIdConsumer() {
 1611               return implementsJspIdConsumer;
 1612           }
 1613   
 1614           public boolean implementsSimpleTag() {
 1615               return implementsSimpleTag;
 1616           }
 1617   
 1618           public boolean implementsDynamicAttributes() {
 1619               return implementsDynamicAttributes;
 1620           }
 1621   
 1622           public TagVariableInfo[] getTagVariableInfos() {
 1623               return tagInfo.getTagVariableInfos();
 1624           }
 1625   
 1626           public VariableInfo[] getVariableInfos() {
 1627               return varInfos;
 1628           }
 1629   
 1630           public void setCustomTagParent(Node.CustomTag n) {
 1631               this.customTagParent = n;
 1632           }
 1633   
 1634           public Node.CustomTag getCustomTagParent() {
 1635               return this.customTagParent;
 1636           }
 1637   
 1638           public void setNumCount(Integer count) {
 1639               this.numCount = count;
 1640           }
 1641   
 1642           public Integer getNumCount() {
 1643               return this.numCount;
 1644           }
 1645   
 1646           public void setScriptingVars(Vector vec, int scope) {
 1647               switch (scope) {
 1648               case VariableInfo.AT_BEGIN:
 1649                   this.atBeginScriptingVars = vec;
 1650                   break;
 1651               case VariableInfo.AT_END:
 1652                   this.atEndScriptingVars = vec;
 1653                   break;
 1654               case VariableInfo.NESTED:
 1655                   this.nestedScriptingVars = vec;
 1656                   break;
 1657               }
 1658           }
 1659   
 1660           /*
 1661            * Gets the scripting variables for the given scope that need to be
 1662            * declared.
 1663            */
 1664           public Vector getScriptingVars(int scope) {
 1665               Vector vec = null;
 1666   
 1667               switch (scope) {
 1668               case VariableInfo.AT_BEGIN:
 1669                   vec = this.atBeginScriptingVars;
 1670                   break;
 1671               case VariableInfo.AT_END:
 1672                   vec = this.atEndScriptingVars;
 1673                   break;
 1674               case VariableInfo.NESTED:
 1675                   vec = this.nestedScriptingVars;
 1676                   break;
 1677               }
 1678   
 1679               return vec;
 1680           }
 1681   
 1682           /*
 1683            * Gets this custom tag's custom nesting level, which is given as the
 1684            * number of times this custom tag is nested inside itself.
 1685            */
 1686           public int getCustomNestingLevel() {
 1687               return customNestingLevel;
 1688           }
 1689   
 1690           /**
 1691            * Checks to see if the attribute of the given name is of type
 1692            * JspFragment.
 1693            */
 1694           public boolean checkIfAttributeIsJspFragment(String name) {
 1695               boolean result = false;
 1696   
 1697               TagAttributeInfo[] attributes = tagInfo.getAttributes();
 1698               for (int i = 0; i < attributes.length; i++) {
 1699                   if (attributes[i].getName().equals(name)
 1700                           && attributes[i].isFragment()) {
 1701                       result = true;
 1702                       break;
 1703                   }
 1704               }
 1705   
 1706               return result;
 1707           }
 1708   
 1709           public void setUseTagPlugin(boolean use) {
 1710               useTagPlugin = use;
 1711           }
 1712   
 1713           public boolean useTagPlugin() {
 1714               return useTagPlugin;
 1715           }
 1716   
 1717           public void setTagPluginContext(TagPluginContext tagPluginContext) {
 1718               this.tagPluginContext = tagPluginContext;
 1719           }
 1720   
 1721           public TagPluginContext getTagPluginContext() {
 1722               return tagPluginContext;
 1723           }
 1724   
 1725           public void setAtSTag(Nodes sTag) {
 1726               atSTag = sTag;
 1727           }
 1728   
 1729           public Nodes getAtSTag() {
 1730               return atSTag;
 1731           }
 1732   
 1733           public void setAtETag(Nodes eTag) {
 1734               atETag = eTag;
 1735           }
 1736   
 1737           public Nodes getAtETag() {
 1738               return atETag;
 1739           }
 1740   
 1741           /*
 1742            * Computes this custom tag's custom nesting level, which corresponds to
 1743            * the number of times this custom tag is nested inside itself.
 1744            * 
 1745            * Example:
 1746            * 
 1747            * <g:h> <a:b> -- nesting level 0 <c:d> <e:f> <a:b> -- nesting level 1
 1748            * <a:b> -- nesting level 2 </a:b> </a:b> <a:b> -- nesting level 1
 1749            * </a:b> </e:f> </c:d> </a:b> </g:h>
 1750            * 
 1751            * @return Custom tag's nesting level
 1752            */
 1753           private int makeCustomNestingLevel() {
 1754               int n = 0;
 1755               Node p = parent;
 1756               while (p != null) {
 1757                   if ((p instanceof Node.CustomTag)
 1758                           && qName.equals(((Node.CustomTag) p).qName)) {
 1759                       n++;
 1760                   }
 1761                   p = p.parent;
 1762               }
 1763               return n;
 1764           }
 1765   
 1766           /**
 1767            * Returns true if this custom action has an empty body, and false
 1768            * otherwise.
 1769            * 
 1770            * A custom action is considered to have an empty body if the following
 1771            * holds true: - getBody() returns null, or - all immediate children are
 1772            * jsp:attribute actions, or - the action's jsp:body is empty.
 1773            */
 1774           public boolean hasEmptyBody() {
 1775               boolean hasEmptyBody = true;
 1776               Nodes nodes = getBody();
 1777               if (nodes != null) {
 1778                   int numChildNodes = nodes.size();
 1779                   for (int i = 0; i < numChildNodes; i++) {
 1780                       Node n = nodes.getNode(i);
 1781                       if (!(n instanceof NamedAttribute)) {
 1782                           if (n instanceof JspBody) {
 1783                               hasEmptyBody = (n.getBody() == null);
 1784                           } else {
 1785                               hasEmptyBody = false;
 1786                           }
 1787                           break;
 1788                       }
 1789                   }
 1790               }
 1791   
 1792               return hasEmptyBody;
 1793           }
 1794       }
 1795   
 1796       /**
 1797        * Used as a placeholder for the evaluation code of a custom action
 1798        * attribute (used by the tag plugin machinery only).
 1799        */
 1800       public static class AttributeGenerator extends Node {
 1801           String name; // name of the attribute
 1802   
 1803           CustomTag tag; // The tag this attribute belongs to
 1804   
 1805           public AttributeGenerator(Mark start, String name, CustomTag tag) {
 1806               super(start, null);
 1807               this.name = name;
 1808               this.tag = tag;
 1809           }
 1810   
 1811           public void accept(Visitor v) throws JasperException {
 1812               v.visit(this);
 1813           }
 1814   
 1815           public String getName() {
 1816               return name;
 1817           }
 1818   
 1819           public CustomTag getTag() {
 1820               return tag;
 1821           }
 1822       }
 1823   
 1824       /**
 1825        * Represents the body of a &lt;jsp:text&gt; element
 1826        */
 1827       public static class JspText extends Node {
 1828   
 1829           public JspText(String qName, Attributes nonTaglibXmlnsAttrs,
 1830                   Attributes taglibAttrs, Mark start, Node parent) {
 1831               super(qName, TEXT_ACTION, null, nonTaglibXmlnsAttrs, taglibAttrs,
 1832                       start, parent);
 1833           }
 1834   
 1835           public void accept(Visitor v) throws JasperException {
 1836               v.visit(this);
 1837           }
 1838       }
 1839   
 1840       /**
 1841        * Represents a Named Attribute (&lt;jsp:attribute&gt;)
 1842        */
 1843       public static class NamedAttribute extends Node {
 1844   
 1845           // A unique temporary variable name suitable for code generation
 1846           private String temporaryVariableName;
 1847   
 1848           // True if this node is to be trimmed, or false otherwise
 1849           private boolean trim = true;
 1850   
 1851           private ChildInfo childInfo;
 1852   
 1853           private String name;
 1854   
 1855           private String localName;
 1856   
 1857           private String prefix;
 1858   
 1859           public NamedAttribute(Attributes attrs, Mark start, Node parent) {
 1860               this(JSP_ATTRIBUTE_ACTION, attrs, null, null, start, parent);
 1861           }
 1862   
 1863           public NamedAttribute(String qName, Attributes attrs,
 1864                   Attributes nonTaglibXmlnsAttrs, Attributes taglibAttrs,
 1865                   Mark start, Node parent) {
 1866   
 1867               super(qName, ATTRIBUTE_ACTION, attrs, nonTaglibXmlnsAttrs,
 1868                       taglibAttrs, start, parent);
 1869               if ("false".equals(this.getAttributeValue("trim"))) {
 1870                   // (if null or true, leave default of true)
 1871                   trim = false;
 1872               }
 1873               childInfo = new ChildInfo();
 1874               name = this.getAttributeValue("name");
 1875               if (name != null) {
 1876                   // Mandatary attribute "name" will be checked in Validator
 1877                   localName = name;
 1878                   int index = name.indexOf(':');
 1879                   if (index != -1) {
 1880                       prefix = name.substring(0, index);
 1881                       localName = name.substring(index + 1);
 1882                   }
 1883               }
 1884           }
 1885   
 1886           public void accept(Visitor v) throws JasperException {
 1887               v.visit(this);
 1888           }
 1889   
 1890           public String getName() {
 1891               return this.name;
 1892           }
 1893   
 1894           public String getLocalName() {
 1895               return this.localName;
 1896           }
 1897   
 1898           public String getPrefix() {
 1899               return this.prefix;
 1900           }
 1901   
 1902           public ChildInfo getChildInfo() {
 1903               return this.childInfo;
 1904           }
 1905   
 1906           public boolean isTrim() {
 1907               return trim;
 1908           }
 1909   
 1910           /**
 1911            * @return A unique temporary variable name to store the result in.
 1912            *         (this probably could go elsewhere, but it's convenient here)
 1913            */
 1914           public String getTemporaryVariableName() {
 1915               if (temporaryVariableName == null) {
 1916                   temporaryVariableName = JspUtil.nextTemporaryVariableName();
 1917               }
 1918               return temporaryVariableName;
 1919           }
 1920   
 1921           /*
 1922            * Get the attribute value from this named attribute (<jsp:attribute>).
 1923            * Since this method is only for attributes that are not rtexpr, we can
 1924            * assume the body of the jsp:attribute is a template text.
 1925            */
 1926           public String getText() {
 1927   
 1928               class AttributeVisitor extends Visitor {
 1929                   String attrValue = null;
 1930   
 1931                   public void visit(TemplateText txt) {
 1932                       attrValue = new String(txt.getText());
 1933                   }
 1934   
 1935                   public String getAttrValue() {
 1936                       return attrValue;
 1937                   }
 1938               }
 1939   
 1940               // According to JSP 2.0, if the body of the <jsp:attribute>
 1941               // action is empty, it is equivalent of specifying "" as the value
 1942               // of the attribute.
 1943               String text = "";
 1944               if (getBody() != null) {
 1945                   AttributeVisitor attributeVisitor = new AttributeVisitor();
 1946                   try {
 1947                       getBody().visit(attributeVisitor);
 1948                   } catch (JasperException e) {
 1949                   }
 1950                   text = attributeVisitor.getAttrValue();
 1951               }
 1952   
 1953               return text;
 1954           }
 1955       }
 1956   
 1957       /**
 1958        * Represents a JspBody node (&lt;jsp:body&gt;)
 1959        */
 1960       public static class JspBody extends Node {
 1961   
 1962           private ChildInfo childInfo;
 1963   
 1964           public JspBody(Mark start, Node parent) {
 1965               this(JSP_BODY_ACTION, null, null, start, parent);
 1966           }
 1967   
 1968           public JspBody(String qName, Attributes nonTaglibXmlnsAttrs,
 1969                   Attributes taglibAttrs, Mark start, Node parent) {
 1970               super(qName, BODY_ACTION, null, nonTaglibXmlnsAttrs, taglibAttrs,
 1971                       start, parent);
 1972               this.childInfo = new ChildInfo();
 1973           }
 1974   
 1975           public void accept(Visitor v) throws JasperException {
 1976               v.visit(this);
 1977           }
 1978   
 1979           public ChildInfo getChildInfo() {
 1980               return childInfo;
 1981           }
 1982       }
 1983   
 1984       /**
 1985        * Represents a template text string
 1986        */
 1987       public static class TemplateText extends Node {
 1988   
 1989           private ArrayList extraSmap = null;
 1990   
 1991           public TemplateText(String text, Mark start, Node parent) {
 1992               super(null, null, text, start, parent);
 1993           }
 1994   
 1995           public void accept(Visitor v) throws JasperException {
 1996               v.visit(this);
 1997           }
 1998   
 1999           /**
 2000            * Trim all whitespace from the left of the template text
 2001            */
 2002           public void ltrim() {
 2003               int index = 0;
 2004               while ((index < text.length()) && (text.charAt(index) <= ' ')) {
 2005                   index++;
 2006               }
 2007               text = text.substring(index);
 2008           }
 2009   
 2010           public void setText(String text) {
 2011               this.text = text;
 2012           }
 2013   
 2014           /**
 2015            * Trim all whitespace from the right of the template text
 2016            */
 2017           public void rtrim() {
 2018               int index = text.length();
 2019               while ((index > 0) && (text.charAt(index - 1) <= ' ')) {
 2020                   index--;
 2021               }
 2022               text = text.substring(0, index);
 2023           }
 2024   
 2025           /**
 2026            * Returns true if this template text contains whitespace only.
 2027            */
 2028           public boolean isAllSpace() {
 2029               boolean isAllSpace = true;
 2030               for (int i = 0; i < text.length(); i++) {
 2031                   if (!Character.isWhitespace(text.charAt(i))) {
 2032                       isAllSpace = false;
 2033                       break;
 2034                   }
 2035               }
 2036               return isAllSpace;
 2037           }
 2038   
 2039           /**
 2040            * Add a source to Java line mapping
 2041            * 
 2042            * @param srcLine
 2043            *            The postion of the source line, relative to the line at
 2044            *            the start of this node. The corresponding java line is
 2045            *            assumed to be consecutive, i.e. one more than the last.
 2046            */
 2047           public void addSmap(int srcLine) {
 2048               if (extraSmap == null) {
 2049                   extraSmap = new ArrayList();
 2050               }
 2051               extraSmap.add(new Integer(srcLine));
 2052           }
 2053   
 2054           public ArrayList getExtraSmap() {
 2055               return extraSmap;
 2056           }
 2057       }
 2058   
 2059       /***************************************************************************
 2060        * Auxillary classes used in Node
 2061        */
 2062   
 2063       /**
 2064        * Represents attributes that can be request time expressions.
 2065        * 
 2066        * Can either be a plain attribute, an attribute that represents a request
 2067        * time expression value, or a named attribute (specified using the
 2068        * jsp:attribute standard action).
 2069        */
 2070   
 2071       public static class JspAttribute {
 2072   
 2073           private String qName;
 2074   
 2075           private String uri;
 2076   
 2077           private String localName;
 2078   
 2079           private String value;
 2080   
 2081           private boolean expression;
 2082   
 2083           private boolean dynamic;
 2084   
 2085           private final ELNode.Nodes el;
 2086   
 2087           private final TagAttributeInfo tai;
 2088   
 2089           // If true, this JspAttribute represents a <jsp:attribute>
 2090           private boolean namedAttribute;
 2091   
 2092           // The node in the parse tree for the NamedAttribute
 2093           private NamedAttribute namedAttributeNode;
 2094   
 2095           JspAttribute(TagAttributeInfo tai, String qName, String uri,
 2096                   String localName, String value, boolean expr, ELNode.Nodes el,
 2097                   boolean dyn) {
 2098               this.qName = qName;
 2099               this.uri = uri;
 2100               this.localName = localName;
 2101               this.value = value;
 2102               this.namedAttributeNode = null;
 2103               this.expression = expr;
 2104               this.el = el;
 2105               this.dynamic = dyn;
 2106               this.namedAttribute = false;
 2107               this.tai = tai;
 2108           }
 2109   
 2110           /**
 2111            * Allow node to validate itself
 2112            * 
 2113            * @param ef
 2114            * @param ctx
 2115            * @throws ELException
 2116            */
 2117           public void validateEL(ExpressionFactory ef, ELContext ctx)
 2118                   throws ELException {
 2119               if (this.el != null) {
 2120                   // determine exact type
 2121                   ValueExpression ve = ef.createValueExpression(ctx, this.value,
 2122                           String.class);
 2123               }
 2124           }
 2125   
 2126           /**
 2127            * Use this constructor if the JspAttribute represents a named
 2128            * attribute. In this case, we have to store the nodes of the body of
 2129            * the attribute.
 2130            */
 2131           JspAttribute(NamedAttribute na, TagAttributeInfo tai, boolean dyn) {
 2132               this.qName = na.getName();
 2133               this.localName = na.getLocalName();
 2134               this.value = null;
 2135               this.namedAttributeNode = na;
 2136               this.expression = false;
 2137               this.el = null;
 2138               this.dynamic = dyn;
 2139               this.namedAttribute = true;
 2140               this.tai = null;
 2141           }
 2142   
 2143           /**
 2144            * @return The name of the attribute
 2145            */
 2146           public String getName() {
 2147               return qName;
 2148           }
 2149   
 2150           /**
 2151            * @return The local name of the attribute
 2152            */
 2153           public String getLocalName() {
 2154               return localName;
 2155           }
 2156   
 2157           /**
 2158            * @return The namespace of the attribute, or null if in the default
 2159            *         namespace
 2160            */
 2161           public String getURI() {
 2162               return uri;
 2163           }
 2164   
 2165           public TagAttributeInfo getTagAttributeInfo() {
 2166               return this.tai;
 2167           }
 2168   
 2169           /**
 2170            * 
 2171            * @return return true if there's TagAttributeInfo meaning we need to
 2172            *         assign a ValueExpression
 2173            */
 2174           public boolean isDeferredInput() {
 2175               return (this.tai != null) ? this.tai.isDeferredValue() : false;
 2176           }
 2177   
 2178           /**
 2179            * 
 2180            * @return return true if there's TagAttributeInfo meaning we need to
 2181            *         assign a MethodExpression
 2182            */
 2183           public boolean isDeferredMethodInput() {
 2184               return (this.tai != null) ? this.tai.isDeferredMethod() : false;
 2185           }
 2186   
 2187           public String getExpectedTypeName() {
 2188               if (this.tai != null) {
 2189                   if (this.isDeferredInput()) {
 2190                       return this.tai.getExpectedTypeName();
 2191                   } else if (this.isDeferredMethodInput()) {
 2192                       String m = this.tai.getMethodSignature();
 2193                       if (m != null) {
 2194                           int rti = m.trim().indexOf(' ');
 2195                           if (rti > 0) {
 2196                               return m.substring(0, rti).trim();
 2197                           }
 2198                       }
 2199                   }
 2200               }
 2201               return "java.lang.Object";
 2202           }
 2203           
 2204           public String[] getParameterTypeNames() {
 2205               if (this.tai != null) {
 2206                   if (this.isDeferredMethodInput()) {
 2207                       String m = this.tai.getMethodSignature();
 2208                       if (m != null) {
 2209                           m = m.trim();
 2210                           m = m.substring(m.indexOf('(') + 1);
 2211                           m = m.substring(0, m.length() - 1);
 2212                           if (m.trim().length() > 0) {
 2213                               String[] p = m.split(",");
 2214                               for (int i = 0; i < p.length; i++) {
 2215                                   p[i] = p[i].trim();
 2216                               }
 2217                               return p;
 2218                           }
 2219                       }
 2220                   }
 2221               }
 2222               return new String[0];
 2223           }
 2224   
 2225           /**
 2226            * Only makes sense if namedAttribute is false.
 2227            * 
 2228            * @return the value for the attribute, or the expression string
 2229            *         (stripped of "<%=", "%>", "%=", or "%" but containing "${"
 2230            *         and "}" for EL expressions)
 2231            */
 2232           public String getValue() {
 2233               return value;
 2234           }
 2235   
 2236           /**
 2237            * Only makes sense if namedAttribute is true.
 2238            * 
 2239            * @return the nodes that evaluate to the body of this attribute.
 2240            */
 2241           public NamedAttribute getNamedAttributeNode() {
 2242               return namedAttributeNode;
 2243           }
 2244   
 2245           /**
 2246            * @return true if the value represents a traditional rtexprvalue
 2247            */
 2248           public boolean isExpression() {
 2249               return expression;
 2250           }
 2251   
 2252           /**
 2253            * @return true if the value represents a NamedAttribute value.
 2254            */
 2255           public boolean isNamedAttribute() {
 2256               return namedAttribute;
 2257           }
 2258   
 2259           /**
 2260            * @return true if the value represents an expression that should be fed
 2261            *         to the expression interpreter
 2262            * @return false for string literals or rtexprvalues that should not be
 2263            *         interpreted or reevaluated
 2264            */
 2265           public boolean isELInterpreterInput() {
 2266               return el != null || this.isDeferredInput()
 2267                       || this.isDeferredMethodInput();
 2268           }
 2269   
 2270           /**
 2271            * @return true if the value is a string literal known at translation
 2272            *         time.
 2273            */
 2274           public boolean isLiteral() {
 2275               return !expression && (el != null) && !namedAttribute;
 2276           }
 2277   
 2278           /**
 2279            * XXX
 2280            */
 2281           public boolean isDynamic() {
 2282               return dynamic;
 2283           }
 2284   
 2285           public ELNode.Nodes getEL() {
 2286               return el;
 2287           }
 2288       }
 2289   
 2290       /**
 2291        * An ordered list of Node, used to represent the body of an element, or a
 2292        * jsp page of jsp document.
 2293        */
 2294       public static class Nodes {
 2295   
 2296           private List list;
 2297   
 2298           private Node.Root root; // null if this is not a page
 2299   
 2300           private boolean generatedInBuffer;
 2301   
 2302           public Nodes() {
 2303               list = new Vector();
 2304           }
 2305   
 2306           public Nodes(Node.Root root) {
 2307               this.root = root;
 2308               list = new Vector();
 2309               list.add(root);
 2310           }
 2311   
 2312           /**
 2313            * Appends a node to the list
 2314            * 
 2315            * @param n
 2316            *            The node to add
 2317            */
 2318           public void add(Node n) {
 2319               list.add(n);
 2320               root = null;
 2321           }
 2322   
 2323           /**
 2324            * Removes the given node from the list.
 2325            * 
 2326            * @param n
 2327            *            The node to be removed
 2328            */
 2329           public void remove(Node n) {
 2330               list.remove(n);
 2331           }
 2332   
 2333           /**
 2334            * Visit the nodes in the list with the supplied visitor
 2335            * 
 2336            * @param v
 2337            *            The visitor used
 2338            */
 2339           public void visit(Visitor v) throws JasperException {
 2340               Iterator iter = list.iterator();
 2341               while (iter.hasNext()) {
 2342                   Node n = (Node) iter.next();
 2343                   n.accept(v);
 2344               }
 2345           }
 2346   
 2347           public int size() {
 2348               return list.size();
 2349           }
 2350   
 2351           public Node getNode(int index) {
 2352               Node n = null;
 2353               try {
 2354                   n = (Node) list.get(index);
 2355               } catch (ArrayIndexOutOfBoundsException e) {
 2356               }
 2357               return n;
 2358           }
 2359   
 2360           public Node.Root getRoot() {
 2361               return root;
 2362           }
 2363   
 2364           public boolean isGeneratedInBuffer() {
 2365               return generatedInBuffer;
 2366           }
 2367   
 2368           public void setGeneratedInBuffer(boolean g) {
 2369               generatedInBuffer = g;
 2370           }
 2371       }
 2372   
 2373       /**
 2374        * A visitor class for visiting the node. This class also provides the
 2375        * default action (i.e. nop) for each of the child class of the Node. An
 2376        * actual visitor should extend this class and supply the visit method for
 2377        * the nodes that it cares.
 2378        */
 2379       public static class Visitor {
 2380   
 2381           /**
 2382            * This method provides a place to put actions that are common to all
 2383            * nodes. Override this in the child visitor class if need to.
 2384            */
 2385           protected void doVisit(Node n) throws JasperException {
 2386           }
 2387   
 2388           /**
 2389            * Visit the body of a node, using the current visitor
 2390            */
 2391           protected void visitBody(Node n) throws JasperException {
 2392               if (n.getBody() != null) {
 2393                   n.getBody().visit(this);
 2394               }
 2395           }
 2396   
 2397           public void visit(Root n) throws JasperException {
 2398               doVisit(n);
 2399               visitBody(n);
 2400           }
 2401   
 2402           public void visit(JspRoot n) throws JasperException {
 2403               doVisit(n);
 2404               visitBody(n);
 2405           }
 2406   
 2407           public void visit(PageDirective n) throws JasperException {
 2408               doVisit(n);
 2409           }
 2410   
 2411           public void visit(TagDirective n) throws JasperException {
 2412               doVisit(n);
 2413           }
 2414   
 2415           public void visit(IncludeDirective n) throws JasperException {
 2416               doVisit(n);
 2417               visitBody(n);
 2418           }
 2419   
 2420           public void visit(TaglibDirective n) throws JasperException {
 2421               doVisit(n);
 2422           }
 2423   
 2424           public void visit(AttributeDirective n) throws JasperException {
 2425               doVisit(n);
 2426           }
 2427   
 2428           public void visit(VariableDirective n) throws JasperException {
 2429               doVisit(n);
 2430           }
 2431   
 2432           public void visit(Comment n) throws JasperException {
 2433               doVisit(n);
 2434           }
 2435   
 2436           public void visit(Declaration n) throws JasperException {
 2437               doVisit(n);
 2438           }
 2439   
 2440           public void visit(Expression n) throws JasperException {
 2441               doVisit(n);
 2442           }
 2443   
 2444           public void visit(Scriptlet n) throws JasperException {
 2445               doVisit(n);
 2446           }
 2447   
 2448           public void visit(ELExpression n) throws JasperException {
 2449               doVisit(n);
 2450           }
 2451   
 2452           public void visit(IncludeAction n) throws JasperException {
 2453               doVisit(n);
 2454               visitBody(n);
 2455           }
 2456   
 2457           public void visit(ForwardAction n) throws JasperException {
 2458               doVisit(n);
 2459               visitBody(n);
 2460           }
 2461   
 2462           public void visit(GetProperty n) throws JasperException {
 2463               doVisit(n);
 2464               visitBody(n);
 2465           }
 2466   
 2467           public void visit(SetProperty n) throws JasperException {
 2468               doVisit(n);
 2469               visitBody(n);
 2470           }
 2471   
 2472           public void visit(ParamAction n) throws JasperException {
 2473               doVisit(n);
 2474               visitBody(n);
 2475           }
 2476   
 2477           public void visit(ParamsAction n) throws JasperException {
 2478               doVisit(n);
 2479               visitBody(n);
 2480           }
 2481   
 2482           public void visit(FallBackAction n) throws JasperException {
 2483               doVisit(n);
 2484               visitBody(n);
 2485           }
 2486   
 2487           public void visit(UseBean n) throws JasperException {
 2488               doVisit(n);
 2489               visitBody(n);
 2490           }
 2491   
 2492           public void visit(PlugIn n) throws JasperException {
 2493               doVisit(n);
 2494               visitBody(n);
 2495           }
 2496   
 2497           public void visit(CustomTag n) throws JasperException {
 2498               doVisit(n);
 2499               visitBody(n);
 2500           }
 2501   
 2502           public void visit(UninterpretedTag n) throws JasperException {
 2503               doVisit(n);
 2504               visitBody(n);
 2505           }
 2506   
 2507           public void visit(JspElement n) throws JasperException {
 2508               doVisit(n);
 2509               visitBody(n);
 2510           }
 2511   
 2512           public void visit(JspText n) throws JasperException {
 2513               doVisit(n);
 2514               visitBody(n);
 2515           }
 2516   
 2517           public void visit(NamedAttribute n) throws JasperException {
 2518               doVisit(n);
 2519               visitBody(n);
 2520           }
 2521   
 2522           public void visit(JspBody n) throws JasperException {
 2523               doVisit(n);
 2524               visitBody(n);
 2525           }
 2526   
 2527           public void visit(InvokeAction n) throws JasperException {
 2528               doVisit(n);
 2529               visitBody(n);
 2530           }
 2531   
 2532           public void visit(DoBodyAction n) throws JasperException {
 2533               doVisit(n);
 2534               visitBody(n);
 2535           }
 2536   
 2537           public void visit(TemplateText n) throws JasperException {
 2538               doVisit(n);
 2539           }
 2540   
 2541           public void visit(JspOutput n) throws JasperException {
 2542               doVisit(n);
 2543           }
 2544   
 2545           public void visit(AttributeGenerator n) throws JasperException {
 2546               doVisit(n);
 2547           }
 2548       }
 2549   }

Save This Page
Home » apache-tomcat-6.0.16-src » org.apache » jasper » compiler » [javadoc | source]