0001: /*
0002: * Copyright 1999,2004 The Apache Software Foundation.
0003: *
0004: * Licensed under the Apache License, Version 2.0 (the "License");
0005: * you may not use this file except in compliance with the License.
0006: * You may obtain a copy of the License at
0007: *
0008: * http://www.apache.org/licenses/LICENSE-2.0
0009: *
0010: * Unless required by applicable law or agreed to in writing, software
0011: * distributed under the License is distributed on an "AS IS" BASIS,
0012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0013: * See the License for the specific language governing permissions and
0014: * limitations under the License.
0015: */
0016:
0017: package org.apache.jasper.compiler;
0018:
0019: import java.util.Iterator;
0020: import java.util.List;
0021: import java.util.Vector;
0022: import java.util.ArrayList;
0023:
0024: import javax.servlet.jsp.tagext.BodyTag;
0025: import javax.servlet.jsp.tagext.DynamicAttributes;
0026: import javax.servlet.jsp.tagext.IterationTag;
0027: import javax.servlet.jsp.tagext.SimpleTag;
0028: import javax.servlet.jsp.tagext.TagAttributeInfo;
0029: import javax.servlet.jsp.tagext.TagData;
0030: import javax.servlet.jsp.tagext.TagFileInfo;
0031: import javax.servlet.jsp.tagext.TagInfo;
0032: import javax.servlet.jsp.tagext.TagVariableInfo;
0033: import javax.servlet.jsp.tagext.TryCatchFinally;
0034: import javax.servlet.jsp.tagext.VariableInfo;
0035:
0036: import org.apache.jasper.JasperException;
0037: import org.apache.jasper.compiler.tagplugin.TagPluginContext;
0038: import org.xml.sax.Attributes;
0039:
0040: /**
0041: * An internal data representation of a JSP page or a JSP docuement (XML).
0042: * Also included here is a visitor class for tranversing nodes.
0043: *
0044: * @author Kin-man Chung
0045: * @author Jan Luehe
0046: * @author Shawn Bayern
0047: * @author Mark Roth
0048: */
0049:
0050: abstract class Node implements TagConstants {
0051:
0052: private static final VariableInfo[] ZERO_VARIABLE_INFO = {};
0053:
0054: protected Attributes attrs;
0055:
0056: // xmlns attributes that represent tag libraries (only in XML syntax)
0057: protected Attributes taglibAttrs;
0058:
0059: /*
0060: * xmlns attributes that do not represent tag libraries
0061: * (only in XML syntax)
0062: */
0063: protected Attributes nonTaglibXmlnsAttrs;
0064:
0065: protected Nodes body;
0066: protected String text;
0067: protected Mark startMark;
0068: protected int beginJavaLine;
0069: protected int endJavaLine;
0070: protected Node parent;
0071: protected Nodes namedAttributeNodes; // cached for performance
0072: protected String qName;
0073: protected String localName;
0074: /*
0075: * The name of the inner class to which the codes for this node and
0076: * its body are generated. For instance, for <jsp:body> in foo.jsp,
0077: * this is "foo_jspHelper". This is primarily used for communicating
0078: * such info from Generator to Smap generator.
0079: */
0080: protected String innerClassName;
0081:
0082: private boolean isDummy;
0083:
0084: /**
0085: * Zero-arg Constructor.
0086: */
0087: public Node() {
0088: this .isDummy = true;
0089: }
0090:
0091: /**
0092: * Constructor.
0093: *
0094: * @param start The location of the jsp page
0095: * @param parent The enclosing node
0096: */
0097: public Node(Mark start, Node parent) {
0098: this .startMark = start;
0099: this .isDummy = (start == null);
0100: addToParent(parent);
0101: }
0102:
0103: /**
0104: * Constructor.
0105: *
0106: * @param qName The action's qualified name
0107: * @param localName The action's local name
0108: * @param start The location of the jsp page
0109: * @param parent The enclosing node
0110: */
0111: public Node(String qName, String localName, Mark start, Node parent) {
0112: this .qName = qName;
0113: this .localName = localName;
0114: this .startMark = start;
0115: this .isDummy = (start == null);
0116: addToParent(parent);
0117: }
0118:
0119: /**
0120: * Constructor for Nodes parsed from standard syntax.
0121: *
0122: * @param qName The action's qualified name
0123: * @param localName The action's local name
0124: * @param attrs The attributes for this node
0125: * @param start The location of the jsp page
0126: * @param parent The enclosing node
0127: */
0128: public Node(String qName, String localName, Attributes attrs,
0129: Mark start, Node parent) {
0130: this .qName = qName;
0131: this .localName = localName;
0132: this .attrs = attrs;
0133: this .startMark = start;
0134: this .isDummy = (start == null);
0135: addToParent(parent);
0136: }
0137:
0138: /**
0139: * Constructor for Nodes parsed from XML syntax.
0140: *
0141: * @param qName The action's qualified name
0142: * @param localName The action's local name
0143: * @param attrs The action's attributes whose name does not start with
0144: * xmlns
0145: * @param nonTaglibXmlnsAttrs The action's xmlns attributes that do not
0146: * represent tag libraries
0147: * @param taglibAttrs The action's xmlns attributes that represent tag
0148: * libraries
0149: * @param start The location of the jsp page
0150: * @param parent The enclosing node
0151: */
0152: public Node(String qName, String localName, Attributes attrs,
0153: Attributes nonTaglibXmlnsAttrs, Attributes taglibAttrs,
0154: Mark start, Node parent) {
0155: this .qName = qName;
0156: this .localName = localName;
0157: this .attrs = attrs;
0158: this .nonTaglibXmlnsAttrs = nonTaglibXmlnsAttrs;
0159: this .taglibAttrs = taglibAttrs;
0160: this .startMark = start;
0161: this .isDummy = (start == null);
0162: addToParent(parent);
0163: }
0164:
0165: /*
0166: * Constructor.
0167: *
0168: * @param qName The action's qualified name
0169: * @param localName The action's local name
0170: * @param text The text associated with this node
0171: * @param start The location of the jsp page
0172: * @param parent The enclosing node
0173: */
0174: public Node(String qName, String localName, String text,
0175: Mark start, Node parent) {
0176: this .qName = qName;
0177: this .localName = localName;
0178: this .text = text;
0179: this .startMark = start;
0180: this .isDummy = (start == null);
0181: addToParent(parent);
0182: }
0183:
0184: public String getQName() {
0185: return this .qName;
0186: }
0187:
0188: public String getLocalName() {
0189: return this .localName;
0190: }
0191:
0192: /*
0193: * Gets this Node's attributes.
0194: *
0195: * In the case of a Node parsed from standard syntax, this method returns
0196: * all the Node's attributes.
0197: *
0198: * In the case of a Node parsed from XML syntax, this method returns only
0199: * those attributes whose name does not start with xmlns.
0200: */
0201: public Attributes getAttributes() {
0202: return this .attrs;
0203: }
0204:
0205: /*
0206: * Gets this Node's xmlns attributes that represent tag libraries
0207: * (only meaningful for Nodes parsed from XML syntax)
0208: */
0209: public Attributes getTaglibAttributes() {
0210: return this .taglibAttrs;
0211: }
0212:
0213: /*
0214: * Gets this Node's xmlns attributes that do not represent tag libraries
0215: * (only meaningful for Nodes parsed from XML syntax)
0216: */
0217: public Attributes getNonTaglibXmlnsAttributes() {
0218: return this .nonTaglibXmlnsAttrs;
0219: }
0220:
0221: public void setAttributes(Attributes attrs) {
0222: this .attrs = attrs;
0223: }
0224:
0225: public String getAttributeValue(String name) {
0226: return (attrs == null) ? null : attrs.getValue(name);
0227: }
0228:
0229: /**
0230: * Get the attribute that is non request time expression, either
0231: * from the attribute of the node, or from a jsp:attrbute
0232: */
0233: public String getTextAttribute(String name) {
0234:
0235: String attr = getAttributeValue(name);
0236: if (attr != null) {
0237: return attr;
0238: }
0239:
0240: NamedAttribute namedAttribute = getNamedAttributeNode(name);
0241: if (namedAttribute == null) {
0242: return null;
0243: }
0244:
0245: return namedAttribute.getText();
0246: }
0247:
0248: /**
0249: * Searches all subnodes of this node for jsp:attribute standard
0250: * actions with the given name, and returns the NamedAttribute node
0251: * of the matching named attribute, nor null if no such node is found.
0252: * <p>
0253: * This should always be called and only be called for nodes that
0254: * accept dynamic runtime attribute expressions.
0255: */
0256: public NamedAttribute getNamedAttributeNode(String name) {
0257: NamedAttribute result = null;
0258:
0259: // Look for the attribute in NamedAttribute children
0260: Nodes nodes = getNamedAttributeNodes();
0261: int numChildNodes = nodes.size();
0262: for (int i = 0; i < numChildNodes; i++) {
0263: NamedAttribute na = (NamedAttribute) nodes.getNode(i);
0264: boolean found = false;
0265: int index = name.indexOf(':');
0266: if (index != -1) {
0267: // qualified name
0268: found = na.getName().equals(name);
0269: } else {
0270: found = na.getLocalName().equals(name);
0271: }
0272: if (found) {
0273: result = na;
0274: break;
0275: }
0276: }
0277:
0278: return result;
0279: }
0280:
0281: /**
0282: * Searches all subnodes of this node for jsp:attribute standard
0283: * actions, and returns that set of nodes as a Node.Nodes object.
0284: *
0285: * @return Possibly empty Node.Nodes object containing any jsp:attribute
0286: * subnodes of this Node
0287: */
0288: public Node.Nodes getNamedAttributeNodes() {
0289:
0290: if (namedAttributeNodes != null) {
0291: return namedAttributeNodes;
0292: }
0293:
0294: Node.Nodes result = new Node.Nodes();
0295:
0296: // Look for the attribute in NamedAttribute children
0297: Nodes nodes = getBody();
0298: if (nodes != null) {
0299: int numChildNodes = nodes.size();
0300: for (int i = 0; i < numChildNodes; i++) {
0301: Node n = nodes.getNode(i);
0302: if (n instanceof NamedAttribute) {
0303: result.add(n);
0304: } else if (!(n instanceof Comment)) {
0305: // Nothing can come before jsp:attribute, and only
0306: // jsp:body can come after it.
0307: break;
0308: }
0309: }
0310: }
0311:
0312: namedAttributeNodes = result;
0313: return result;
0314: }
0315:
0316: public Nodes getBody() {
0317: return body;
0318: }
0319:
0320: public void setBody(Nodes body) {
0321: this .body = body;
0322: }
0323:
0324: public String getText() {
0325: return text;
0326: }
0327:
0328: public Mark getStart() {
0329: return startMark;
0330: }
0331:
0332: public Node getParent() {
0333: return parent;
0334: }
0335:
0336: public int getBeginJavaLine() {
0337: return beginJavaLine;
0338: }
0339:
0340: public void setBeginJavaLine(int begin) {
0341: beginJavaLine = begin;
0342: }
0343:
0344: public int getEndJavaLine() {
0345: return endJavaLine;
0346: }
0347:
0348: public void setEndJavaLine(int end) {
0349: endJavaLine = end;
0350: }
0351:
0352: public boolean isDummy() {
0353: return isDummy;
0354: }
0355:
0356: public Node.Root getRoot() {
0357: Node n = this ;
0358: while (!(n instanceof Node.Root)) {
0359: n = n.getParent();
0360: }
0361: return (Node.Root) n;
0362: }
0363:
0364: public String getInnerClassName() {
0365: return innerClassName;
0366: }
0367:
0368: public void setInnerClassName(String icn) {
0369: innerClassName = icn;
0370: }
0371:
0372: /**
0373: * Selects and invokes a method in the visitor class based on the node
0374: * type. This is abstract and should be overrode by the extending classes.
0375: * @param v The visitor class
0376: */
0377: abstract void accept(Visitor v) throws JasperException;
0378:
0379: //*********************************************************************
0380: // Private utility methods
0381:
0382: /*
0383: * Adds this Node to the body of the given parent.
0384: */
0385: private void addToParent(Node parent) {
0386: if (parent != null) {
0387: this .parent = parent;
0388: Nodes parentBody = parent.getBody();
0389: if (parentBody == null) {
0390: parentBody = new Nodes();
0391: parent.setBody(parentBody);
0392: }
0393: parentBody.add(this );
0394: }
0395: }
0396:
0397: /*********************************************************************
0398: * Child classes
0399: */
0400:
0401: /**
0402: * Represents the root of a Jsp page or Jsp document
0403: */
0404: public static class Root extends Node {
0405:
0406: private Root parentRoot;
0407: private boolean isXmlSyntax;
0408:
0409: // Source encoding of the page containing this Root
0410: private String pageEnc;
0411:
0412: // Page encoding specified in JSP config element
0413: private String jspConfigPageEnc;
0414:
0415: /*
0416: * Flag indicating if the default page encoding is being used (only
0417: * applicable with standard syntax).
0418: *
0419: * True if the page does not provide a page directive with a
0420: * 'contentType' attribute (or the 'contentType' attribute doesn't
0421: * have a CHARSET value), the page does not provide a page directive
0422: * with a 'pageEncoding' attribute, and there is no JSP configuration
0423: * element page-encoding whose URL pattern matches the page.
0424: */
0425: private boolean isDefaultPageEncoding;
0426:
0427: /*
0428: * Indicates whether an encoding has been explicitly specified in the
0429: * page's XML prolog (only used for pages in XML syntax).
0430: * This information is used to decide whether a translation error must
0431: * be reported for encoding conflicts.
0432: */
0433: private boolean isEncodingSpecifiedInProlog;
0434:
0435: /*
0436: * Constructor.
0437: */
0438: Root(Mark start, Node parent, boolean isXmlSyntax) {
0439: super (start, parent);
0440: this .isXmlSyntax = isXmlSyntax;
0441: this .qName = JSP_ROOT_ACTION;
0442: this .localName = ROOT_ACTION;
0443:
0444: // Figure out and set the parent root
0445: Node r = parent;
0446: while ((r != null) && !(r instanceof Node.Root))
0447: r = r.getParent();
0448: parentRoot = (Node.Root) r;
0449: }
0450:
0451: public void accept(Visitor v) throws JasperException {
0452: v.visit(this );
0453: }
0454:
0455: public boolean isXmlSyntax() {
0456: return isXmlSyntax;
0457: }
0458:
0459: /*
0460: * Sets the encoding specified in the JSP config element whose URL
0461: * pattern matches the page containing this Root.
0462: */
0463: public void setJspConfigPageEncoding(String enc) {
0464: jspConfigPageEnc = enc;
0465: }
0466:
0467: /*
0468: * Gets the encoding specified in the JSP config element whose URL
0469: * pattern matches the page containing this Root.
0470: */
0471: public String getJspConfigPageEncoding() {
0472: return jspConfigPageEnc;
0473: }
0474:
0475: public void setPageEncoding(String enc) {
0476: pageEnc = enc;
0477: }
0478:
0479: public String getPageEncoding() {
0480: return pageEnc;
0481: }
0482:
0483: public void setIsDefaultPageEncoding(boolean isDefault) {
0484: isDefaultPageEncoding = isDefault;
0485: }
0486:
0487: public boolean isDefaultPageEncoding() {
0488: return isDefaultPageEncoding;
0489: }
0490:
0491: public void setIsEncodingSpecifiedInProlog(boolean isSpecified) {
0492: isEncodingSpecifiedInProlog = isSpecified;
0493: }
0494:
0495: public boolean isEncodingSpecifiedInProlog() {
0496: return isEncodingSpecifiedInProlog;
0497: }
0498:
0499: /**
0500: * @return The enclosing root to this Root. Usually represents the
0501: * page that includes this one.
0502: */
0503: public Root getParentRoot() {
0504: return parentRoot;
0505: }
0506: }
0507:
0508: /**
0509: * Represents the root of a Jsp document (XML syntax)
0510: */
0511: public static class JspRoot extends Node {
0512:
0513: public JspRoot(String qName, Attributes attrs,
0514: Attributes nonTaglibXmlnsAttrs, Attributes taglibAttrs,
0515: Mark start, Node parent) {
0516: super (qName, ROOT_ACTION, attrs, nonTaglibXmlnsAttrs,
0517: taglibAttrs, start, parent);
0518: }
0519:
0520: public void accept(Visitor v) throws JasperException {
0521: v.visit(this );
0522: }
0523: }
0524:
0525: /**
0526: * Represents a page directive
0527: */
0528: public static class PageDirective extends Node {
0529:
0530: private Vector imports;
0531:
0532: public PageDirective(Attributes attrs, Mark start, Node parent) {
0533: this (JSP_PAGE_DIRECTIVE_ACTION, attrs, null, null, start,
0534: parent);
0535: }
0536:
0537: public PageDirective(String qName, Attributes attrs,
0538: Attributes nonTaglibXmlnsAttrs, Attributes taglibAttrs,
0539: Mark start, Node parent) {
0540: super (qName, PAGE_DIRECTIVE_ACTION, attrs,
0541: nonTaglibXmlnsAttrs, taglibAttrs, start, parent);
0542: imports = new Vector();
0543: }
0544:
0545: public void accept(Visitor v) throws JasperException {
0546: v.visit(this );
0547: }
0548:
0549: /**
0550: * Parses the comma-separated list of class or package names in the
0551: * given attribute value and adds each component to this
0552: * PageDirective's vector of imported classes and packages.
0553: * @param value A comma-separated string of imports.
0554: */
0555: public void addImport(String value) {
0556: int start = 0;
0557: int index;
0558: while ((index = value.indexOf(',', start)) != -1) {
0559: imports.add(value.substring(start, index).trim());
0560: start = index + 1;
0561: }
0562: if (start == 0) {
0563: // No comma found
0564: imports.add(value.trim());
0565: } else {
0566: imports.add(value.substring(start).trim());
0567: }
0568: }
0569:
0570: public List getImports() {
0571: return imports;
0572: }
0573: }
0574:
0575: /**
0576: * Represents an include directive
0577: */
0578: public static class IncludeDirective extends Node {
0579:
0580: public IncludeDirective(Attributes attrs, Mark start,
0581: Node parent) {
0582: this (JSP_INCLUDE_DIRECTIVE_ACTION, attrs, null, null,
0583: start, parent);
0584: }
0585:
0586: public IncludeDirective(String qName, Attributes attrs,
0587: Attributes nonTaglibXmlnsAttrs, Attributes taglibAttrs,
0588: Mark start, Node parent) {
0589: super (qName, INCLUDE_DIRECTIVE_ACTION, attrs,
0590: nonTaglibXmlnsAttrs, taglibAttrs, start, parent);
0591: }
0592:
0593: public void accept(Visitor v) throws JasperException {
0594: v.visit(this );
0595: }
0596: }
0597:
0598: /**
0599: * Represents a custom taglib directive
0600: */
0601: public static class TaglibDirective extends Node {
0602:
0603: public TaglibDirective(Attributes attrs, Mark start, Node parent) {
0604: super (JSP_TAGLIB_DIRECTIVE_ACTION, TAGLIB_DIRECTIVE_ACTION,
0605: attrs, start, parent);
0606: }
0607:
0608: public void accept(Visitor v) throws JasperException {
0609: v.visit(this );
0610: }
0611: }
0612:
0613: /**
0614: * Represents a tag directive
0615: */
0616: public static class TagDirective extends Node {
0617: private Vector imports;
0618:
0619: public TagDirective(Attributes attrs, Mark start, Node parent) {
0620: this (JSP_TAG_DIRECTIVE_ACTION, attrs, null, null, start,
0621: parent);
0622: }
0623:
0624: public TagDirective(String qName, Attributes attrs,
0625: Attributes nonTaglibXmlnsAttrs, Attributes taglibAttrs,
0626: Mark start, Node parent) {
0627: super (qName, TAG_DIRECTIVE_ACTION, attrs,
0628: nonTaglibXmlnsAttrs, taglibAttrs, start, parent);
0629: imports = new Vector();
0630: }
0631:
0632: public void accept(Visitor v) throws JasperException {
0633: v.visit(this );
0634: }
0635:
0636: /**
0637: * Parses the comma-separated list of class or package names in the
0638: * given attribute value and adds each component to this
0639: * PageDirective's vector of imported classes and packages.
0640: * @param value A comma-separated string of imports.
0641: */
0642: public void addImport(String value) {
0643: int start = 0;
0644: int index;
0645: while ((index = value.indexOf(',', start)) != -1) {
0646: imports.add(value.substring(start, index).trim());
0647: start = index + 1;
0648: }
0649: if (start == 0) {
0650: // No comma found
0651: imports.add(value.trim());
0652: } else {
0653: imports.add(value.substring(start).trim());
0654: }
0655: }
0656:
0657: public List getImports() {
0658: return imports;
0659: }
0660: }
0661:
0662: /**
0663: * Represents an attribute directive
0664: */
0665: public static class AttributeDirective extends Node {
0666:
0667: public AttributeDirective(Attributes attrs, Mark start,
0668: Node parent) {
0669: this (JSP_ATTRIBUTE_DIRECTIVE_ACTION, attrs, null, null,
0670: start, parent);
0671: }
0672:
0673: public AttributeDirective(String qName, Attributes attrs,
0674: Attributes nonTaglibXmlnsAttrs, Attributes taglibAttrs,
0675: Mark start, Node parent) {
0676: super (qName, ATTRIBUTE_DIRECTIVE_ACTION, attrs,
0677: nonTaglibXmlnsAttrs, taglibAttrs, start, parent);
0678: }
0679:
0680: public void accept(Visitor v) throws JasperException {
0681: v.visit(this );
0682: }
0683: }
0684:
0685: /**
0686: * Represents a variable directive
0687: */
0688: public static class VariableDirective extends Node {
0689:
0690: public VariableDirective(Attributes attrs, Mark start,
0691: Node parent) {
0692: this (JSP_VARIABLE_DIRECTIVE_ACTION, attrs, null, null,
0693: start, parent);
0694: }
0695:
0696: public VariableDirective(String qName, Attributes attrs,
0697: Attributes nonTaglibXmlnsAttrs, Attributes taglibAttrs,
0698: Mark start, Node parent) {
0699: super (qName, VARIABLE_DIRECTIVE_ACTION, attrs,
0700: nonTaglibXmlnsAttrs, taglibAttrs, start, parent);
0701: }
0702:
0703: public void accept(Visitor v) throws JasperException {
0704: v.visit(this );
0705: }
0706: }
0707:
0708: /**
0709: * Represents a <jsp:invoke> tag file action
0710: */
0711: public static class InvokeAction extends Node {
0712:
0713: public InvokeAction(Attributes attrs, Mark start, Node parent) {
0714: this (JSP_INVOKE_ACTION, attrs, null, null, start, parent);
0715: }
0716:
0717: public InvokeAction(String qName, Attributes attrs,
0718: Attributes nonTaglibXmlnsAttrs, Attributes taglibAttrs,
0719: Mark start, Node parent) {
0720: super (qName, INVOKE_ACTION, attrs, nonTaglibXmlnsAttrs,
0721: taglibAttrs, start, parent);
0722: }
0723:
0724: public void accept(Visitor v) throws JasperException {
0725: v.visit(this );
0726: }
0727: }
0728:
0729: /**
0730: * Represents a <jsp:doBody> tag file action
0731: */
0732: public static class DoBodyAction extends Node {
0733:
0734: public DoBodyAction(Attributes attrs, Mark start, Node parent) {
0735: this (JSP_DOBODY_ACTION, attrs, null, null, start, parent);
0736: }
0737:
0738: public DoBodyAction(String qName, Attributes attrs,
0739: Attributes nonTaglibXmlnsAttrs, Attributes taglibAttrs,
0740: Mark start, Node parent) {
0741: super (qName, DOBODY_ACTION, attrs, nonTaglibXmlnsAttrs,
0742: taglibAttrs, start, parent);
0743: }
0744:
0745: public void accept(Visitor v) throws JasperException {
0746: v.visit(this );
0747: }
0748: }
0749:
0750: /**
0751: * Represents a Jsp comment
0752: * Comments are kept for completeness.
0753: */
0754: public static class Comment extends Node {
0755:
0756: public Comment(String text, Mark start, Node parent) {
0757: super (null, null, text, start, parent);
0758: }
0759:
0760: public void accept(Visitor v) throws JasperException {
0761: v.visit(this );
0762: }
0763: }
0764:
0765: /**
0766: * Represents an expression, declaration, or scriptlet
0767: */
0768: public static abstract class ScriptingElement extends Node {
0769:
0770: public ScriptingElement(String qName, String localName,
0771: String text, Mark start, Node parent) {
0772: super (qName, localName, text, start, parent);
0773: }
0774:
0775: public ScriptingElement(String qName, String localName,
0776: Attributes nonTaglibXmlnsAttrs, Attributes taglibAttrs,
0777: Mark start, Node parent) {
0778: super (qName, localName, null, nonTaglibXmlnsAttrs,
0779: taglibAttrs, start, parent);
0780: }
0781:
0782: /**
0783: * When this node was created from a JSP page in JSP syntax, its text
0784: * was stored as a String in the "text" field, whereas when this node
0785: * was created from a JSP document, its text was stored as one or more
0786: * TemplateText nodes in its body. This method handles either case.
0787: * @return The text string
0788: */
0789: public String getText() {
0790: String ret = text;
0791: if ((ret == null) && (body != null)) {
0792: StringBuffer buf = new StringBuffer();
0793: for (int i = 0; i < body.size(); i++) {
0794: buf.append(body.getNode(i).getText());
0795: }
0796: ret = buf.toString();
0797: }
0798: return ret;
0799: }
0800:
0801: /**
0802: * For the same reason as above, the source line information in the
0803: * contained TemplateText node should be used.
0804: */
0805: public Mark getStart() {
0806: if (text == null && body != null && body.size() > 0) {
0807: return body.getNode(0).getStart();
0808: } else {
0809: return super .getStart();
0810: }
0811: }
0812: }
0813:
0814: /**
0815: * Represents a declaration
0816: */
0817: public static class Declaration extends ScriptingElement {
0818:
0819: public Declaration(String text, Mark start, Node parent) {
0820: super (JSP_DECLARATION_ACTION, DECLARATION_ACTION, text,
0821: start, parent);
0822: }
0823:
0824: public Declaration(String qName,
0825: Attributes nonTaglibXmlnsAttrs, Attributes taglibAttrs,
0826: Mark start, Node parent) {
0827: super (qName, DECLARATION_ACTION, nonTaglibXmlnsAttrs,
0828: taglibAttrs, start, parent);
0829: }
0830:
0831: public void accept(Visitor v) throws JasperException {
0832: v.visit(this );
0833: }
0834: }
0835:
0836: /**
0837: * Represents an expression. Expressions in attributes are embedded
0838: * in the attribute string and not here.
0839: */
0840: public static class Expression extends ScriptingElement {
0841:
0842: public Expression(String text, Mark start, Node parent) {
0843: super (JSP_EXPRESSION_ACTION, EXPRESSION_ACTION, text,
0844: start, parent);
0845: }
0846:
0847: public Expression(String qName, Attributes nonTaglibXmlnsAttrs,
0848: Attributes taglibAttrs, Mark start, Node parent) {
0849: super (qName, EXPRESSION_ACTION, nonTaglibXmlnsAttrs,
0850: taglibAttrs, start, parent);
0851: }
0852:
0853: public void accept(Visitor v) throws JasperException {
0854: v.visit(this );
0855: }
0856: }
0857:
0858: /**
0859: * Represents a scriptlet
0860: */
0861: public static class Scriptlet extends ScriptingElement {
0862:
0863: public Scriptlet(String text, Mark start, Node parent) {
0864: super (JSP_SCRIPTLET_ACTION, SCRIPTLET_ACTION, text, start,
0865: parent);
0866: }
0867:
0868: public Scriptlet(String qName, Attributes nonTaglibXmlnsAttrs,
0869: Attributes taglibAttrs, Mark start, Node parent) {
0870: super (qName, SCRIPTLET_ACTION, nonTaglibXmlnsAttrs,
0871: taglibAttrs, start, parent);
0872: }
0873:
0874: public void accept(Visitor v) throws JasperException {
0875: v.visit(this );
0876: }
0877: }
0878:
0879: /**
0880: * Represents an EL expression. Expressions in attributes are embedded
0881: * in the attribute string and not here.
0882: */
0883: public static class ELExpression extends Node {
0884:
0885: private ELNode.Nodes el;
0886:
0887: public ELExpression(String text, Mark start, Node parent) {
0888: super (null, null, text, start, parent);
0889: }
0890:
0891: public void accept(Visitor v) throws JasperException {
0892: v.visit(this );
0893: }
0894:
0895: public void setEL(ELNode.Nodes el) {
0896: this .el = el;
0897: }
0898:
0899: public ELNode.Nodes getEL() {
0900: return el;
0901: }
0902: }
0903:
0904: /**
0905: * Represents a param action
0906: */
0907: public static class ParamAction extends Node {
0908:
0909: JspAttribute value;
0910:
0911: public ParamAction(Attributes attrs, Mark start, Node parent) {
0912: this (JSP_PARAM_ACTION, attrs, null, null, start, parent);
0913: }
0914:
0915: public ParamAction(String qName, Attributes attrs,
0916: Attributes nonTaglibXmlnsAttrs, Attributes taglibAttrs,
0917: Mark start, Node parent) {
0918: super (qName, PARAM_ACTION, attrs, nonTaglibXmlnsAttrs,
0919: taglibAttrs, start, parent);
0920: }
0921:
0922: public void accept(Visitor v) throws JasperException {
0923: v.visit(this );
0924: }
0925:
0926: public void setValue(JspAttribute value) {
0927: this .value = value;
0928: }
0929:
0930: public JspAttribute getValue() {
0931: return value;
0932: }
0933: }
0934:
0935: /**
0936: * Represents a params action
0937: */
0938: public static class ParamsAction extends Node {
0939:
0940: public ParamsAction(Mark start, Node parent) {
0941: this (JSP_PARAMS_ACTION, null, null, start, parent);
0942: }
0943:
0944: public ParamsAction(String qName,
0945: Attributes nonTaglibXmlnsAttrs, Attributes taglibAttrs,
0946: Mark start, Node parent) {
0947: super (qName, PARAMS_ACTION, null, nonTaglibXmlnsAttrs,
0948: taglibAttrs, start, parent);
0949: }
0950:
0951: public void accept(Visitor v) throws JasperException {
0952: v.visit(this );
0953: }
0954: }
0955:
0956: /**
0957: * Represents a fallback action
0958: */
0959: public static class FallBackAction extends Node {
0960:
0961: public FallBackAction(Mark start, Node parent) {
0962: this (JSP_FALLBACK_ACTION, null, null, start, parent);
0963: }
0964:
0965: public FallBackAction(String qName,
0966: Attributes nonTaglibXmlnsAttrs, Attributes taglibAttrs,
0967: Mark start, Node parent) {
0968: super (qName, FALLBACK_ACTION, null, nonTaglibXmlnsAttrs,
0969: taglibAttrs, start, parent);
0970: }
0971:
0972: public void accept(Visitor v) throws JasperException {
0973: v.visit(this );
0974: }
0975: }
0976:
0977: /**
0978: * Represents an include action
0979: */
0980: public static class IncludeAction extends Node {
0981:
0982: private JspAttribute page;
0983:
0984: public IncludeAction(Attributes attrs, Mark start, Node parent) {
0985: this (JSP_INCLUDE_ACTION, attrs, null, null, start, parent);
0986: }
0987:
0988: public IncludeAction(String qName, Attributes attrs,
0989: Attributes nonTaglibXmlnsAttrs, Attributes taglibAttrs,
0990: Mark start, Node parent) {
0991: super (qName, INCLUDE_ACTION, attrs, nonTaglibXmlnsAttrs,
0992: taglibAttrs, start, parent);
0993: }
0994:
0995: public void accept(Visitor v) throws JasperException {
0996: v.visit(this );
0997: }
0998:
0999: public void setPage(JspAttribute page) {
1000: this .page = page;
1001: }
1002:
1003: public JspAttribute getPage() {
1004: return page;
1005: }
1006: }
1007:
1008: /**
1009: * Represents a forward action
1010: */
1011: public static class ForwardAction extends Node {
1012:
1013: private JspAttribute page;
1014:
1015: public ForwardAction(Attributes attrs, Mark start, Node parent) {
1016: this (JSP_FORWARD_ACTION, attrs, null, null, start, parent);
1017: }
1018:
1019: public ForwardAction(String qName, Attributes attrs,
1020: Attributes nonTaglibXmlnsAttrs, Attributes taglibAttrs,
1021: Mark start, Node parent) {
1022: super (qName, FORWARD_ACTION, attrs, nonTaglibXmlnsAttrs,
1023: taglibAttrs, start, parent);
1024: }
1025:
1026: public void accept(Visitor v) throws JasperException {
1027: v.visit(this );
1028: }
1029:
1030: public void setPage(JspAttribute page) {
1031: this .page = page;
1032: }
1033:
1034: public JspAttribute getPage() {
1035: return page;
1036: }
1037: }
1038:
1039: /**
1040: * Represents a getProperty action
1041: */
1042: public static class GetProperty extends Node {
1043:
1044: public GetProperty(Attributes attrs, Mark start, Node parent) {
1045: this (JSP_GET_PROPERTY_ACTION, attrs, null, null, start,
1046: parent);
1047: }
1048:
1049: public GetProperty(String qName, Attributes attrs,
1050: Attributes nonTaglibXmlnsAttrs, Attributes taglibAttrs,
1051: Mark start, Node parent) {
1052: super (qName, GET_PROPERTY_ACTION, attrs,
1053: nonTaglibXmlnsAttrs, taglibAttrs, start, parent);
1054: }
1055:
1056: public void accept(Visitor v) throws JasperException {
1057: v.visit(this );
1058: }
1059: }
1060:
1061: /**
1062: * Represents a setProperty action
1063: */
1064: public static class SetProperty extends Node {
1065:
1066: private JspAttribute value;
1067:
1068: public SetProperty(Attributes attrs, Mark start, Node parent) {
1069: this (JSP_SET_PROPERTY_ACTION, attrs, null, null, start,
1070: parent);
1071: }
1072:
1073: public SetProperty(String qName, Attributes attrs,
1074: Attributes nonTaglibXmlnsAttrs, Attributes taglibAttrs,
1075: Mark start, Node parent) {
1076: super (qName, SET_PROPERTY_ACTION, attrs,
1077: nonTaglibXmlnsAttrs, taglibAttrs, start, parent);
1078: }
1079:
1080: public void accept(Visitor v) throws JasperException {
1081: v.visit(this );
1082: }
1083:
1084: public void setValue(JspAttribute value) {
1085: this .value = value;
1086: }
1087:
1088: public JspAttribute getValue() {
1089: return value;
1090: }
1091: }
1092:
1093: /**
1094: * Represents a useBean action
1095: */
1096: public static class UseBean extends Node {
1097:
1098: JspAttribute beanName;
1099:
1100: public UseBean(Attributes attrs, Mark start, Node parent) {
1101: this (JSP_USE_BEAN_ACTION, attrs, null, null, start, parent);
1102: }
1103:
1104: public UseBean(String qName, Attributes attrs,
1105: Attributes nonTaglibXmlnsAttrs, Attributes taglibAttrs,
1106: Mark start, Node parent) {
1107: super (qName, USE_BEAN_ACTION, attrs, nonTaglibXmlnsAttrs,
1108: taglibAttrs, start, parent);
1109: }
1110:
1111: public void accept(Visitor v) throws JasperException {
1112: v.visit(this );
1113: }
1114:
1115: public void setBeanName(JspAttribute beanName) {
1116: this .beanName = beanName;
1117: }
1118:
1119: public JspAttribute getBeanName() {
1120: return beanName;
1121: }
1122: }
1123:
1124: /**
1125: * Represents a plugin action
1126: */
1127: public static class PlugIn extends Node {
1128:
1129: private JspAttribute width;
1130: private JspAttribute height;
1131:
1132: public PlugIn(Attributes attrs, Mark start, Node parent) {
1133: this (JSP_PLUGIN_ACTION, attrs, null, null, start, parent);
1134: }
1135:
1136: public PlugIn(String qName, Attributes attrs,
1137: Attributes nonTaglibXmlnsAttrs, Attributes taglibAttrs,
1138: Mark start, Node parent) {
1139: super (qName, PLUGIN_ACTION, attrs, nonTaglibXmlnsAttrs,
1140: taglibAttrs, start, parent);
1141: }
1142:
1143: public void accept(Visitor v) throws JasperException {
1144: v.visit(this );
1145: }
1146:
1147: public void setHeight(JspAttribute height) {
1148: this .height = height;
1149: }
1150:
1151: public void setWidth(JspAttribute width) {
1152: this .width = width;
1153: }
1154:
1155: public JspAttribute getHeight() {
1156: return height;
1157: }
1158:
1159: public JspAttribute getWidth() {
1160: return width;
1161: }
1162: }
1163:
1164: /**
1165: * Represents an uninterpreted tag, from a Jsp document
1166: */
1167: public static class UninterpretedTag extends Node {
1168:
1169: private JspAttribute[] jspAttrs;
1170:
1171: public UninterpretedTag(String qName, String localName,
1172: Attributes attrs, Attributes nonTaglibXmlnsAttrs,
1173: Attributes taglibAttrs, Mark start, Node parent) {
1174: super (qName, localName, attrs, nonTaglibXmlnsAttrs,
1175: taglibAttrs, start, parent);
1176: }
1177:
1178: public void accept(Visitor v) throws JasperException {
1179: v.visit(this );
1180: }
1181:
1182: public void setJspAttributes(JspAttribute[] jspAttrs) {
1183: this .jspAttrs = jspAttrs;
1184: }
1185:
1186: public JspAttribute[] getJspAttributes() {
1187: return jspAttrs;
1188: }
1189: }
1190:
1191: /**
1192: * Represents a <jsp:element>.
1193: */
1194: public static class JspElement extends Node {
1195:
1196: private JspAttribute[] jspAttrs;
1197: private JspAttribute nameAttr;
1198:
1199: public JspElement(Attributes attrs, Mark start, Node parent) {
1200: this (JSP_ELEMENT_ACTION, attrs, null, null, start, parent);
1201: }
1202:
1203: public JspElement(String qName, Attributes attrs,
1204: Attributes nonTaglibXmlnsAttrs, Attributes taglibAttrs,
1205: Mark start, Node parent) {
1206: super (qName, ELEMENT_ACTION, attrs, nonTaglibXmlnsAttrs,
1207: taglibAttrs, start, parent);
1208: }
1209:
1210: public void accept(Visitor v) throws JasperException {
1211: v.visit(this );
1212: }
1213:
1214: public void setJspAttributes(JspAttribute[] jspAttrs) {
1215: this .jspAttrs = jspAttrs;
1216: }
1217:
1218: public JspAttribute[] getJspAttributes() {
1219: return jspAttrs;
1220: }
1221:
1222: /*
1223: * Sets the XML-style 'name' attribute
1224: */
1225: public void setNameAttribute(JspAttribute nameAttr) {
1226: this .nameAttr = nameAttr;
1227: }
1228:
1229: /*
1230: * Gets the XML-style 'name' attribute
1231: */
1232: public JspAttribute getNameAttribute() {
1233: return this .nameAttr;
1234: }
1235: }
1236:
1237: /**
1238: * Represents a <jsp:output>.
1239: */
1240: public static class JspOutput extends Node {
1241:
1242: public JspOutput(String qName, Attributes attrs,
1243: Attributes nonTaglibXmlnsAttrs, Attributes taglibAttrs,
1244: Mark start, Node parent) {
1245: super (qName, OUTPUT_ACTION, attrs, nonTaglibXmlnsAttrs,
1246: taglibAttrs, start, parent);
1247: }
1248:
1249: public void accept(Visitor v) throws JasperException {
1250: v.visit(this );
1251: }
1252: }
1253:
1254: /**
1255: * Collected information about child elements. Used by nodes like
1256: * CustomTag, JspBody, and NamedAttribute. The information is
1257: * set in the Collector.
1258: */
1259: public static class ChildInfo {
1260: private boolean scriptless; // true if the tag and its body
1261: // contain no scripting elements.
1262: private boolean hasUseBean;
1263: private boolean hasIncludeAction;
1264: private boolean hasParamAction;
1265: private boolean hasSetProperty;
1266: private boolean hasScriptingVars;
1267:
1268: public void setScriptless(boolean s) {
1269: scriptless = s;
1270: }
1271:
1272: public boolean isScriptless() {
1273: return scriptless;
1274: }
1275:
1276: public void setHasUseBean(boolean u) {
1277: hasUseBean = u;
1278: }
1279:
1280: public boolean hasUseBean() {
1281: return hasUseBean;
1282: }
1283:
1284: public void setHasIncludeAction(boolean i) {
1285: hasIncludeAction = i;
1286: }
1287:
1288: public boolean hasIncludeAction() {
1289: return hasIncludeAction;
1290: }
1291:
1292: public void setHasParamAction(boolean i) {
1293: hasParamAction = i;
1294: }
1295:
1296: public boolean hasParamAction() {
1297: return hasParamAction;
1298: }
1299:
1300: public void setHasSetProperty(boolean s) {
1301: hasSetProperty = s;
1302: }
1303:
1304: public boolean hasSetProperty() {
1305: return hasSetProperty;
1306: }
1307:
1308: public void setHasScriptingVars(boolean s) {
1309: hasScriptingVars = s;
1310: }
1311:
1312: public boolean hasScriptingVars() {
1313: return hasScriptingVars;
1314: }
1315: }
1316:
1317: /**
1318: * Represents a custom tag
1319: */
1320: public static class CustomTag extends Node {
1321:
1322: private String uri;
1323: private String prefix;
1324: private JspAttribute[] jspAttrs;
1325: private TagData tagData;
1326: private String tagHandlerPoolName;
1327: private TagInfo tagInfo;
1328: private TagFileInfo tagFileInfo;
1329: private Class tagHandlerClass;
1330: private VariableInfo[] varInfos;
1331: private int customNestingLevel;
1332: private ChildInfo childInfo;
1333: private boolean implements IterationTag;
1334: private boolean implements BodyTag;
1335: private boolean implements TryCatchFinally;
1336: private boolean implements SimpleTag;
1337: private boolean implements DynamicAttributes;
1338: private Vector atBeginScriptingVars;
1339: private Vector atEndScriptingVars;
1340: private Vector nestedScriptingVars;
1341: private Node.CustomTag customTagParent;
1342: private Integer numCount;
1343: private boolean useTagPlugin;
1344: private TagPluginContext tagPluginContext;
1345:
1346: /**
1347: * The following two fields are used for holding the Java
1348: * scriptlets that the tag plugins may generate. Meaningful
1349: * only if useTagPlugin is true;
1350: * Could move them into TagPluginContextImpl, but we'll need
1351: * to cast tagPluginContext to TagPluginContextImpl all the time...
1352: */
1353: private Nodes atSTag;
1354: private Nodes atETag;
1355:
1356: /*
1357: * Constructor for custom action implemented by tag handler.
1358: */
1359: public CustomTag(String qName, String prefix, String localName,
1360: String uri, Attributes attrs, Mark start, Node parent,
1361: TagInfo tagInfo, Class tagHandlerClass) {
1362: this (qName, prefix, localName, uri, attrs, null, null,
1363: start, parent, tagInfo, tagHandlerClass);
1364: }
1365:
1366: /*
1367: * Constructor for custom action implemented by tag handler.
1368: */
1369: public CustomTag(String qName, String prefix, String localName,
1370: String uri, Attributes attrs,
1371: Attributes nonTaglibXmlnsAttrs, Attributes taglibAttrs,
1372: Mark start, Node parent, TagInfo tagInfo,
1373: Class tagHandlerClass) {
1374: super (qName, localName, attrs, nonTaglibXmlnsAttrs,
1375: taglibAttrs, start, parent);
1376:
1377: this .uri = uri;
1378: this .prefix = prefix;
1379: this .tagInfo = tagInfo;
1380: this .tagHandlerClass = tagHandlerClass;
1381: this .customNestingLevel = makeCustomNestingLevel();
1382: this .childInfo = new ChildInfo();
1383:
1384: this .implements IterationTag = IterationTag.class
1385: .isAssignableFrom(tagHandlerClass);
1386: this .implements BodyTag = BodyTag.class
1387: .isAssignableFrom(tagHandlerClass);
1388: this .implements TryCatchFinally = TryCatchFinally.class
1389: .isAssignableFrom(tagHandlerClass);
1390: this .implements SimpleTag = SimpleTag.class
1391: .isAssignableFrom(tagHandlerClass);
1392: this .implements DynamicAttributes = DynamicAttributes.class
1393: .isAssignableFrom(tagHandlerClass);
1394: }
1395:
1396: /*
1397: * Constructor for custom action implemented by tag file.
1398: */
1399: public CustomTag(String qName, String prefix, String localName,
1400: String uri, Attributes attrs, Mark start, Node parent,
1401: TagFileInfo tagFileInfo) {
1402: this (qName, prefix, localName, uri, attrs, null, null,
1403: start, parent, tagFileInfo);
1404: }
1405:
1406: /*
1407: * Constructor for custom action implemented by tag file.
1408: */
1409: public CustomTag(String qName, String prefix, String localName,
1410: String uri, Attributes attrs,
1411: Attributes nonTaglibXmlnsAttrs, Attributes taglibAttrs,
1412: Mark start, Node parent, TagFileInfo tagFileInfo) {
1413:
1414: super (qName, localName, attrs, nonTaglibXmlnsAttrs,
1415: taglibAttrs, start, parent);
1416:
1417: this .uri = uri;
1418: this .prefix = prefix;
1419: this .tagFileInfo = tagFileInfo;
1420: this .tagInfo = tagFileInfo.getTagInfo();
1421: this .customNestingLevel = makeCustomNestingLevel();
1422: this .childInfo = new ChildInfo();
1423:
1424: this .implements IterationTag = false;
1425: this .implements BodyTag = false;
1426: this .implements TryCatchFinally = false;
1427: this .implements SimpleTag = true;
1428: this .implements DynamicAttributes = tagInfo
1429: .hasDynamicAttributes();
1430: }
1431:
1432: public void accept(Visitor v) throws JasperException {
1433: v.visit(this );
1434: }
1435:
1436: /**
1437: * @return The URI namespace that this custom action belongs to
1438: */
1439: public String getURI() {
1440: return this .uri;
1441: }
1442:
1443: /**
1444: * @return The tag prefix
1445: */
1446: public String getPrefix() {
1447: return prefix;
1448: }
1449:
1450: public void setJspAttributes(JspAttribute[] jspAttrs) {
1451: this .jspAttrs = jspAttrs;
1452: }
1453:
1454: public JspAttribute[] getJspAttributes() {
1455: return jspAttrs;
1456: }
1457:
1458: public ChildInfo getChildInfo() {
1459: return childInfo;
1460: }
1461:
1462: public void setTagData(TagData tagData) {
1463: this .tagData = tagData;
1464: this .varInfos = tagInfo.getVariableInfo(tagData);
1465: if (this .varInfos == null) {
1466: this .varInfos = ZERO_VARIABLE_INFO;
1467: }
1468: }
1469:
1470: public TagData getTagData() {
1471: return tagData;
1472: }
1473:
1474: public void setTagHandlerPoolName(String s) {
1475: tagHandlerPoolName = s;
1476: }
1477:
1478: public String getTagHandlerPoolName() {
1479: return tagHandlerPoolName;
1480: }
1481:
1482: public TagInfo getTagInfo() {
1483: return tagInfo;
1484: }
1485:
1486: public TagFileInfo getTagFileInfo() {
1487: return tagFileInfo;
1488: }
1489:
1490: /*
1491: * @return true if this custom action is supported by a tag file,
1492: * false otherwise
1493: */
1494: public boolean isTagFile() {
1495: return tagFileInfo != null;
1496: }
1497:
1498: public Class getTagHandlerClass() {
1499: return tagHandlerClass;
1500: }
1501:
1502: public void setTagHandlerClass(Class hc) {
1503: tagHandlerClass = hc;
1504: }
1505:
1506: public boolean implements IterationTag() {
1507: return implements IterationTag;
1508: }
1509:
1510: public boolean implements BodyTag() {
1511: return implements BodyTag;
1512: }
1513:
1514: public boolean implements TryCatchFinally() {
1515: return implements TryCatchFinally;
1516: }
1517:
1518: public boolean implements SimpleTag() {
1519: return implements SimpleTag;
1520: }
1521:
1522: public boolean implements DynamicAttributes() {
1523: return implements DynamicAttributes;
1524: }
1525:
1526: public TagVariableInfo[] getTagVariableInfos() {
1527: return tagInfo.getTagVariableInfos();
1528: }
1529:
1530: public VariableInfo[] getVariableInfos() {
1531: return varInfos;
1532: }
1533:
1534: public void setCustomTagParent(Node.CustomTag n) {
1535: this .customTagParent = n;
1536: }
1537:
1538: public Node.CustomTag getCustomTagParent() {
1539: return this .customTagParent;
1540: }
1541:
1542: public void setNumCount(Integer count) {
1543: this .numCount = count;
1544: }
1545:
1546: public Integer getNumCount() {
1547: return this .numCount;
1548: }
1549:
1550: public void setScriptingVars(Vector vec, int scope) {
1551: switch (scope) {
1552: case VariableInfo.AT_BEGIN:
1553: this .atBeginScriptingVars = vec;
1554: break;
1555: case VariableInfo.AT_END:
1556: this .atEndScriptingVars = vec;
1557: break;
1558: case VariableInfo.NESTED:
1559: this .nestedScriptingVars = vec;
1560: break;
1561: }
1562: }
1563:
1564: /*
1565: * Gets the scripting variables for the given scope that need to be
1566: * declared.
1567: */
1568: public Vector getScriptingVars(int scope) {
1569: Vector vec = null;
1570:
1571: switch (scope) {
1572: case VariableInfo.AT_BEGIN:
1573: vec = this .atBeginScriptingVars;
1574: break;
1575: case VariableInfo.AT_END:
1576: vec = this .atEndScriptingVars;
1577: break;
1578: case VariableInfo.NESTED:
1579: vec = this .nestedScriptingVars;
1580: break;
1581: }
1582:
1583: return vec;
1584: }
1585:
1586: /*
1587: * Gets this custom tag's custom nesting level, which is given as
1588: * the number of times this custom tag is nested inside itself.
1589: */
1590: public int getCustomNestingLevel() {
1591: return customNestingLevel;
1592: }
1593:
1594: /**
1595: * Checks to see if the attribute of the given name is of type
1596: * JspFragment.
1597: */
1598: public boolean checkIfAttributeIsJspFragment(String name) {
1599: boolean result = false;
1600:
1601: TagAttributeInfo[] attributes = tagInfo.getAttributes();
1602: for (int i = 0; i < attributes.length; i++) {
1603: if (attributes[i].getName().equals(name)
1604: && attributes[i].isFragment()) {
1605: result = true;
1606: break;
1607: }
1608: }
1609:
1610: return result;
1611: }
1612:
1613: public void setUseTagPlugin(boolean use) {
1614: useTagPlugin = use;
1615: }
1616:
1617: public boolean useTagPlugin() {
1618: return useTagPlugin;
1619: }
1620:
1621: public void setTagPluginContext(
1622: TagPluginContext tagPluginContext) {
1623: this .tagPluginContext = tagPluginContext;
1624: }
1625:
1626: public TagPluginContext getTagPluginContext() {
1627: return tagPluginContext;
1628: }
1629:
1630: public void setAtSTag(Nodes sTag) {
1631: atSTag = sTag;
1632: }
1633:
1634: public Nodes getAtSTag() {
1635: return atSTag;
1636: }
1637:
1638: public void setAtETag(Nodes eTag) {
1639: atETag = eTag;
1640: }
1641:
1642: public Nodes getAtETag() {
1643: return atETag;
1644: }
1645:
1646: /*
1647: * Computes this custom tag's custom nesting level, which corresponds
1648: * to the number of times this custom tag is nested inside itself.
1649: *
1650: * Example:
1651: *
1652: * <g:h>
1653: * <a:b> -- nesting level 0
1654: * <c:d>
1655: * <e:f>
1656: * <a:b> -- nesting level 1
1657: * <a:b> -- nesting level 2
1658: * </a:b>
1659: * </a:b>
1660: * <a:b> -- nesting level 1
1661: * </a:b>
1662: * </e:f>
1663: * </c:d>
1664: * </a:b>
1665: * </g:h>
1666: *
1667: * @return Custom tag's nesting level
1668: */
1669: private int makeCustomNestingLevel() {
1670: int n = 0;
1671: Node p = parent;
1672: while (p != null) {
1673: if ((p instanceof Node.CustomTag)
1674: && qName.equals(((Node.CustomTag) p).qName)) {
1675: n++;
1676: }
1677: p = p.parent;
1678: }
1679: return n;
1680: }
1681:
1682: /**
1683: * Returns true if this custom action has an empty body, and false
1684: * otherwise.
1685: *
1686: * A custom action is considered to have an empty body if the
1687: * following holds true:
1688: * - getBody() returns null, or
1689: * - all immediate children are jsp:attribute actions, or
1690: * - the action's jsp:body is empty.
1691: */
1692: public boolean hasEmptyBody() {
1693: boolean hasEmptyBody = true;
1694: Nodes nodes = getBody();
1695: if (nodes != null) {
1696: int numChildNodes = nodes.size();
1697: for (int i = 0; i < numChildNodes; i++) {
1698: Node n = nodes.getNode(i);
1699: if (!(n instanceof NamedAttribute)) {
1700: if (n instanceof JspBody) {
1701: hasEmptyBody = (n.getBody() == null);
1702: } else {
1703: hasEmptyBody = false;
1704: }
1705: break;
1706: }
1707: }
1708: }
1709:
1710: return hasEmptyBody;
1711: }
1712: }
1713:
1714: /**
1715: * Used as a placeholder for the evaluation code of a custom action
1716: * attribute (used by the tag plugin machinery only).
1717: */
1718: public static class AttributeGenerator extends Node {
1719: String name; // name of the attribute
1720: CustomTag tag; // The tag this attribute belongs to
1721:
1722: public AttributeGenerator(Mark start, String name, CustomTag tag) {
1723: super (start, null);
1724: this .name = name;
1725: this .tag = tag;
1726: }
1727:
1728: public void accept(Visitor v) throws JasperException {
1729: v.visit(this );
1730: }
1731:
1732: public String getName() {
1733: return name;
1734: }
1735:
1736: public CustomTag getTag() {
1737: return tag;
1738: }
1739: }
1740:
1741: /**
1742: * Represents the body of a <jsp:text> element
1743: */
1744: public static class JspText extends Node {
1745:
1746: public JspText(String qName, Attributes nonTaglibXmlnsAttrs,
1747: Attributes taglibAttrs, Mark start, Node parent) {
1748: super (qName, TEXT_ACTION, null, nonTaglibXmlnsAttrs,
1749: taglibAttrs, start, parent);
1750: }
1751:
1752: public void accept(Visitor v) throws JasperException {
1753: v.visit(this );
1754: }
1755: }
1756:
1757: /**
1758: * Represents a Named Attribute (<jsp:attribute>)
1759: */
1760: public static class NamedAttribute extends Node {
1761:
1762: // A unique temporary variable name suitable for code generation
1763: private String temporaryVariableName;
1764:
1765: // True if this node is to be trimmed, or false otherwise
1766: private boolean trim = true;
1767:
1768: private ChildInfo childInfo;
1769: private String name;
1770: private String localName;
1771: private String prefix;
1772:
1773: public NamedAttribute(Attributes attrs, Mark start, Node parent) {
1774: this (JSP_ATTRIBUTE_ACTION, attrs, null, null, start, parent);
1775: }
1776:
1777: public NamedAttribute(String qName, Attributes attrs,
1778: Attributes nonTaglibXmlnsAttrs, Attributes taglibAttrs,
1779: Mark start, Node parent) {
1780:
1781: super (qName, ATTRIBUTE_ACTION, attrs, nonTaglibXmlnsAttrs,
1782: taglibAttrs, start, parent);
1783: temporaryVariableName = JspUtil.nextTemporaryVariableName();
1784: if ("false".equals(this .getAttributeValue("trim"))) {
1785: // (if null or true, leave default of true)
1786: trim = false;
1787: }
1788: childInfo = new ChildInfo();
1789: name = this .getAttributeValue("name");
1790: if (name != null) {
1791: // Mandatary attribute "name" will be checked in Validator
1792: localName = name;
1793: int index = name.indexOf(':');
1794: if (index != -1) {
1795: prefix = name.substring(0, index);
1796: localName = name.substring(index + 1);
1797: }
1798: }
1799: }
1800:
1801: public void accept(Visitor v) throws JasperException {
1802: v.visit(this );
1803: }
1804:
1805: public String getName() {
1806: return this .name;
1807: }
1808:
1809: public String getLocalName() {
1810: return this .localName;
1811: }
1812:
1813: public String getPrefix() {
1814: return this .prefix;
1815: }
1816:
1817: public ChildInfo getChildInfo() {
1818: return this .childInfo;
1819: }
1820:
1821: public boolean isTrim() {
1822: return trim;
1823: }
1824:
1825: /**
1826: * @return A unique temporary variable name to store the result in.
1827: * (this probably could go elsewhere, but it's convenient here)
1828: */
1829: public String getTemporaryVariableName() {
1830: return temporaryVariableName;
1831: }
1832:
1833: /*
1834: * Get the attribute value from this named attribute (<jsp:attribute>).
1835: * Since this method is only for attributes that are not rtexpr,
1836: * we can assume the body of the jsp:attribute is a template text.
1837: */
1838: public String getText() {
1839:
1840: class AttributeVisitor extends Visitor {
1841: String attrValue = null;
1842:
1843: public void visit(TemplateText txt) {
1844: attrValue = new String(txt.getText());
1845: }
1846:
1847: public String getAttrValue() {
1848: return attrValue;
1849: }
1850: }
1851:
1852: // According to JSP 2.0, if the body of the <jsp:attribute>
1853: // action is empty, it is equivalent of specifying "" as the value
1854: // of the attribute.
1855: String text = "";
1856: if (getBody() != null) {
1857: AttributeVisitor attributeVisitor = new AttributeVisitor();
1858: try {
1859: getBody().visit(attributeVisitor);
1860: } catch (JasperException e) {
1861: }
1862: text = attributeVisitor.getAttrValue();
1863: }
1864:
1865: return text;
1866: }
1867: }
1868:
1869: /**
1870: * Represents a JspBody node (<jsp:body>)
1871: */
1872: public static class JspBody extends Node {
1873:
1874: private ChildInfo childInfo;
1875:
1876: public JspBody(Mark start, Node parent) {
1877: this (JSP_BODY_ACTION, null, null, start, parent);
1878: }
1879:
1880: public JspBody(String qName, Attributes nonTaglibXmlnsAttrs,
1881: Attributes taglibAttrs, Mark start, Node parent) {
1882: super (qName, BODY_ACTION, null, nonTaglibXmlnsAttrs,
1883: taglibAttrs, start, parent);
1884: this .childInfo = new ChildInfo();
1885: }
1886:
1887: public void accept(Visitor v) throws JasperException {
1888: v.visit(this );
1889: }
1890:
1891: public ChildInfo getChildInfo() {
1892: return childInfo;
1893: }
1894: }
1895:
1896: /**
1897: * Represents a template text string
1898: */
1899: public static class TemplateText extends Node {
1900:
1901: private ArrayList extraSmap = null;
1902:
1903: public TemplateText(String text, Mark start, Node parent) {
1904: super (null, null, text, start, parent);
1905: }
1906:
1907: public void accept(Visitor v) throws JasperException {
1908: v.visit(this );
1909: }
1910:
1911: /**
1912: * Trim all whitespace from the left of the template text
1913: */
1914: public void ltrim() {
1915: int index = 0;
1916: while ((index < text.length())
1917: && (text.charAt(index) <= ' ')) {
1918: index++;
1919: }
1920: text = text.substring(index);
1921: }
1922:
1923: public void setText(String text) {
1924: this .text = text;
1925: }
1926:
1927: /**
1928: * Trim all whitespace from the right of the template text
1929: */
1930: public void rtrim() {
1931: int index = text.length();
1932: while ((index > 0) && (text.charAt(index - 1) <= ' ')) {
1933: index--;
1934: }
1935: text = text.substring(0, index);
1936: }
1937:
1938: /**
1939: * Returns true if this template text contains whitespace only.
1940: */
1941: public boolean isAllSpace() {
1942: boolean isAllSpace = true;
1943: for (int i = 0; i < text.length(); i++) {
1944: if (!Character.isWhitespace(text.charAt(i))) {
1945: isAllSpace = false;
1946: break;
1947: }
1948: }
1949: return isAllSpace;
1950: }
1951:
1952: /**
1953: * Add a source to Java line mapping
1954: * @param srcLine The postion of the source line, relative to the line
1955: * at the start of this node. The corresponding java line is
1956: * assumed to be consecutive, i.e. one more than the last.
1957: */
1958: public void addSmap(int srcLine) {
1959: if (extraSmap == null) {
1960: extraSmap = new ArrayList();
1961: }
1962: extraSmap.add(new Integer(srcLine));
1963: }
1964:
1965: public ArrayList getExtraSmap() {
1966: return extraSmap;
1967: }
1968: }
1969:
1970: /*********************************************************************
1971: * Auxillary classes used in Node
1972: */
1973:
1974: /**
1975: * Represents attributes that can be request time expressions.
1976: *
1977: * Can either be a plain attribute, an attribute that represents a
1978: * request time expression value, or a named attribute (specified using
1979: * the jsp:attribute standard action).
1980: */
1981:
1982: public static class JspAttribute {
1983:
1984: private String qName;
1985: private String uri;
1986: private String localName;
1987: private String value;
1988: private boolean expression;
1989: private boolean dynamic;
1990: private ELNode.Nodes el;
1991:
1992: // If true, this JspAttribute represents a <jsp:attribute>
1993: private boolean namedAttribute;
1994: // The node in the parse tree for the NamedAttribute
1995: private NamedAttribute namedAttributeNode;
1996:
1997: JspAttribute(String qName, String uri, String localName,
1998: String value, boolean expr, ELNode.Nodes el, boolean dyn) {
1999: this .qName = qName;
2000: this .uri = uri;
2001: this .localName = localName;
2002: this .value = value;
2003: this .namedAttributeNode = null;
2004: this .expression = expr;
2005: this .el = el;
2006: this .dynamic = dyn;
2007: this .namedAttribute = false;
2008: }
2009:
2010: /**
2011: * Use this constructor if the JspAttribute represents a
2012: * named attribute. In this case, we have to store the nodes of
2013: * the body of the attribute.
2014: */
2015: JspAttribute(NamedAttribute na, boolean dyn) {
2016: this .qName = na.getName();
2017: this .localName = na.getLocalName();
2018: this .value = null;
2019: this .namedAttributeNode = na;
2020: this .expression = false;
2021: this .el = null;
2022: this .dynamic = dyn;
2023: this .namedAttribute = true;
2024: }
2025:
2026: /**
2027: * @return The name of the attribute
2028: */
2029: public String getName() {
2030: return qName;
2031: }
2032:
2033: /**
2034: * @return The local name of the attribute
2035: */
2036: public String getLocalName() {
2037: return localName;
2038: }
2039:
2040: /**
2041: * @return The namespace of the attribute, or null if in the default
2042: * namespace
2043: */
2044: public String getURI() {
2045: return uri;
2046: }
2047:
2048: /**
2049: * Only makes sense if namedAttribute is false.
2050: *
2051: * @return the value for the attribute, or the expression string
2052: * (stripped of "<%=", "%>", "%=", or "%"
2053: * but containing "${" and "}" for EL expressions)
2054: */
2055: public String getValue() {
2056: return value;
2057: }
2058:
2059: /**
2060: * Only makes sense if namedAttribute is true.
2061: *
2062: * @return the nodes that evaluate to the body of this attribute.
2063: */
2064: public NamedAttribute getNamedAttributeNode() {
2065: return namedAttributeNode;
2066: }
2067:
2068: /**
2069: * @return true if the value represents a traditional rtexprvalue
2070: */
2071: public boolean isExpression() {
2072: return expression;
2073: }
2074:
2075: /**
2076: * @return true if the value represents a NamedAttribute value.
2077: */
2078: public boolean isNamedAttribute() {
2079: return namedAttribute;
2080: }
2081:
2082: /**
2083: * @return true if the value represents an expression that should
2084: * be fed to the expression interpreter
2085: * @return false for string literals or rtexprvalues that should
2086: * not be interpreted or reevaluated
2087: */
2088: public boolean isELInterpreterInput() {
2089: return el != null;
2090: }
2091:
2092: /**
2093: * @return true if the value is a string literal known at translation
2094: * time.
2095: */
2096: public boolean isLiteral() {
2097: return !expression && (el != null) && !namedAttribute;
2098: }
2099:
2100: /**
2101: * XXX
2102: */
2103: public boolean isDynamic() {
2104: return dynamic;
2105: }
2106:
2107: public ELNode.Nodes getEL() {
2108: return el;
2109: }
2110: }
2111:
2112: /**
2113: * An ordered list of Node, used to represent the body of an element, or
2114: * a jsp page of jsp document.
2115: */
2116: public static class Nodes {
2117:
2118: private List list;
2119: private Node.Root root; // null if this is not a page
2120: private boolean generatedInBuffer;
2121:
2122: public Nodes() {
2123: list = new Vector();
2124: }
2125:
2126: public Nodes(Node.Root root) {
2127: this .root = root;
2128: list = new Vector();
2129: list.add(root);
2130: }
2131:
2132: /**
2133: * Appends a node to the list
2134: * @param n The node to add
2135: */
2136: public void add(Node n) {
2137: list.add(n);
2138: root = null;
2139: }
2140:
2141: /**
2142: * Removes the given node from the list.
2143: * @param n The node to be removed
2144: */
2145: public void remove(Node n) {
2146: list.remove(n);
2147: }
2148:
2149: /**
2150: * Visit the nodes in the list with the supplied visitor
2151: * @param v The visitor used
2152: */
2153: public void visit(Visitor v) throws JasperException {
2154: Iterator iter = list.iterator();
2155: while (iter.hasNext()) {
2156: Node n = (Node) iter.next();
2157: n.accept(v);
2158: }
2159: }
2160:
2161: public int size() {
2162: return list.size();
2163: }
2164:
2165: public Node getNode(int index) {
2166: Node n = null;
2167: try {
2168: n = (Node) list.get(index);
2169: } catch (ArrayIndexOutOfBoundsException e) {
2170: }
2171: return n;
2172: }
2173:
2174: public Node.Root getRoot() {
2175: return root;
2176: }
2177:
2178: public boolean isGeneratedInBuffer() {
2179: return generatedInBuffer;
2180: }
2181:
2182: public void setGeneratedInBuffer(boolean g) {
2183: generatedInBuffer = g;
2184: }
2185: }
2186:
2187: /**
2188: * A visitor class for visiting the node. This class also provides the
2189: * default action (i.e. nop) for each of the child class of the Node.
2190: * An actual visitor should extend this class and supply the visit
2191: * method for the nodes that it cares.
2192: */
2193: public static class Visitor {
2194:
2195: /**
2196: * This method provides a place to put actions that are common to
2197: * all nodes. Override this in the child visitor class if need to.
2198: */
2199: protected void doVisit(Node n) throws JasperException {
2200: }
2201:
2202: /**
2203: * Visit the body of a node, using the current visitor
2204: */
2205: protected void visitBody(Node n) throws JasperException {
2206: if (n.getBody() != null) {
2207: n.getBody().visit(this );
2208: }
2209: }
2210:
2211: public void visit(Root n) throws JasperException {
2212: doVisit(n);
2213: visitBody(n);
2214: }
2215:
2216: public void visit(JspRoot n) throws JasperException {
2217: doVisit(n);
2218: visitBody(n);
2219: }
2220:
2221: public void visit(PageDirective n) throws JasperException {
2222: doVisit(n);
2223: }
2224:
2225: public void visit(TagDirective n) throws JasperException {
2226: doVisit(n);
2227: }
2228:
2229: public void visit(IncludeDirective n) throws JasperException {
2230: doVisit(n);
2231: visitBody(n);
2232: }
2233:
2234: public void visit(TaglibDirective n) throws JasperException {
2235: doVisit(n);
2236: }
2237:
2238: public void visit(AttributeDirective n) throws JasperException {
2239: doVisit(n);
2240: }
2241:
2242: public void visit(VariableDirective n) throws JasperException {
2243: doVisit(n);
2244: }
2245:
2246: public void visit(Comment n) throws JasperException {
2247: doVisit(n);
2248: }
2249:
2250: public void visit(Declaration n) throws JasperException {
2251: doVisit(n);
2252: }
2253:
2254: public void visit(Expression n) throws JasperException {
2255: doVisit(n);
2256: }
2257:
2258: public void visit(Scriptlet n) throws JasperException {
2259: doVisit(n);
2260: }
2261:
2262: public void visit(ELExpression n) throws JasperException {
2263: doVisit(n);
2264: }
2265:
2266: public void visit(IncludeAction n) throws JasperException {
2267: doVisit(n);
2268: visitBody(n);
2269: }
2270:
2271: public void visit(ForwardAction n) throws JasperException {
2272: doVisit(n);
2273: visitBody(n);
2274: }
2275:
2276: public void visit(GetProperty n) throws JasperException {
2277: doVisit(n);
2278: visitBody(n);
2279: }
2280:
2281: public void visit(SetProperty n) throws JasperException {
2282: doVisit(n);
2283: visitBody(n);
2284: }
2285:
2286: public void visit(ParamAction n) throws JasperException {
2287: doVisit(n);
2288: visitBody(n);
2289: }
2290:
2291: public void visit(ParamsAction n) throws JasperException {
2292: doVisit(n);
2293: visitBody(n);
2294: }
2295:
2296: public void visit(FallBackAction n) throws JasperException {
2297: doVisit(n);
2298: visitBody(n);
2299: }
2300:
2301: public void visit(UseBean n) throws JasperException {
2302: doVisit(n);
2303: visitBody(n);
2304: }
2305:
2306: public void visit(PlugIn n) throws JasperException {
2307: doVisit(n);
2308: visitBody(n);
2309: }
2310:
2311: public void visit(CustomTag n) throws JasperException {
2312: doVisit(n);
2313: visitBody(n);
2314: }
2315:
2316: public void visit(UninterpretedTag n) throws JasperException {
2317: doVisit(n);
2318: visitBody(n);
2319: }
2320:
2321: public void visit(JspElement n) throws JasperException {
2322: doVisit(n);
2323: visitBody(n);
2324: }
2325:
2326: public void visit(JspText n) throws JasperException {
2327: doVisit(n);
2328: visitBody(n);
2329: }
2330:
2331: public void visit(NamedAttribute n) throws JasperException {
2332: doVisit(n);
2333: visitBody(n);
2334: }
2335:
2336: public void visit(JspBody n) throws JasperException {
2337: doVisit(n);
2338: visitBody(n);
2339: }
2340:
2341: public void visit(InvokeAction n) throws JasperException {
2342: doVisit(n);
2343: visitBody(n);
2344: }
2345:
2346: public void visit(DoBodyAction n) throws JasperException {
2347: doVisit(n);
2348: visitBody(n);
2349: }
2350:
2351: public void visit(TemplateText n) throws JasperException {
2352: doVisit(n);
2353: }
2354:
2355: public void visit(JspOutput n) throws JasperException {
2356: doVisit(n);
2357: }
2358:
2359: public void visit(AttributeGenerator n) throws JasperException {
2360: doVisit(n);
2361: }
2362: }
2363: }
|