1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.struts2.jasper.compiler;
19
20 import org.apache.struts2.JSPRuntime;
21 import org.apache.struts2.jasper.Constants;
22 import org.apache.struts2.jasper.JasperException;
23 import org.apache.struts2.jasper.JspCompilationContext;
24 import org.apache.struts2.jasper.runtime.JspRuntimeLibrary;
25 import org.xml.sax.Attributes;
26
27 import javax.servlet.jsp.tagext.TagAttributeInfo;
28 import javax.servlet.jsp.tagext.TagInfo;
29 import javax.servlet.jsp.tagext.TagVariableInfo;
30 import javax.servlet.jsp.tagext.VariableInfo;
31 import java.beans.BeanInfo;
32 import java.beans.IntrospectionException;
33 import java.beans.Introspector;
34 import java.beans.PropertyDescriptor;
35 import java.lang.reflect.Method;
36 import java.lang.reflect.Modifier;
37 import java.util.*;
38
39 /***
40 * Generate Java source from Nodes
41 *
42 * @author Anil K. Vijendran
43 * @author Danno Ferrin
44 * @author Mandar Raje
45 * @author Rajiv Mordani
46 * @author Pierre Delisle
47 * <p/>
48 * Tomcat 4.1.x and Tomcat 5:
49 * @author Kin-man Chung
50 * @author Jan Luehe
51 * @author Shawn Bayern
52 * @author Mark Roth
53 * @author Denis Benoit
54 */
55
56 class Generator {
57
58 private static final Class[] OBJECT_CLASS = {Object.class};
59 private ServletWriter out;
60 private ArrayList methodsBuffered;
61 private FragmentHelperClass fragmentHelperClass;
62 private ErrorDispatcher err;
63 private BeanRepository beanInfo;
64 private JspCompilationContext ctxt;
65 private boolean isPoolingEnabled;
66 private boolean breakAtLF;
67 private PageInfo pageInfo;
68 private Vector tagHandlerPoolNames;
69 private GenBuffer charArrayBuffer;
70
71 /***
72 * @param s the input string
73 * @return quoted and escaped string, per Java rule
74 */
75 static String quote(String s) {
76
77 if (s == null)
78 return "null";
79
80 return '"' + escape(s) + '"';
81 }
82
83 /***
84 * @param s the input string
85 * @return escaped string, per Java rule
86 */
87 static String escape(String s) {
88
89 if (s == null)
90 return "";
91
92 StringBuffer b = new StringBuffer();
93 for (int i = 0; i < s.length(); i++) {
94 char c = s.charAt(i);
95 if (c == '"')
96 b.append('//').append('"');
97 else if (c == '//')
98 b.append('//').append('//');
99 else if (c == '\n')
100 b.append('//').append('n');
101 else if (c == '\r')
102 b.append('//').append('r');
103 else
104 b.append(c);
105 }
106 return b.toString();
107 }
108
109 /***
110 * Single quote and escape a character
111 */
112 static String quote(char c) {
113
114 StringBuffer b = new StringBuffer();
115 b.append('\'');
116 if (c == '\'')
117 b.append('//').append('\'');
118 else if (c == '//')
119 b.append('//').append('//');
120 else if (c == '\n')
121 b.append('//').append('n');
122 else if (c == '\r')
123 b.append('//').append('r');
124 else
125 b.append(c);
126 b.append('\'');
127 return b.toString();
128 }
129
130 /***
131 * Generates declarations. This includes "info" of the page directive,
132 * and scriptlet declarations.
133 */
134 private void generateDeclarations(Node.Nodes page) throws JasperException {
135
136 class DeclarationVisitor extends Node.Visitor {
137
138 private boolean getServletInfoGenerated = false;
139
140
141
142
143
144
145
146
147
148 public void visit(Node.PageDirective n) throws JasperException {
149
150 if (getServletInfoGenerated) {
151 return;
152 }
153
154 String info = n.getAttributeValue("info");
155 if (info == null)
156 return;
157
158 getServletInfoGenerated = true;
159 out.printil("public String getServletInfo() {");
160 out.pushIndent();
161 out.printin("return ");
162 out.print(quote(info));
163 out.println(";");
164 out.popIndent();
165 out.printil("}");
166 out.println();
167 }
168
169 public void visit(Node.Declaration n) throws JasperException {
170 n.setBeginJavaLine(out.getJavaLine());
171 out.printMultiLn(new String(n.getText()));
172 out.println();
173 n.setEndJavaLine(out.getJavaLine());
174 }
175
176
177 public void visit(Node.CustomTag n) throws JasperException {
178 if (n.useTagPlugin()) {
179 if (n.getAtSTag() != null) {
180 n.getAtSTag().visit(this);
181 }
182 visitBody(n);
183 if (n.getAtETag() != null) {
184 n.getAtETag().visit(this);
185 }
186 } else {
187 visitBody(n);
188 }
189 }
190 }
191
192 out.println();
193 page.visit(new DeclarationVisitor());
194 }
195
196 /***
197 * Compiles list of tag handler pool names.
198 */
199 private void compileTagHandlerPoolList(Node.Nodes page)
200 throws JasperException {
201
202 class TagHandlerPoolVisitor extends Node.Visitor {
203
204 private Vector names;
205
206
207
208
209
210
211 TagHandlerPoolVisitor(Vector v) {
212 names = v;
213 }
214
215
216
217
218
219
220 public void visit(Node.CustomTag n) throws JasperException {
221
222 if (!n.implementsSimpleTag()) {
223 String name =
224 createTagHandlerPoolName(
225 n.getPrefix(),
226 n.getLocalName(),
227 n.getAttributes(),
228 n.hasEmptyBody());
229 n.setTagHandlerPoolName(name);
230 if (!names.contains(name)) {
231 names.add(name);
232 }
233 }
234 visitBody(n);
235 }
236
237
238
239
240
241
242
243 private String createTagHandlerPoolName(
244 String prefix,
245 String shortName,
246 Attributes attrs,
247 boolean hasEmptyBody) {
248 String poolName = null;
249
250 poolName = "_jspx_tagPool_" + prefix + "_" + shortName;
251 if (attrs != null) {
252 String[] attrNames = new String[attrs.getLength()];
253 for (int i = 0; i < attrNames.length; i++) {
254 attrNames[i] = attrs.getQName(i);
255 }
256 Arrays.sort(attrNames, Collections.reverseOrder());
257 if (attrNames.length > 0) {
258 poolName = poolName + "&";
259 }
260 for (int i = 0; i < attrNames.length; i++) {
261 poolName = poolName + "_" + attrNames[i];
262 }
263 }
264 if (hasEmptyBody) {
265 poolName = poolName + "_nobody";
266 }
267 return JspUtil.makeJavaIdentifier(poolName);
268 }
269 }
270
271 page.visit(new TagHandlerPoolVisitor(tagHandlerPoolNames));
272 }
273
274 private void declareTemporaryScriptingVars(Node.Nodes page)
275 throws JasperException {
276
277 class ScriptingVarVisitor extends Node.Visitor {
278
279 private Vector vars;
280
281 ScriptingVarVisitor() {
282 vars = new Vector();
283 }
284
285 public void visit(Node.CustomTag n) throws JasperException {
286
287 if (n.getCustomNestingLevel() > 0) {
288 TagVariableInfo[] tagVarInfos = n.getTagVariableInfos();
289 VariableInfo[] varInfos = n.getVariableInfos();
290
291 if (varInfos.length > 0) {
292 for (int i = 0; i < varInfos.length; i++) {
293 String varName = varInfos[i].getVarName();
294 String tmpVarName =
295 "_jspx_"
296 + varName
297 + "_"
298 + n.getCustomNestingLevel();
299 if (!vars.contains(tmpVarName)) {
300 vars.add(tmpVarName);
301 out.printin(varInfos[i].getClassName());
302 out.print(" ");
303 out.print(tmpVarName);
304 out.print(" = ");
305 out.print(null);
306 out.println(";");
307 }
308 }
309 } else {
310 for (int i = 0; i < tagVarInfos.length; i++) {
311 String varName = tagVarInfos[i].getNameGiven();
312 if (varName == null) {
313 varName =
314 n.getTagData().getAttributeString(
315 tagVarInfos[i].getNameFromAttribute());
316 } else if (
317 tagVarInfos[i].getNameFromAttribute()
318 != null) {
319
320 continue;
321 }
322 String tmpVarName =
323 "_jspx_"
324 + varName
325 + "_"
326 + n.getCustomNestingLevel();
327 if (!vars.contains(tmpVarName)) {
328 vars.add(tmpVarName);
329 out.printin(tagVarInfos[i].getClassName());
330 out.print(" ");
331 out.print(tmpVarName);
332 out.print(" = ");
333 out.print(null);
334 out.println(";");
335 }
336 }
337 }
338 }
339
340 visitBody(n);
341 }
342 }
343
344 page.visit(new ScriptingVarVisitor());
345 }
346
347 /***
348 * Generates the _jspInit() method for instantiating the tag handler pools.
349 * For tag file, _jspInit has to be invoked manually, and the ServletConfig
350 * object explicitly passed.
351 */
352 private void generateInit() {
353
354 if (ctxt.isTagFile()) {
355 out.printil("private void _jspInit(ServletConfig config) {");
356 } else {
357 out.printil("public void _jspInit() {");
358 }
359
360 out.pushIndent();
361 for (int i = 0; i < tagHandlerPoolNames.size(); i++) {
362 out.printin((String) tagHandlerPoolNames.elementAt(i));
363 out.print(
364 " = org.apache.struts2.jasper.runtime.TagHandlerPool.getTagHandlerPool(");
365 if (ctxt.isTagFile()) {
366 out.print("config");
367 } else {
368 out.print("getServletConfig()");
369 }
370 out.println(");");
371 }
372 out.popIndent();
373 out.printil("}");
374 out.println();
375 }
376
377 /***
378 * Generates the _jspDestroy() method which is responsible for calling the
379 * release() method on every tag handler in any of the tag handler pools.
380 */
381 private void generateDestroy() {
382
383 out.printil("public void _jspDestroy() {");
384 out.pushIndent();
385 for (int i = 0; i < tagHandlerPoolNames.size(); i++) {
386 out.printin((String) tagHandlerPoolNames.elementAt(i));
387 out.println(".release();");
388 }
389 out.popIndent();
390 out.printil("}");
391 out.println();
392 }
393
394 /***
395 * Generate preamble package name
396 * (shared by servlet and tag handler preamble generation)
397 */
398 private void genPreamblePackage(String packageName)
399 throws JasperException {
400 if (!"".equals(packageName) && packageName != null) {
401 out.printil("package " + packageName + ";");
402 out.println();
403 }
404 }
405
406 /***
407 * Generate preamble imports
408 * (shared by servlet and tag handler preamble generation)
409 */
410 private void genPreambleImports() throws JasperException {
411 Iterator iter = pageInfo.getImports().iterator();
412 while (iter.hasNext()) {
413 out.printin("import ");
414 out.print((String) iter.next());
415 out.println(";");
416 }
417 out.println();
418 }
419
420 /***
421 * Generation of static initializers in preamble.
422 * For example, dependant list, el function map, prefix map.
423 * (shared by servlet and tag handler preamble generation)
424 */
425 private void genPreambleStaticInitializers() throws JasperException {
426
427 out.printil("private static java.util.List _jspx_dependants;");
428 out.println();
429 List dependants = pageInfo.getDependants();
430 Iterator iter = dependants.iterator();
431 if (!dependants.isEmpty()) {
432 out.printil("static {");
433 out.pushIndent();
434 out.printin("_jspx_dependants = new java.util.ArrayList(");
435 out.print("" + dependants.size());
436 out.println(");");
437 while (iter.hasNext()) {
438 out.printin("_jspx_dependants.add(\"");
439 out.print((String) iter.next());
440 out.println("\");");
441 }
442 out.popIndent();
443 out.printil("}");
444 out.println();
445 }
446 }
447
448 /***
449 * Declare tag handler pools (tags of the same type and with the same
450 * attribute set share the same tag handler pool)
451 * (shared by servlet and tag handler preamble generation)
452 */
453 private void genPreambleClassVariableDeclarations(String className)
454 throws JasperException {
455 if (isPoolingEnabled && !tagHandlerPoolNames.isEmpty()) {
456 for (int i = 0; i < tagHandlerPoolNames.size(); i++) {
457 out.printil(
458 "private org.apache.struts2.jasper.runtime.TagHandlerPool "
459 + tagHandlerPoolNames.elementAt(i)
460 + ";");
461 }
462 out.println();
463 }
464 }
465
466 /***
467 * Declare general-purpose methods
468 * (shared by servlet and tag handler preamble generation)
469 */
470 private void genPreambleMethods() throws JasperException {
471
472 out.printil("public Object getDependants() {");
473 out.pushIndent();
474 out.printil("return _jspx_dependants;");
475 out.popIndent();
476 out.printil("}");
477 out.println();
478
479 if (isPoolingEnabled && !tagHandlerPoolNames.isEmpty()) {
480 generateInit();
481 generateDestroy();
482 }
483 }
484
485 /***
486 * Generates the beginning of the static portion of the servlet.
487 */
488 private void generatePreamble(Node.Nodes page) throws JasperException {
489
490 String servletPackageName = ctxt.getServletPackageName();
491 String servletClassName = ctxt.getServletClassName();
492 String serviceMethodName = Constants.SERVICE_METHOD_NAME;
493
494
495 genPreamblePackage(servletPackageName);
496
497
498 genPreambleImports();
499
500
501 out.printin("public final class ");
502 out.print(servletClassName);
503 out.print(" extends ");
504 out.println(pageInfo.getExtends());
505 out.printin(
506 " implements org.apache.struts2.jasper.runtime.JspSourceDependent");
507 if (!pageInfo.isThreadSafe()) {
508 out.println(",");
509 out.printin(" SingleThreadModel");
510 }
511 out.println(" {");
512 out.pushIndent();
513
514
515 generateDeclarations(page);
516
517
518 genPreambleStaticInitializers();
519
520
521 genPreambleClassVariableDeclarations(servletClassName);
522
523
524
525
526
527 genPreambleMethods();
528
529
530 out.printin("public void ");
531 out.print(serviceMethodName);
532 out.println(
533 "(HttpServletRequest request, HttpServletResponse response)");
534 out.println(" throws java.io.IOException, ServletException {");
535
536 out.pushIndent();
537 out.println();
538
539
540 out.printil("JspFactory _jspxFactory = null;");
541 out.printil("PageContext pageContext = null;");
542 if (pageInfo.isSession())
543 out.printil("HttpSession session = null;");
544
545 if (pageInfo.isErrorPage()) {
546 out.printil(
547 "Throwable exception = org.apache.struts2.jasper.runtime.JspRuntimeLibrary.getThrowable(request);");
548 out.printil("if (exception != null) {");
549 out.pushIndent();
550 out.printil(
551 "response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);");
552 out.popIndent();
553 out.printil("}");
554 }
555
556 out.printil("ServletContext application = null;");
557 out.printil("ServletConfig config = null;");
558 out.printil("JspWriter out = null;");
559 out.printil("Object page = this;");
560
561 out.printil("JspWriter _jspx_out = null;");
562 out.printil("PageContext _jspx_page_context = null;");
563 out.println();
564
565 declareTemporaryScriptingVars(page);
566 out.println();
567
568 out.printil("try {");
569 out.pushIndent();
570
571 out.printil("_jspxFactory = JspFactory.getDefaultFactory();");
572
573 out.printin("response.setContentType(");
574 out.print(quote(pageInfo.getContentType()));
575 out.println(");");
576
577 if (ctxt.getOptions().isXpoweredBy()) {
578 out.printil("response.addHeader(\"X-Powered-By\", \"JSP/2.0\");");
579 }
580
581 out.printil(
582 "pageContext = _jspxFactory.getPageContext(this, request, response,");
583 out.printin("\t\t\t");
584 out.print(quote(pageInfo.getErrorPage()));
585 out.print(", " + pageInfo.isSession());
586 out.print(", " + pageInfo.getBuffer());
587 out.print(", " + pageInfo.isAutoFlush());
588 out.println(");");
589 out.printil("_jspx_page_context = pageContext;");
590
591 out.printil("application = pageContext.getServletContext();");
592 out.printil("config = pageContext.getServletConfig();");
593
594 if (pageInfo.isSession())
595 out.printil("session = pageContext.getSession();");
596 out.printil("out = pageContext.getOut();");
597 out.printil("_jspx_out = out;");
598 out.println();
599 }
600
601 /***
602 * Generates an XML Prolog, which includes an XML declaration and
603 * an XML doctype declaration.
604 */
605 private void generateXmlProlog(Node.Nodes page) {
606
607
608
609
610
611
612
613
614 String omitXmlDecl = pageInfo.getOmitXmlDecl();
615 if ((omitXmlDecl != null && !JspUtil.booleanValue(omitXmlDecl))
616 || (omitXmlDecl == null
617 && page.getRoot().isXmlSyntax()
618 && !pageInfo.hasJspRoot()
619 && !ctxt.isTagFile())) {
620 String cType = pageInfo.getContentType();
621 String charSet = cType.substring(cType.indexOf("charset=") + 8);
622 out.printil(
623 "out.write(\"<?xml version=//\"1.0//\" encoding=//\""
624 + charSet
625 + "//\"?>//n\");");
626 }
627
628
629
630
631
632
633
634
635
636 String doctypeName = pageInfo.getDoctypeName();
637 if (doctypeName != null) {
638 String doctypePublic = pageInfo.getDoctypePublic();
639 String doctypeSystem = pageInfo.getDoctypeSystem();
640 out.printin("out.write(\"<!DOCTYPE ");
641 out.print(doctypeName);
642 if (doctypePublic == null) {
643 out.print(" SYSTEM //\"");
644 } else {
645 out.print(" PUBLIC //\"");
646 out.print(doctypePublic);
647 out.print("//\" //\"");
648 }
649 out.print(doctypeSystem);
650 out.println("//\">//n\");");
651 }
652 }
653
654
655
656
657
658 private void generateConstructor(String className) {
659 out.printil("public " + className + "() {");
660 out.printil("}");
661 out.println();
662 }
663
664 /***
665 * A visitor that generates codes for the elements in the page.
666 */
667 class GenerateVisitor extends Node.Visitor {
668
669
670
671
672
673
674
675
676
677 private Hashtable handlerInfos;
678
679 private Hashtable tagVarNumbers;
680 private String parent;
681 private boolean isSimpleTagParent;
682 private String pushBodyCountVar;
683 private String simpleTagHandlerVar;
684 private boolean isSimpleTagHandler;
685 private boolean isFragment;
686 private boolean isTagFile;
687 private ServletWriter out;
688 private ArrayList methodsBuffered;
689 private FragmentHelperClass fragmentHelperClass;
690 private int methodNesting;
691 private TagInfo tagInfo;
692 private ClassLoader loader;
693 private int charArrayCount;
694 private HashMap textMap;
695
696 /***
697 * Constructor.
698 */
699 public GenerateVisitor(
700 boolean isTagFile,
701 ServletWriter out,
702 ArrayList methodsBuffered,
703 FragmentHelperClass fragmentHelperClass,
704 ClassLoader loader,
705 TagInfo tagInfo) {
706
707 this.isTagFile = isTagFile;
708 this.out = out;
709 this.methodsBuffered = methodsBuffered;
710 this.fragmentHelperClass = fragmentHelperClass;
711 this.loader = loader;
712 this.tagInfo = tagInfo;
713 methodNesting = 0;
714 handlerInfos = new Hashtable();
715 tagVarNumbers = new Hashtable();
716 textMap = new HashMap();
717 }
718
719 /***
720 * Returns an attribute value, optionally URL encoded. If
721 * the value is a runtime expression, the result is the expression
722 * itself, as a string. If the result is an EL expression, we insert
723 * a call to the interpreter. If the result is a Named Attribute
724 * we insert the generated variable name. Otherwise the result is a
725 * string literal, quoted and escaped.
726 *
727 * @param attr An JspAttribute object
728 * @param encode true if to be URL encoded
729 * @param expectedType the expected type for an EL evaluation
730 * (ignored for attributes that aren't EL expressions)
731 */
732 private String attributeValue(
733 Node.JspAttribute attr,
734 boolean encode,
735 Class expectedType) {
736 String v = attr.getValue();
737 if (!attr.isNamedAttribute() && (v == null))
738 return "";
739
740 if (attr.isExpression()) {
741 if (encode) {
742 return "org.apache.struts2.jasper.runtime.JspRuntimeLibrary.URLEncode(String.valueOf("
743 + v
744 + "), request.getCharacterEncoding())";
745 }
746 return v;
747 } else if (attr.isELInterpreterInput()) {
748 boolean replaceESC = v.indexOf(Constants.HACK_CHAR) > 0;
749 v =
750 JspUtil.interpreterCall(
751 this.isTagFile,
752 v,
753 expectedType,
754 attr.getEL().getMapName(),
755 false);
756
757 if (replaceESC) {
758 v = "(" + v + ").replace(" + Constants.HACK_STR + ", '$')";
759 }
760 if (encode) {
761 return "org.apache.struts2.jasper.runtime.JspRuntimeLibrary.URLEncode("
762 + v
763 + ", request.getCharacterEncoding())";
764 }
765 return v;
766 } else if (attr.isNamedAttribute()) {
767 return attr.getNamedAttributeNode().getTemporaryVariableName();
768 } else {
769 if (encode) {
770 return "org.apache.struts2.jasper.runtime.JspRuntimeLibrary.URLEncode("
771 + quote(v)
772 + ", request.getCharacterEncoding())";
773 }
774 return quote(v);
775 }
776 }
777
778 /***
779 * Prints the attribute value specified in the param action, in the
780 * form of name=value string.
781 *
782 * @param n the parent node for the param action nodes.
783 */
784 private void printParams(Node n, String pageParam, boolean literal)
785 throws JasperException {
786
787 class ParamVisitor extends Node.Visitor {
788 String separator;
789
790 ParamVisitor(String separator) {
791 this.separator = separator;
792 }
793
794 public void visit(Node.ParamAction n) throws JasperException {
795
796 out.print(" + ");
797 out.print(separator);
798 out.print(" + ");
799 out.print(
800 "org.apache.struts2.jasper.runtime.JspRuntimeLibrary."
801 + "URLEncode("
802 + quote(n.getTextAttribute("name"))
803 + ", request.getCharacterEncoding())");
804 out.print("+ \"=\" + ");
805 out.print(attributeValue(n.getValue(), true, String.class));
806
807
808 separator = "\"&\"";
809 }
810 }
811
812 String sep;
813 if (literal) {
814 sep = pageParam.indexOf('?') > 0 ? "\"&\"" : "\"?\"";
815 } else {
816 sep = "((" + pageParam + ").indexOf('?')>0? '&': '?')";
817 }
818 if (n.getBody() != null) {
819 n.getBody().visit(new ParamVisitor(sep));
820 }
821 }
822
823 public void visit(Node.Expression n) throws JasperException {
824 n.setBeginJavaLine(out.getJavaLine());
825 out.printin("out.print(");
826 out.printMultiLn(n.getText());
827 out.println(");");
828 n.setEndJavaLine(out.getJavaLine());
829 }
830
831 public void visit(Node.Scriptlet n) throws JasperException {
832 n.setBeginJavaLine(out.getJavaLine());
833 out.printMultiLn(n.getText());
834 out.println();
835 n.setEndJavaLine(out.getJavaLine());
836 }
837
838 public void visit(Node.ELExpression n) throws JasperException {
839 n.setBeginJavaLine(out.getJavaLine());
840 if (!pageInfo.isELIgnored()) {
841 out.printil(
842 "out.write("
843 + JspUtil.interpreterCall(
844 this.isTagFile,
845 "${" + new String(n.getText()) + "}",
846 String.class,
847 n.getEL().getMapName(),
848 false)
849 + ");");
850 } else {
851 out.printil(
852 "out.write("
853 + quote("${" + new String(n.getText()) + "}")
854 + ");");
855 }
856 n.setEndJavaLine(out.getJavaLine());
857 }
858
859 public void visit(Node.IncludeAction n) throws JasperException {
860
861 String flush = n.getTextAttribute("flush");
862 Node.JspAttribute page = n.getPage();
863
864 boolean isFlush = false;
865 if ("true".equals(flush))
866 isFlush = true;
867
868 n.setBeginJavaLine(out.getJavaLine());
869
870 String pageParam;
871 if (page.isNamedAttribute()) {
872
873
874
875 pageParam =
876 generateNamedAttributeValue(page.getNamedAttributeNode());
877 } else {
878 pageParam = attributeValue(page, false, String.class);
879 }
880
881
882
883 Node jspBody = findJspBody(n);
884 if (jspBody != null) {
885 prepareParams(jspBody);
886 } else {
887 prepareParams(n);
888 }
889
890 out.printin(
891 JSPRuntime.class.getName() + ".handle("
892 + pageParam);
893 printParams(n, pageParam, page.isLiteral());
894 out.println(", " + isFlush + ");");
895
896 n.setEndJavaLine(out.getJavaLine());
897 }
898
899 /***
900 * Scans through all child nodes of the given parent for
901 * <param> subelements. For each <param> element, if its value
902 * is specified via a Named Attribute (<jsp:attribute>),
903 * generate the code to evaluate those bodies first.
904 * <p/>
905 * If parent is null, simply returns.
906 */
907 private void prepareParams(Node parent) throws JasperException {
908 if (parent == null)
909 return;
910
911 Node.Nodes subelements = parent.getBody();
912 if (subelements != null) {
913 for (int i = 0; i < subelements.size(); i++) {
914 Node n = subelements.getNode(i);
915 if (n instanceof Node.ParamAction) {
916 Node.Nodes paramSubElements = n.getBody();
917 for (int j = 0;
918 (paramSubElements != null)
919 && (j < paramSubElements.size());
920 j++) {
921 Node m = paramSubElements.getNode(j);
922 if (m instanceof Node.NamedAttribute) {
923 generateNamedAttributeValue(
924 (Node.NamedAttribute) m);
925 }
926 }
927 }
928 }
929 }
930 }
931
932 /***
933 * Finds the <jsp:body> subelement of the given parent node.
934 * If not found, null is returned.
935 */
936 private Node.JspBody findJspBody(Node parent) throws JasperException {
937 Node.JspBody result = null;
938
939 Node.Nodes subelements = parent.getBody();
940 for (int i = 0;
941 (subelements != null) && (i < subelements.size());
942 i++) {
943 Node n = subelements.getNode(i);
944 if (n instanceof Node.JspBody) {
945 result = (Node.JspBody) n;
946 break;
947 }
948 }
949
950 return result;
951 }
952
953 public void visit(Node.ForwardAction n) throws JasperException {
954 Node.JspAttribute page = n.getPage();
955
956 n.setBeginJavaLine(out.getJavaLine());
957
958 out.printil("if (true) {");
959 out.pushIndent();
960
961 String pageParam;
962 if (page.isNamedAttribute()) {
963
964
965
966 pageParam =
967 generateNamedAttributeValue(page.getNamedAttributeNode());
968 } else {
969 pageParam = attributeValue(page, false, String.class);
970 }
971
972
973
974 Node jspBody = findJspBody(n);
975 if (jspBody != null) {
976 prepareParams(jspBody);
977 } else {
978 prepareParams(n);
979 }
980
981 out.printin("_jspx_page_context.forward(");
982 out.print(pageParam);
983 printParams(n, pageParam, page.isLiteral());
984 out.println(");");
985 if (isTagFile || isFragment) {
986 out.printil("throw new SkipPageException();");
987 } else {
988 out.printil((methodNesting > 0) ? "return true;" : "return;");
989 }
990 out.popIndent();
991 out.printil("}");
992
993 n.setEndJavaLine(out.getJavaLine());
994
995 }
996
997 public void visit(Node.GetProperty n) throws JasperException {
998 String name = n.getTextAttribute("name");
999 String property = n.getTextAttribute("property");
1000
1001 n.setBeginJavaLine(out.getJavaLine());
1002
1003 if (beanInfo.checkVariable(name)) {
1004
1005 Class bean = beanInfo.getBeanType(name);
1006 String beanName = JspUtil.getCanonicalName(bean);
1007 java.lang.reflect.Method meth =
1008 JspRuntimeLibrary.getReadMethod(bean, property);
1009 String methodName = meth.getName();
1010 out.printil(
1011 "out.write(org.apache.struts2.jasper.runtime.JspRuntimeLibrary.toString("
1012 + "((("
1013 + beanName
1014 + ")_jspx_page_context.findAttribute("
1015 + "\""
1016 + name
1017 + "\"))."
1018 + methodName
1019 + "())));");
1020 } else {
1021
1022
1023
1024 out.printil(
1025 "out.write(org.apache.struts2.jasper.runtime.JspRuntimeLibrary.toString"
1026 + "(org.apache.struts2.jasper.runtime.JspRuntimeLibrary.handleGetProperty"
1027 + "(_jspx_page_context.getAttribute(\""
1028 + name
1029 + "\", PageContext.PAGE_SCOPE), \""
1030 + property
1031 + "\")));");
1032 }
1033
1034 n.setEndJavaLine(out.getJavaLine());
1035 }
1036
1037 public void visit(Node.SetProperty n) throws JasperException {
1038 String name = n.getTextAttribute("name");
1039 String property = n.getTextAttribute("property");
1040 String param = n.getTextAttribute("param");
1041 Node.JspAttribute value = n.getValue();
1042
1043 n.setBeginJavaLine(out.getJavaLine());
1044
1045 if ("*".equals(property)) {
1046 out.printil(
1047 "org.apache.struts2.jasper.runtime.JspRuntimeLibrary.introspect("
1048 + "_jspx_page_context.findAttribute("
1049 + "\""
1050 + name
1051 + "\"), request);");
1052 } else if (value == null) {
1053 if (param == null)
1054 param = property;
1055 out.printil(
1056 "org.apache.struts2.jasper.runtime.JspRuntimeLibrary.introspecthelper("
1057 + "_jspx_page_context.findAttribute(\""
1058 + name
1059 + "\"), \""
1060 + property
1061 + "\", request.getParameter(\""
1062 + param
1063 + "\"), "
1064 + "request, \""
1065 + param
1066 + "\", false);");
1067 } else if (value.isExpression()) {
1068 out.printil(
1069 "org.apache.struts2.jasper.runtime.JspRuntimeLibrary.handleSetProperty("
1070 + "_jspx_page_context.findAttribute(\""
1071 + name
1072 + "\"), \""
1073 + property
1074 + "\",");
1075 out.print(attributeValue(value, false, null));
1076 out.println(");");
1077 } else if (value.isELInterpreterInput()) {
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091 out.printil(
1092 "org.apache.struts2.jasper.runtime.JspRuntimeLibrary.handleSetPropertyExpression("
1093 + "_jspx_page_context.findAttribute(\""
1094 + name
1095 + "\"), \""
1096 + property
1097 + "\", "
1098 + quote(value.getValue())
1099 + ", "
1100 + "_jspx_page_context, "
1101 + value.getEL().getMapName()
1102 + ");");
1103 } else if (value.isNamedAttribute()) {
1104
1105
1106
1107 String valueVarName =
1108 generateNamedAttributeValue(value.getNamedAttributeNode());
1109 out.printil(
1110 "org.apache.struts2.jasper.runtime.JspRuntimeLibrary.introspecthelper("
1111 + "_jspx_page_context.findAttribute(\""
1112 + name
1113 + "\"), \""
1114 + property
1115 + "\", "
1116 + valueVarName
1117 + ", null, null, false);");
1118 } else {
1119 out.printin(
1120 "org.apache.struts2.jasper.runtime.JspRuntimeLibrary.introspecthelper("
1121 + "_jspx_page_context.findAttribute(\""
1122 + name
1123 + "\"), \""
1124 + property
1125 + "\", ");
1126 out.print(attributeValue(value, false, null));
1127 out.println(", null, null, false);");
1128 }
1129
1130 n.setEndJavaLine(out.getJavaLine());
1131 }
1132
1133 public void visit(Node.UseBean n) throws JasperException {
1134
1135 String name = n.getTextAttribute("id");
1136 String scope = n.getTextAttribute("scope");
1137 String klass = n.getTextAttribute("class");
1138 String type = n.getTextAttribute("type");
1139 Node.JspAttribute beanName = n.getBeanName();
1140
1141
1142 boolean generateNew = false;
1143 String canonicalName = null;
1144 if (klass != null) {
1145 try {
1146 Class bean = ctxt.getClassLoader().loadClass(klass);
1147 if (klass.indexOf('$') >= 0) {
1148
1149 canonicalName = JspUtil.getCanonicalName(bean);
1150 } else {
1151 canonicalName = klass;
1152 }
1153 int modifiers = bean.getModifiers();
1154 if (!Modifier.isPublic(modifiers) ||
1155 Modifier.isInterface(modifiers) ||
1156 Modifier.isAbstract(modifiers)) {
1157 throw new Exception("Invalid bean class modifier");
1158 }
1159
1160 bean.getConstructor(new Class[]{});
1161
1162
1163
1164 generateNew = true;
1165 } catch (Exception e) {
1166
1167
1168
1169 if (ctxt.getOptions().getErrorOnUseBeanInvalidClassAttribute()) {
1170 err.jspError(n, "jsp.error.invalid.bean", klass);
1171 }
1172 if (canonicalName == null) {
1173
1174
1175 canonicalName = klass.replace('$', '.');
1176 }
1177 }
1178 if (type == null) {
1179
1180 type = canonicalName;
1181 }
1182 }
1183
1184 String scopename = "PageContext.PAGE_SCOPE";
1185 String lock = "_jspx_page_context";
1186
1187 if ("request".equals(scope)) {
1188 scopename = "PageContext.REQUEST_SCOPE";
1189 lock = "request";
1190 } else if ("session".equals(scope)) {
1191 scopename = "PageContext.SESSION_SCOPE";
1192 lock = "session";
1193 } else if ("application".equals(scope)) {
1194 scopename = "PageContext.APPLICATION_SCOPE";
1195 lock = "application";
1196 }
1197
1198 n.setBeginJavaLine(out.getJavaLine());
1199
1200
1201 out.printin(type);
1202 out.print(' ');
1203 out.print(name);
1204 out.println(" = null;");
1205
1206
1207 out.printin("synchronized (");
1208 out.print(lock);
1209 out.println(") {");
1210 out.pushIndent();
1211
1212
1213 out.printin(name);
1214 out.print(" = (");
1215 out.print(type);
1216 out.print(") _jspx_page_context.getAttribute(");
1217 out.print(quote(name));
1218 out.print(", ");
1219 out.print(scopename);
1220 out.println(");");
1221
1222
1223
1224
1225
1226 out.printin("if (");
1227 out.print(name);
1228 out.println(" == null){");
1229 out.pushIndent();
1230 if (klass == null && beanName == null) {
1231
1232
1233
1234
1235 out.printin(
1236 "throw new java.lang.InstantiationException(\"bean ");
1237 out.print(name);
1238 out.println(" not found within scope\");");
1239 } else {
1240
1241
1242
1243 if (!generateNew) {
1244 String binaryName;
1245 if (beanName != null) {
1246 if (beanName.isNamedAttribute()) {
1247
1248
1249
1250 binaryName =
1251 generateNamedAttributeValue(
1252 beanName.getNamedAttributeNode());
1253 } else {
1254 binaryName =
1255 attributeValue(beanName, false, String.class);
1256 }
1257 } else {
1258
1259 binaryName = quote(klass);
1260 }
1261 out.printil("try {");
1262 out.pushIndent();
1263 out.printin(name);
1264 out.print(" = (");
1265 out.print(type);
1266 out.print(") java.beans.Beans.instantiate(");
1267 out.print("this.getClass().getClassLoader(), ");
1268 out.print(binaryName);
1269 out.println(");");
1270 out.popIndent();
1271
1272
1273
1274
1275 out.printil("} catch (ClassNotFoundException exc) {");
1276 out.pushIndent();
1277 out.printil(
1278 "throw new InstantiationException(exc.getMessage());");
1279 out.popIndent();
1280 out.printil("} catch (Exception exc) {");
1281 out.pushIndent();
1282 out.printin("throw new ServletException(");
1283 out.print("\"Cannot create bean of class \" + ");
1284 out.print(binaryName);
1285 out.println(", exc);");
1286 out.popIndent();
1287 out.printil("}");
1288 } else {
1289
1290
1291 out.printin(name);
1292 out.print(" = new ");
1293 out.print(canonicalName);
1294 out.println("();");
1295 }
1296
1297
1298
1299 out.printin("_jspx_page_context.setAttribute(");
1300 out.print(quote(name));
1301 out.print(", ");
1302 out.print(name);
1303 out.print(", ");
1304 out.print(scopename);
1305 out.println(");");
1306
1307
1308 visitBody(n);
1309 }
1310 out.popIndent();
1311 out.printil("}");
1312
1313
1314 out.popIndent();
1315 out.printil("}");
1316
1317 n.setEndJavaLine(out.getJavaLine());
1318 }
1319
1320 /***
1321 * @return a string for the form 'attr = "value"'
1322 */
1323 private String makeAttr(String attr, String value) {
1324 if (value == null)
1325 return "";
1326
1327 return " " + attr + "=\"" + value + '\"';
1328 }
1329
1330 public void visit(Node.PlugIn n) throws JasperException {
1331
1332 /***
1333 * A visitor to handle <jsp:param> in a plugin
1334 */
1335 class ParamVisitor extends Node.Visitor {
1336
1337 private boolean ie;
1338
1339 ParamVisitor(boolean ie) {
1340 this.ie = ie;
1341 }
1342
1343 public void visit(Node.ParamAction n) throws JasperException {
1344
1345 String name = n.getTextAttribute("name");
1346 if (name.equalsIgnoreCase("object"))
1347 name = "java_object";
1348 else if (name.equalsIgnoreCase("type"))
1349 name = "java_type";
1350
1351 n.setBeginJavaLine(out.getJavaLine());
1352
1353
1354
1355
1356
1357 if (ie) {
1358
1359
1360
1361 out.printil(
1362 "out.write( \"<param name=//\""
1363 + escape(name)
1364 + "//\" value=//\"\" + "
1365 + attributeValue(
1366 n.getValue(),
1367 false,
1368 String.class)
1369 + " + \"//\">\" );");
1370 out.printil("out.write(\"//n\");");
1371 } else {
1372
1373
1374 out.printil(
1375 "out.write( \" "
1376 + escape(name)
1377 + "=//\"\" + "
1378 + attributeValue(
1379 n.getValue(),
1380 false,
1381 String.class)
1382 + " + \"//\"\" );");
1383 }
1384
1385 n.setEndJavaLine(out.getJavaLine());
1386 }
1387 }
1388
1389 String type = n.getTextAttribute("type");
1390 String code = n.getTextAttribute("code");
1391 String name = n.getTextAttribute("name");
1392 Node.JspAttribute height = n.getHeight();
1393 Node.JspAttribute width = n.getWidth();
1394 String hspace = n.getTextAttribute("hspace");
1395 String vspace = n.getTextAttribute("vspace");
1396 String align = n.getTextAttribute("align");
1397 String iepluginurl = n.getTextAttribute("iepluginurl");
1398 String nspluginurl = n.getTextAttribute("nspluginurl");
1399 String codebase = n.getTextAttribute("codebase");
1400 String archive = n.getTextAttribute("archive");
1401 String jreversion = n.getTextAttribute("jreversion");
1402
1403 String widthStr = null;
1404 if (width != null) {
1405 if (width.isNamedAttribute()) {
1406 widthStr =
1407 generateNamedAttributeValue(
1408 width.getNamedAttributeNode());
1409 } else {
1410 widthStr = attributeValue(width, false, String.class);
1411 }
1412 }
1413
1414 String heightStr = null;
1415 if (height != null) {
1416 if (height.isNamedAttribute()) {
1417 heightStr =
1418 generateNamedAttributeValue(
1419 height.getNamedAttributeNode());
1420 } else {
1421 heightStr = attributeValue(height, false, String.class);
1422 }
1423 }
1424
1425 if (iepluginurl == null)
1426 iepluginurl = Constants.IE_PLUGIN_URL;
1427 if (nspluginurl == null)
1428 nspluginurl = Constants.NS_PLUGIN_URL;
1429
1430 n.setBeginJavaLine(out.getJavaLine());
1431
1432
1433
1434
1435 Node.JspBody jspBody = findJspBody(n);
1436 if (jspBody != null) {
1437 Node.Nodes subelements = jspBody.getBody();
1438 if (subelements != null) {
1439 for (int i = 0; i < subelements.size(); i++) {
1440 Node m = subelements.getNode(i);
1441 if (m instanceof Node.ParamsAction) {
1442 prepareParams(m);
1443 break;
1444 }
1445 }
1446 }
1447 }
1448
1449
1450
1451
1452
1453
1454
1455 String s0 = "<object"
1456 + makeAttr("classid", ctxt.getOptions().getIeClassId())
1457 + makeAttr("name", name);
1458
1459 String s1 = "";
1460 if (width != null) {
1461 s1 = " + \" width=//\"\" + " + widthStr + " + \"//\"\"";
1462 }
1463
1464 String s2 = "";
1465 if (height != null) {
1466 s2 = " + \" height=//\"\" + " + heightStr + " + \"//\"\"";
1467 }
1468
1469 String s3 = makeAttr("hspace", hspace)
1470 + makeAttr("vspace", vspace)
1471 + makeAttr("align", align)
1472 + makeAttr("codebase", iepluginurl)
1473 + '>';
1474
1475
1476 out.printil(
1477 "out.write(" + quote(s0) + s1 + s2 + " + " + quote(s3) + ");");
1478 out.printil("out.write(\"//n\");");
1479
1480
1481 s0 = "<param name=\"java_code\"" + makeAttr("value", code) + '>';
1482 out.printil("out.write(" + quote(s0) + ");");
1483 out.printil("out.write(\"//n\");");
1484
1485
1486 if (codebase != null) {
1487 s0 = "<param name=\"java_codebase\""
1488 + makeAttr("value", codebase)
1489 + '>';
1490 out.printil("out.write(" + quote(s0) + ");");
1491 out.printil("out.write(\"//n\");");
1492 }
1493
1494
1495 if (archive != null) {
1496 s0 = "<param name=\"java_archive\""
1497 + makeAttr("value", archive)
1498 + '>';
1499 out.printil("out.write(" + quote(s0) + ");");
1500 out.printil("out.write(\"//n\");");
1501 }
1502
1503
1504 s0 = "<param name=\"type\""
1505 + makeAttr(
1506 "value",
1507 "application/x-java-"
1508 + type
1509 + ";"
1510 + ((jreversion == null)
1511 ? ""
1512 : "version=" + jreversion))
1513 + '>';
1514 out.printil("out.write(" + quote(s0) + ");");
1515 out.printil("out.write(\"//n\");");
1516
1517
1518
1519
1520 if (n.getBody() != null)
1521 n.getBody().visit(new ParamVisitor(true));
1522
1523
1524
1525
1526 out.printil("out.write(" + quote("<comment>") + ");");
1527 out.printil("out.write(\"//n\");");
1528 s0 = "<embed"
1529 + makeAttr(
1530 "type",
1531 "application/x-java-"
1532 + type
1533 + ";"
1534 + ((jreversion == null)
1535 ? ""
1536 : "version=" + jreversion))
1537 + makeAttr("name", name);
1538
1539
1540
1541 s3 = makeAttr("hspace", hspace)
1542 + makeAttr("vspace", vspace)
1543 + makeAttr("align", align)
1544 + makeAttr("pluginspage", nspluginurl)
1545 + makeAttr("java_code", code)
1546 + makeAttr("java_codebase", codebase)
1547 + makeAttr("java_archive", archive);
1548 out.printil(
1549 "out.write(" + quote(s0) + s1 + s2 + " + " + quote(s3) + ");");
1550
1551
1552
1553
1554 if (n.getBody() != null)
1555 n.getBody().visit(new ParamVisitor(false));
1556
1557 out.printil("out.write(" + quote("/>") + ");");
1558 out.printil("out.write(\"//n\");");
1559
1560 out.printil("out.write(" + quote("<noembed>") + ");");
1561 out.printil("out.write(\"//n\");");
1562
1563
1564
1565
1566 if (n.getBody() != null) {
1567 visitBody(n);
1568 out.printil("out.write(\"//n\");");
1569 }
1570
1571 out.printil("out.write(" + quote("</noembed>") + ");");
1572 out.printil("out.write(\"//n\");");
1573
1574 out.printil("out.write(" + quote("</comment>") + ");");
1575 out.printil("out.write(\"//n\");");
1576
1577 out.printil("out.write(" + quote("</object>") + ");");
1578 out.printil("out.write(\"//n\");");
1579
1580 n.setEndJavaLine(out.getJavaLine());
1581 }
1582
1583 public void visit(Node.NamedAttribute n) throws JasperException {
1584
1585 }
1586
1587 public void visit(Node.CustomTag n) throws JasperException {
1588
1589
1590 if (n.useTagPlugin()) {
1591 generateTagPlugin(n);
1592 return;
1593 }
1594
1595 TagHandlerInfo handlerInfo = getTagHandlerInfo(n);
1596
1597
1598 String baseVar =
1599 createTagVarName(n.getQName(), n.getPrefix(), n.getLocalName());
1600 String tagEvalVar = "_jspx_eval_" + baseVar;
1601 String tagHandlerVar = "_jspx_th_" + baseVar;
1602 String tagPushBodyCountVar = "_jspx_push_body_count_" + baseVar;
1603
1604
1605
1606 ServletWriter outSave = null;
1607 Node.ChildInfo ci = n.getChildInfo();
1608 if (ci.isScriptless() && !ci.hasScriptingVars()) {
1609
1610
1611
1612
1613 String tagMethod = "_jspx_meth_" + baseVar;
1614
1615
1616 out.printin("if (");
1617 out.print(tagMethod);
1618 out.print("(");
1619 if (parent != null) {
1620 out.print(parent);
1621 out.print(", ");
1622 }
1623 out.print("_jspx_page_context");
1624 if (pushBodyCountVar != null) {
1625 out.print(", ");
1626 out.print(pushBodyCountVar);
1627 }
1628 out.println("))");
1629 out.pushIndent();
1630 out.printil((methodNesting > 0) ? "return true;" : "return;");
1631 out.popIndent();
1632
1633
1634 outSave = out;
1635
1636
1637
1638
1639
1640 GenBuffer genBuffer =
1641 new GenBuffer(n, n.implementsSimpleTag() ? null : n.getBody());
1642 methodsBuffered.add(genBuffer);
1643 out = genBuffer.getOut();
1644
1645 methodNesting++;
1646
1647 out.println();
1648 out.pushIndent();
1649 out.printin("private boolean ");
1650 out.print(tagMethod);
1651 out.print("(");
1652 if (parent != null) {
1653 out.print("javax.servlet.jsp.tagext.JspTag ");
1654 out.print(parent);
1655 out.print(", ");
1656 }
1657 out.print("PageContext _jspx_page_context");
1658 if (pushBodyCountVar != null) {
1659 out.print(", int[] ");
1660 out.print(pushBodyCountVar);
1661 }
1662 out.println(")");
1663 out.printil(" throws Throwable {");
1664 out.pushIndent();
1665
1666
1667 if (!isTagFile) {
1668 out.printil("PageContext pageContext = _jspx_page_context;");
1669 }
1670 out.printil("JspWriter out = _jspx_page_context.getOut();");
1671 generateLocalVariables(out, n);
1672 }
1673
1674 if (n.implementsSimpleTag()) {
1675 generateCustomDoTag(n, handlerInfo, tagHandlerVar);
1676 } else {
1677
1678
1679
1680
1681 generateCustomStart(
1682 n,
1683 handlerInfo,
1684 tagHandlerVar,
1685 tagEvalVar,
1686 tagPushBodyCountVar);
1687
1688
1689 String tmpParent = parent;
1690 parent = tagHandlerVar;
1691 boolean isSimpleTagParentSave = isSimpleTagParent;
1692 isSimpleTagParent = false;
1693 String tmpPushBodyCountVar = null;
1694 if (n.implementsTryCatchFinally()) {
1695 tmpPushBodyCountVar = pushBodyCountVar;
1696 pushBodyCountVar = tagPushBodyCountVar;
1697 }
1698 boolean tmpIsSimpleTagHandler = isSimpleTagHandler;
1699 isSimpleTagHandler = false;
1700
1701 visitBody(n);
1702
1703 parent = tmpParent;
1704 isSimpleTagParent = isSimpleTagParentSave;
1705 if (n.implementsTryCatchFinally()) {
1706 pushBodyCountVar = tmpPushBodyCountVar;
1707 }
1708 isSimpleTagHandler = tmpIsSimpleTagHandler;
1709
1710 generateCustomEnd(
1711 n,
1712 tagHandlerVar,
1713 tagEvalVar,
1714 tagPushBodyCountVar);
1715 }
1716
1717 if (ci.isScriptless() && !ci.hasScriptingVars()) {
1718
1719 if (methodNesting > 0) {
1720 out.printil("return false;");
1721 }
1722 out.popIndent();
1723 out.printil("}");
1724 out.popIndent();
1725
1726 methodNesting--;
1727
1728
1729 out = outSave;
1730 }
1731 }
1732
1733 private static final String SINGLE_QUOTE = "'";
1734 private static final String DOUBLE_QUOTE = "//\"";
1735
1736 public void visit(Node.UninterpretedTag n) throws JasperException {
1737
1738 n.setBeginJavaLine(out.getJavaLine());
1739
1740
1741
1742
1743 out.printin("out.write(\"<");
1744 out.print(n.getQName());
1745
1746 Attributes attrs = n.getNonTaglibXmlnsAttributes();
1747 int attrsLen = (attrs == null) ? 0 : attrs.getLength();
1748 for (int i = 0; i < attrsLen; i++) {
1749 out.print(" ");
1750 out.print(attrs.getQName(i));
1751 out.print("=");
1752 String quote = DOUBLE_QUOTE;
1753 String value = attrs.getValue(i);
1754 if (value.indexOf('"') != -1) {
1755 quote = SINGLE_QUOTE;
1756 }
1757 out.print(quote);
1758 out.print(value);
1759 out.print(quote);
1760 }
1761
1762 attrs = n.getAttributes();
1763 attrsLen = (attrs == null) ? 0 : attrs.getLength();
1764 Node.JspAttribute[] jspAttrs = n.getJspAttributes();
1765 for (int i = 0; i < attrsLen; i++) {
1766 out.print(" ");
1767 out.print(attrs.getQName(i));
1768 out.print("=");
1769 if (jspAttrs[i].isELInterpreterInput()) {
1770 out.print("//\"\" + ");
1771 out.print(attributeValue(jspAttrs[i], false, String.class));
1772 out.print(" + \"//\"");
1773 } else {
1774 String quote = DOUBLE_QUOTE;
1775 String value = attrs.getValue(i);
1776 if (value.indexOf('"') != -1) {
1777 quote = SINGLE_QUOTE;
1778 }
1779 out.print(quote);
1780 out.print(value);
1781 out.print(quote);
1782 }
1783 }
1784
1785 if (n.getBody() != null) {
1786 out.println(">\");");
1787
1788
1789 visitBody(n);
1790
1791
1792
1793
1794 out.printin("out.write(\"</");
1795 out.print(n.getQName());
1796 out.println(">\");");
1797 } else {
1798 out.println("/>\");");
1799 }
1800
1801 n.setEndJavaLine(out.getJavaLine());
1802 }
1803
1804 public void visit(Node.JspElement n) throws JasperException {
1805
1806 n.setBeginJavaLine(out.getJavaLine());
1807
1808
1809
1810 Hashtable map = new Hashtable();
1811 Node.JspAttribute[] attrs = n.getJspAttributes();
1812 for (int i = 0; attrs != null && i < attrs.length; i++) {
1813 String attrStr = null;
1814 if (attrs[i].isNamedAttribute()) {
1815 attrStr =
1816 generateNamedAttributeValue(
1817 attrs[i].getNamedAttributeNode());
1818 } else {
1819 attrStr = attributeValue(attrs[i], false, Object.class);
1820 }
1821 String s =
1822 " + \" "
1823 + attrs[i].getName()
1824 + "=//\"\" + "
1825 + attrStr
1826 + " + \"//\"\"";
1827 map.put(attrs[i].getName(), s);
1828 }
1829
1830
1831
1832 String elemName =
1833 attributeValue(n.getNameAttribute(), false, String.class);
1834 out.printin("out.write(\"<\"");
1835 out.print(" + " + elemName);
1836
1837
1838 Enumeration enumeration = map.keys();
1839 while (enumeration.hasMoreElements()) {
1840 String attrName = (String) enumeration.nextElement();
1841 out.print((String) map.get(attrName));
1842 }
1843
1844
1845
1846 boolean hasBody = false;
1847 Node.Nodes subelements = n.getBody();
1848 if (subelements != null) {
1849 for (int i = 0; i < subelements.size(); i++) {
1850 Node subelem = subelements.getNode(i);
1851 if (!(subelem instanceof Node.NamedAttribute)) {
1852 hasBody = true;
1853 break;
1854 }
1855 }
1856 }
1857 if (hasBody) {
1858 out.println(" + \">\");");
1859
1860
1861 n.setEndJavaLine(out.getJavaLine());
1862
1863
1864 visitBody(n);
1865
1866
1867 out.printin("out.write(\"</\"");
1868 out.print(" + " + elemName);
1869 out.println(" + \">\");");
1870 } else {
1871 out.println(" + \"/>\");");
1872 n.setEndJavaLine(out.getJavaLine());
1873 }
1874 }
1875
1876 public void visit(Node.TemplateText n) throws JasperException {
1877
1878 String text = n.getText();
1879
1880 int textSize = text.length();
1881 if (textSize == 0) {
1882 return;
1883 }
1884
1885
1886 if (text.indexOf(Constants.HACK_CHAR) > 0) {
1887 if (pageInfo.isELIgnored()) {
1888 text = text.replaceAll(String.valueOf(Constants.HACK_CHAR),
1889 "//////$");
1890 textSize++;
1891 } else {
1892 text = text.replace(Constants.HACK_CHAR, '$');
1893 }
1894 }
1895
1896 if (textSize <= 3) {
1897
1898 n.setBeginJavaLine(out.getJavaLine());
1899 int lineInc = 0;
1900 for (int i = 0; i < textSize; i++) {
1901 char ch = text.charAt(i);
1902 out.printil("out.write(" + quote(ch) + ");");
1903 if (i > 0) {
1904 n.addSmap(lineInc);
1905 }
1906 if (ch == '\n') {
1907 lineInc++;
1908 }
1909 }
1910 n.setEndJavaLine(out.getJavaLine());
1911 return;
1912 }
1913
1914 if (ctxt.getOptions().genStringAsCharArray()) {
1915
1916 ServletWriter caOut;
1917 if (charArrayBuffer == null) {
1918 charArrayBuffer = new GenBuffer();
1919 caOut = charArrayBuffer.getOut();
1920 caOut.pushIndent();
1921 textMap = new HashMap();
1922 } else {
1923 caOut = charArrayBuffer.getOut();
1924 }
1925 String charArrayName = (String) textMap.get(text);
1926 if (charArrayName == null) {
1927 charArrayName = "_jspx_char_array_" + charArrayCount++;
1928 textMap.put(text, charArrayName);
1929 caOut.printin("static char[] ");
1930 caOut.print(charArrayName);
1931 caOut.print(" = ");
1932 caOut.print(quote(text));
1933 caOut.println(".toCharArray();");
1934 }
1935
1936 n.setBeginJavaLine(out.getJavaLine());
1937 out.printil("out.write(" + charArrayName + ");");
1938 n.setEndJavaLine(out.getJavaLine());
1939 return;
1940 }
1941
1942 n.setBeginJavaLine(out.getJavaLine());
1943
1944 out.printin();
1945 StringBuffer sb = new StringBuffer("out.write(\"");
1946 int initLength = sb.length();
1947 int count = JspUtil.CHUNKSIZE;
1948 int srcLine = 0;
1949 for (int i = 0; i < text.length(); i++) {
1950 char ch = text.charAt(i);
1951 --count;
1952 switch (ch) {
1953 case '"':
1954 sb.append('//').append('\"');
1955 break;
1956 case '//':
1957 sb.append('//').append('//');
1958 break;
1959 case '\r':
1960 sb.append('//').append('r');
1961 break;
1962 case '\n':
1963 sb.append('//').append('n');
1964 srcLine++;
1965
1966 if (breakAtLF || count < 0) {
1967
1968 sb.append("\");");
1969 out.println(sb.toString());
1970 if (i < text.length() - 1) {
1971 out.printin();
1972 }
1973 sb.setLength(initLength);
1974 count = JspUtil.CHUNKSIZE;
1975 }
1976
1977 n.addSmap(srcLine);
1978 break;
1979 case '\t':
1980 sb.append('//').append('t');
1981 break;
1982 default:
1983 sb.append(ch);
1984 }
1985 }
1986
1987 if (sb.length() > initLength) {
1988 sb.append("\");");
1989 out.println(sb.toString());
1990 }
1991
1992 n.setEndJavaLine(out.getJavaLine());
1993 }
1994
1995 public void visit(Node.JspBody n) throws JasperException {
1996 if (n.getBody() != null) {
1997 if (isSimpleTagHandler) {
1998 out.printin(simpleTagHandlerVar);
1999 out.print(".setJspBody(");
2000 generateJspFragment(n, simpleTagHandlerVar);
2001 out.println(");");
2002 } else {
2003 visitBody(n);
2004 }
2005 }
2006 }
2007
2008 public void visit(Node.InvokeAction n) throws JasperException {
2009
2010 n.setBeginJavaLine(out.getJavaLine());
2011
2012
2013
2014 out.printil(
2015 "((org.apache.struts2.jasper.runtime.JspContextWrapper) this.jspContext).syncBeforeInvoke();");
2016 String varReaderAttr = n.getTextAttribute("varReader");
2017 String varAttr = n.getTextAttribute("var");
2018 if (varReaderAttr != null || varAttr != null) {
2019 out.printil("_jspx_sout = new java.io.StringWriter();");
2020 } else {
2021 out.printil("_jspx_sout = null;");
2022 }
2023
2024
2025 out.printin("if (");
2026 out.print(toGetterMethod(n.getTextAttribute("fragment")));
2027 out.println(" != null) {");
2028 out.pushIndent();
2029 out.printin(toGetterMethod(n.getTextAttribute("fragment")));
2030 out.println(".invoke(_jspx_sout);");
2031 out.popIndent();
2032 out.printil("}");
2033
2034
2035 if (varReaderAttr != null || varAttr != null) {
2036 String scopeName = n.getTextAttribute("scope");
2037 out.printin("_jspx_page_context.setAttribute(");
2038 if (varReaderAttr != null) {
2039 out.print(quote(varReaderAttr));
2040 out.print(
2041 ", new java.io.StringReader(_jspx_sout.toString())");
2042 } else {
2043 out.print(quote(varAttr));
2044 out.print(", _jspx_sout.toString()");
2045 }
2046 if (scopeName != null) {
2047 out.print(", ");
2048 out.print(getScopeConstant(scopeName));
2049 }
2050 out.println(");");
2051 }
2052
2053 n.setEndJavaLine(out.getJavaLine());
2054 }
2055
2056 public void visit(Node.DoBodyAction n) throws JasperException {
2057
2058 n.setBeginJavaLine(out.getJavaLine());
2059
2060
2061
2062 out.printil(
2063 "((org.apache.struts2.jasper.runtime.JspContextWrapper) this.jspContext).syncBeforeInvoke();");
2064
2065
2066 String varReaderAttr = n.getTextAttribute("varReader");
2067 String varAttr = n.getTextAttribute("var");
2068 if (varReaderAttr != null || varAttr != null) {
2069 out.printil("_jspx_sout = new java.io.StringWriter();");
2070 } else {
2071 out.printil("_jspx_sout = null;");
2072 }
2073 out.printil("if (getJspBody() != null)");
2074 out.pushIndent();
2075 out.printil("getJspBody().invoke(_jspx_sout);");
2076 out.popIndent();
2077
2078
2079 if (varReaderAttr != null || varAttr != null) {
2080 String scopeName = n.getTextAttribute("scope");
2081 out.printin("_jspx_page_context.setAttribute(");
2082 if (varReaderAttr != null) {
2083 out.print(quote(varReaderAttr));
2084 out.print(
2085 ", new java.io.StringReader(_jspx_sout.toString())");
2086 } else {
2087 out.print(quote(varAttr));
2088 out.print(", _jspx_sout.toString()");
2089 }
2090 if (scopeName != null) {
2091 out.print(", ");
2092 out.print(getScopeConstant(scopeName));
2093 }
2094 out.println(");");
2095 }
2096
2097 n.setEndJavaLine(out.getJavaLine());
2098 }
2099
2100 public void visit(Node.AttributeGenerator n) throws JasperException {
2101 Node.CustomTag tag = n.getTag();
2102 Node.JspAttribute[] attrs = tag.getJspAttributes();
2103 for (int i = 0; attrs != null && i < attrs.length; i++) {
2104 if (attrs[i].getName().equals(n.getName())) {
2105 out.print(
2106 evaluateAttribute(
2107 getTagHandlerInfo(tag),
2108 attrs[i],
2109 tag,
2110 null));
2111 break;
2112 }
2113 }
2114 }
2115
2116 private TagHandlerInfo getTagHandlerInfo(Node.CustomTag n)
2117 throws JasperException {
2118 Hashtable handlerInfosByShortName =
2119 (Hashtable) handlerInfos.get(n.getPrefix());
2120 if (handlerInfosByShortName == null) {
2121 handlerInfosByShortName = new Hashtable();
2122 handlerInfos.put(n.getPrefix(), handlerInfosByShortName);
2123 }
2124 TagHandlerInfo handlerInfo =
2125 (TagHandlerInfo) handlerInfosByShortName.get(n.getLocalName());
2126 if (handlerInfo == null) {
2127 handlerInfo =
2128 new TagHandlerInfo(n, n.getTagHandlerClass(), err);
2129 handlerInfosByShortName.put(n.getLocalName(), handlerInfo);
2130 }
2131 return handlerInfo;
2132 }
2133
2134 private void generateTagPlugin(Node.CustomTag n)
2135 throws JasperException {
2136 if (n.getAtSTag() != null) {
2137 n.getAtSTag().visit(this);
2138 }
2139 visitBody(n);
2140 if (n.getAtETag() != null) {
2141 n.getAtETag().visit(this);
2142 }
2143 }
2144
2145 private void generateCustomStart(
2146 Node.CustomTag n,
2147 TagHandlerInfo handlerInfo,
2148 String tagHandlerVar,
2149 String tagEvalVar,
2150 String tagPushBodyCountVar)
2151 throws JasperException {
2152
2153 Class tagHandlerClass = handlerInfo.getTagHandlerClass();
2154
2155 out.printin("// ");
2156 out.println(n.getQName());
2157 n.setBeginJavaLine(out.getJavaLine());
2158
2159
2160 declareScriptingVars(n, VariableInfo.AT_BEGIN);
2161 saveScriptingVars(n, VariableInfo.AT_BEGIN);
2162
2163 String tagHandlerClassName =
2164 JspUtil.getCanonicalName(tagHandlerClass);
2165 out.printin(tagHandlerClassName);
2166 out.print(" ");
2167 out.print(tagHandlerVar);
2168 out.print(" = ");
2169 if (isPoolingEnabled) {
2170 out.print("(");
2171 out.print(tagHandlerClassName);
2172 out.print(") ");
2173 out.print(n.getTagHandlerPoolName());
2174 out.print(".get(");
2175 out.print(tagHandlerClassName);
2176 out.println(".class);");
2177 } else {
2178 out.print("new ");
2179 out.print(tagHandlerClassName);
2180 out.println("();");
2181 }
2182
2183 generateSetters(n, tagHandlerVar, handlerInfo, false);
2184
2185 if (n.implementsTryCatchFinally()) {
2186 out.printin("int[] ");
2187 out.print(tagPushBodyCountVar);
2188 out.println(" = new int[] { 0 };");
2189 out.printil("try {");
2190 out.pushIndent();
2191 }
2192 out.printin("int ");
2193 out.print(tagEvalVar);
2194 out.print(" = ");
2195 out.print(tagHandlerVar);
2196 out.println(".doStartTag();");
2197
2198 if (!n.implementsBodyTag()) {
2199
2200 syncScriptingVars(n, VariableInfo.AT_BEGIN);
2201 }
2202
2203 if (!n.hasEmptyBody()) {
2204 out.printin("if (");
2205 out.print(tagEvalVar);
2206 out.println(" != javax.servlet.jsp.tagext.Tag.SKIP_BODY) {");
2207 out.pushIndent();
2208
2209
2210 declareScriptingVars(n, VariableInfo.NESTED);
2211 saveScriptingVars(n, VariableInfo.NESTED);
2212
2213 if (n.implementsBodyTag()) {
2214 out.printin("if (");
2215 out.print(tagEvalVar);
2216 out.println(
2217 " != javax.servlet.jsp.tagext.Tag.EVAL_BODY_INCLUDE) {");
2218
2219 out.pushIndent();
2220 out.printil("out = _jspx_page_context.pushBody();");
2221 if (n.implementsTryCatchFinally()) {
2222 out.printin(tagPushBodyCountVar);
2223 out.println("[0]++;");
2224 } else if (pushBodyCountVar != null) {
2225 out.printin(pushBodyCountVar);
2226 out.println("[0]++;");
2227 }
2228 out.printin(tagHandlerVar);
2229 out.println(
2230 ".setBodyContent((javax.servlet.jsp.tagext.BodyContent) out);");
2231 out.printin(tagHandlerVar);
2232 out.println(".doInitBody();");
2233
2234 out.popIndent();
2235 out.printil("}");
2236
2237
2238 syncScriptingVars(n, VariableInfo.AT_BEGIN);
2239 syncScriptingVars(n, VariableInfo.NESTED);
2240
2241 } else {
2242
2243 syncScriptingVars(n, VariableInfo.NESTED);
2244 }
2245
2246 if (n.implementsIterationTag()) {
2247 out.printil("do {");
2248 out.pushIndent();
2249 }
2250 }
2251
2252
2253 n.setEndJavaLine(out.getJavaLine());
2254 }
2255
2256 private void generateCustomEnd(
2257 Node.CustomTag n,
2258 String tagHandlerVar,
2259 String tagEvalVar,
2260 String tagPushBodyCountVar) {
2261
2262 if (!n.hasEmptyBody()) {
2263 if (n.implementsIterationTag()) {
2264 out.printin("int evalDoAfterBody = ");
2265 out.print(tagHandlerVar);
2266 out.println(".doAfterBody();");
2267
2268
2269 syncScriptingVars(n, VariableInfo.AT_BEGIN);
2270 syncScriptingVars(n, VariableInfo.NESTED);
2271
2272 out.printil(
2273 "if (evalDoAfterBody != javax.servlet.jsp.tagext.BodyTag.EVAL_BODY_AGAIN)");
2274 out.pushIndent();
2275 out.printil("break;");
2276 out.popIndent();
2277
2278 out.popIndent();
2279 out.printil("} while (true);");
2280 }
2281
2282 restoreScriptingVars(n, VariableInfo.NESTED);
2283
2284 if (n.implementsBodyTag()) {
2285 out.printin("if (");
2286 out.print(tagEvalVar);
2287 out.println(
2288 " != javax.servlet.jsp.tagext.Tag.EVAL_BODY_INCLUDE) {");
2289 out.pushIndent();
2290 out.printil("out = _jspx_page_context.popBody();");
2291 if (n.implementsTryCatchFinally()) {
2292 out.printin(tagPushBodyCountVar);
2293 out.println("[0]--;");
2294 } else if (pushBodyCountVar != null) {
2295 out.printin(pushBodyCountVar);
2296 out.println("[0]--;");
2297 }
2298 out.popIndent();
2299 out.printil("}");
2300 }
2301
2302 out.popIndent();
2303 out.printil("}");
2304 }
2305
2306 out.printin("if (");
2307 out.print(tagHandlerVar);
2308 out.println(
2309 ".doEndTag() == javax.servlet.jsp.tagext.Tag.SKIP_PAGE) {");
2310 out.pushIndent();
2311 if (!n.implementsTryCatchFinally()) {
2312 if (isPoolingEnabled) {
2313 out.printin(n.getTagHandlerPoolName());
2314 out.print(".reuse(");
2315 out.print(tagHandlerVar);
2316 out.println(");");
2317 } else {
2318 out.printin(tagHandlerVar);
2319 out.println(".release();");
2320 }
2321 }
2322 if (isTagFile || isFragment) {
2323 out.printil("throw new SkipPageException();");
2324 } else {
2325 out.printil((methodNesting > 0) ? "return true;" : "return;");
2326 }
2327 out.popIndent();
2328 out.printil("}");
2329
2330 syncScriptingVars(n, VariableInfo.AT_BEGIN);
2331
2332
2333 if (n.implementsTryCatchFinally()) {
2334 out.popIndent();
2335 out.printil("} catch (Throwable _jspx_exception) {");
2336 out.pushIndent();
2337
2338 out.printin("while (");
2339 out.print(tagPushBodyCountVar);
2340 out.println("[0]-- > 0)");
2341 out.pushIndent();
2342 out.printil("out = _jspx_page_context.popBody();");
2343 out.popIndent();
2344
2345 out.printin(tagHandlerVar);
2346 out.println(".doCatch(_jspx_exception);");
2347 out.popIndent();
2348 out.printil("} finally {");
2349 out.pushIndent();
2350 out.printin(tagHandlerVar);
2351 out.println(".doFinally();");
2352 }
2353
2354 if (isPoolingEnabled) {
2355 out.printin(n.getTagHandlerPoolName());
2356 out.print(".reuse(");
2357 out.print(tagHandlerVar);
2358 out.println(");");
2359 } else {
2360 out.printin(tagHandlerVar);
2361 out.println(".release();");
2362 }
2363
2364 if (n.implementsTryCatchFinally()) {
2365 out.popIndent();
2366 out.printil("}");
2367 }
2368
2369
2370
2371 declareScriptingVars(n, VariableInfo.AT_END);
2372 syncScriptingVars(n, VariableInfo.AT_END);
2373
2374 restoreScriptingVars(n, VariableInfo.AT_BEGIN);
2375 }
2376
2377 private void generateCustomDoTag(
2378 Node.CustomTag n,
2379 TagHandlerInfo handlerInfo,
2380 String tagHandlerVar)
2381 throws JasperException {
2382
2383 Class tagHandlerClass = handlerInfo.getTagHandlerClass();
2384
2385 n.setBeginJavaLine(out.getJavaLine());
2386 out.printin("// ");
2387 out.println(n.getQName());
2388
2389
2390 declareScriptingVars(n, VariableInfo.AT_BEGIN);
2391 saveScriptingVars(n, VariableInfo.AT_BEGIN);
2392
2393 String tagHandlerClassName =
2394 JspUtil.getCanonicalName(tagHandlerClass);
2395 out.printin(tagHandlerClassName);
2396 out.print(" ");
2397 out.print(tagHandlerVar);
2398 out.print(" = ");
2399 out.print("new ");
2400 out.print(tagHandlerClassName);
2401 out.println("();");
2402
2403 generateSetters(n, tagHandlerVar, handlerInfo, true);
2404
2405
2406 if (findJspBody(n) == null) {
2407
2408
2409
2410
2411
2412 if (!n.hasEmptyBody()) {
2413 out.printin(tagHandlerVar);
2414 out.print(".setJspBody(");
2415 generateJspFragment(n, tagHandlerVar);
2416 out.println(");");
2417 }
2418 } else {
2419
2420
2421
2422
2423
2424
2425 String tmpTagHandlerVar = simpleTagHandlerVar;
2426 simpleTagHandlerVar = tagHandlerVar;
2427 boolean tmpIsSimpleTagHandler = isSimpleTagHandler;
2428 isSimpleTagHandler = true;
2429 visitBody(n);
2430 simpleTagHandlerVar = tmpTagHandlerVar;
2431 isSimpleTagHandler = tmpIsSimpleTagHandler;
2432 }
2433
2434 out.printin(tagHandlerVar);
2435 out.println(".doTag();");
2436
2437 restoreScriptingVars(n, VariableInfo.AT_BEGIN);
2438
2439
2440 syncScriptingVars(n, VariableInfo.AT_BEGIN);
2441
2442
2443 declareScriptingVars(n, VariableInfo.AT_END);
2444 syncScriptingVars(n, VariableInfo.AT_END);
2445
2446 n.setEndJavaLine(out.getJavaLine());
2447 }
2448
2449 private void declareScriptingVars(Node.CustomTag n, int scope) {
2450
2451 Vector vec = n.getScriptingVars(scope);
2452 if (vec != null) {
2453 for (int i = 0; i < vec.size(); i++) {
2454 Object elem = vec.elementAt(i);
2455 if (elem instanceof VariableInfo) {
2456 VariableInfo varInfo = (VariableInfo) elem;
2457 if (varInfo.getDeclare()) {
2458 out.printin(varInfo.getClassName());
2459 out.print(" ");
2460 out.print(varInfo.getVarName());
2461 out.println(" = null;");
2462 }
2463 } else {
2464 TagVariableInfo tagVarInfo = (TagVariableInfo) elem;
2465 if (tagVarInfo.getDeclare()) {
2466 String varName = tagVarInfo.getNameGiven();
2467 if (varName == null) {
2468 varName =
2469 n.getTagData().getAttributeString(
2470 tagVarInfo.getNameFromAttribute());
2471 } else if (
2472 tagVarInfo.getNameFromAttribute() != null) {
2473
2474 continue;
2475 }
2476 out.printin(tagVarInfo.getClassName());
2477 out.print(" ");
2478 out.print(varName);
2479 out.println(" = null;");
2480 }
2481 }
2482 }
2483 }
2484 }
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495 private void saveScriptingVars(Node.CustomTag n, int scope) {
2496 if (n.getCustomNestingLevel() == 0) {
2497 return;
2498 }
2499
2500 TagVariableInfo[] tagVarInfos = n.getTagVariableInfos();
2501 VariableInfo[] varInfos = n.getVariableInfos();
2502 if ((varInfos.length == 0) && (tagVarInfos.length == 0)) {
2503 return;
2504 }
2505
2506 if (varInfos.length > 0) {
2507 for (int i = 0; i < varInfos.length; i++) {
2508 if (varInfos[i].getScope() != scope)
2509 continue;
2510
2511
2512 if (n.getScriptingVars(scope).contains(varInfos[i]))
2513 continue;
2514 String varName = varInfos[i].getVarName();
2515 String tmpVarName =
2516 "_jspx_" + varName + "_" + n.getCustomNestingLevel();
2517 out.printin(tmpVarName);
2518 out.print(" = ");
2519 out.print(varName);
2520 out.println(";");
2521 }
2522 } else {
2523 for (int i = 0; i < tagVarInfos.length; i++) {
2524 if (tagVarInfos[i].getScope() != scope)
2525 continue;
2526
2527
2528 if (n.getScriptingVars(scope).contains(tagVarInfos[i]))
2529 continue;
2530 String varName = tagVarInfos[i].getNameGiven();
2531 if (varName == null) {
2532 varName =
2533 n.getTagData().getAttributeString(
2534 tagVarInfos[i].getNameFromAttribute());
2535 } else if (tagVarInfos[i].getNameFromAttribute() != null) {
2536
2537 continue;
2538 }
2539 String tmpVarName =
2540 "_jspx_" + varName + "_" + n.getCustomNestingLevel();
2541 out.printin(tmpVarName);
2542 out.print(" = ");
2543 out.print(varName);
2544 out.println(";");
2545 }
2546 }
2547 }
2548
2549
2550
2551
2552
2553
2554
2555
2556 private void restoreScriptingVars(Node.CustomTag n, int scope) {
2557 if (n.getCustomNestingLevel() == 0) {
2558 return;
2559 }
2560
2561 TagVariableInfo[] tagVarInfos = n.getTagVariableInfos();
2562 VariableInfo[] varInfos = n.getVariableInfos();
2563 if ((varInfos.length == 0) && (tagVarInfos.length == 0)) {
2564 return;
2565 }
2566
2567 if (varInfos.length > 0) {
2568 for (int i = 0; i < varInfos.length; i++) {
2569 if (varInfos[i].getScope() != scope)
2570 continue;
2571
2572
2573 if (n.getScriptingVars(scope).contains(varInfos[i]))
2574 continue;
2575 String varName = varInfos[i].getVarName();
2576 String tmpVarName =
2577 "_jspx_" + varName + "_" + n.getCustomNestingLevel();
2578 out.printin(varName);
2579 out.print(" = ");
2580 out.print(tmpVarName);
2581 out.println(";");
2582 }
2583 } else {
2584 for (int i = 0; i < tagVarInfos.length; i++) {
2585 if (tagVarInfos[i].getScope() != scope)
2586 continue;
2587
2588
2589 if (n.getScriptingVars(scope).contains(tagVarInfos[i]))
2590 continue;
2591 String varName = tagVarInfos[i].getNameGiven();
2592 if (varName == null) {
2593 varName =
2594 n.getTagData().getAttributeString(
2595 tagVarInfos[i].getNameFromAttribute());
2596 } else if (tagVarInfos[i].getNameFromAttribute() != null) {
2597
2598 continue;
2599 }
2600 String tmpVarName =
2601 "_jspx_" + varName + "_" + n.getCustomNestingLevel();
2602 out.printin(varName);
2603 out.print(" = ");
2604 out.print(tmpVarName);
2605 out.println(";");
2606 }
2607 }
2608 }
2609
2610
2611
2612
2613
2614 private void syncScriptingVars(Node.CustomTag n, int scope) {
2615 TagVariableInfo[] tagVarInfos = n.getTagVariableInfos();
2616 VariableInfo[] varInfos = n.getVariableInfos();
2617
2618 if ((varInfos.length == 0) && (tagVarInfos.length == 0)) {
2619 return;
2620 }
2621
2622 if (varInfos.length > 0) {
2623 for (int i = 0; i < varInfos.length; i++) {
2624 if (varInfos[i].getScope() == scope) {
2625 out.printin(varInfos[i].getVarName());
2626 out.print(" = (");
2627 out.print(varInfos[i].getClassName());
2628 out.print(") _jspx_page_context.findAttribute(");
2629 out.print(quote(varInfos[i].getVarName()));
2630 out.println(");");
2631 }
2632 }
2633 } else {
2634 for (int i = 0; i < tagVarInfos.length; i++) {
2635 if (tagVarInfos[i].getScope() == scope) {
2636 String name = tagVarInfos[i].getNameGiven();
2637 if (name == null) {
2638 name =
2639 n.getTagData().getAttributeString(
2640 tagVarInfos[i].getNameFromAttribute());
2641 } else if (
2642 tagVarInfos[i].getNameFromAttribute() != null) {
2643
2644 continue;
2645 }
2646 out.printin(name);
2647 out.print(" = (");
2648 out.print(tagVarInfos[i].getClassName());
2649 out.print(") _jspx_page_context.findAttribute(");
2650 out.print(quote(name));
2651 out.println(");");
2652 }
2653 }
2654 }
2655 }
2656
2657
2658
2659
2660
2661
2662 private String createTagVarName(
2663 String fullName,
2664 String prefix,
2665 String shortName) {
2666
2667 String varName;
2668 synchronized (tagVarNumbers) {
2669 varName = prefix + "_" + shortName + "_";
2670 if (tagVarNumbers.get(fullName) != null) {
2671 Integer i = (Integer) tagVarNumbers.get(fullName);
2672 varName = varName + i.intValue();
2673 tagVarNumbers.put(fullName, new Integer(i.intValue() + 1));
2674 } else {
2675 tagVarNumbers.put(fullName, new Integer(1));
2676 varName = varName + "0";
2677 }
2678 }
2679 return JspUtil.makeJavaIdentifier(varName);
2680 }
2681
2682 private String evaluateAttribute(
2683 TagHandlerInfo handlerInfo,
2684 Node.JspAttribute attr,
2685 Node.CustomTag n,
2686 String tagHandlerVar)
2687 throws JasperException {
2688
2689 String attrValue = attr.getValue();
2690 if (attrValue == null) {
2691 if (attr.isNamedAttribute()) {
2692 if (n.checkIfAttributeIsJspFragment(attr.getName())) {
2693
2694 attrValue =
2695 generateNamedAttributeJspFragment(
2696 attr.getNamedAttributeNode(),
2697 tagHandlerVar);
2698 } else {
2699 attrValue =
2700 generateNamedAttributeValue(
2701 attr.getNamedAttributeNode());
2702 }
2703 } else {
2704 return null;
2705 }
2706 }
2707
2708 String localName = attr.getLocalName();
2709
2710 Method m = null;
2711 Class[] c = null;
2712 if (attr.isDynamic()) {
2713 c = OBJECT_CLASS;
2714 } else {
2715 m = handlerInfo.getSetterMethod(localName);
2716 if (m == null) {
2717 err.jspError(
2718 n,
2719 "jsp.error.unable.to_find_method",
2720 attr.getName());
2721 }
2722 c = m.getParameterTypes();
2723
2724 }
2725
2726 if (attr.isExpression()) {
2727
2728 } else if (attr.isNamedAttribute()) {
2729 if (!n.checkIfAttributeIsJspFragment(attr.getName())
2730 && !attr.isDynamic()) {
2731 attrValue =
2732 convertString(
2733 c[0],
2734 attrValue,
2735 localName,
2736 handlerInfo.getPropertyEditorClass(localName),
2737 true);
2738 }
2739 } else if (attr.isELInterpreterInput()) {
2740
2741 boolean replaceESC = attrValue.indexOf(Constants.HACK_CHAR) > 0;
2742 attrValue =
2743 JspUtil.interpreterCall(
2744 this.isTagFile,
2745 attrValue,
2746 c[0],
2747 attr.getEL().getMapName(),
2748 false);
2749
2750 if (replaceESC) {
2751 attrValue =
2752 "("
2753 + attrValue
2754 + ").replace("
2755 + Constants.HACK_STR
2756 + ", '$')";
2757 }
2758 } else {
2759 attrValue =
2760 convertString(
2761 c[0],
2762 attrValue,
2763 localName,
2764 handlerInfo.getPropertyEditorClass(localName),
2765 false);
2766 }
2767 return attrValue;
2768 }
2769
2770 /***
2771 * Generate code to create a map for the alias variables
2772 *
2773 * @return the name of the map
2774 */
2775 private String generateAliasMap(Node.CustomTag n, String tagHandlerVar)
2776 throws JasperException {
2777
2778 TagVariableInfo[] tagVars = n.getTagVariableInfos();
2779 String aliasMapVar = null;
2780
2781 boolean aliasSeen = false;
2782 for (int i = 0; i < tagVars.length; i++) {
2783
2784 String nameFrom = tagVars[i].getNameFromAttribute();
2785 if (nameFrom != null) {
2786 String aliasedName = n.getAttributeValue(nameFrom);
2787 if (aliasedName == null)
2788 continue;
2789
2790 if (!aliasSeen) {
2791 out.printin("java.util.HashMap ");
2792 aliasMapVar = tagHandlerVar + "_aliasMap";
2793 out.print(aliasMapVar);
2794 out.println(" = new java.util.HashMap();");
2795 aliasSeen = true;
2796 }
2797 out.printin(aliasMapVar);
2798 out.print(".put(");
2799 out.print(quote(tagVars[i].getNameGiven()));
2800 out.print(", ");
2801 out.print(quote(aliasedName));
2802 out.println(");");
2803 }
2804 }
2805 return aliasMapVar;
2806 }
2807
2808 private void generateSetters(
2809 Node.CustomTag n,
2810 String tagHandlerVar,
2811 TagHandlerInfo handlerInfo,
2812 boolean simpleTag)
2813 throws JasperException {
2814
2815
2816 if (simpleTag) {
2817
2818 String aliasMapVar = null;
2819 if (n.isTagFile()) {
2820 aliasMapVar = generateAliasMap(n, tagHandlerVar);
2821 }
2822 out.printin(tagHandlerVar);
2823 if (aliasMapVar == null) {
2824 out.println(".setJspContext(_jspx_page_context);");
2825 } else {
2826 out.print(".setJspContext(_jspx_page_context, ");
2827 out.print(aliasMapVar);
2828 out.println(");");
2829 }
2830 } else {
2831 out.printin(tagHandlerVar);
2832 out.println(".setPageContext(_jspx_page_context);");
2833 }
2834
2835
2836 if (isTagFile && parent == null) {
2837 out.printin(tagHandlerVar);
2838 out.print(".setParent(");
2839 out.print("new javax.servlet.jsp.tagext.TagAdapter(");
2840 out.print("(javax.servlet.jsp.tagext.SimpleTag) this ));");
2841 } else if (!simpleTag) {
2842 out.printin(tagHandlerVar);
2843 out.print(".setParent(");
2844 if (parent != null) {
2845 if (isSimpleTagParent) {
2846 out.print("new javax.servlet.jsp.tagext.TagAdapter(");
2847 out.print("(javax.servlet.jsp.tagext.SimpleTag) ");
2848 out.print(parent);
2849 out.println("));");
2850 } else {
2851 out.print("(javax.servlet.jsp.tagext.Tag) ");
2852 out.print(parent);
2853 out.println(");");
2854 }
2855 } else {
2856 out.println("null);");
2857 }
2858 } else {
2859
2860
2861 if (parent != null) {
2862 out.printin(tagHandlerVar);
2863 out.print(".setParent(");
2864 out.print(parent);
2865 out.println(");");
2866 }
2867 }
2868
2869 Node.JspAttribute[] attrs = n.getJspAttributes();
2870 for (int i = 0; attrs != null && i < attrs.length; i++) {
2871 String attrValue =
2872 evaluateAttribute(handlerInfo, attrs[i], n, tagHandlerVar);
2873
2874 if (attrs[i].isDynamic()) {
2875 out.printin(tagHandlerVar);
2876 out.print(".");
2877 out.print("setDynamicAttribute(");
2878 String uri = attrs[i].getURI();
2879 if ("".equals(uri) || (uri == null)) {
2880 out.print("null");
2881 } else {
2882 out.print("\"" + attrs[i].getURI() + "\"");
2883 }
2884 out.print(", \"");
2885 out.print(attrs[i].getLocalName());
2886 out.print("\", ");
2887 out.print(attrValue);
2888 out.println(");");
2889 } else {
2890 out.printin(tagHandlerVar);
2891 out.print(".");
2892 out.print(
2893 handlerInfo
2894 .getSetterMethod(attrs[i].getLocalName())
2895 .getName());
2896 out.print("(");
2897 out.print(attrValue);
2898 out.println(");");
2899 }
2900 }
2901 }
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911
2912
2913 private String convertString(
2914 Class c,
2915 String s,
2916 String attrName,
2917 Class propEditorClass,
2918 boolean isNamedAttribute)
2919 throws JasperException {
2920
2921 String quoted = s;
2922 if (!isNamedAttribute) {
2923 quoted = quote(s);
2924 }
2925
2926 if (propEditorClass != null) {
2927 String className = JspUtil.getCanonicalName(c);
2928 return "("
2929 + className
2930 + ")org.apache.struts2.jasper.runtime.JspRuntimeLibrary.getValueFromBeanInfoPropertyEditor("
2931 + className
2932 + ".class, \""
2933 + attrName
2934 + "\", "
2935 + quoted
2936 + ", "
2937 + JspUtil.getCanonicalName(propEditorClass)
2938 + ".class)";
2939 } else if (c == String.class) {
2940 return quoted;
2941 } else if (c == boolean.class) {
2942 return JspUtil.coerceToPrimitiveBoolean(s, isNamedAttribute);
2943 } else if (c == Boolean.class) {
2944 return JspUtil.coerceToBoolean(s, isNamedAttribute);
2945 } else if (c == byte.class) {
2946 return JspUtil.coerceToPrimitiveByte(s, isNamedAttribute);
2947 } else if (c == Byte.class) {
2948 return JspUtil.coerceToByte(s, isNamedAttribute);
2949 } else if (c == char.class) {
2950 return JspUtil.coerceToChar(s, isNamedAttribute);
2951 } else if (c == Character.class) {
2952 return JspUtil.coerceToCharacter(s, isNamedAttribute);
2953 } else if (c == double.class) {
2954 return JspUtil.coerceToPrimitiveDouble(s, isNamedAttribute);
2955 } else if (c == Double.class) {
2956 return JspUtil.coerceToDouble(s, isNamedAttribute);
2957 } else if (c == float.class) {
2958 return JspUtil.coerceToPrimitiveFloat(s, isNamedAttribute);
2959 } else if (c == Float.class) {
2960 return JspUtil.coerceToFloat(s, isNamedAttribute);
2961 } else if (c == int.class) {
2962 return JspUtil.coerceToInt(s, isNamedAttribute);
2963 } else if (c == Integer.class) {
2964 return JspUtil.coerceToInteger(s, isNamedAttribute);
2965 } else if (c == short.class) {
2966 return JspUtil.coerceToPrimitiveShort(s, isNamedAttribute);
2967 } else if (c == Short.class) {
2968 return JspUtil.coerceToShort(s, isNamedAttribute);
2969 } else if (c == long.class) {
2970 return JspUtil.coerceToPrimitiveLong(s, isNamedAttribute);
2971 } else if (c == Long.class) {
2972 return JspUtil.coerceToLong(s, isNamedAttribute);
2973 } else if (c == Object.class) {
2974 return "new String(" + quoted + ")";
2975 } else {
2976 String className = JspUtil.getCanonicalName(c);
2977 return "("
2978 + className
2979 + ")org.apache.struts2.jasper.runtime.JspRuntimeLibrary.getValueFromPropertyEditorManager("
2980 + className
2981 + ".class, \""
2982 + attrName
2983 + "\", "
2984 + quoted
2985 + ")";
2986 }
2987 }
2988
2989
2990
2991
2992
2993
2994 private String getScopeConstant(String scope) {
2995 String scopeName = "PageContext.PAGE_SCOPE";
2996
2997 if ("request".equals(scope)) {
2998 scopeName = "PageContext.REQUEST_SCOPE";
2999 } else if ("session".equals(scope)) {
3000 scopeName = "PageContext.SESSION_SCOPE";
3001 } else if ("application".equals(scope)) {
3002 scopeName = "PageContext.APPLICATION_SCOPE";
3003 }
3004
3005 return scopeName;
3006 }
3007
3008 /***
3009 * Generates anonymous JspFragment inner class which is passed as an
3010 * argument to SimpleTag.setJspBody().
3011 */
3012 private void generateJspFragment(Node n, String tagHandlerVar)
3013 throws JasperException {
3014
3015
3016
3017
3018
3019
3020 FragmentHelperClass.Fragment fragment =
3021 fragmentHelperClass.openFragment(
3022 n,
3023 tagHandlerVar,
3024 methodNesting);
3025 ServletWriter outSave = out;
3026 out = fragment.getGenBuffer().getOut();
3027 String tmpParent = parent;
3028 parent = "_jspx_parent";
3029 boolean isSimpleTagParentSave = isSimpleTagParent;
3030 isSimpleTagParent = true;
3031 boolean tmpIsFragment = isFragment;
3032 isFragment = true;
3033 String pushBodyCountVarSave = pushBodyCountVar;
3034 if (pushBodyCountVar != null) {
3035
3036 pushBodyCountVar = "_jspx_push_body_count";
3037 }
3038 visitBody(n);
3039 out = outSave;
3040 parent = tmpParent;
3041 isSimpleTagParent = isSimpleTagParentSave;
3042 isFragment = tmpIsFragment;
3043 pushBodyCountVar = pushBodyCountVarSave;
3044 fragmentHelperClass.closeFragment(fragment, methodNesting);
3045
3046
3047
3048 out.print(
3049 "new "
3050 + fragmentHelperClass.getClassName()
3051 + "( "
3052 + fragment.getId()
3053 + ", _jspx_page_context, "
3054 + tagHandlerVar
3055 + ", "
3056 + pushBodyCountVar
3057 + ")");
3058 }
3059
3060 /***
3061 * Generate the code required to obtain the runtime value of the
3062 * given named attribute.
3063 *
3064 * @return The name of the temporary variable the result is stored in.
3065 */
3066 public String generateNamedAttributeValue(Node.NamedAttribute n)
3067 throws JasperException {
3068
3069 String varName = n.getTemporaryVariableName();
3070
3071
3072
3073
3074
3075
3076 Node.Nodes body = n.getBody();
3077 if (body != null) {
3078 boolean templateTextOptimization = false;
3079 if (body.size() == 1) {
3080 Node bodyElement = body.getNode(0);
3081 if (bodyElement instanceof Node.TemplateText) {
3082 templateTextOptimization = true;
3083 out.printil(
3084 "String "
3085 + varName
3086 + " = "
3087 + quote(
3088 new String(
3089 ((Node.TemplateText) bodyElement)
3090 .getText()))
3091 + ";");
3092 }
3093 }
3094
3095
3096
3097
3098 if (!templateTextOptimization) {
3099 out.printil("out = _jspx_page_context.pushBody();");
3100 visitBody(n);
3101 out.printil(
3102 "String "
3103 + varName
3104 + " = "
3105 + "((javax.servlet.jsp.tagext.BodyContent)"
3106 + "out).getString();");
3107 out.printil("out = _jspx_page_context.popBody();");
3108 }
3109 } else {
3110
3111 out.printil("String " + varName + " = \"\";");
3112 }
3113
3114 return varName;
3115 }
3116
3117 /***
3118 * Similar to generateNamedAttributeValue, but create a JspFragment
3119 * instead.
3120 *
3121 * @param n The parent node of the named attribute
3122 * @param tagHandlerVar The variable the tag handler is stored in,
3123 * so the fragment knows its parent tag.
3124 * @return The name of the temporary variable the fragment
3125 * is stored in.
3126 */
3127 public String generateNamedAttributeJspFragment(
3128 Node.NamedAttribute n,
3129 String tagHandlerVar)
3130 throws JasperException {
3131 String varName = n.getTemporaryVariableName();
3132
3133 out.printin(
3134 "javax.servlet.jsp.tagext.JspFragment " + varName + " = ");
3135 generateJspFragment(n, tagHandlerVar);
3136 out.println(";");
3137
3138 return varName;
3139 }
3140 }
3141
3142 private static void generateLocalVariables(ServletWriter out, Node n)
3143 throws JasperException {
3144 Node.ChildInfo ci;
3145 if (n instanceof Node.CustomTag) {
3146 ci = ((Node.CustomTag) n).getChildInfo();
3147 } else if (n instanceof Node.JspBody) {
3148 ci = ((Node.JspBody) n).getChildInfo();
3149 } else if (n instanceof Node.NamedAttribute) {
3150 ci = ((Node.NamedAttribute) n).getChildInfo();
3151 } else {
3152
3153
3154 throw new JasperException("Unexpected Node Type");
3155
3156
3157 }
3158
3159 if (ci.hasUseBean()) {
3160 out.printil("HttpSession session = _jspx_page_context.getSession();");
3161 out.printil(
3162 "ServletContext application = _jspx_page_context.getServletContext();");
3163 }
3164 if (ci.hasUseBean()
3165 || ci.hasIncludeAction()
3166 || ci.hasSetProperty()
3167 || ci.hasParamAction()) {
3168 out.printil(
3169 "HttpServletRequest request = (HttpServletRequest)_jspx_page_context.getRequest();");
3170 }
3171 if (ci.hasIncludeAction()) {
3172 out.printil(
3173 "HttpServletResponse response = (HttpServletResponse)_jspx_page_context.getResponse();");
3174 }
3175 }
3176
3177 /***
3178 * Common part of postamble, shared by both servlets and tag files.
3179 */
3180 private void genCommonPostamble() {
3181
3182 for (int i = 0; i < methodsBuffered.size(); i++) {
3183 GenBuffer methodBuffer = (GenBuffer) methodsBuffered.get(i);
3184 methodBuffer.adjustJavaLines(out.getJavaLine() - 1);
3185 out.printMultiLn(methodBuffer.toString());
3186 }
3187
3188
3189 if (fragmentHelperClass.isUsed()) {
3190 fragmentHelperClass.generatePostamble();
3191 fragmentHelperClass.adjustJavaLines(out.getJavaLine() - 1);
3192 out.printMultiLn(fragmentHelperClass.toString());
3193 }
3194
3195
3196 if (charArrayBuffer != null) {
3197 out.printMultiLn(charArrayBuffer.toString());
3198 }
3199
3200
3201 out.popIndent();
3202 out.printil("}");
3203 }
3204
3205 /***
3206 * Generates the ending part of the static portion of the servlet.
3207 */
3208 private void generatePostamble(Node.Nodes page) {
3209 out.popIndent();
3210 out.printil("} catch (Throwable t) {");
3211 out.pushIndent();
3212 out.printil(
3213 "if (!(t instanceof SkipPageException)){");
3214 out.pushIndent();
3215 out.printil("out = _jspx_out;");
3216 out.printil("if (out != null && out.getBufferSize() != 0)");
3217 out.pushIndent();
3218 out.printil("out.clearBuffer();");
3219 out.popIndent();
3220
3221 out.printil(
3222 "if (_jspx_page_context != null) _jspx_page_context.handlePageException(t);");
3223 out.popIndent();
3224 out.printil("}");
3225 out.popIndent();
3226 out.printil("} finally {");
3227 out.pushIndent();
3228
3229 out.printil(
3230 "if (_jspxFactory != null) _jspxFactory.releasePageContext(_jspx_page_context);");
3231
3232 out.popIndent();
3233 out.printil("}");
3234
3235
3236 out.popIndent();
3237 out.printil("}");
3238
3239
3240 genCommonPostamble();
3241 }
3242
3243 /***
3244 * Constructor.
3245 */
3246 Generator(ServletWriter out, Compiler compiler) {
3247 this.out = out;
3248 methodsBuffered = new ArrayList();
3249 charArrayBuffer = null;
3250 err = compiler.getErrorDispatcher();
3251 ctxt = compiler.getCompilationContext();
3252 fragmentHelperClass = new FragmentHelperClass("Helper");
3253 pageInfo = compiler.getPageInfo();
3254
3255
3256
3257
3258
3259
3260
3261
3262
3263
3264
3265 if (pageInfo.getExtends(false) == null) {
3266 isPoolingEnabled = ctxt.getOptions().isPoolingEnabled();
3267 } else {
3268 isPoolingEnabled = false;
3269 }
3270 beanInfo = pageInfo.getBeanRepository();
3271 breakAtLF = ctxt.getOptions().getMappedFile();
3272 if (isPoolingEnabled) {
3273 tagHandlerPoolNames = new Vector();
3274 }
3275 }
3276
3277 /***
3278 * The main entry for Generator.
3279 *
3280 * @param out The servlet output writer
3281 * @param compiler The compiler
3282 * @param page The input page
3283 */
3284 public static void generate(
3285 ServletWriter out,
3286 Compiler compiler,
3287 Node.Nodes page)
3288 throws JasperException {
3289
3290 Generator gen = new Generator(out, compiler);
3291
3292 if (gen.isPoolingEnabled) {
3293 gen.compileTagHandlerPoolList(page);
3294 }
3295 if (gen.ctxt.isTagFile()) {
3296 JasperTagInfo tagInfo = (JasperTagInfo) gen.ctxt.getTagInfo();
3297 gen.generateTagHandlerPreamble(tagInfo, page);
3298
3299 if (gen.ctxt.isPrototypeMode()) {
3300 return;
3301 }
3302
3303 gen.generateXmlProlog(page);
3304 gen.fragmentHelperClass.generatePreamble();
3305 page.visit(
3306 gen.new GenerateVisitor(
3307 gen.ctxt.isTagFile(),
3308 out,
3309 gen.methodsBuffered,
3310 gen.fragmentHelperClass,
3311 gen.ctxt.getClassLoader(),
3312 tagInfo));
3313 gen.generateTagHandlerPostamble(tagInfo);
3314 } else {
3315 gen.generatePreamble(page);
3316 gen.generateXmlProlog(page);
3317 gen.fragmentHelperClass.generatePreamble();
3318 page.visit(
3319 gen.new GenerateVisitor(
3320 gen.ctxt.isTagFile(),
3321 out,
3322 gen.methodsBuffered,
3323 gen.fragmentHelperClass,
3324 gen.ctxt.getClassLoader(),
3325 null));
3326 gen.generatePostamble(page);
3327 }
3328 }
3329
3330
3331
3332
3333 private void generateTagHandlerPreamble(
3334 JasperTagInfo tagInfo,
3335 Node.Nodes tag)
3336 throws JasperException {
3337
3338
3339 String className = tagInfo.getTagClassName();
3340 int lastIndex = className.lastIndexOf('.');
3341 if (lastIndex != -1) {
3342 String pkgName = className.substring(0, lastIndex);
3343 genPreamblePackage(pkgName);
3344 className = className.substring(lastIndex + 1);
3345 }
3346
3347
3348 genPreambleImports();
3349
3350
3351 out.printin("public final class ");
3352 out.println(className);
3353 out.printil(" extends javax.servlet.jsp.tagext.SimpleTagSupport");
3354 out.printin(
3355 " implements org.apache.struts2.jasper.runtime.JspSourceDependent");
3356 if (tagInfo.hasDynamicAttributes()) {
3357 out.println(",");
3358 out.printin(
3359 " javax.servlet.jsp.tagext.DynamicAttributes");
3360 }
3361 out.println(" {");
3362 out.println();
3363 out.pushIndent();
3364
3365
3366
3367
3368
3369 generateDeclarations(tag);
3370
3371
3372 genPreambleStaticInitializers();
3373
3374 out.printil("private JspContext jspContext;");
3375
3376
3377
3378 out.printil("private java.io.Writer _jspx_sout;");
3379
3380
3381 genPreambleClassVariableDeclarations(tagInfo.getTagName());
3382
3383 generateSetJspContext(tagInfo);
3384
3385
3386 generateTagHandlerAttributes(tagInfo);
3387 if (tagInfo.hasDynamicAttributes())
3388 generateSetDynamicAttribute();
3389
3390
3391 genPreambleMethods();
3392
3393
3394 out.printil(
3395 "public void doTag() throws JspException, java.io.IOException {");
3396
3397 if (ctxt.isPrototypeMode()) {
3398 out.printil("}");
3399 out.popIndent();
3400 out.printil("}");
3401 return;
3402 }
3403
3404 out.pushIndent();
3405
3406
3407
3408
3409
3410
3411
3412 out.printil("PageContext _jspx_page_context = (PageContext)jspContext;");
3413
3414
3415 out.printil(
3416 "HttpServletRequest request = "
3417 + "(HttpServletRequest) _jspx_page_context.getRequest();");
3418 out.printil(
3419 "HttpServletResponse response = "
3420 + "(HttpServletResponse) _jspx_page_context.getResponse();");
3421 out.printil("HttpSession session = _jspx_page_context.getSession();");
3422 out.printil(
3423 "ServletContext application = _jspx_page_context.getServletContext();");
3424 out.printil("ServletConfig config = _jspx_page_context.getServletConfig();");
3425 out.printil("JspWriter out = jspContext.getOut();");
3426 if (isPoolingEnabled && !tagHandlerPoolNames.isEmpty()) {
3427 out.printil("_jspInit(config);");
3428 }
3429 generatePageScopedVariables(tagInfo);
3430
3431 declareTemporaryScriptingVars(tag);
3432 out.println();
3433
3434 out.printil("try {");
3435 out.pushIndent();
3436 }
3437
3438 private void generateTagHandlerPostamble(TagInfo tagInfo) {
3439 out.popIndent();
3440
3441
3442
3443 out.printil("} catch( Throwable t ) {");
3444 out.pushIndent();
3445 out.printil("if( t instanceof SkipPageException )");
3446 out.printil(" throw (SkipPageException) t;");
3447 out.printil("if( t instanceof java.io.IOException )");
3448 out.printil(" throw (java.io.IOException) t;");
3449 out.printil("if( t instanceof IllegalStateException )");
3450 out.printil(" throw (IllegalStateException) t;");
3451 out.printil("if( t instanceof JspException )");
3452 out.printil(" throw (JspException) t;");
3453 out.printil("throw new JspException(t);");
3454 out.popIndent();
3455 out.printil("} finally {");
3456 out.pushIndent();
3457 out.printil(
3458 "((org.apache.struts2.jasper.runtime.JspContextWrapper) jspContext).syncEndTagFile();");
3459 if (isPoolingEnabled && !tagHandlerPoolNames.isEmpty()) {
3460 out.printil("_jspDestroy();");
3461 }
3462 out.popIndent();
3463 out.printil("}");
3464
3465
3466 out.popIndent();
3467 out.printil("}");
3468
3469
3470 genCommonPostamble();
3471 }
3472
3473 /***
3474 * Generates declarations for tag handler attributes, and defines the
3475 * getter and setter methods for each.
3476 */
3477 private void generateTagHandlerAttributes(TagInfo tagInfo)
3478 throws JasperException {
3479
3480 if (tagInfo.hasDynamicAttributes()) {
3481 out.printil(
3482 "private java.util.HashMap _jspx_dynamic_attrs = new java.util.HashMap();");
3483 }
3484
3485
3486 TagAttributeInfo[] attrInfos = tagInfo.getAttributes();
3487 for (int i = 0; i < attrInfos.length; i++) {
3488 out.printin("private ");
3489 if (attrInfos[i].isFragment()) {
3490 out.print("javax.servlet.jsp.tagext.JspFragment ");
3491 } else {
3492 out.print(JspUtil.toJavaSourceType(attrInfos[i].getTypeName()));
3493 out.print(" ");
3494 }
3495 out.print(attrInfos[i].getName());
3496 out.println(";");
3497 }
3498 out.println();
3499
3500
3501 if (attrInfos != null) {
3502 for (int i = 0; i < attrInfos.length; i++) {
3503
3504 out.printin("public ");
3505 if (attrInfos[i].isFragment()) {
3506 out.print("javax.servlet.jsp.tagext.JspFragment ");
3507 } else {
3508 out.print(JspUtil.toJavaSourceType(attrInfos[i].getTypeName()));
3509 out.print(" ");
3510 }
3511 out.print(toGetterMethod(attrInfos[i].getName()));
3512 out.println(" {");
3513 out.pushIndent();
3514 out.printin("return this.");
3515 out.print(attrInfos[i].getName());
3516 out.println(";");
3517 out.popIndent();
3518 out.printil("}");
3519 out.println();
3520
3521
3522 out.printin("public void ");
3523 out.print(toSetterMethodName(attrInfos[i].getName()));
3524 if (attrInfos[i].isFragment()) {
3525 out.print("(javax.servlet.jsp.tagext.JspFragment ");
3526 } else {
3527 out.print("(");
3528 out.print(JspUtil.toJavaSourceType(attrInfos[i].getTypeName()));
3529 out.print(" ");
3530 }
3531 out.print(attrInfos[i].getName());
3532 out.println(") {");
3533 out.pushIndent();
3534 out.printin("this.");
3535 out.print(attrInfos[i].getName());
3536 out.print(" = ");
3537 out.print(attrInfos[i].getName());
3538 out.println(";");
3539 out.popIndent();
3540 out.printil("}");
3541 out.println();
3542 }
3543 }
3544 }
3545
3546
3547
3548
3549
3550
3551
3552
3553 private void generateSetJspContext(TagInfo tagInfo) {
3554
3555 boolean nestedSeen = false;
3556 boolean atBeginSeen = false;
3557 boolean atEndSeen = false;
3558
3559
3560 boolean aliasSeen = false;
3561 TagVariableInfo[] tagVars = tagInfo.getTagVariableInfos();
3562 for (int i = 0; i < tagVars.length; i++) {
3563 if (tagVars[i].getNameFromAttribute() != null
3564 && tagVars[i].getNameGiven() != null) {
3565 aliasSeen = true;
3566 break;
3567 }
3568 }
3569
3570 if (aliasSeen) {
3571 out.printil(
3572 "public void setJspContext(JspContext ctx, java.util.Map aliasMap) {");
3573 } else {
3574 out.printil("public void setJspContext(JspContext ctx) {");
3575 }
3576 out.pushIndent();
3577 out.printil("super.setJspContext(ctx);");
3578 out.printil("java.util.ArrayList _jspx_nested = null;");
3579 out.printil("java.util.ArrayList _jspx_at_begin = null;");
3580 out.printil("java.util.ArrayList _jspx_at_end = null;");
3581
3582 for (int i = 0; i < tagVars.length; i++) {
3583
3584 switch (tagVars[i].getScope()) {
3585 case VariableInfo.NESTED:
3586 if (!nestedSeen) {
3587 out.printil(
3588 "_jspx_nested = new java.util.ArrayList();");
3589 nestedSeen = true;
3590 }
3591 out.printin("_jspx_nested.add(");
3592 break;
3593
3594 case VariableInfo.AT_BEGIN:
3595 if (!atBeginSeen) {
3596 out.printil(
3597 "_jspx_at_begin = new java.util.ArrayList();");
3598 atBeginSeen = true;
3599 }
3600 out.printin("_jspx_at_begin.add(");
3601 break;
3602
3603 case VariableInfo.AT_END:
3604 if (!atEndSeen) {
3605 out.printil(
3606 "_jspx_at_end = new java.util.ArrayList();");
3607 atEndSeen = true;
3608 }
3609 out.printin("_jspx_at_end.add(");
3610 break;
3611 }
3612
3613 out.print(quote(tagVars[i].getNameGiven()));
3614 out.println(");");
3615 }
3616 if (aliasSeen) {
3617 out.printil(
3618 "this.jspContext = new org.apache.struts2.jasper.runtime.JspContextWrapper(ctx, _jspx_nested, _jspx_at_begin, _jspx_at_end, aliasMap);");
3619 } else {
3620 out.printil(
3621 "this.jspContext = new org.apache.struts2.jasper.runtime.JspContextWrapper(ctx, _jspx_nested, _jspx_at_begin, _jspx_at_end, null);");
3622 }
3623 out.popIndent();
3624 out.printil("}");
3625 out.println();
3626 out.printil("public JspContext getJspContext() {");
3627 out.pushIndent();
3628 out.printil("return this.jspContext;");
3629 out.popIndent();
3630 out.printil("}");
3631 }
3632
3633
3634
3635
3636
3637
3638
3639 public void generateSetDynamicAttribute() {
3640 out.printil(
3641 "public void setDynamicAttribute(String uri, String localName, Object value) throws JspException {");
3642 out.pushIndent();
3643
3644
3645
3646
3647 out.printil("if (uri == null)");
3648 out.pushIndent();
3649 out.printil("_jspx_dynamic_attrs.put(localName, value);");
3650 out.popIndent();
3651 out.popIndent();
3652 out.printil("}");
3653 }
3654
3655
3656
3657
3658
3659
3660 private void generatePageScopedVariables(JasperTagInfo tagInfo) {
3661
3662
3663 TagAttributeInfo[] attrInfos = tagInfo.getAttributes();
3664 for (int i = 0; i < attrInfos.length; i++) {
3665 String attrName = attrInfos[i].getName();
3666 out.printil("if( " + toGetterMethod(attrName) + " != null ) ");
3667 out.pushIndent();
3668 out.printin("_jspx_page_context.setAttribute(");
3669 out.print(quote(attrName));
3670 out.print(", ");
3671 out.print(toGetterMethod(attrName));
3672 out.println(");");
3673 out.popIndent();
3674 }
3675
3676
3677 if (tagInfo.hasDynamicAttributes()) {
3678 out.printin("_jspx_page_context.setAttribute(\"");
3679 out.print(tagInfo.getDynamicAttributesMapName());
3680 out.print("\", _jspx_dynamic_attrs);");
3681 }
3682 }
3683
3684
3685
3686
3687 private String toGetterMethod(String attrName) {
3688 char[] attrChars = attrName.toCharArray();
3689 attrChars[0] = Character.toUpperCase(attrChars[0]);
3690 return "get" + new String(attrChars) + "()";
3691 }
3692
3693
3694
3695
3696 private String toSetterMethodName(String attrName) {
3697 char[] attrChars = attrName.toCharArray();
3698 attrChars[0] = Character.toUpperCase(attrChars[0]);
3699 return "set" + new String(attrChars);
3700 }
3701
3702 /***
3703 * Class storing the result of introspecting a custom tag handler.
3704 */
3705 private static class TagHandlerInfo {
3706
3707 private Hashtable methodMaps;
3708 private Hashtable propertyEditorMaps;
3709 private Class tagHandlerClass;
3710
3711 /***
3712 * Constructor.
3713 *
3714 * @param n The custom tag whose tag handler class is to be
3715 * introspected
3716 * @param tagHandlerClass Tag handler class
3717 * @param err Error dispatcher
3718 */
3719 TagHandlerInfo(Node n, Class tagHandlerClass, ErrorDispatcher err)
3720 throws JasperException {
3721 this.tagHandlerClass = tagHandlerClass;
3722 this.methodMaps = new Hashtable();
3723 this.propertyEditorMaps = new Hashtable();
3724
3725 try {
3726 BeanInfo tagClassInfo =
3727 Introspector.getBeanInfo(tagHandlerClass);
3728 PropertyDescriptor[] pd = tagClassInfo.getPropertyDescriptors();
3729 for (int i = 0; i < pd.length; i++) {
3730
3731
3732
3733
3734 if (pd[i].getWriteMethod() != null) {
3735 methodMaps.put(pd[i].getName(), pd[i].getWriteMethod());
3736 }
3737 if (pd[i].getPropertyEditorClass() != null)
3738 propertyEditorMaps.put(
3739 pd[i].getName(),
3740 pd[i].getPropertyEditorClass());
3741 }
3742 } catch (IntrospectionException ie) {
3743 err.jspError(
3744 n,
3745 "jsp.error.introspect.taghandler",
3746 tagHandlerClass.getName(),
3747 ie);
3748 }
3749 }
3750
3751 /***
3752 * XXX
3753 */
3754 public Method getSetterMethod(String attrName) {
3755 return (Method) methodMaps.get(attrName);
3756 }
3757
3758 /***
3759 * XXX
3760 */
3761 public Class getPropertyEditorClass(String attrName) {
3762 return (Class) propertyEditorMaps.get(attrName);
3763 }
3764
3765 /***
3766 * XXX
3767 */
3768 public Class getTagHandlerClass() {
3769 return tagHandlerClass;
3770 }
3771 }
3772
3773 /***
3774 * A class for generating codes to a buffer. Included here are some
3775 * support for tracking source to Java lines mapping.
3776 */
3777 private static class GenBuffer {
3778
3779
3780
3781
3782
3783
3784
3785 private Node node;
3786 private Node.Nodes body;
3787 private java.io.CharArrayWriter charWriter;
3788 protected ServletWriter out;
3789
3790 GenBuffer() {
3791 this(null, null);
3792 }
3793
3794 GenBuffer(Node n, Node.Nodes b) {
3795 node = n;
3796 body = b;
3797 if (body != null) {
3798 body.setGeneratedInBuffer(true);
3799 }
3800 charWriter = new java.io.CharArrayWriter();
3801 out = new ServletWriter(new java.io.PrintWriter(charWriter));
3802 }
3803
3804 public ServletWriter getOut() {
3805 return out;
3806 }
3807
3808 public String toString() {
3809 return charWriter.toString();
3810 }
3811
3812 /***
3813 * Adjust the Java Lines. This is necessary because the Java lines
3814 * stored with the nodes are relative the beginning of this buffer
3815 * and need to be adjusted when this buffer is inserted into the
3816 * source.
3817 */
3818 public void adjustJavaLines(final int offset) {
3819
3820 if (node != null) {
3821 adjustJavaLine(node, offset);
3822 }
3823
3824 if (body != null) {
3825 try {
3826 body.visit(new Node.Visitor() {
3827
3828 public void doVisit(Node n) {
3829 adjustJavaLine(n, offset);
3830 }
3831
3832 public void visit(Node.CustomTag n)
3833 throws JasperException {
3834 Node.Nodes b = n.getBody();
3835 if (b != null && !b.isGeneratedInBuffer()) {
3836
3837
3838
3839 b.visit(this);
3840 }
3841 }
3842 });
3843 } catch (JasperException ex) {
3844 }
3845 }
3846 }
3847
3848 private static void adjustJavaLine(Node n, int offset) {
3849 if (n.getBeginJavaLine() > 0) {
3850 n.setBeginJavaLine(n.getBeginJavaLine() + offset);
3851 n.setEndJavaLine(n.getEndJavaLine() + offset);
3852 }
3853 }
3854 }
3855
3856 /***
3857 * Keeps track of the generated Fragment Helper Class
3858 */
3859 private static class FragmentHelperClass {
3860
3861 private static class Fragment {
3862 private GenBuffer genBuffer;
3863 private int id;
3864
3865 public Fragment(int id, Node node) {
3866 this.id = id;
3867 genBuffer = new GenBuffer(null, node.getBody());
3868 }
3869
3870 public GenBuffer getGenBuffer() {
3871 return this.genBuffer;
3872 }
3873
3874 public int getId() {
3875 return this.id;
3876 }
3877 }
3878
3879
3880 private boolean used = false;
3881
3882 private ArrayList fragments = new ArrayList();
3883
3884 private String className;
3885
3886
3887 private GenBuffer classBuffer = new GenBuffer();
3888
3889 public FragmentHelperClass(String className) {
3890 this.className = className;
3891 }
3892
3893 public String getClassName() {
3894 return this.className;
3895 }
3896
3897 public boolean isUsed() {
3898 return this.used;
3899 }
3900
3901 public void generatePreamble() {
3902 ServletWriter out = this.classBuffer.getOut();
3903 out.println();
3904 out.pushIndent();
3905
3906
3907 out.printil("private class " + className);
3908 out.printil(
3909 " extends " + "org.apache.struts2.jasper.runtime.JspFragmentHelper");
3910 out.printil("{");
3911 out.pushIndent();
3912 out.printil(
3913 "private javax.servlet.jsp.tagext.JspTag _jspx_parent;");
3914 out.printil("private int[] _jspx_push_body_count;");
3915 out.println();
3916 out.printil(
3917 "public "
3918 + className
3919 + "( int discriminator, JspContext jspContext, "
3920 + "javax.servlet.jsp.tagext.JspTag _jspx_parent, "
3921 + "int[] _jspx_push_body_count ) {");
3922 out.pushIndent();
3923 out.printil("super( discriminator, jspContext, _jspx_parent );");
3924 out.printil("this._jspx_parent = _jspx_parent;");
3925 out.printil("this._jspx_push_body_count = _jspx_push_body_count;");
3926 out.popIndent();
3927 out.printil("}");
3928 }
3929
3930 public Fragment openFragment(
3931 Node parent,
3932 String tagHandlerVar,
3933 int methodNesting)
3934 throws JasperException {
3935 Fragment result = new Fragment(fragments.size(), parent);
3936 fragments.add(result);
3937 this.used = true;
3938 parent.setInnerClassName(className);
3939
3940 ServletWriter out = result.getGenBuffer().getOut();
3941 out.pushIndent();
3942 out.pushIndent();
3943
3944
3945
3946
3947
3948
3949 if (methodNesting > 0) {
3950 out.printin("public boolean invoke");
3951 } else {
3952 out.printin("public void invoke");
3953 }
3954 out.println(result.getId() + "( " + "JspWriter out ) ");
3955 out.pushIndent();
3956
3957
3958 out.printil("throws Throwable");
3959 out.popIndent();
3960 out.printil("{");
3961 out.pushIndent();
3962 generateLocalVariables(out, parent);
3963
3964 return result;
3965 }
3966
3967 public void closeFragment(Fragment fragment, int methodNesting) {
3968 ServletWriter out = fragment.getGenBuffer().getOut();
3969
3970 if (methodNesting > 0) {
3971 out.printil("return false;");
3972 } else {
3973 out.printil("return;");
3974 }
3975 out.popIndent();
3976 out.printil("}");
3977 }
3978
3979 public void generatePostamble() {
3980 ServletWriter out = this.classBuffer.getOut();
3981
3982 for (int i = 0; i < fragments.size(); i++) {
3983 Fragment fragment = (Fragment) fragments.get(i);
3984 fragment.getGenBuffer().adjustJavaLines(out.getJavaLine() - 1);
3985 out.printMultiLn(fragment.getGenBuffer().toString());
3986 }
3987
3988
3989 out.printil("public void invoke( java.io.Writer writer )");
3990 out.pushIndent();
3991 out.printil("throws JspException");
3992 out.popIndent();
3993 out.printil("{");
3994 out.pushIndent();
3995 out.printil("JspWriter out = null;");
3996 out.printil("if( writer != null ) {");
3997 out.pushIndent();
3998 out.printil("out = this.jspContext.pushBody(writer);");
3999 out.popIndent();
4000 out.printil("} else {");
4001 out.pushIndent();
4002 out.printil("out = this.jspContext.getOut();");
4003 out.popIndent();
4004 out.printil("}");
4005 out.printil("try {");
4006 out.pushIndent();
4007 out.printil("switch( this.discriminator ) {");
4008 out.pushIndent();
4009 for (int i = 0; i < fragments.size(); i++) {
4010 out.printil("case " + i + ":");
4011 out.pushIndent();
4012 out.printil("invoke" + i + "( out );");
4013 out.printil("break;");
4014 out.popIndent();
4015 }
4016 out.popIndent();
4017 out.printil("}");
4018 out.popIndent();
4019 out.printil("}");
4020 out.printil("catch( Throwable e ) {");
4021 out.pushIndent();
4022 out.printil(
4023 "if (e instanceof SkipPageException)");
4024 out.printil(" throw (SkipPageException) e;");
4025 out.printil("throw new JspException( e );");
4026 out.popIndent();
4027 out.printil("}");
4028 out.printil("finally {");
4029 out.pushIndent();
4030
4031 out.printil("if( writer != null ) {");
4032 out.pushIndent();
4033 out.printil("this.jspContext.popBody();");
4034 out.popIndent();
4035 out.printil("}");
4036
4037 out.popIndent();
4038 out.printil("}");
4039 out.popIndent();
4040 out.printil("}");
4041 out.popIndent();
4042 out.printil("}");
4043 out.popIndent();
4044 }
4045
4046 public String toString() {
4047 return classBuffer.toString();
4048 }
4049
4050 public void adjustJavaLines(int offset) {
4051 for (int i = 0; i < fragments.size(); i++) {
4052 Fragment fragment = (Fragment) fragments.get(i);
4053 fragment.getGenBuffer().adjustJavaLines(offset);
4054 }
4055 }
4056 }
4057 }