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 <jsp:text> 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 (<jsp:attribute>)
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 (<jsp:body>)
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 }