Source Code Cross Referenced for Generator.java in  » Sevlet-Container » apache-tomcat-6.0.14 » org » apache » jasper » compiler » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Sevlet Container » apache tomcat 6.0.14 » org.apache.jasper.compiler 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * Licensed to the Apache Software Foundation (ASF) under one or more
0003:         * contributor license agreements.  See the NOTICE file distributed with
0004:         * this work for additional information regarding copyright ownership.
0005:         * The ASF licenses this file to You under the Apache License, Version 2.0
0006:         * (the "License"); you may not use this file except in compliance with
0007:         * the License.  You may obtain a copy of the License at
0008:         *
0009:         *      http://www.apache.org/licenses/LICENSE-2.0
0010:         *
0011:         * Unless required by applicable law or agreed to in writing, software
0012:         * distributed under the License is distributed on an "AS IS" BASIS,
0013:         * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0014:         * See the License for the specific language governing permissions and
0015:         * limitations under the License.
0016:         */
0017:
0018:        package org.apache.jasper.compiler;
0019:
0020:        import java.beans.BeanInfo;
0021:        import java.beans.IntrospectionException;
0022:        import java.beans.Introspector;
0023:        import java.beans.PropertyDescriptor;
0024:        import java.lang.reflect.Method;
0025:        import java.lang.reflect.Modifier;
0026:        import java.util.ArrayList;
0027:        import java.util.Arrays;
0028:        import java.util.Collections;
0029:        import java.util.Enumeration;
0030:        import java.util.Hashtable;
0031:        import java.util.HashMap;
0032:        import java.util.Iterator;
0033:        import java.util.List;
0034:        import java.util.Vector;
0035:
0036:        import javax.el.MethodExpression;
0037:        import javax.el.ValueExpression;
0038:        import javax.servlet.jsp.tagext.TagAttributeInfo;
0039:        import javax.servlet.jsp.tagext.TagInfo;
0040:        import javax.servlet.jsp.tagext.TagVariableInfo;
0041:        import javax.servlet.jsp.tagext.VariableInfo;
0042:
0043:        import org.apache.jasper.Constants;
0044:        import org.apache.jasper.JasperException;
0045:        import org.apache.jasper.JspCompilationContext;
0046:        import org.apache.jasper.runtime.JspRuntimeLibrary;
0047:        import org.xml.sax.Attributes;
0048:
0049:        /**
0050:         * Generate Java source from Nodes
0051:         * 
0052:         * @author Anil K. Vijendran
0053:         * @author Danno Ferrin
0054:         * @author Mandar Raje
0055:         * @author Rajiv Mordani
0056:         * @author Pierre Delisle
0057:         * 
0058:         * Tomcat 4.1.x and Tomcat 5:
0059:         * @author Kin-man Chung
0060:         * @author Jan Luehe
0061:         * @author Shawn Bayern
0062:         * @author Mark Roth
0063:         * @author Denis Benoit
0064:         * 
0065:         * Tomcat 6.x
0066:         * @author Jacob Hookom
0067:         * @author Remy Maucherat
0068:         */
0069:
0070:        class Generator {
0071:
0072:            private static final Class[] OBJECT_CLASS = { Object.class };
0073:
0074:            private static final String VAR_EXPRESSIONFACTORY = System
0075:                    .getProperty(
0076:                            "org.apache.jasper.compiler.Generator.VAR_EXPRESSIONFACTORY",
0077:                            "_el_expressionfactory");
0078:            private static final String VAR_ANNOTATIONPROCESSOR = System
0079:                    .getProperty(
0080:                            "org.apache.jasper.compiler.Generator.VAR_ANNOTATIONPROCESSOR",
0081:                            "_jsp_annotationprocessor");
0082:
0083:            private ServletWriter out;
0084:
0085:            private ArrayList methodsBuffered;
0086:
0087:            private FragmentHelperClass fragmentHelperClass;
0088:
0089:            private ErrorDispatcher err;
0090:
0091:            private BeanRepository beanInfo;
0092:
0093:            private JspCompilationContext ctxt;
0094:
0095:            private boolean isPoolingEnabled;
0096:
0097:            private boolean breakAtLF;
0098:
0099:            private String jspIdPrefix;
0100:
0101:            private int jspId;
0102:
0103:            private PageInfo pageInfo;
0104:
0105:            private Vector<String> tagHandlerPoolNames;
0106:
0107:            private GenBuffer charArrayBuffer;
0108:
0109:            /**
0110:             * @param s
0111:             *            the input string
0112:             * @return quoted and escaped string, per Java rule
0113:             */
0114:            static String quote(String s) {
0115:
0116:                if (s == null)
0117:                    return "null";
0118:
0119:                return '"' + escape(s) + '"';
0120:            }
0121:
0122:            /**
0123:             * @param s
0124:             *            the input string
0125:             * @return escaped string, per Java rule
0126:             */
0127:            static String escape(String s) {
0128:
0129:                if (s == null)
0130:                    return "";
0131:
0132:                StringBuffer b = new StringBuffer();
0133:                for (int i = 0; i < s.length(); i++) {
0134:                    char c = s.charAt(i);
0135:                    if (c == '"')
0136:                        b.append('\\').append('"');
0137:                    else if (c == '\\')
0138:                        b.append('\\').append('\\');
0139:                    else if (c == '\n')
0140:                        b.append('\\').append('n');
0141:                    else if (c == '\r')
0142:                        b.append('\\').append('r');
0143:                    else
0144:                        b.append(c);
0145:                }
0146:                return b.toString();
0147:            }
0148:
0149:            /**
0150:             * Single quote and escape a character
0151:             */
0152:            static String quote(char c) {
0153:
0154:                StringBuffer b = new StringBuffer();
0155:                b.append('\'');
0156:                if (c == '\'')
0157:                    b.append('\\').append('\'');
0158:                else if (c == '\\')
0159:                    b.append('\\').append('\\');
0160:                else if (c == '\n')
0161:                    b.append('\\').append('n');
0162:                else if (c == '\r')
0163:                    b.append('\\').append('r');
0164:                else
0165:                    b.append(c);
0166:                b.append('\'');
0167:                return b.toString();
0168:            }
0169:
0170:            private String createJspId() throws JasperException {
0171:                if (this .jspIdPrefix == null) {
0172:                    StringBuffer sb = new StringBuffer(32);
0173:                    String name = ctxt.getServletJavaFileName();
0174:                    sb.append("jsp_").append(Math.abs(name.hashCode())).append(
0175:                            '_');
0176:                    this .jspIdPrefix = sb.toString();
0177:                }
0178:                return this .jspIdPrefix + (this .jspId++);
0179:            }
0180:
0181:            /**
0182:             * Generates declarations. This includes "info" of the page directive, and
0183:             * scriptlet declarations.
0184:             */
0185:            private void generateDeclarations(Node.Nodes page)
0186:                    throws JasperException {
0187:
0188:                class DeclarationVisitor extends Node.Visitor {
0189:
0190:                    private boolean getServletInfoGenerated = false;
0191:
0192:                    /*
0193:                     * Generates getServletInfo() method that returns the value of the
0194:                     * page directive's 'info' attribute, if present.
0195:                     * 
0196:                     * The Validator has already ensured that if the translation unit
0197:                     * contains more than one page directive with an 'info' attribute,
0198:                     * their values match.
0199:                     */
0200:                    public void visit(Node.PageDirective n)
0201:                            throws JasperException {
0202:
0203:                        if (getServletInfoGenerated) {
0204:                            return;
0205:                        }
0206:
0207:                        String info = n.getAttributeValue("info");
0208:                        if (info == null)
0209:                            return;
0210:
0211:                        getServletInfoGenerated = true;
0212:                        out.printil("public String getServletInfo() {");
0213:                        out.pushIndent();
0214:                        out.printin("return ");
0215:                        out.print(quote(info));
0216:                        out.println(";");
0217:                        out.popIndent();
0218:                        out.printil("}");
0219:                        out.println();
0220:                    }
0221:
0222:                    public void visit(Node.Declaration n)
0223:                            throws JasperException {
0224:                        n.setBeginJavaLine(out.getJavaLine());
0225:                        out.printMultiLn(new String(n.getText()));
0226:                        out.println();
0227:                        n.setEndJavaLine(out.getJavaLine());
0228:                    }
0229:
0230:                    // Custom Tags may contain declarations from tag plugins.
0231:                    public void visit(Node.CustomTag n) throws JasperException {
0232:                        if (n.useTagPlugin()) {
0233:                            if (n.getAtSTag() != null) {
0234:                                n.getAtSTag().visit(this );
0235:                            }
0236:                            visitBody(n);
0237:                            if (n.getAtETag() != null) {
0238:                                n.getAtETag().visit(this );
0239:                            }
0240:                        } else {
0241:                            visitBody(n);
0242:                        }
0243:                    }
0244:                }
0245:
0246:                out.println();
0247:                page.visit(new DeclarationVisitor());
0248:            }
0249:
0250:            /**
0251:             * Compiles list of tag handler pool names.
0252:             */
0253:            private void compileTagHandlerPoolList(Node.Nodes page)
0254:                    throws JasperException {
0255:
0256:                class TagHandlerPoolVisitor extends Node.Visitor {
0257:
0258:                    private Vector names;
0259:
0260:                    /*
0261:                     * Constructor
0262:                     * 
0263:                     * @param v Vector of tag handler pool names to populate
0264:                     */
0265:                    TagHandlerPoolVisitor(Vector v) {
0266:                        names = v;
0267:                    }
0268:
0269:                    /*
0270:                     * Gets the name of the tag handler pool for the given custom tag
0271:                     * and adds it to the list of tag handler pool names unless it is
0272:                     * already contained in it.
0273:                     */
0274:                    public void visit(Node.CustomTag n) throws JasperException {
0275:
0276:                        if (!n.implements SimpleTag()) {
0277:                            String name = createTagHandlerPoolName(n
0278:                                    .getPrefix(), n.getLocalName(), n
0279:                                    .getAttributes(), n.hasEmptyBody());
0280:                            n.setTagHandlerPoolName(name);
0281:                            if (!names.contains(name)) {
0282:                                names.add(name);
0283:                            }
0284:                        }
0285:                        visitBody(n);
0286:                    }
0287:
0288:                    /*
0289:                     * Creates the name of the tag handler pool whose tag handlers may
0290:                     * be (re)used to service this action.
0291:                     * 
0292:                     * @return The name of the tag handler pool
0293:                     */
0294:                    private String createTagHandlerPoolName(String prefix,
0295:                            String shortName, Attributes attrs,
0296:                            boolean hasEmptyBody) {
0297:                        String poolName = null;
0298:
0299:                        poolName = "_jspx_tagPool_" + prefix + "_" + shortName;
0300:                        if (attrs != null) {
0301:                            String[] attrNames = new String[attrs.getLength()];
0302:                            for (int i = 0; i < attrNames.length; i++) {
0303:                                attrNames[i] = attrs.getQName(i);
0304:                            }
0305:                            Arrays.sort(attrNames, Collections.reverseOrder());
0306:                            for (int i = 0; i < attrNames.length; i++) {
0307:                                poolName = poolName + "_" + attrNames[i];
0308:                            }
0309:                        }
0310:                        if (hasEmptyBody) {
0311:                            poolName = poolName + "_nobody";
0312:                        }
0313:                        return JspUtil.makeJavaIdentifier(poolName);
0314:                    }
0315:                }
0316:
0317:                page.visit(new TagHandlerPoolVisitor(tagHandlerPoolNames));
0318:            }
0319:
0320:            private void declareTemporaryScriptingVars(Node.Nodes page)
0321:                    throws JasperException {
0322:
0323:                class ScriptingVarVisitor extends Node.Visitor {
0324:
0325:                    private Vector vars;
0326:
0327:                    ScriptingVarVisitor() {
0328:                        vars = new Vector();
0329:                    }
0330:
0331:                    public void visit(Node.CustomTag n) throws JasperException {
0332:
0333:                        if (n.getCustomNestingLevel() > 0) {
0334:                            TagVariableInfo[] tagVarInfos = n
0335:                                    .getTagVariableInfos();
0336:                            VariableInfo[] varInfos = n.getVariableInfos();
0337:
0338:                            if (varInfos.length > 0) {
0339:                                for (int i = 0; i < varInfos.length; i++) {
0340:                                    String varName = varInfos[i].getVarName();
0341:                                    String tmpVarName = "_jspx_" + varName
0342:                                            + "_" + n.getCustomNestingLevel();
0343:                                    if (!vars.contains(tmpVarName)) {
0344:                                        vars.add(tmpVarName);
0345:                                        out.printin(varInfos[i].getClassName());
0346:                                        out.print(" ");
0347:                                        out.print(tmpVarName);
0348:                                        out.print(" = ");
0349:                                        out.print(null);
0350:                                        out.println(";");
0351:                                    }
0352:                                }
0353:                            } else {
0354:                                for (int i = 0; i < tagVarInfos.length; i++) {
0355:                                    String varName = tagVarInfos[i]
0356:                                            .getNameGiven();
0357:                                    if (varName == null) {
0358:                                        varName = n
0359:                                                .getTagData()
0360:                                                .getAttributeString(
0361:                                                        tagVarInfos[i]
0362:                                                                .getNameFromAttribute());
0363:                                    } else if (tagVarInfos[i]
0364:                                            .getNameFromAttribute() != null) {
0365:                                        // alias
0366:                                        continue;
0367:                                    }
0368:                                    String tmpVarName = "_jspx_" + varName
0369:                                            + "_" + n.getCustomNestingLevel();
0370:                                    if (!vars.contains(tmpVarName)) {
0371:                                        vars.add(tmpVarName);
0372:                                        out.printin(tagVarInfos[i]
0373:                                                .getClassName());
0374:                                        out.print(" ");
0375:                                        out.print(tmpVarName);
0376:                                        out.print(" = ");
0377:                                        out.print(null);
0378:                                        out.println(";");
0379:                                    }
0380:                                }
0381:                            }
0382:                        }
0383:
0384:                        visitBody(n);
0385:                    }
0386:                }
0387:
0388:                page.visit(new ScriptingVarVisitor());
0389:            }
0390:
0391:            /**
0392:             * Generates the _jspInit() method for instantiating the tag handler pools.
0393:             * For tag file, _jspInit has to be invoked manually, and the ServletConfig
0394:             * object explicitly passed.
0395:             * 
0396:             * In JSP 2.1, we also instantiate an ExpressionFactory
0397:             */
0398:            private void generateInit() {
0399:
0400:                if (ctxt.isTagFile()) {
0401:                    out
0402:                            .printil("private void _jspInit(ServletConfig config) {");
0403:                } else {
0404:                    out.printil("public void _jspInit() {");
0405:                }
0406:
0407:                out.pushIndent();
0408:                if (isPoolingEnabled) {
0409:                    for (int i = 0; i < tagHandlerPoolNames.size(); i++) {
0410:                        out.printin(tagHandlerPoolNames.elementAt(i));
0411:                        out
0412:                                .print(" = org.apache.jasper.runtime.TagHandlerPool.getTagHandlerPool(");
0413:                        if (ctxt.isTagFile()) {
0414:                            out.print("config");
0415:                        } else {
0416:                            out.print("getServletConfig()");
0417:                        }
0418:                        out.println(");");
0419:                    }
0420:                }
0421:
0422:                out.printin(VAR_EXPRESSIONFACTORY);
0423:                out.print(" = _jspxFactory.getJspApplicationContext(");
0424:                if (ctxt.isTagFile()) {
0425:                    out.print("config");
0426:                } else {
0427:                    out.print("getServletConfig()");
0428:                }
0429:                out.println(".getServletContext()).getExpressionFactory();");
0430:
0431:                out.printin(VAR_ANNOTATIONPROCESSOR);
0432:                out.print(" = (org.apache.AnnotationProcessor) ");
0433:                if (ctxt.isTagFile()) {
0434:                    out.print("config");
0435:                } else {
0436:                    out.print("getServletConfig()");
0437:                }
0438:                out
0439:                        .println(".getServletContext().getAttribute(org.apache.AnnotationProcessor.class.getName());");
0440:
0441:                out.popIndent();
0442:                out.printil("}");
0443:                out.println();
0444:            }
0445:
0446:            /**
0447:             * Generates the _jspDestroy() method which is responsible for calling the
0448:             * release() method on every tag handler in any of the tag handler pools.
0449:             */
0450:            private void generateDestroy() {
0451:
0452:                out.printil("public void _jspDestroy() {");
0453:                out.pushIndent();
0454:
0455:                if (isPoolingEnabled) {
0456:                    for (int i = 0; i < tagHandlerPoolNames.size(); i++) {
0457:                        out.printin((String) tagHandlerPoolNames.elementAt(i));
0458:                        out.println(".release();");
0459:                    }
0460:                }
0461:
0462:                out.popIndent();
0463:                out.printil("}");
0464:                out.println();
0465:            }
0466:
0467:            /**
0468:             * Generate preamble package name (shared by servlet and tag handler
0469:             * preamble generation)
0470:             */
0471:            private void genPreamblePackage(String packageName)
0472:                    throws JasperException {
0473:                if (!"".equals(packageName) && packageName != null) {
0474:                    out.printil("package " + packageName + ";");
0475:                    out.println();
0476:                }
0477:            }
0478:
0479:            /**
0480:             * Generate preamble imports (shared by servlet and tag handler preamble
0481:             * generation)
0482:             */
0483:            private void genPreambleImports() throws JasperException {
0484:                Iterator iter = pageInfo.getImports().iterator();
0485:                while (iter.hasNext()) {
0486:                    out.printin("import ");
0487:                    out.print((String) iter.next());
0488:                    out.println(";");
0489:                }
0490:
0491:                out.println();
0492:            }
0493:
0494:            /**
0495:             * Generation of static initializers in preamble. For example, dependant
0496:             * list, el function map, prefix map. (shared by servlet and tag handler
0497:             * preamble generation)
0498:             */
0499:            private void genPreambleStaticInitializers() throws JasperException {
0500:                out
0501:                        .printil("private static final JspFactory _jspxFactory = JspFactory.getDefaultFactory();");
0502:                out.println();
0503:
0504:                // Static data for getDependants()
0505:                out.printil("private static java.util.List _jspx_dependants;");
0506:                out.println();
0507:                List dependants = pageInfo.getDependants();
0508:                Iterator iter = dependants.iterator();
0509:                if (!dependants.isEmpty()) {
0510:                    out.printil("static {");
0511:                    out.pushIndent();
0512:                    out.printin("_jspx_dependants = new java.util.ArrayList(");
0513:                    out.print("" + dependants.size());
0514:                    out.println(");");
0515:                    while (iter.hasNext()) {
0516:                        out.printin("_jspx_dependants.add(\"");
0517:                        out.print((String) iter.next());
0518:                        out.println("\");");
0519:                    }
0520:                    out.popIndent();
0521:                    out.printil("}");
0522:                    out.println();
0523:                }
0524:            }
0525:
0526:            /**
0527:             * Declare tag handler pools (tags of the same type and with the same
0528:             * attribute set share the same tag handler pool) (shared by servlet and tag
0529:             * handler preamble generation)
0530:             * 
0531:             * In JSP 2.1, we also scope an instance of ExpressionFactory
0532:             */
0533:            private void genPreambleClassVariableDeclarations(String className)
0534:                    throws JasperException {
0535:                if (isPoolingEnabled && !tagHandlerPoolNames.isEmpty()) {
0536:                    for (int i = 0; i < tagHandlerPoolNames.size(); i++) {
0537:                        out
0538:                                .printil("private org.apache.jasper.runtime.TagHandlerPool "
0539:                                        + tagHandlerPoolNames.elementAt(i)
0540:                                        + ";");
0541:                    }
0542:                    out.println();
0543:                }
0544:                out.printin("private javax.el.ExpressionFactory ");
0545:                out.print(VAR_EXPRESSIONFACTORY);
0546:                out.println(";");
0547:                out.printin("private org.apache.AnnotationProcessor ");
0548:                out.print(VAR_ANNOTATIONPROCESSOR);
0549:                out.println(";");
0550:                out.println();
0551:            }
0552:
0553:            /**
0554:             * Declare general-purpose methods (shared by servlet and tag handler
0555:             * preamble generation)
0556:             */
0557:            private void genPreambleMethods() throws JasperException {
0558:                // Method used to get compile time file dependencies
0559:                out.printil("public Object getDependants() {");
0560:                out.pushIndent();
0561:                out.printil("return _jspx_dependants;");
0562:                out.popIndent();
0563:                out.printil("}");
0564:                out.println();
0565:
0566:                generateInit();
0567:                generateDestroy();
0568:            }
0569:
0570:            /**
0571:             * Generates the beginning of the static portion of the servlet.
0572:             */
0573:            private void generatePreamble(Node.Nodes page)
0574:                    throws JasperException {
0575:
0576:                String servletPackageName = ctxt.getServletPackageName();
0577:                String servletClassName = ctxt.getServletClassName();
0578:                String serviceMethodName = Constants.SERVICE_METHOD_NAME;
0579:
0580:                // First the package name:
0581:                genPreamblePackage(servletPackageName);
0582:
0583:                // Generate imports
0584:                genPreambleImports();
0585:
0586:                // Generate class declaration
0587:                out.printin("public final class ");
0588:                out.print(servletClassName);
0589:                out.print(" extends ");
0590:                out.println(pageInfo.getExtends());
0591:                out
0592:                        .printin("    implements org.apache.jasper.runtime.JspSourceDependent");
0593:                if (!pageInfo.isThreadSafe()) {
0594:                    out.println(",");
0595:                    out.printin("                 SingleThreadModel");
0596:                }
0597:                out.println(" {");
0598:                out.pushIndent();
0599:
0600:                // Class body begins here
0601:                generateDeclarations(page);
0602:
0603:                // Static initializations here
0604:                genPreambleStaticInitializers();
0605:
0606:                // Class variable declarations
0607:                genPreambleClassVariableDeclarations(servletClassName);
0608:
0609:                // Constructor
0610:                // generateConstructor(className);
0611:
0612:                // Methods here
0613:                genPreambleMethods();
0614:
0615:                // Now the service method
0616:                out.printin("public void ");
0617:                out.print(serviceMethodName);
0618:                out
0619:                        .println("(HttpServletRequest request, HttpServletResponse response)");
0620:                out
0621:                        .println("        throws java.io.IOException, ServletException {");
0622:
0623:                out.pushIndent();
0624:                out.println();
0625:
0626:                // Local variable declarations
0627:                out.printil("PageContext pageContext = null;");
0628:
0629:                if (pageInfo.isSession())
0630:                    out.printil("HttpSession session = null;");
0631:
0632:                if (pageInfo.isErrorPage()) {
0633:                    out
0634:                            .printil("Throwable exception = org.apache.jasper.runtime.JspRuntimeLibrary.getThrowable(request);");
0635:                    out.printil("if (exception != null) {");
0636:                    out.pushIndent();
0637:                    out
0638:                            .printil("response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);");
0639:                    out.popIndent();
0640:                    out.printil("}");
0641:                }
0642:
0643:                out.printil("ServletContext application = null;");
0644:                out.printil("ServletConfig config = null;");
0645:                out.printil("JspWriter out = null;");
0646:                out.printil("Object page = this;");
0647:
0648:                out.printil("JspWriter _jspx_out = null;");
0649:                out.printil("PageContext _jspx_page_context = null;");
0650:                out.println();
0651:
0652:                declareTemporaryScriptingVars(page);
0653:                out.println();
0654:
0655:                out.printil("try {");
0656:                out.pushIndent();
0657:
0658:                out.printin("response.setContentType(");
0659:                out.print(quote(pageInfo.getContentType()));
0660:                out.println(");");
0661:
0662:                if (ctxt.getOptions().isXpoweredBy()) {
0663:                    out
0664:                            .printil("response.addHeader(\"X-Powered-By\", \"JSP/2.1\");");
0665:                }
0666:
0667:                out
0668:                        .printil("pageContext = _jspxFactory.getPageContext(this, request, response,");
0669:                out.printin("\t\t\t");
0670:                out.print(quote(pageInfo.getErrorPage()));
0671:                out.print(", " + pageInfo.isSession());
0672:                out.print(", " + pageInfo.getBuffer());
0673:                out.print(", " + pageInfo.isAutoFlush());
0674:                out.println(");");
0675:                out.printil("_jspx_page_context = pageContext;");
0676:
0677:                out.printil("application = pageContext.getServletContext();");
0678:                out.printil("config = pageContext.getServletConfig();");
0679:
0680:                if (pageInfo.isSession())
0681:                    out.printil("session = pageContext.getSession();");
0682:                out.printil("out = pageContext.getOut();");
0683:                out.printil("_jspx_out = out;");
0684:                out.println();
0685:            }
0686:
0687:            /**
0688:             * Generates an XML Prolog, which includes an XML declaration and an XML
0689:             * doctype declaration.
0690:             */
0691:            private void generateXmlProlog(Node.Nodes page) {
0692:
0693:                /*
0694:                 * An XML declaration is generated under the following conditions: -
0695:                 * 'omit-xml-declaration' attribute of <jsp:output> action is set to
0696:                 * "no" or "false" - JSP document without a <jsp:root>
0697:                 */
0698:                String omitXmlDecl = pageInfo.getOmitXmlDecl();
0699:                if ((omitXmlDecl != null && !JspUtil.booleanValue(omitXmlDecl))
0700:                        || (omitXmlDecl == null && page.getRoot().isXmlSyntax()
0701:                                && !pageInfo.hasJspRoot() && !ctxt.isTagFile())) {
0702:                    String cType = pageInfo.getContentType();
0703:                    String charSet = cType
0704:                            .substring(cType.indexOf("charset=") + 8);
0705:                    out
0706:                            .printil("out.write(\"<?xml version=\\\"1.0\\\" encoding=\\\""
0707:                                    + charSet + "\\\"?>\\n\");");
0708:                }
0709:
0710:                /*
0711:                 * Output a DOCTYPE declaration if the doctype-root-element appears. If
0712:                 * doctype-public appears: <!DOCTYPE name PUBLIC "doctypePublic"
0713:                 * "doctypeSystem"> else <!DOCTYPE name SYSTEM "doctypeSystem" >
0714:                 */
0715:
0716:                String doctypeName = pageInfo.getDoctypeName();
0717:                if (doctypeName != null) {
0718:                    String doctypePublic = pageInfo.getDoctypePublic();
0719:                    String doctypeSystem = pageInfo.getDoctypeSystem();
0720:                    out.printin("out.write(\"<!DOCTYPE ");
0721:                    out.print(doctypeName);
0722:                    if (doctypePublic == null) {
0723:                        out.print(" SYSTEM \\\"");
0724:                    } else {
0725:                        out.print(" PUBLIC \\\"");
0726:                        out.print(doctypePublic);
0727:                        out.print("\\\" \\\"");
0728:                    }
0729:                    out.print(doctypeSystem);
0730:                    out.println("\\\">\\n\");");
0731:                }
0732:            }
0733:
0734:            /*
0735:             * Generates the constructor. (shared by servlet and tag handler preamble
0736:             * generation)
0737:             */
0738:            private void generateConstructor(String className) {
0739:                out.printil("public " + className + "() {");
0740:                out.printil("}");
0741:                out.println();
0742:            }
0743:
0744:            /**
0745:             * A visitor that generates codes for the elements in the page.
0746:             */
0747:            class GenerateVisitor extends Node.Visitor {
0748:
0749:                /*
0750:                 * Hashtable containing introspection information on tag handlers:
0751:                 * <key>: tag prefix <value>: hashtable containing introspection on tag
0752:                 * handlers: <key>: tag short name <value>: introspection info of tag
0753:                 * handler for <prefix:shortName> tag
0754:                 */
0755:                private Hashtable handlerInfos;
0756:
0757:                private Hashtable tagVarNumbers;
0758:
0759:                private String parent;
0760:
0761:                private boolean isSimpleTagParent; // Is parent a SimpleTag?
0762:
0763:                private String pushBodyCountVar;
0764:
0765:                private String simpleTagHandlerVar;
0766:
0767:                private boolean isSimpleTagHandler;
0768:
0769:                private boolean isFragment;
0770:
0771:                private boolean isTagFile;
0772:
0773:                private ServletWriter out;
0774:
0775:                private ArrayList methodsBuffered;
0776:
0777:                private FragmentHelperClass fragmentHelperClass;
0778:
0779:                private int methodNesting;
0780:
0781:                private TagInfo tagInfo;
0782:
0783:                private ClassLoader loader;
0784:
0785:                private int charArrayCount;
0786:
0787:                private HashMap textMap;
0788:
0789:                /**
0790:                 * Constructor.
0791:                 */
0792:                public GenerateVisitor(boolean isTagFile, ServletWriter out,
0793:                        ArrayList methodsBuffered,
0794:                        FragmentHelperClass fragmentHelperClass,
0795:                        ClassLoader loader, TagInfo tagInfo) {
0796:
0797:                    this .isTagFile = isTagFile;
0798:                    this .out = out;
0799:                    this .methodsBuffered = methodsBuffered;
0800:                    this .fragmentHelperClass = fragmentHelperClass;
0801:                    this .loader = loader;
0802:                    this .tagInfo = tagInfo;
0803:                    methodNesting = 0;
0804:                    handlerInfos = new Hashtable();
0805:                    tagVarNumbers = new Hashtable();
0806:                    textMap = new HashMap();
0807:                }
0808:
0809:                /**
0810:                 * Returns an attribute value, optionally URL encoded. If the value is a
0811:                 * runtime expression, the result is the expression itself, as a string.
0812:                 * If the result is an EL expression, we insert a call to the
0813:                 * interpreter. If the result is a Named Attribute we insert the
0814:                 * generated variable name. Otherwise the result is a string literal,
0815:                 * quoted and escaped.
0816:                 * 
0817:                 * @param attr
0818:                 *            An JspAttribute object
0819:                 * @param encode
0820:                 *            true if to be URL encoded
0821:                 * @param expectedType
0822:                 *            the expected type for an EL evaluation (ignored for
0823:                 *            attributes that aren't EL expressions)
0824:                 */
0825:                private String attributeValue(Node.JspAttribute attr,
0826:                        boolean encode, Class expectedType) {
0827:                    String v = attr.getValue();
0828:                    if (!attr.isNamedAttribute() && (v == null))
0829:                        return "";
0830:
0831:                    if (attr.isExpression()) {
0832:                        if (encode) {
0833:                            return "org.apache.jasper.runtime.JspRuntimeLibrary.URLEncode(String.valueOf("
0834:                                    + v + "), request.getCharacterEncoding())";
0835:                        }
0836:                        return v;
0837:                    } else if (attr.isELInterpreterInput()) {
0838:                        boolean replaceESC = v.indexOf(Constants.ESC) > 0;
0839:                        v = JspUtil.interpreterCall(this .isTagFile, v,
0840:                                expectedType, attr.getEL().getMapName(), false);
0841:                        // XXX ESC replacement hack
0842:                        if (replaceESC) {
0843:                            v = "(" + v + ").replace(" + Constants.ESCStr
0844:                                    + ", '$')";
0845:                        }
0846:                        if (encode) {
0847:                            return "org.apache.jasper.runtime.JspRuntimeLibrary.URLEncode("
0848:                                    + v + ", request.getCharacterEncoding())";
0849:                        }
0850:                        return v;
0851:                    } else if (attr.isNamedAttribute()) {
0852:                        return attr.getNamedAttributeNode()
0853:                                .getTemporaryVariableName();
0854:                    } else {
0855:                        if (encode) {
0856:                            return "org.apache.jasper.runtime.JspRuntimeLibrary.URLEncode("
0857:                                    + quote(v)
0858:                                    + ", request.getCharacterEncoding())";
0859:                        }
0860:                        return quote(v);
0861:                    }
0862:                }
0863:
0864:                /**
0865:                 * Prints the attribute value specified in the param action, in the form
0866:                 * of name=value string.
0867:                 * 
0868:                 * @param n
0869:                 *            the parent node for the param action nodes.
0870:                 */
0871:                private void printParams(Node n, String pageParam,
0872:                        boolean literal) throws JasperException {
0873:
0874:                    class ParamVisitor extends Node.Visitor {
0875:                        String separator;
0876:
0877:                        ParamVisitor(String separator) {
0878:                            this .separator = separator;
0879:                        }
0880:
0881:                        public void visit(Node.ParamAction n)
0882:                                throws JasperException {
0883:
0884:                            out.print(" + ");
0885:                            out.print(separator);
0886:                            out.print(" + ");
0887:                            out
0888:                                    .print("org.apache.jasper.runtime.JspRuntimeLibrary."
0889:                                            + "URLEncode("
0890:                                            + quote(n.getTextAttribute("name"))
0891:                                            + ", request.getCharacterEncoding())");
0892:                            out.print("+ \"=\" + ");
0893:                            out.print(attributeValue(n.getValue(), true,
0894:                                    String.class));
0895:
0896:                            // The separator is '&' after the second use
0897:                            separator = "\"&\"";
0898:                        }
0899:                    }
0900:
0901:                    String sep;
0902:                    if (literal) {
0903:                        sep = pageParam.indexOf('?') > 0 ? "\"&\"" : "\"?\"";
0904:                    } else {
0905:                        sep = "((" + pageParam + ").indexOf('?')>0? '&': '?')";
0906:                    }
0907:                    if (n.getBody() != null) {
0908:                        n.getBody().visit(new ParamVisitor(sep));
0909:                    }
0910:                }
0911:
0912:                public void visit(Node.Expression n) throws JasperException {
0913:                    n.setBeginJavaLine(out.getJavaLine());
0914:                    out.printin("out.print(");
0915:                    out.printMultiLn(n.getText());
0916:                    out.println(");");
0917:                    n.setEndJavaLine(out.getJavaLine());
0918:                }
0919:
0920:                public void visit(Node.Scriptlet n) throws JasperException {
0921:                    n.setBeginJavaLine(out.getJavaLine());
0922:                    out.printMultiLn(n.getText());
0923:                    out.println();
0924:                    n.setEndJavaLine(out.getJavaLine());
0925:                }
0926:
0927:                public void visit(Node.ELExpression n) throws JasperException {
0928:                    n.setBeginJavaLine(out.getJavaLine());
0929:                    if (!pageInfo.isELIgnored() && (n.getEL() != null)) {
0930:                        out.printil("out.write("
0931:                                + JspUtil.interpreterCall(this .isTagFile, n
0932:                                        .getType()
0933:                                        + "{" + new String(n.getText()) + "}",
0934:                                        String.class, n.getEL().getMapName(),
0935:                                        false) + ");");
0936:                    } else {
0937:                        out
0938:                                .printil("out.write("
0939:                                        + quote(n.getType() + "{"
0940:                                                + new String(n.getText()) + "}")
0941:                                        + ");");
0942:                    }
0943:                    n.setEndJavaLine(out.getJavaLine());
0944:                }
0945:
0946:                public void visit(Node.IncludeAction n) throws JasperException {
0947:
0948:                    String flush = n.getTextAttribute("flush");
0949:                    Node.JspAttribute page = n.getPage();
0950:
0951:                    boolean isFlush = false; // default to false;
0952:                    if ("true".equals(flush))
0953:                        isFlush = true;
0954:
0955:                    n.setBeginJavaLine(out.getJavaLine());
0956:
0957:                    String pageParam;
0958:                    if (page.isNamedAttribute()) {
0959:                        // If the page for jsp:include was specified via
0960:                        // jsp:attribute, first generate code to evaluate
0961:                        // that body.
0962:                        pageParam = generateNamedAttributeValue(page
0963:                                .getNamedAttributeNode());
0964:                    } else {
0965:                        pageParam = attributeValue(page, false, String.class);
0966:                    }
0967:
0968:                    // If any of the params have their values specified by
0969:                    // jsp:attribute, prepare those values first.
0970:                    Node jspBody = findJspBody(n);
0971:                    if (jspBody != null) {
0972:                        prepareParams(jspBody);
0973:                    } else {
0974:                        prepareParams(n);
0975:                    }
0976:
0977:                    out
0978:                            .printin("org.apache.jasper.runtime.JspRuntimeLibrary.include(request, response, "
0979:                                    + pageParam);
0980:                    printParams(n, pageParam, page.isLiteral());
0981:                    out.println(", out, " + isFlush + ");");
0982:
0983:                    n.setEndJavaLine(out.getJavaLine());
0984:                }
0985:
0986:                /**
0987:                 * Scans through all child nodes of the given parent for <param>
0988:                 * subelements. For each <param> element, if its value is specified via
0989:                 * a Named Attribute (<jsp:attribute>), generate the code to evaluate
0990:                 * those bodies first.
0991:                 * <p>
0992:                 * If parent is null, simply returns.
0993:                 */
0994:                private void prepareParams(Node parent) throws JasperException {
0995:                    if (parent == null)
0996:                        return;
0997:
0998:                    Node.Nodes subelements = parent.getBody();
0999:                    if (subelements != null) {
1000:                        for (int i = 0; i < subelements.size(); i++) {
1001:                            Node n = subelements.getNode(i);
1002:                            if (n instanceof  Node.ParamAction) {
1003:                                Node.Nodes paramSubElements = n.getBody();
1004:                                for (int j = 0; (paramSubElements != null)
1005:                                        && (j < paramSubElements.size()); j++) {
1006:                                    Node m = paramSubElements.getNode(j);
1007:                                    if (m instanceof  Node.NamedAttribute) {
1008:                                        generateNamedAttributeValue((Node.NamedAttribute) m);
1009:                                    }
1010:                                }
1011:                            }
1012:                        }
1013:                    }
1014:                }
1015:
1016:                /**
1017:                 * Finds the <jsp:body> subelement of the given parent node. If not
1018:                 * found, null is returned.
1019:                 */
1020:                private Node.JspBody findJspBody(Node parent)
1021:                        throws JasperException {
1022:                    Node.JspBody result = null;
1023:
1024:                    Node.Nodes subelements = parent.getBody();
1025:                    for (int i = 0; (subelements != null)
1026:                            && (i < subelements.size()); i++) {
1027:                        Node n = subelements.getNode(i);
1028:                        if (n instanceof  Node.JspBody) {
1029:                            result = (Node.JspBody) n;
1030:                            break;
1031:                        }
1032:                    }
1033:
1034:                    return result;
1035:                }
1036:
1037:                public void visit(Node.ForwardAction n) throws JasperException {
1038:                    Node.JspAttribute page = n.getPage();
1039:
1040:                    n.setBeginJavaLine(out.getJavaLine());
1041:
1042:                    out.printil("if (true) {"); // So that javac won't complain about
1043:                    out.pushIndent(); // codes after "return"
1044:
1045:                    String pageParam;
1046:                    if (page.isNamedAttribute()) {
1047:                        // If the page for jsp:forward was specified via
1048:                        // jsp:attribute, first generate code to evaluate
1049:                        // that body.
1050:                        pageParam = generateNamedAttributeValue(page
1051:                                .getNamedAttributeNode());
1052:                    } else {
1053:                        pageParam = attributeValue(page, false, String.class);
1054:                    }
1055:
1056:                    // If any of the params have their values specified by
1057:                    // jsp:attribute, prepare those values first.
1058:                    Node jspBody = findJspBody(n);
1059:                    if (jspBody != null) {
1060:                        prepareParams(jspBody);
1061:                    } else {
1062:                        prepareParams(n);
1063:                    }
1064:
1065:                    out.printin("_jspx_page_context.forward(");
1066:                    out.print(pageParam);
1067:                    printParams(n, pageParam, page.isLiteral());
1068:                    out.println(");");
1069:                    if (isTagFile || isFragment) {
1070:                        out.printil("throw new SkipPageException();");
1071:                    } else {
1072:                        out.printil((methodNesting > 0) ? "return true;"
1073:                                : "return;");
1074:                    }
1075:                    out.popIndent();
1076:                    out.printil("}");
1077:
1078:                    n.setEndJavaLine(out.getJavaLine());
1079:                    // XXX Not sure if we can eliminate dead codes after this.
1080:                }
1081:
1082:                public void visit(Node.GetProperty n) throws JasperException {
1083:                    String name = n.getTextAttribute("name");
1084:                    String property = n.getTextAttribute("property");
1085:
1086:                    n.setBeginJavaLine(out.getJavaLine());
1087:
1088:                    if (beanInfo.checkVariable(name)) {
1089:                        // Bean is defined using useBean, introspect at compile time
1090:                        Class bean = beanInfo.getBeanType(name);
1091:                        String beanName = JspUtil.getCanonicalName(bean);
1092:                        java.lang.reflect.Method meth = JspRuntimeLibrary
1093:                                .getReadMethod(bean, property);
1094:                        String methodName = meth.getName();
1095:                        out
1096:                                .printil("out.write(org.apache.jasper.runtime.JspRuntimeLibrary.toString("
1097:                                        + "((("
1098:                                        + beanName
1099:                                        + ")_jspx_page_context.findAttribute("
1100:                                        + "\""
1101:                                        + name
1102:                                        + "\"))."
1103:                                        + methodName
1104:                                        + "())));");
1105:                    } else {
1106:                        // The object could be a custom action with an associated
1107:                        // VariableInfo entry for this name.
1108:                        // Get the class name and then introspect at runtime.
1109:                        out
1110:                                .printil("out.write(org.apache.jasper.runtime.JspRuntimeLibrary.toString"
1111:                                        + "(org.apache.jasper.runtime.JspRuntimeLibrary.handleGetProperty"
1112:                                        + "(_jspx_page_context.getAttribute(\""
1113:                                        + name
1114:                                        + "\", PageContext.PAGE_SCOPE), \""
1115:                                        + property + "\")));");
1116:                    }
1117:
1118:                    n.setEndJavaLine(out.getJavaLine());
1119:                }
1120:
1121:                public void visit(Node.SetProperty n) throws JasperException {
1122:                    String name = n.getTextAttribute("name");
1123:                    String property = n.getTextAttribute("property");
1124:                    String param = n.getTextAttribute("param");
1125:                    Node.JspAttribute value = n.getValue();
1126:
1127:                    n.setBeginJavaLine(out.getJavaLine());
1128:
1129:                    if ("*".equals(property)) {
1130:                        out
1131:                                .printil("org.apache.jasper.runtime.JspRuntimeLibrary.introspect("
1132:                                        + "_jspx_page_context.findAttribute("
1133:                                        + "\"" + name + "\"), request);");
1134:                    } else if (value == null) {
1135:                        if (param == null)
1136:                            param = property; // default to same as property
1137:                        out
1138:                                .printil("org.apache.jasper.runtime.JspRuntimeLibrary.introspecthelper("
1139:                                        + "_jspx_page_context.findAttribute(\""
1140:                                        + name
1141:                                        + "\"), \""
1142:                                        + property
1143:                                        + "\", request.getParameter(\""
1144:                                        + param
1145:                                        + "\"), "
1146:                                        + "request, \""
1147:                                        + param
1148:                                        + "\", false);");
1149:                    } else if (value.isExpression()) {
1150:                        out
1151:                                .printil("org.apache.jasper.runtime.JspRuntimeLibrary.handleSetProperty("
1152:                                        + "_jspx_page_context.findAttribute(\""
1153:                                        + name + "\"), \"" + property + "\",");
1154:                        out.print(attributeValue(value, false, null));
1155:                        out.println(");");
1156:                    } else if (value.isELInterpreterInput()) {
1157:                        // We've got to resolve the very call to the interpreter
1158:                        // at runtime since we don't know what type to expect
1159:                        // in the general case; we thus can't hard-wire the call
1160:                        // into the generated code. (XXX We could, however,
1161:                        // optimize the case where the bean is exposed with
1162:                        // <jsp:useBean>, much as the code here does for
1163:                        // getProperty.)
1164:
1165:                        // The following holds true for the arguments passed to
1166:                        // JspRuntimeLibrary.handleSetPropertyExpression():
1167:                        // - 'pageContext' is a VariableResolver.
1168:                        // - 'this' (either the generated Servlet or the generated tag
1169:                        // handler for Tag files) is a FunctionMapper.
1170:                        out
1171:                                .printil("org.apache.jasper.runtime.JspRuntimeLibrary.handleSetPropertyExpression("
1172:                                        + "_jspx_page_context.findAttribute(\""
1173:                                        + name
1174:                                        + "\"), \""
1175:                                        + property
1176:                                        + "\", "
1177:                                        + quote(value.getValue())
1178:                                        + ", "
1179:                                        + "_jspx_page_context, "
1180:                                        + value.getEL().getMapName() + ");");
1181:                    } else if (value.isNamedAttribute()) {
1182:                        // If the value for setProperty was specified via
1183:                        // jsp:attribute, first generate code to evaluate
1184:                        // that body.
1185:                        String valueVarName = generateNamedAttributeValue(value
1186:                                .getNamedAttributeNode());
1187:                        out
1188:                                .printil("org.apache.jasper.runtime.JspRuntimeLibrary.introspecthelper("
1189:                                        + "_jspx_page_context.findAttribute(\""
1190:                                        + name
1191:                                        + "\"), \""
1192:                                        + property
1193:                                        + "\", "
1194:                                        + valueVarName
1195:                                        + ", null, null, false);");
1196:                    } else {
1197:                        out
1198:                                .printin("org.apache.jasper.runtime.JspRuntimeLibrary.introspecthelper("
1199:                                        + "_jspx_page_context.findAttribute(\""
1200:                                        + name + "\"), \"" + property + "\", ");
1201:                        out.print(attributeValue(value, false, null));
1202:                        out.println(", null, null, false);");
1203:                    }
1204:
1205:                    n.setEndJavaLine(out.getJavaLine());
1206:                }
1207:
1208:                public void visit(Node.UseBean n) throws JasperException {
1209:
1210:                    String name = n.getTextAttribute("id");
1211:                    String scope = n.getTextAttribute("scope");
1212:                    String klass = n.getTextAttribute("class");
1213:                    String type = n.getTextAttribute("type");
1214:                    Node.JspAttribute beanName = n.getBeanName();
1215:
1216:                    // If "class" is specified, try an instantiation at compile time
1217:                    boolean generateNew = false;
1218:                    String canonicalName = null; // Canonical name for klass
1219:                    if (klass != null) {
1220:                        try {
1221:                            Class bean = ctxt.getClassLoader().loadClass(klass);
1222:                            if (klass.indexOf('$') >= 0) {
1223:                                // Obtain the canonical type name
1224:                                canonicalName = JspUtil.getCanonicalName(bean);
1225:                            } else {
1226:                                canonicalName = klass;
1227:                            }
1228:                            int modifiers = bean.getModifiers();
1229:                            if (!Modifier.isPublic(modifiers)
1230:                                    || Modifier.isInterface(modifiers)
1231:                                    || Modifier.isAbstract(modifiers)) {
1232:                                throw new Exception(
1233:                                        "Invalid bean class modifier");
1234:                            }
1235:                            // Check that there is a 0 arg constructor
1236:                            bean.getConstructor(new Class[] {});
1237:                            // At compile time, we have determined that the bean class
1238:                            // exists, with a public zero constructor, new() can be
1239:                            // used for bean instantiation.
1240:                            generateNew = true;
1241:                        } catch (Exception e) {
1242:                            // Cannot instantiate the specified class, either a
1243:                            // compilation error or a runtime error will be raised,
1244:                            // depending on a compiler flag.
1245:                            if (ctxt.getOptions()
1246:                                    .getErrorOnUseBeanInvalidClassAttribute()) {
1247:                                err
1248:                                        .jspError(n, "jsp.error.invalid.bean",
1249:                                                klass);
1250:                            }
1251:                            if (canonicalName == null) {
1252:                                // Doing our best here to get a canonical name
1253:                                // from the binary name, should work 99.99% of time.
1254:                                canonicalName = klass.replace('$', '.');
1255:                            }
1256:                        }
1257:                        if (type == null) {
1258:                            // if type is unspecified, use "class" as type of bean
1259:                            type = canonicalName;
1260:                        }
1261:                    }
1262:
1263:                    String scopename = "PageContext.PAGE_SCOPE"; // Default to page
1264:                    String lock = "_jspx_page_context";
1265:
1266:                    if ("request".equals(scope)) {
1267:                        scopename = "PageContext.REQUEST_SCOPE";
1268:                        lock = "request";
1269:                    } else if ("session".equals(scope)) {
1270:                        scopename = "PageContext.SESSION_SCOPE";
1271:                        lock = "session";
1272:                    } else if ("application".equals(scope)) {
1273:                        scopename = "PageContext.APPLICATION_SCOPE";
1274:                        lock = "application";
1275:                    }
1276:
1277:                    n.setBeginJavaLine(out.getJavaLine());
1278:
1279:                    // Declare bean
1280:                    out.printin(type);
1281:                    out.print(' ');
1282:                    out.print(name);
1283:                    out.println(" = null;");
1284:
1285:                    // Lock while getting or creating bean
1286:                    out.printin("synchronized (");
1287:                    out.print(lock);
1288:                    out.println(") {");
1289:                    out.pushIndent();
1290:
1291:                    // Locate bean from context
1292:                    out.printin(name);
1293:                    out.print(" = (");
1294:                    out.print(type);
1295:                    out.print(") _jspx_page_context.getAttribute(");
1296:                    out.print(quote(name));
1297:                    out.print(", ");
1298:                    out.print(scopename);
1299:                    out.println(");");
1300:
1301:                    // Create bean
1302:                    /*
1303:                     * Check if bean is alredy there
1304:                     */
1305:                    out.printin("if (");
1306:                    out.print(name);
1307:                    out.println(" == null){");
1308:                    out.pushIndent();
1309:                    if (klass == null && beanName == null) {
1310:                        /*
1311:                         * If both class name and beanName is not specified, the bean
1312:                         * must be found locally, otherwise it's an error
1313:                         */
1314:                        out
1315:                                .printin("throw new java.lang.InstantiationException(\"bean ");
1316:                        out.print(name);
1317:                        out.println(" not found within scope\");");
1318:                    } else {
1319:                        /*
1320:                         * Instantiate the bean if it is not in the specified scope.
1321:                         */
1322:                        if (!generateNew) {
1323:                            String binaryName;
1324:                            if (beanName != null) {
1325:                                if (beanName.isNamedAttribute()) {
1326:                                    // If the value for beanName was specified via
1327:                                    // jsp:attribute, first generate code to evaluate
1328:                                    // that body.
1329:                                    binaryName = generateNamedAttributeValue(beanName
1330:                                            .getNamedAttributeNode());
1331:                                } else {
1332:                                    binaryName = attributeValue(beanName,
1333:                                            false, String.class);
1334:                                }
1335:                            } else {
1336:                                // Implies klass is not null
1337:                                binaryName = quote(klass);
1338:                            }
1339:                            out.printil("try {");
1340:                            out.pushIndent();
1341:                            out.printin(name);
1342:                            out.print(" = (");
1343:                            out.print(type);
1344:                            out.print(") java.beans.Beans.instantiate(");
1345:                            out.print("this.getClass().getClassLoader(), ");
1346:                            out.print(binaryName);
1347:                            out.println(");");
1348:                            out.popIndent();
1349:                            /*
1350:                             * Note: Beans.instantiate throws ClassNotFoundException if
1351:                             * the bean class is abstract.
1352:                             */
1353:                            out
1354:                                    .printil("} catch (ClassNotFoundException exc) {");
1355:                            out.pushIndent();
1356:                            out
1357:                                    .printil("throw new InstantiationException(exc.getMessage());");
1358:                            out.popIndent();
1359:                            out.printil("} catch (Exception exc) {");
1360:                            out.pushIndent();
1361:                            out.printin("throw new ServletException(");
1362:                            out.print("\"Cannot create bean of class \" + ");
1363:                            out.print(binaryName);
1364:                            out.println(", exc);");
1365:                            out.popIndent();
1366:                            out.printil("}"); // close of try
1367:                        } else {
1368:                            // Implies klass is not null
1369:                            // Generate codes to instantiate the bean class
1370:                            out.printin(name);
1371:                            out.print(" = new ");
1372:                            out.print(canonicalName);
1373:                            out.println("();");
1374:                        }
1375:                        /*
1376:                         * Set attribute for bean in the specified scope
1377:                         */
1378:                        out.printin("_jspx_page_context.setAttribute(");
1379:                        out.print(quote(name));
1380:                        out.print(", ");
1381:                        out.print(name);
1382:                        out.print(", ");
1383:                        out.print(scopename);
1384:                        out.println(");");
1385:
1386:                        // Only visit the body when bean is instantiated
1387:                        visitBody(n);
1388:                    }
1389:                    out.popIndent();
1390:                    out.printil("}");
1391:
1392:                    // End of lock block
1393:                    out.popIndent();
1394:                    out.printil("}");
1395:
1396:                    n.setEndJavaLine(out.getJavaLine());
1397:                }
1398:
1399:                /**
1400:                 * @return a string for the form 'attr = "value"'
1401:                 */
1402:                private String makeAttr(String attr, String value) {
1403:                    if (value == null)
1404:                        return "";
1405:
1406:                    return " " + attr + "=\"" + value + '\"';
1407:                }
1408:
1409:                public void visit(Node.PlugIn n) throws JasperException {
1410:
1411:                    /**
1412:                     * A visitor to handle <jsp:param> in a plugin
1413:                     */
1414:                    class ParamVisitor extends Node.Visitor {
1415:
1416:                        private boolean ie;
1417:
1418:                        ParamVisitor(boolean ie) {
1419:                            this .ie = ie;
1420:                        }
1421:
1422:                        public void visit(Node.ParamAction n)
1423:                                throws JasperException {
1424:
1425:                            String name = n.getTextAttribute("name");
1426:                            if (name.equalsIgnoreCase("object"))
1427:                                name = "java_object";
1428:                            else if (name.equalsIgnoreCase("type"))
1429:                                name = "java_type";
1430:
1431:                            n.setBeginJavaLine(out.getJavaLine());
1432:                            // XXX - Fixed a bug here - value used to be output
1433:                            // inline, which is only okay if value is not an EL
1434:                            // expression. Also, key/value pairs for the
1435:                            // embed tag were not being generated correctly.
1436:                            // Double check that this is now the correct behavior.
1437:                            if (ie) {
1438:                                // We want something of the form
1439:                                // out.println( "<param name=\"blah\"
1440:                                // value=\"" + ... + "\">" );
1441:                                out.printil("out.write( \"<param name=\\\""
1442:                                        + escape(name)
1443:                                        + "\\\" value=\\\"\" + "
1444:                                        + attributeValue(n.getValue(), false,
1445:                                                String.class)
1446:                                        + " + \"\\\">\" );");
1447:                                out.printil("out.write(\"\\n\");");
1448:                            } else {
1449:                                // We want something of the form
1450:                                // out.print( " blah=\"" + ... + "\"" );
1451:                                out.printil("out.write( \" "
1452:                                        + escape(name)
1453:                                        + "=\\\"\" + "
1454:                                        + attributeValue(n.getValue(), false,
1455:                                                String.class)
1456:                                        + " + \"\\\"\" );");
1457:                            }
1458:
1459:                            n.setEndJavaLine(out.getJavaLine());
1460:                        }
1461:                    }
1462:
1463:                    String type = n.getTextAttribute("type");
1464:                    String code = n.getTextAttribute("code");
1465:                    String name = n.getTextAttribute("name");
1466:                    Node.JspAttribute height = n.getHeight();
1467:                    Node.JspAttribute width = n.getWidth();
1468:                    String hspace = n.getTextAttribute("hspace");
1469:                    String vspace = n.getTextAttribute("vspace");
1470:                    String align = n.getTextAttribute("align");
1471:                    String iepluginurl = n.getTextAttribute("iepluginurl");
1472:                    String nspluginurl = n.getTextAttribute("nspluginurl");
1473:                    String codebase = n.getTextAttribute("codebase");
1474:                    String archive = n.getTextAttribute("archive");
1475:                    String jreversion = n.getTextAttribute("jreversion");
1476:
1477:                    String widthStr = null;
1478:                    if (width != null) {
1479:                        if (width.isNamedAttribute()) {
1480:                            widthStr = generateNamedAttributeValue(width
1481:                                    .getNamedAttributeNode());
1482:                        } else {
1483:                            widthStr = attributeValue(width, false,
1484:                                    String.class);
1485:                        }
1486:                    }
1487:
1488:                    String heightStr = null;
1489:                    if (height != null) {
1490:                        if (height.isNamedAttribute()) {
1491:                            heightStr = generateNamedAttributeValue(height
1492:                                    .getNamedAttributeNode());
1493:                        } else {
1494:                            heightStr = attributeValue(height, false,
1495:                                    String.class);
1496:                        }
1497:                    }
1498:
1499:                    if (iepluginurl == null)
1500:                        iepluginurl = Constants.IE_PLUGIN_URL;
1501:                    if (nspluginurl == null)
1502:                        nspluginurl = Constants.NS_PLUGIN_URL;
1503:
1504:                    n.setBeginJavaLine(out.getJavaLine());
1505:
1506:                    // If any of the params have their values specified by
1507:                    // jsp:attribute, prepare those values first.
1508:                    // Look for a params node and prepare its param subelements:
1509:                    Node.JspBody jspBody = findJspBody(n);
1510:                    if (jspBody != null) {
1511:                        Node.Nodes subelements = jspBody.getBody();
1512:                        if (subelements != null) {
1513:                            for (int i = 0; i < subelements.size(); i++) {
1514:                                Node m = subelements.getNode(i);
1515:                                if (m instanceof  Node.ParamsAction) {
1516:                                    prepareParams(m);
1517:                                    break;
1518:                                }
1519:                            }
1520:                        }
1521:                    }
1522:
1523:                    // XXX - Fixed a bug here - width and height can be set
1524:                    // dynamically. Double-check if this generation is correct.
1525:
1526:                    // IE style plugin
1527:                    // <object ...>
1528:                    // First compose the runtime output string
1529:                    String s0 = "<object"
1530:                            + makeAttr("classid", ctxt.getOptions()
1531:                                    .getIeClassId()) + makeAttr("name", name);
1532:
1533:                    String s1 = "";
1534:                    if (width != null) {
1535:                        s1 = " + \" width=\\\"\" + " + widthStr + " + \"\\\"\"";
1536:                    }
1537:
1538:                    String s2 = "";
1539:                    if (height != null) {
1540:                        s2 = " + \" height=\\\"\" + " + heightStr
1541:                                + " + \"\\\"\"";
1542:                    }
1543:
1544:                    String s3 = makeAttr("hspace", hspace)
1545:                            + makeAttr("vspace", vspace)
1546:                            + makeAttr("align", align)
1547:                            + makeAttr("codebase", iepluginurl) + '>';
1548:
1549:                    // Then print the output string to the java file
1550:                    out.printil("out.write(" + quote(s0) + s1 + s2 + " + "
1551:                            + quote(s3) + ");");
1552:                    out.printil("out.write(\"\\n\");");
1553:
1554:                    // <param > for java_code
1555:                    s0 = "<param name=\"java_code\"" + makeAttr("value", code)
1556:                            + '>';
1557:                    out.printil("out.write(" + quote(s0) + ");");
1558:                    out.printil("out.write(\"\\n\");");
1559:
1560:                    // <param > for java_codebase
1561:                    if (codebase != null) {
1562:                        s0 = "<param name=\"java_codebase\""
1563:                                + makeAttr("value", codebase) + '>';
1564:                        out.printil("out.write(" + quote(s0) + ");");
1565:                        out.printil("out.write(\"\\n\");");
1566:                    }
1567:
1568:                    // <param > for java_archive
1569:                    if (archive != null) {
1570:                        s0 = "<param name=\"java_archive\""
1571:                                + makeAttr("value", archive) + '>';
1572:                        out.printil("out.write(" + quote(s0) + ");");
1573:                        out.printil("out.write(\"\\n\");");
1574:                    }
1575:
1576:                    // <param > for type
1577:                    s0 = "<param name=\"type\""
1578:                            + makeAttr("value", "application/x-java-"
1579:                                    + type
1580:                                    + ";"
1581:                                    + ((jreversion == null) ? "" : "version="
1582:                                            + jreversion)) + '>';
1583:                    out.printil("out.write(" + quote(s0) + ");");
1584:                    out.printil("out.write(\"\\n\");");
1585:
1586:                    /*
1587:                     * generate a <param> for each <jsp:param> in the plugin body
1588:                     */
1589:                    if (n.getBody() != null)
1590:                        n.getBody().visit(new ParamVisitor(true));
1591:
1592:                    /*
1593:                     * Netscape style plugin part
1594:                     */
1595:                    out.printil("out.write(" + quote("<comment>") + ");");
1596:                    out.printil("out.write(\"\\n\");");
1597:                    s0 = "<EMBED"
1598:                            + makeAttr("type", "application/x-java-"
1599:                                    + type
1600:                                    + ";"
1601:                                    + ((jreversion == null) ? "" : "version="
1602:                                            + jreversion))
1603:                            + makeAttr("name", name);
1604:
1605:                    // s1 and s2 are the same as before.
1606:
1607:                    s3 = makeAttr("hspace", hspace)
1608:                            + makeAttr("vspace", vspace)
1609:                            + makeAttr("align", align)
1610:                            + makeAttr("pluginspage", nspluginurl)
1611:                            + makeAttr("java_code", code)
1612:                            + makeAttr("java_codebase", codebase)
1613:                            + makeAttr("java_archive", archive);
1614:                    out.printil("out.write(" + quote(s0) + s1 + s2 + " + "
1615:                            + quote(s3) + ");");
1616:
1617:                    /*
1618:                     * Generate a 'attr = "value"' for each <jsp:param> in plugin body
1619:                     */
1620:                    if (n.getBody() != null)
1621:                        n.getBody().visit(new ParamVisitor(false));
1622:
1623:                    out.printil("out.write(" + quote("/>") + ");");
1624:                    out.printil("out.write(\"\\n\");");
1625:
1626:                    out.printil("out.write(" + quote("<noembed>") + ");");
1627:                    out.printil("out.write(\"\\n\");");
1628:
1629:                    /*
1630:                     * Fallback
1631:                     */
1632:                    if (n.getBody() != null) {
1633:                        visitBody(n);
1634:                        out.printil("out.write(\"\\n\");");
1635:                    }
1636:
1637:                    out.printil("out.write(" + quote("</noembed>") + ");");
1638:                    out.printil("out.write(\"\\n\");");
1639:
1640:                    out.printil("out.write(" + quote("</comment>") + ");");
1641:                    out.printil("out.write(\"\\n\");");
1642:
1643:                    out.printil("out.write(" + quote("</object>") + ");");
1644:                    out.printil("out.write(\"\\n\");");
1645:
1646:                    n.setEndJavaLine(out.getJavaLine());
1647:                }
1648:
1649:                public void visit(Node.NamedAttribute n) throws JasperException {
1650:                    // Don't visit body of this tag - we already did earlier.
1651:                }
1652:
1653:                public void visit(Node.CustomTag n) throws JasperException {
1654:
1655:                    // Use plugin to generate more efficient code if there is one.
1656:                    if (n.useTagPlugin()) {
1657:                        generateTagPlugin(n);
1658:                        return;
1659:                    }
1660:
1661:                    TagHandlerInfo handlerInfo = getTagHandlerInfo(n);
1662:
1663:                    // Create variable names
1664:                    String baseVar = createTagVarName(n.getQName(), n
1665:                            .getPrefix(), n.getLocalName());
1666:                    String tagEvalVar = "_jspx_eval_" + baseVar;
1667:                    String tagHandlerVar = "_jspx_th_" + baseVar;
1668:                    String tagPushBodyCountVar = "_jspx_push_body_count_"
1669:                            + baseVar;
1670:
1671:                    // If the tag contains no scripting element, generate its codes
1672:                    // to a method.
1673:                    ServletWriter outSave = null;
1674:                    Node.ChildInfo ci = n.getChildInfo();
1675:                    if (ci.isScriptless() && !ci.hasScriptingVars()) {
1676:                        // The tag handler and its body code can reside in a separate
1677:                        // method if it is scriptless and does not have any scripting
1678:                        // variable defined.
1679:
1680:                        String tagMethod = "_jspx_meth_" + baseVar;
1681:
1682:                        // Generate a call to this method
1683:                        out.printin("if (");
1684:                        out.print(tagMethod);
1685:                        out.print("(");
1686:                        if (parent != null) {
1687:                            out.print(parent);
1688:                            out.print(", ");
1689:                        }
1690:                        out.print("_jspx_page_context");
1691:                        if (pushBodyCountVar != null) {
1692:                            out.print(", ");
1693:                            out.print(pushBodyCountVar);
1694:                        }
1695:                        out.println("))");
1696:                        out.pushIndent();
1697:                        out.printil((methodNesting > 0) ? "return true;"
1698:                                : "return;");
1699:                        out.popIndent();
1700:
1701:                        // Set up new buffer for the method
1702:                        outSave = out;
1703:                        /*
1704:                         * For fragments, their bodies will be generated in fragment
1705:                         * helper classes, and the Java line adjustments will be done
1706:                         * there, hence they are set to null here to avoid double
1707:                         * adjustments.
1708:                         */
1709:                        GenBuffer genBuffer = new GenBuffer(n, n
1710:                                .implements SimpleTag() ? null : n.getBody());
1711:                        methodsBuffered.add(genBuffer);
1712:                        out = genBuffer.getOut();
1713:
1714:                        methodNesting++;
1715:                        // Generate code for method declaration
1716:                        out.println();
1717:                        out.pushIndent();
1718:                        out.printin("private boolean ");
1719:                        out.print(tagMethod);
1720:                        out.print("(");
1721:                        if (parent != null) {
1722:                            out.print("javax.servlet.jsp.tagext.JspTag ");
1723:                            out.print(parent);
1724:                            out.print(", ");
1725:                        }
1726:                        out.print("PageContext _jspx_page_context");
1727:                        if (pushBodyCountVar != null) {
1728:                            out.print(", int[] ");
1729:                            out.print(pushBodyCountVar);
1730:                        }
1731:                        out.println(")");
1732:                        out.printil("        throws Throwable {");
1733:                        out.pushIndent();
1734:
1735:                        // Initilaize local variables used in this method.
1736:                        if (!isTagFile) {
1737:                            out
1738:                                    .printil("PageContext pageContext = _jspx_page_context;");
1739:                        }
1740:                        out
1741:                                .printil("JspWriter out = _jspx_page_context.getOut();");
1742:                        generateLocalVariables(out, n);
1743:                    }
1744:
1745:                    if (n.implements SimpleTag()) {
1746:                        generateCustomDoTag(n, handlerInfo, tagHandlerVar);
1747:                    } else {
1748:                        /*
1749:                         * Classic tag handler: Generate code for start element, body,
1750:                         * and end element
1751:                         */
1752:                        generateCustomStart(n, handlerInfo, tagHandlerVar,
1753:                                tagEvalVar, tagPushBodyCountVar);
1754:
1755:                        // visit body
1756:                        String tmpParent = parent;
1757:                        parent = tagHandlerVar;
1758:                        boolean isSimpleTagParentSave = isSimpleTagParent;
1759:                        isSimpleTagParent = false;
1760:                        String tmpPushBodyCountVar = null;
1761:                        if (n.implements TryCatchFinally()) {
1762:                            tmpPushBodyCountVar = pushBodyCountVar;
1763:                            pushBodyCountVar = tagPushBodyCountVar;
1764:                        }
1765:                        boolean tmpIsSimpleTagHandler = isSimpleTagHandler;
1766:                        isSimpleTagHandler = false;
1767:
1768:                        visitBody(n);
1769:
1770:                        parent = tmpParent;
1771:                        isSimpleTagParent = isSimpleTagParentSave;
1772:                        if (n.implements TryCatchFinally()) {
1773:                            pushBodyCountVar = tmpPushBodyCountVar;
1774:                        }
1775:                        isSimpleTagHandler = tmpIsSimpleTagHandler;
1776:
1777:                        generateCustomEnd(n, tagHandlerVar, tagEvalVar,
1778:                                tagPushBodyCountVar);
1779:                    }
1780:
1781:                    if (ci.isScriptless() && !ci.hasScriptingVars()) {
1782:                        // Generate end of method
1783:                        if (methodNesting > 0) {
1784:                            out.printil("return false;");
1785:                        }
1786:                        out.popIndent();
1787:                        out.printil("}");
1788:                        out.popIndent();
1789:
1790:                        methodNesting--;
1791:
1792:                        // restore previous writer
1793:                        out = outSave;
1794:                    }
1795:                }
1796:
1797:                private static final String SINGLE_QUOTE = "'";
1798:
1799:                private static final String DOUBLE_QUOTE = "\\\"";
1800:
1801:                public void visit(Node.UninterpretedTag n)
1802:                        throws JasperException {
1803:
1804:                    n.setBeginJavaLine(out.getJavaLine());
1805:
1806:                    /*
1807:                     * Write begin tag
1808:                     */
1809:                    out.printin("out.write(\"<");
1810:                    out.print(n.getQName());
1811:
1812:                    Attributes attrs = n.getNonTaglibXmlnsAttributes();
1813:                    int attrsLen = (attrs == null) ? 0 : attrs.getLength();
1814:                    for (int i = 0; i < attrsLen; i++) {
1815:                        out.print(" ");
1816:                        out.print(attrs.getQName(i));
1817:                        out.print("=");
1818:                        String quote = DOUBLE_QUOTE;
1819:                        String value = attrs.getValue(i);
1820:                        if (value.indexOf('"') != -1) {
1821:                            quote = SINGLE_QUOTE;
1822:                        }
1823:                        out.print(quote);
1824:                        out.print(value);
1825:                        out.print(quote);
1826:                    }
1827:
1828:                    attrs = n.getAttributes();
1829:                    attrsLen = (attrs == null) ? 0 : attrs.getLength();
1830:                    Node.JspAttribute[] jspAttrs = n.getJspAttributes();
1831:                    for (int i = 0; i < attrsLen; i++) {
1832:                        out.print(" ");
1833:                        out.print(attrs.getQName(i));
1834:                        out.print("=");
1835:                        if (jspAttrs[i].isELInterpreterInput()) {
1836:                            out.print("\\\"\" + ");
1837:                            out.print(attributeValue(jspAttrs[i], false,
1838:                                    String.class));
1839:                            out.print(" + \"\\\"");
1840:                        } else {
1841:                            String quote = DOUBLE_QUOTE;
1842:                            String value = attrs.getValue(i);
1843:                            if (value.indexOf('"') != -1) {
1844:                                quote = SINGLE_QUOTE;
1845:                            }
1846:                            out.print(quote);
1847:                            out.print(value);
1848:                            out.print(quote);
1849:                        }
1850:                    }
1851:
1852:                    if (n.getBody() != null) {
1853:                        out.println(">\");");
1854:
1855:                        // Visit tag body
1856:                        visitBody(n);
1857:
1858:                        /*
1859:                         * Write end tag
1860:                         */
1861:                        out.printin("out.write(\"</");
1862:                        out.print(n.getQName());
1863:                        out.println(">\");");
1864:                    } else {
1865:                        out.println("/>\");");
1866:                    }
1867:
1868:                    n.setEndJavaLine(out.getJavaLine());
1869:                }
1870:
1871:                public void visit(Node.JspElement n) throws JasperException {
1872:
1873:                    n.setBeginJavaLine(out.getJavaLine());
1874:
1875:                    // Compute attribute value string for XML-style and named
1876:                    // attributes
1877:                    Hashtable map = new Hashtable();
1878:                    Node.JspAttribute[] attrs = n.getJspAttributes();
1879:                    for (int i = 0; attrs != null && i < attrs.length; i++) {
1880:                        String attrStr = null;
1881:                        if (attrs[i].isNamedAttribute()) {
1882:                            attrStr = generateNamedAttributeValue(attrs[i]
1883:                                    .getNamedAttributeNode());
1884:                        } else {
1885:                            attrStr = attributeValue(attrs[i], false,
1886:                                    Object.class);
1887:                        }
1888:                        String s = " + \" " + attrs[i].getName() + "=\\\"\" + "
1889:                                + attrStr + " + \"\\\"\"";
1890:                        map.put(attrs[i].getName(), s);
1891:                    }
1892:
1893:                    // Write begin tag, using XML-style 'name' attribute as the
1894:                    // element name
1895:                    String elemName = attributeValue(n.getNameAttribute(),
1896:                            false, String.class);
1897:                    out.printin("out.write(\"<\"");
1898:                    out.print(" + " + elemName);
1899:
1900:                    // Write remaining attributes
1901:                    Enumeration enumeration = map.keys();
1902:                    while (enumeration.hasMoreElements()) {
1903:                        String attrName = (String) enumeration.nextElement();
1904:                        out.print((String) map.get(attrName));
1905:                    }
1906:
1907:                    // Does the <jsp:element> have nested tags other than
1908:                    // <jsp:attribute>
1909:                    boolean hasBody = false;
1910:                    Node.Nodes subelements = n.getBody();
1911:                    if (subelements != null) {
1912:                        for (int i = 0; i < subelements.size(); i++) {
1913:                            Node subelem = subelements.getNode(i);
1914:                            if (!(subelem instanceof  Node.NamedAttribute)) {
1915:                                hasBody = true;
1916:                                break;
1917:                            }
1918:                        }
1919:                    }
1920:                    if (hasBody) {
1921:                        out.println(" + \">\");");
1922:
1923:                        // Smap should not include the body
1924:                        n.setEndJavaLine(out.getJavaLine());
1925:
1926:                        // Visit tag body
1927:                        visitBody(n);
1928:
1929:                        // Write end tag
1930:                        out.printin("out.write(\"</\"");
1931:                        out.print(" + " + elemName);
1932:                        out.println(" + \">\");");
1933:                    } else {
1934:                        out.println(" + \"/>\");");
1935:                        n.setEndJavaLine(out.getJavaLine());
1936:                    }
1937:                }
1938:
1939:                public void visit(Node.TemplateText n) throws JasperException {
1940:
1941:                    String text = n.getText();
1942:
1943:                    int textSize = text.length();
1944:                    if (textSize == 0) {
1945:                        return;
1946:                    }
1947:
1948:                    if (textSize <= 3) {
1949:                        // Special case small text strings
1950:                        n.setBeginJavaLine(out.getJavaLine());
1951:                        int lineInc = 0;
1952:                        for (int i = 0; i < textSize; i++) {
1953:                            char ch = text.charAt(i);
1954:                            out.printil("out.write(" + quote(ch) + ");");
1955:                            if (i > 0) {
1956:                                n.addSmap(lineInc);
1957:                            }
1958:                            if (ch == '\n') {
1959:                                lineInc++;
1960:                            }
1961:                        }
1962:                        n.setEndJavaLine(out.getJavaLine());
1963:                        return;
1964:                    }
1965:
1966:                    if (ctxt.getOptions().genStringAsCharArray()) {
1967:                        // Generate Strings as char arrays, for performance
1968:                        ServletWriter caOut;
1969:                        if (charArrayBuffer == null) {
1970:                            charArrayBuffer = new GenBuffer();
1971:                            caOut = charArrayBuffer.getOut();
1972:                            caOut.pushIndent();
1973:                            textMap = new HashMap();
1974:                        } else {
1975:                            caOut = charArrayBuffer.getOut();
1976:                        }
1977:                        String charArrayName = (String) textMap.get(text);
1978:                        if (charArrayName == null) {
1979:                            charArrayName = "_jspx_char_array_"
1980:                                    + charArrayCount++;
1981:                            textMap.put(text, charArrayName);
1982:                            caOut.printin("static char[] ");
1983:                            caOut.print(charArrayName);
1984:                            caOut.print(" = ");
1985:                            caOut.print(quote(text));
1986:                            caOut.println(".toCharArray();");
1987:                        }
1988:
1989:                        n.setBeginJavaLine(out.getJavaLine());
1990:                        out.printil("out.write(" + charArrayName + ");");
1991:                        n.setEndJavaLine(out.getJavaLine());
1992:                        return;
1993:                    }
1994:
1995:                    n.setBeginJavaLine(out.getJavaLine());
1996:
1997:                    out.printin();
1998:                    StringBuffer sb = new StringBuffer("out.write(\"");
1999:                    int initLength = sb.length();
2000:                    int count = JspUtil.CHUNKSIZE;
2001:                    int srcLine = 0; // relative to starting srouce line
2002:                    for (int i = 0; i < text.length(); i++) {
2003:                        char ch = text.charAt(i);
2004:                        --count;
2005:                        switch (ch) {
2006:                        case '"':
2007:                            sb.append('\\').append('\"');
2008:                            break;
2009:                        case '\\':
2010:                            sb.append('\\').append('\\');
2011:                            break;
2012:                        case '\r':
2013:                            sb.append('\\').append('r');
2014:                            break;
2015:                        case '\n':
2016:                            sb.append('\\').append('n');
2017:                            srcLine++;
2018:
2019:                            if (breakAtLF || count < 0) {
2020:                                // Generate an out.write() when see a '\n' in template
2021:                                sb.append("\");");
2022:                                out.println(sb.toString());
2023:                                if (i < text.length() - 1) {
2024:                                    out.printin();
2025:                                }
2026:                                sb.setLength(initLength);
2027:                                count = JspUtil.CHUNKSIZE;
2028:                            }
2029:                            // add a Smap for this line
2030:                            n.addSmap(srcLine);
2031:                            break;
2032:                        case '\t': // Not sure we need this
2033:                            sb.append('\\').append('t');
2034:                            break;
2035:                        default:
2036:                            sb.append(ch);
2037:                        }
2038:                    }
2039:
2040:                    if (sb.length() > initLength) {
2041:                        sb.append("\");");
2042:                        out.println(sb.toString());
2043:                    }
2044:
2045:                    n.setEndJavaLine(out.getJavaLine());
2046:                }
2047:
2048:                public void visit(Node.JspBody n) throws JasperException {
2049:                    if (n.getBody() != null) {
2050:                        if (isSimpleTagHandler) {
2051:                            out.printin(simpleTagHandlerVar);
2052:                            out.print(".setJspBody(");
2053:                            generateJspFragment(n, simpleTagHandlerVar);
2054:                            out.println(");");
2055:                        } else {
2056:                            visitBody(n);
2057:                        }
2058:                    }
2059:                }
2060:
2061:                public void visit(Node.InvokeAction n) throws JasperException {
2062:
2063:                    n.setBeginJavaLine(out.getJavaLine());
2064:
2065:                    // Copy virtual page scope of tag file to page scope of invoking
2066:                    // page
2067:                    out
2068:                            .printil("((org.apache.jasper.runtime.JspContextWrapper) this.jspContext).syncBeforeInvoke();");
2069:                    String varReaderAttr = n.getTextAttribute("varReader");
2070:                    String varAttr = n.getTextAttribute("var");
2071:                    if (varReaderAttr != null || varAttr != null) {
2072:                        out.printil("_jspx_sout = new java.io.StringWriter();");
2073:                    } else {
2074:                        out.printil("_jspx_sout = null;");
2075:                    }
2076:
2077:                    // Invoke fragment, unless fragment is null
2078:                    out.printin("if (");
2079:                    out.print(toGetterMethod(n.getTextAttribute("fragment")));
2080:                    out.println(" != null) {");
2081:                    out.pushIndent();
2082:                    out.printin(toGetterMethod(n.getTextAttribute("fragment")));
2083:                    out.println(".invoke(_jspx_sout);");
2084:                    out.popIndent();
2085:                    out.printil("}");
2086:
2087:                    // Store varReader in appropriate scope
2088:                    if (varReaderAttr != null || varAttr != null) {
2089:                        String scopeName = n.getTextAttribute("scope");
2090:                        out.printin("_jspx_page_context.setAttribute(");
2091:                        if (varReaderAttr != null) {
2092:                            out.print(quote(varReaderAttr));
2093:                            out
2094:                                    .print(", new java.io.StringReader(_jspx_sout.toString())");
2095:                        } else {
2096:                            out.print(quote(varAttr));
2097:                            out.print(", _jspx_sout.toString()");
2098:                        }
2099:                        if (scopeName != null) {
2100:                            out.print(", ");
2101:                            out.print(getScopeConstant(scopeName));
2102:                        }
2103:                        out.println(");");
2104:                    }
2105:
2106:                    // Restore EL context
2107:                    out
2108:                            .printil("jspContext.getELContext().putContext(JspContext.class,getJspContext());");
2109:
2110:                    n.setEndJavaLine(out.getJavaLine());
2111:                }
2112:
2113:                public void visit(Node.DoBodyAction n) throws JasperException {
2114:
2115:                    n.setBeginJavaLine(out.getJavaLine());
2116:
2117:                    // Copy virtual page scope of tag file to page scope of invoking
2118:                    // page
2119:                    out
2120:                            .printil("((org.apache.jasper.runtime.JspContextWrapper) this.jspContext).syncBeforeInvoke();");
2121:
2122:                    // Invoke body
2123:                    String varReaderAttr = n.getTextAttribute("varReader");
2124:                    String varAttr = n.getTextAttribute("var");
2125:                    if (varReaderAttr != null || varAttr != null) {
2126:                        out.printil("_jspx_sout = new java.io.StringWriter();");
2127:                    } else {
2128:                        out.printil("_jspx_sout = null;");
2129:                    }
2130:                    out.printil("if (getJspBody() != null)");
2131:                    out.pushIndent();
2132:                    out.printil("getJspBody().invoke(_jspx_sout);");
2133:                    out.popIndent();
2134:
2135:                    // Store varReader in appropriate scope
2136:                    if (varReaderAttr != null || varAttr != null) {
2137:                        String scopeName = n.getTextAttribute("scope");
2138:                        out.printin("_jspx_page_context.setAttribute(");
2139:                        if (varReaderAttr != null) {
2140:                            out.print(quote(varReaderAttr));
2141:                            out
2142:                                    .print(", new java.io.StringReader(_jspx_sout.toString())");
2143:                        } else {
2144:                            out.print(quote(varAttr));
2145:                            out.print(", _jspx_sout.toString()");
2146:                        }
2147:                        if (scopeName != null) {
2148:                            out.print(", ");
2149:                            out.print(getScopeConstant(scopeName));
2150:                        }
2151:                        out.println(");");
2152:                    }
2153:
2154:                    // Restore EL context
2155:                    out
2156:                            .printil("jspContext.getELContext().putContext(JspContext.class,getJspContext());");
2157:
2158:                    n.setEndJavaLine(out.getJavaLine());
2159:                }
2160:
2161:                public void visit(Node.AttributeGenerator n)
2162:                        throws JasperException {
2163:                    Node.CustomTag tag = n.getTag();
2164:                    Node.JspAttribute[] attrs = tag.getJspAttributes();
2165:                    for (int i = 0; attrs != null && i < attrs.length; i++) {
2166:                        if (attrs[i].getName().equals(n.getName())) {
2167:                            out.print(evaluateAttribute(getTagHandlerInfo(tag),
2168:                                    attrs[i], tag, null));
2169:                            break;
2170:                        }
2171:                    }
2172:                }
2173:
2174:                private TagHandlerInfo getTagHandlerInfo(Node.CustomTag n)
2175:                        throws JasperException {
2176:                    Hashtable handlerInfosByShortName = (Hashtable) handlerInfos
2177:                            .get(n.getPrefix());
2178:                    if (handlerInfosByShortName == null) {
2179:                        handlerInfosByShortName = new Hashtable();
2180:                        handlerInfos
2181:                                .put(n.getPrefix(), handlerInfosByShortName);
2182:                    }
2183:                    TagHandlerInfo handlerInfo = (TagHandlerInfo) handlerInfosByShortName
2184:                            .get(n.getLocalName());
2185:                    if (handlerInfo == null) {
2186:                        handlerInfo = new TagHandlerInfo(n, n
2187:                                .getTagHandlerClass(), err);
2188:                        handlerInfosByShortName.put(n.getLocalName(),
2189:                                handlerInfo);
2190:                    }
2191:                    return handlerInfo;
2192:                }
2193:
2194:                private void generateTagPlugin(Node.CustomTag n)
2195:                        throws JasperException {
2196:                    if (n.getAtSTag() != null) {
2197:                        n.getAtSTag().visit(this );
2198:                    }
2199:                    visitBody(n);
2200:                    if (n.getAtETag() != null) {
2201:                        n.getAtETag().visit(this );
2202:                    }
2203:                }
2204:
2205:                private void generateCustomStart(Node.CustomTag n,
2206:                        TagHandlerInfo handlerInfo, String tagHandlerVar,
2207:                        String tagEvalVar, String tagPushBodyCountVar)
2208:                        throws JasperException {
2209:
2210:                    Class tagHandlerClass = handlerInfo.getTagHandlerClass();
2211:
2212:                    out.printin("//  ");
2213:                    out.println(n.getQName());
2214:                    n.setBeginJavaLine(out.getJavaLine());
2215:
2216:                    // Declare AT_BEGIN scripting variables
2217:                    declareScriptingVars(n, VariableInfo.AT_BEGIN);
2218:                    saveScriptingVars(n, VariableInfo.AT_BEGIN);
2219:
2220:                    String tagHandlerClassName = JspUtil
2221:                            .getCanonicalName(tagHandlerClass);
2222:                    out.printin(tagHandlerClassName);
2223:                    out.print(" ");
2224:                    out.print(tagHandlerVar);
2225:                    out.print(" = ");
2226:                    if (isPoolingEnabled && !(n.implements JspIdConsumer())) {
2227:                        out.print("(");
2228:                        out.print(tagHandlerClassName);
2229:                        out.print(") ");
2230:                        out.print(n.getTagHandlerPoolName());
2231:                        out.print(".get(");
2232:                        out.print(tagHandlerClassName);
2233:                        out.println(".class);");
2234:                    } else {
2235:                        out.print("new ");
2236:                        out.print(tagHandlerClassName);
2237:                        out.println("();");
2238:                        out
2239:                                .printin("org.apache.jasper.runtime.AnnotationHelper.postConstruct(");
2240:                        out.print(VAR_ANNOTATIONPROCESSOR);
2241:                        out.print(", ");
2242:                        out.print(tagHandlerVar);
2243:                        out.println(");");
2244:                    }
2245:
2246:                    // includes setting the context
2247:                    generateSetters(n, tagHandlerVar, handlerInfo, false);
2248:
2249:                    // JspIdConsumer (after context has been set)
2250:                    if (n.implements JspIdConsumer()) {
2251:                        out.printin(tagHandlerVar);
2252:                        out.print(".setJspId(\"");
2253:                        out.print(createJspId());
2254:                        out.println("\");");
2255:                    }
2256:
2257:                    if (n.implements TryCatchFinally()) {
2258:                        out.printin("int[] ");
2259:                        out.print(tagPushBodyCountVar);
2260:                        out.println(" = new int[] { 0 };");
2261:                        out.printil("try {");
2262:                        out.pushIndent();
2263:                    }
2264:                    out.printin("int ");
2265:                    out.print(tagEvalVar);
2266:                    out.print(" = ");
2267:                    out.print(tagHandlerVar);
2268:                    out.println(".doStartTag();");
2269:
2270:                    if (!n.implements BodyTag()) {
2271:                        // Synchronize AT_BEGIN scripting variables
2272:                        syncScriptingVars(n, VariableInfo.AT_BEGIN);
2273:                    }
2274:
2275:                    if (!n.hasEmptyBody()) {
2276:                        out.printin("if (");
2277:                        out.print(tagEvalVar);
2278:                        out
2279:                                .println(" != javax.servlet.jsp.tagext.Tag.SKIP_BODY) {");
2280:                        out.pushIndent();
2281:
2282:                        // Declare NESTED scripting variables
2283:                        declareScriptingVars(n, VariableInfo.NESTED);
2284:                        saveScriptingVars(n, VariableInfo.NESTED);
2285:
2286:                        if (n.implements BodyTag()) {
2287:                            out.printin("if (");
2288:                            out.print(tagEvalVar);
2289:                            out
2290:                                    .println(" != javax.servlet.jsp.tagext.Tag.EVAL_BODY_INCLUDE) {");
2291:                            // Assume EVAL_BODY_BUFFERED
2292:                            out.pushIndent();
2293:                            out.printil("out = _jspx_page_context.pushBody();");
2294:                            if (n.implements TryCatchFinally()) {
2295:                                out.printin(tagPushBodyCountVar);
2296:                                out.println("[0]++;");
2297:                            } else if (pushBodyCountVar != null) {
2298:                                out.printin(pushBodyCountVar);
2299:                                out.println("[0]++;");
2300:                            }
2301:                            out.printin(tagHandlerVar);
2302:                            out
2303:                                    .println(".setBodyContent((javax.servlet.jsp.tagext.BodyContent) out);");
2304:                            out.printin(tagHandlerVar);
2305:                            out.println(".doInitBody();");
2306:
2307:                            out.popIndent();
2308:                            out.printil("}");
2309:
2310:                            // Synchronize AT_BEGIN and NESTED scripting variables
2311:                            syncScriptingVars(n, VariableInfo.AT_BEGIN);
2312:                            syncScriptingVars(n, VariableInfo.NESTED);
2313:
2314:                        } else {
2315:                            // Synchronize NESTED scripting variables
2316:                            syncScriptingVars(n, VariableInfo.NESTED);
2317:                        }
2318:
2319:                        if (n.implements IterationTag()) {
2320:                            out.printil("do {");
2321:                            out.pushIndent();
2322:                        }
2323:                    }
2324:                    // Map the Java lines that handles start of custom tags to the
2325:                    // JSP line for this tag
2326:                    n.setEndJavaLine(out.getJavaLine());
2327:                }
2328:
2329:                private void generateCustomEnd(Node.CustomTag n,
2330:                        String tagHandlerVar, String tagEvalVar,
2331:                        String tagPushBodyCountVar) {
2332:
2333:                    if (!n.hasEmptyBody()) {
2334:                        if (n.implements IterationTag()) {
2335:                            out.printin("int evalDoAfterBody = ");
2336:                            out.print(tagHandlerVar);
2337:                            out.println(".doAfterBody();");
2338:
2339:                            // Synchronize AT_BEGIN and NESTED scripting variables
2340:                            syncScriptingVars(n, VariableInfo.AT_BEGIN);
2341:                            syncScriptingVars(n, VariableInfo.NESTED);
2342:
2343:                            out
2344:                                    .printil("if (evalDoAfterBody != javax.servlet.jsp.tagext.BodyTag.EVAL_BODY_AGAIN)");
2345:                            out.pushIndent();
2346:                            out.printil("break;");
2347:                            out.popIndent();
2348:
2349:                            out.popIndent();
2350:                            out.printil("} while (true);");
2351:                        }
2352:
2353:                        restoreScriptingVars(n, VariableInfo.NESTED);
2354:
2355:                        if (n.implements BodyTag()) {
2356:                            out.printin("if (");
2357:                            out.print(tagEvalVar);
2358:                            out
2359:                                    .println(" != javax.servlet.jsp.tagext.Tag.EVAL_BODY_INCLUDE) {");
2360:                            out.pushIndent();
2361:                            out.printil("out = _jspx_page_context.popBody();");
2362:                            if (n.implements TryCatchFinally()) {
2363:                                out.printin(tagPushBodyCountVar);
2364:                                out.println("[0]--;");
2365:                            } else if (pushBodyCountVar != null) {
2366:                                out.printin(pushBodyCountVar);
2367:                                out.println("[0]--;");
2368:                            }
2369:                            out.popIndent();
2370:                            out.printil("}");
2371:                        }
2372:
2373:                        out.popIndent(); // EVAL_BODY
2374:                        out.printil("}");
2375:                    }
2376:
2377:                    out.printin("if (");
2378:                    out.print(tagHandlerVar);
2379:                    out
2380:                            .println(".doEndTag() == javax.servlet.jsp.tagext.Tag.SKIP_PAGE) {");
2381:                    out.pushIndent();
2382:                    if (!n.implements TryCatchFinally()) {
2383:                        if (isPoolingEnabled && !(n.implements JspIdConsumer())) {
2384:                            out.printin(n.getTagHandlerPoolName());
2385:                            out.print(".reuse(");
2386:                            out.print(tagHandlerVar);
2387:                            out.println(");");
2388:                        } else {
2389:                            out.printin(tagHandlerVar);
2390:                            out.println(".release();");
2391:                            out
2392:                                    .printin("org.apache.jasper.runtime.AnnotationHelper.preDestroy(");
2393:                            out.print(VAR_ANNOTATIONPROCESSOR);
2394:                            out.print(", ");
2395:                            out.print(tagHandlerVar);
2396:                            out.println(");");
2397:                        }
2398:                    }
2399:                    if (isTagFile || isFragment) {
2400:                        out.printil("throw new SkipPageException();");
2401:                    } else {
2402:                        out.printil((methodNesting > 0) ? "return true;"
2403:                                : "return;");
2404:                    }
2405:                    out.popIndent();
2406:                    out.printil("}");
2407:                    // Synchronize AT_BEGIN scripting variables
2408:                    syncScriptingVars(n, VariableInfo.AT_BEGIN);
2409:
2410:                    // TryCatchFinally
2411:                    if (n.implements TryCatchFinally()) {
2412:                        out.popIndent(); // try
2413:                        out.printil("} catch (Throwable _jspx_exception) {");
2414:                        out.pushIndent();
2415:
2416:                        out.printin("while (");
2417:                        out.print(tagPushBodyCountVar);
2418:                        out.println("[0]-- > 0)");
2419:                        out.pushIndent();
2420:                        out.printil("out = _jspx_page_context.popBody();");
2421:                        out.popIndent();
2422:
2423:                        out.printin(tagHandlerVar);
2424:                        out.println(".doCatch(_jspx_exception);");
2425:                        out.popIndent();
2426:                        out.printil("} finally {");
2427:                        out.pushIndent();
2428:                        out.printin(tagHandlerVar);
2429:                        out.println(".doFinally();");
2430:                    }
2431:
2432:                    if (isPoolingEnabled) {
2433:                        out.printin(n.getTagHandlerPoolName());
2434:                        out.print(".reuse(");
2435:                        out.print(tagHandlerVar);
2436:                        out.println(");");
2437:                    } else {
2438:                        out.printin(tagHandlerVar);
2439:                        out.println(".release();");
2440:                        out
2441:                                .printin("org.apache.jasper.runtime.AnnotationHelper.preDestroy(");
2442:                        out.print(VAR_ANNOTATIONPROCESSOR);
2443:                        out.print(", ");
2444:                        out.print(tagHandlerVar);
2445:                        out.println(");");
2446:                    }
2447:
2448:                    if (n.implements TryCatchFinally()) {
2449:                        out.popIndent();
2450:                        out.printil("}");
2451:                    }
2452:
2453:                    // Declare and synchronize AT_END scripting variables (must do this
2454:                    // outside the try/catch/finally block)
2455:                    declareScriptingVars(n, VariableInfo.AT_END);
2456:                    syncScriptingVars(n, VariableInfo.AT_END);
2457:
2458:                    restoreScriptingVars(n, VariableInfo.AT_BEGIN);
2459:                }
2460:
2461:                private void generateCustomDoTag(Node.CustomTag n,
2462:                        TagHandlerInfo handlerInfo, String tagHandlerVar)
2463:                        throws JasperException {
2464:
2465:                    Class tagHandlerClass = handlerInfo.getTagHandlerClass();
2466:
2467:                    n.setBeginJavaLine(out.getJavaLine());
2468:                    out.printin("//  ");
2469:                    out.println(n.getQName());
2470:
2471:                    // Declare AT_BEGIN scripting variables
2472:                    declareScriptingVars(n, VariableInfo.AT_BEGIN);
2473:                    saveScriptingVars(n, VariableInfo.AT_BEGIN);
2474:
2475:                    String tagHandlerClassName = JspUtil
2476:                            .getCanonicalName(tagHandlerClass);
2477:                    out.printin(tagHandlerClassName);
2478:                    out.print(" ");
2479:                    out.print(tagHandlerVar);
2480:                    out.print(" = ");
2481:                    out.print("new ");
2482:                    out.print(tagHandlerClassName);
2483:                    out.println("();");
2484:
2485:                    // Resource injection
2486:                    out
2487:                            .printin("org.apache.jasper.runtime.AnnotationHelper.postConstruct(");
2488:                    out.print(VAR_ANNOTATIONPROCESSOR);
2489:                    out.print(", ");
2490:                    out.print(tagHandlerVar);
2491:                    out.println(");");
2492:
2493:                    generateSetters(n, tagHandlerVar, handlerInfo, true);
2494:
2495:                    // JspIdConsumer (after context has been set)
2496:                    if (n.implements JspIdConsumer()) {
2497:                        out.printin(tagHandlerVar);
2498:                        out.print(".setJspId(\"");
2499:                        out.print(createJspId());
2500:                        out.println("\");");
2501:                    }
2502:
2503:                    // Set the body
2504:                    if (findJspBody(n) == null) {
2505:                        /*
2506:                         * Encapsulate body of custom tag invocation in JspFragment and
2507:                         * pass it to tag handler's setJspBody(), unless tag body is
2508:                         * empty
2509:                         */
2510:                        if (!n.hasEmptyBody()) {
2511:                            out.printin(tagHandlerVar);
2512:                            out.print(".setJspBody(");
2513:                            generateJspFragment(n, tagHandlerVar);
2514:                            out.println(");");
2515:                        }
2516:                    } else {
2517:                        /*
2518:                         * Body of tag is the body of the <jsp:body> element. The visit
2519:                         * method for that element is going to encapsulate that
2520:                         * element's body in a JspFragment and pass it to the tag
2521:                         * handler's setJspBody()
2522:                         */
2523:                        String tmpTagHandlerVar = simpleTagHandlerVar;
2524:                        simpleTagHandlerVar = tagHandlerVar;
2525:                        boolean tmpIsSimpleTagHandler = isSimpleTagHandler;
2526:                        isSimpleTagHandler = true;
2527:                        visitBody(n);
2528:                        simpleTagHandlerVar = tmpTagHandlerVar;
2529:                        isSimpleTagHandler = tmpIsSimpleTagHandler;
2530:                    }
2531:
2532:                    out.printin(tagHandlerVar);
2533:                    out.println(".doTag();");
2534:
2535:                    restoreScriptingVars(n, VariableInfo.AT_BEGIN);
2536:
2537:                    // Synchronize AT_BEGIN scripting variables
2538:                    syncScriptingVars(n, VariableInfo.AT_BEGIN);
2539:
2540:                    // Declare and synchronize AT_END scripting variables
2541:                    declareScriptingVars(n, VariableInfo.AT_END);
2542:                    syncScriptingVars(n, VariableInfo.AT_END);
2543:
2544:                    // Resource injection
2545:                    out
2546:                            .printin("org.apache.jasper.runtime.AnnotationHelper.preDestroy(");
2547:                    out.print(VAR_ANNOTATIONPROCESSOR);
2548:                    out.print(", ");
2549:                    out.print(tagHandlerVar);
2550:                    out.println(");");
2551:
2552:                    n.setEndJavaLine(out.getJavaLine());
2553:                }
2554:
2555:                private void declareScriptingVars(Node.CustomTag n, int scope) {
2556:
2557:                    Vector vec = n.getScriptingVars(scope);
2558:                    if (vec != null) {
2559:                        for (int i = 0; i < vec.size(); i++) {
2560:                            Object elem = vec.elementAt(i);
2561:                            if (elem instanceof  VariableInfo) {
2562:                                VariableInfo varInfo = (VariableInfo) elem;
2563:                                if (varInfo.getDeclare()) {
2564:                                    out.printin(varInfo.getClassName());
2565:                                    out.print(" ");
2566:                                    out.print(varInfo.getVarName());
2567:                                    out.println(" = null;");
2568:                                }
2569:                            } else {
2570:                                TagVariableInfo tagVarInfo = (TagVariableInfo) elem;
2571:                                if (tagVarInfo.getDeclare()) {
2572:                                    String varName = tagVarInfo.getNameGiven();
2573:                                    if (varName == null) {
2574:                                        varName = n
2575:                                                .getTagData()
2576:                                                .getAttributeString(
2577:                                                        tagVarInfo
2578:                                                                .getNameFromAttribute());
2579:                                    } else if (tagVarInfo
2580:                                            .getNameFromAttribute() != null) {
2581:                                        // alias
2582:                                        continue;
2583:                                    }
2584:                                    out.printin(tagVarInfo.getClassName());
2585:                                    out.print(" ");
2586:                                    out.print(varName);
2587:                                    out.println(" = null;");
2588:                                }
2589:                            }
2590:                        }
2591:                    }
2592:                }
2593:
2594:                /*
2595:                 * This method is called as part of the custom tag's start element.
2596:                 * 
2597:                 * If the given custom tag has a custom nesting level greater than 0,
2598:                 * save the current values of its scripting variables to temporary
2599:                 * variables, so those values may be restored in the tag's end element.
2600:                 * This way, the scripting variables may be synchronized by the given
2601:                 * tag without affecting their original values.
2602:                 */
2603:                private void saveScriptingVars(Node.CustomTag n, int scope) {
2604:                    if (n.getCustomNestingLevel() == 0) {
2605:                        return;
2606:                    }
2607:
2608:                    TagVariableInfo[] tagVarInfos = n.getTagVariableInfos();
2609:                    VariableInfo[] varInfos = n.getVariableInfos();
2610:                    if ((varInfos.length == 0) && (tagVarInfos.length == 0)) {
2611:                        return;
2612:                    }
2613:
2614:                    if (varInfos.length > 0) {
2615:                        for (int i = 0; i < varInfos.length; i++) {
2616:                            if (varInfos[i].getScope() != scope)
2617:                                continue;
2618:                            // If the scripting variable has been declared, skip codes
2619:                            // for saving and restoring it.
2620:                            if (n.getScriptingVars(scope).contains(varInfos[i]))
2621:                                continue;
2622:                            String varName = varInfos[i].getVarName();
2623:                            String tmpVarName = "_jspx_" + varName + "_"
2624:                                    + n.getCustomNestingLevel();
2625:                            out.printin(tmpVarName);
2626:                            out.print(" = ");
2627:                            out.print(varName);
2628:                            out.println(";");
2629:                        }
2630:                    } else {
2631:                        for (int i = 0; i < tagVarInfos.length; i++) {
2632:                            if (tagVarInfos[i].getScope() != scope)
2633:                                continue;
2634:                            // If the scripting variable has been declared, skip codes
2635:                            // for saving and restoring it.
2636:                            if (n.getScriptingVars(scope).contains(
2637:                                    tagVarInfos[i]))
2638:                                continue;
2639:                            String varName = tagVarInfos[i].getNameGiven();
2640:                            if (varName == null) {
2641:                                varName = n.getTagData().getAttributeString(
2642:                                        tagVarInfos[i].getNameFromAttribute());
2643:                            } else if (tagVarInfos[i].getNameFromAttribute() != null) {
2644:                                // alias
2645:                                continue;
2646:                            }
2647:                            String tmpVarName = "_jspx_" + varName + "_"
2648:                                    + n.getCustomNestingLevel();
2649:                            out.printin(tmpVarName);
2650:                            out.print(" = ");
2651:                            out.print(varName);
2652:                            out.println(";");
2653:                        }
2654:                    }
2655:                }
2656:
2657:                /*
2658:                 * This method is called as part of the custom tag's end element.
2659:                 * 
2660:                 * If the given custom tag has a custom nesting level greater than 0,
2661:                 * restore its scripting variables to their original values that were
2662:                 * saved in the tag's start element.
2663:                 */
2664:                private void restoreScriptingVars(Node.CustomTag n, int scope) {
2665:                    if (n.getCustomNestingLevel() == 0) {
2666:                        return;
2667:                    }
2668:
2669:                    TagVariableInfo[] tagVarInfos = n.getTagVariableInfos();
2670:                    VariableInfo[] varInfos = n.getVariableInfos();
2671:                    if ((varInfos.length == 0) && (tagVarInfos.length == 0)) {
2672:                        return;
2673:                    }
2674:
2675:                    if (varInfos.length > 0) {
2676:                        for (int i = 0; i < varInfos.length; i++) {
2677:                            if (varInfos[i].getScope() != scope)
2678:                                continue;
2679:                            // If the scripting variable has been declared, skip codes
2680:                            // for saving and restoring it.
2681:                            if (n.getScriptingVars(scope).contains(varInfos[i]))
2682:                                continue;
2683:                            String varName = varInfos[i].getVarName();
2684:                            String tmpVarName = "_jspx_" + varName + "_"
2685:                                    + n.getCustomNestingLevel();
2686:                            out.printin(varName);
2687:                            out.print(" = ");
2688:                            out.print(tmpVarName);
2689:                            out.println(";");
2690:                        }
2691:                    } else {
2692:                        for (int i = 0; i < tagVarInfos.length; i++) {
2693:                            if (tagVarInfos[i].getScope() != scope)
2694:                                continue;
2695:                            // If the scripting variable has been declared, skip codes
2696:                            // for saving and restoring it.
2697:                            if (n.getScriptingVars(scope).contains(
2698:                                    tagVarInfos[i]))
2699:                                continue;
2700:                            String varName = tagVarInfos[i].getNameGiven();
2701:                            if (varName == null) {
2702:                                varName = n.getTagData().getAttributeString(
2703:                                        tagVarInfos[i].getNameFromAttribute());
2704:                            } else if (tagVarInfos[i].getNameFromAttribute() != null) {
2705:                                // alias
2706:                                continue;
2707:                            }
2708:                            String tmpVarName = "_jspx_" + varName + "_"
2709:                                    + n.getCustomNestingLevel();
2710:                            out.printin(varName);
2711:                            out.print(" = ");
2712:                            out.print(tmpVarName);
2713:                            out.println(";");
2714:                        }
2715:                    }
2716:                }
2717:
2718:                /*
2719:                 * Synchronizes the scripting variables of the given custom tag for the
2720:                 * given scope.
2721:                 */
2722:                private void syncScriptingVars(Node.CustomTag n, int scope) {
2723:                    TagVariableInfo[] tagVarInfos = n.getTagVariableInfos();
2724:                    VariableInfo[] varInfos = n.getVariableInfos();
2725:
2726:                    if ((varInfos.length == 0) && (tagVarInfos.length == 0)) {
2727:                        return;
2728:                    }
2729:
2730:                    if (varInfos.length > 0) {
2731:                        for (int i = 0; i < varInfos.length; i++) {
2732:                            if (varInfos[i].getScope() == scope) {
2733:                                out.printin(varInfos[i].getVarName());
2734:                                out.print(" = (");
2735:                                out.print(varInfos[i].getClassName());
2736:                                out
2737:                                        .print(") _jspx_page_context.findAttribute(");
2738:                                out.print(quote(varInfos[i].getVarName()));
2739:                                out.println(");");
2740:                            }
2741:                        }
2742:                    } else {
2743:                        for (int i = 0; i < tagVarInfos.length; i++) {
2744:                            if (tagVarInfos[i].getScope() == scope) {
2745:                                String name = tagVarInfos[i].getNameGiven();
2746:                                if (name == null) {
2747:                                    name = n.getTagData().getAttributeString(
2748:                                            tagVarInfos[i]
2749:                                                    .getNameFromAttribute());
2750:                                } else if (tagVarInfos[i]
2751:                                        .getNameFromAttribute() != null) {
2752:                                    // alias
2753:                                    continue;
2754:                                }
2755:                                out.printin(name);
2756:                                out.print(" = (");
2757:                                out.print(tagVarInfos[i].getClassName());
2758:                                out
2759:                                        .print(") _jspx_page_context.findAttribute(");
2760:                                out.print(quote(name));
2761:                                out.println(");");
2762:                            }
2763:                        }
2764:                    }
2765:                }
2766:
2767:                private String getJspContextVar() {
2768:                    if (this .isTagFile) {
2769:                        return "this.getJspContext()";
2770:                    } else {
2771:                        return "_jspx_page_context";
2772:                    }
2773:                }
2774:
2775:                private String getExpressionFactoryVar() {
2776:                    return VAR_EXPRESSIONFACTORY;
2777:                }
2778:
2779:                /*
2780:                 * Creates a tag variable name by concatenating the given prefix and
2781:                 * shortName and endcoded to make the resultant string a valid Java
2782:                 * Identifier.
2783:                 */
2784:                private String createTagVarName(String fullName, String prefix,
2785:                        String shortName) {
2786:
2787:                    String varName;
2788:                    synchronized (tagVarNumbers) {
2789:                        varName = prefix + "_" + shortName + "_";
2790:                        if (tagVarNumbers.get(fullName) != null) {
2791:                            Integer i = (Integer) tagVarNumbers.get(fullName);
2792:                            varName = varName + i.intValue();
2793:                            tagVarNumbers.put(fullName, new Integer(i
2794:                                    .intValue() + 1));
2795:                        } else {
2796:                            tagVarNumbers.put(fullName, new Integer(1));
2797:                            varName = varName + "0";
2798:                        }
2799:                    }
2800:                    return JspUtil.makeJavaIdentifier(varName);
2801:                }
2802:
2803:                private String evaluateAttribute(TagHandlerInfo handlerInfo,
2804:                        Node.JspAttribute attr, Node.CustomTag n,
2805:                        String tagHandlerVar) throws JasperException {
2806:
2807:                    String attrValue = attr.getValue();
2808:                    if (attrValue == null) {
2809:                        if (attr.isNamedAttribute()) {
2810:                            if (n.checkIfAttributeIsJspFragment(attr.getName())) {
2811:                                // XXX - no need to generate temporary variable here
2812:                                attrValue = generateNamedAttributeJspFragment(
2813:                                        attr.getNamedAttributeNode(),
2814:                                        tagHandlerVar);
2815:                            } else {
2816:                                attrValue = generateNamedAttributeValue(attr
2817:                                        .getNamedAttributeNode());
2818:                            }
2819:                        } else {
2820:                            return null;
2821:                        }
2822:                    }
2823:
2824:                    String localName = attr.getLocalName();
2825:
2826:                    Method m = null;
2827:                    Class[] c = null;
2828:                    if (attr.isDynamic()) {
2829:                        c = OBJECT_CLASS;
2830:                    } else {
2831:                        m = handlerInfo.getSetterMethod(localName);
2832:                        if (m == null) {
2833:                            err.jspError(n, "jsp.error.unable.to_find_method",
2834:                                    attr.getName());
2835:                        }
2836:                        c = m.getParameterTypes();
2837:                        // XXX assert(c.length > 0)
2838:                    }
2839:
2840:                    if (attr.isExpression()) {
2841:                        // Do nothing
2842:                    } else if (attr.isNamedAttribute()) {
2843:                        if (!n.checkIfAttributeIsJspFragment(attr.getName())
2844:                                && !attr.isDynamic()) {
2845:                            attrValue = convertString(c[0], attrValue,
2846:                                    localName, handlerInfo
2847:                                            .getPropertyEditorClass(localName),
2848:                                    true);
2849:                        }
2850:                    } else if (attr.isELInterpreterInput()) {
2851:
2852:                        // results buffer
2853:                        StringBuffer sb = new StringBuffer(64);
2854:
2855:                        TagAttributeInfo tai = attr.getTagAttributeInfo();
2856:
2857:                        // generate elContext reference
2858:                        sb.append(getJspContextVar());
2859:                        sb.append(".getELContext()");
2860:                        String elContext = sb.toString();
2861:                        if (attr.getEL() != null
2862:                                && attr.getEL().getMapName() != null) {
2863:                            sb.setLength(0);
2864:                            sb
2865:                                    .append("new org.apache.jasper.el.ELContextWrapper(");
2866:                            sb.append(elContext);
2867:                            sb.append(',');
2868:                            sb.append(attr.getEL().getMapName());
2869:                            sb.append(')');
2870:                            elContext = sb.toString();
2871:                        }
2872:
2873:                        // reset buffer
2874:                        sb.setLength(0);
2875:
2876:                        // create our mark
2877:                        sb.append(n.getStart().toString());
2878:                        sb.append(" '");
2879:                        sb.append(attrValue);
2880:                        sb.append('\'');
2881:                        String mark = sb.toString();
2882:
2883:                        // reset buffer
2884:                        sb.setLength(0);
2885:
2886:                        // depending on type
2887:                        if (attr.isDeferredInput()
2888:                                || ((tai != null) && ValueExpression.class
2889:                                        .getName().equals(tai.getTypeName()))) {
2890:                            sb
2891:                                    .append("new org.apache.jasper.el.JspValueExpression(");
2892:                            sb.append(quote(mark));
2893:                            sb.append(',');
2894:                            sb.append(getExpressionFactoryVar());
2895:                            sb.append(".createValueExpression(");
2896:                            if (attr.getEL() != null) { // optimize
2897:                                sb.append(elContext);
2898:                                sb.append(',');
2899:                            }
2900:                            sb.append(quote(attrValue));
2901:                            sb.append(',');
2902:                            sb.append(JspUtil.toJavaSourceTypeFromTld(attr
2903:                                    .getExpectedTypeName()));
2904:                            sb.append("))");
2905:                            // should the expression be evaluated before passing to
2906:                            // the setter?
2907:                            boolean evaluate = false;
2908:                            if (tai.canBeRequestTime()) {
2909:                                evaluate = true; // JSP.2.3.2
2910:                            }
2911:                            if (attr.isDeferredInput()) {
2912:                                evaluate = false; // JSP.2.3.3
2913:                            }
2914:                            if (attr.isDeferredInput()
2915:                                    && tai.canBeRequestTime()) {
2916:                                evaluate = !attrValue.contains("#{"); // JSP.2.3.5
2917:                            }
2918:                            if (evaluate) {
2919:                                sb.append(".getValue(");
2920:                                sb.append(getJspContextVar());
2921:                                sb.append(".getELContext()");
2922:                                sb.append(")");
2923:                            }
2924:                            attrValue = sb.toString();
2925:                        } else if (attr.isDeferredMethodInput()
2926:                                || ((tai != null) && MethodExpression.class
2927:                                        .getName().equals(tai.getTypeName()))) {
2928:                            sb
2929:                                    .append("new org.apache.jasper.el.JspMethodExpression(");
2930:                            sb.append(quote(mark));
2931:                            sb.append(',');
2932:                            sb.append(getExpressionFactoryVar());
2933:                            sb.append(".createMethodExpression(");
2934:                            sb.append(elContext);
2935:                            sb.append(',');
2936:                            sb.append(quote(attrValue));
2937:                            sb.append(',');
2938:                            sb.append(JspUtil.toJavaSourceTypeFromTld(attr
2939:                                    .getExpectedTypeName()));
2940:                            sb.append(',');
2941:                            sb.append("new Class[] {");
2942:
2943:                            String[] p = attr.getParameterTypeNames();
2944:                            for (int i = 0; i < p.length; i++) {
2945:                                sb
2946:                                        .append(JspUtil
2947:                                                .toJavaSourceTypeFromTld(p[i]));
2948:                                sb.append(',');
2949:                            }
2950:                            if (p.length > 0) {
2951:                                sb.setLength(sb.length() - 1);
2952:                            }
2953:
2954:                            sb.append("}))");
2955:                            attrValue = sb.toString();
2956:                        } else {
2957:                            // run attrValue through the expression interpreter
2958:                            boolean replaceESC = attrValue
2959:                                    .indexOf(Constants.ESC) > 0;
2960:                            String mapName = (attr.getEL() != null) ? attr
2961:                                    .getEL().getMapName() : null;
2962:                            attrValue = JspUtil.interpreterCall(this .isTagFile,
2963:                                    attrValue, c[0], mapName, false);
2964:                            // XXX hack: Replace ESC with '$'
2965:                            if (replaceESC) {
2966:                                attrValue = "(" + attrValue + ").replace("
2967:                                        + Constants.ESCStr + ", '$')";
2968:                            }
2969:                        }
2970:                    } else {
2971:                        attrValue = convertString(c[0], attrValue, localName,
2972:                                handlerInfo.getPropertyEditorClass(localName),
2973:                                false);
2974:                    }
2975:                    return attrValue;
2976:                }
2977:
2978:                /**
2979:                 * Generate code to create a map for the alias variables
2980:                 * 
2981:                 * @return the name of the map
2982:                 */
2983:                private String generateAliasMap(Node.CustomTag n,
2984:                        String tagHandlerVar) throws JasperException {
2985:
2986:                    TagVariableInfo[] tagVars = n.getTagVariableInfos();
2987:                    String aliasMapVar = null;
2988:
2989:                    boolean aliasSeen = false;
2990:                    for (int i = 0; i < tagVars.length; i++) {
2991:
2992:                        String nameFrom = tagVars[i].getNameFromAttribute();
2993:                        if (nameFrom != null) {
2994:                            String aliasedName = n.getAttributeValue(nameFrom);
2995:                            if (aliasedName == null)
2996:                                continue;
2997:
2998:                            if (!aliasSeen) {
2999:                                out.printin("java.util.HashMap ");
3000:                                aliasMapVar = tagHandlerVar + "_aliasMap";
3001:                                out.print(aliasMapVar);
3002:                                out.println(" = new java.util.HashMap();");
3003:                                aliasSeen = true;
3004:                            }
3005:                            out.printin(aliasMapVar);
3006:                            out.print(".put(");
3007:                            out.print(quote(tagVars[i].getNameGiven()));
3008:                            out.print(", ");
3009:                            out.print(quote(aliasedName));
3010:                            out.println(");");
3011:                        }
3012:                    }
3013:                    return aliasMapVar;
3014:                }
3015:
3016:                private void generateSetters(Node.CustomTag n,
3017:                        String tagHandlerVar, TagHandlerInfo handlerInfo,
3018:                        boolean simpleTag) throws JasperException {
3019:
3020:                    // Set context
3021:                    if (simpleTag) {
3022:                        // Generate alias map
3023:                        String aliasMapVar = null;
3024:                        if (n.isTagFile()) {
3025:                            aliasMapVar = generateAliasMap(n, tagHandlerVar);
3026:                        }
3027:                        out.printin(tagHandlerVar);
3028:                        if (aliasMapVar == null) {
3029:                            out.println(".setJspContext(_jspx_page_context);");
3030:                        } else {
3031:                            out.print(".setJspContext(_jspx_page_context, ");
3032:                            out.print(aliasMapVar);
3033:                            out.println(");");
3034:                        }
3035:                    } else {
3036:                        out.printin(tagHandlerVar);
3037:                        out.println(".setPageContext(_jspx_page_context);");
3038:                    }
3039:
3040:                    // Set parent
3041:                    if (isTagFile && parent == null) {
3042:                        out.printin(tagHandlerVar);
3043:                        out.print(".setParent(");
3044:                        out.print("new javax.servlet.jsp.tagext.TagAdapter(");
3045:                        out
3046:                                .print("(javax.servlet.jsp.tagext.SimpleTag) this ));");
3047:                    } else if (!simpleTag) {
3048:                        out.printin(tagHandlerVar);
3049:                        out.print(".setParent(");
3050:                        if (parent != null) {
3051:                            if (isSimpleTagParent) {
3052:                                out
3053:                                        .print("new javax.servlet.jsp.tagext.TagAdapter(");
3054:                                out
3055:                                        .print("(javax.servlet.jsp.tagext.SimpleTag) ");
3056:                                out.print(parent);
3057:                                out.println("));");
3058:                            } else {
3059:                                out.print("(javax.servlet.jsp.tagext.Tag) ");
3060:                                out.print(parent);
3061:                                out.println(");");
3062:                            }
3063:                        } else {
3064:                            out.println("null);");
3065:                        }
3066:                    } else {
3067:                        // The setParent() method need not be called if the value being
3068:                        // passed is null, since SimpleTag instances are not reused
3069:                        if (parent != null) {
3070:                            out.printin(tagHandlerVar);
3071:                            out.print(".setParent(");
3072:                            out.print(parent);
3073:                            out.println(");");
3074:                        }
3075:                    }
3076:
3077:                    // need to handle deferred values and methods
3078:                    Node.JspAttribute[] attrs = n.getJspAttributes();
3079:                    for (int i = 0; attrs != null && i < attrs.length; i++) {
3080:                        String attrValue = evaluateAttribute(handlerInfo,
3081:                                attrs[i], n, tagHandlerVar);
3082:
3083:                        Mark m = n.getStart();
3084:                        out.printil("// " + m.getFile() + "("
3085:                                + m.getLineNumber() + "," + m.getColumnNumber()
3086:                                + ") " + attrs[i].getTagAttributeInfo());
3087:                        if (attrs[i].isDynamic()) {
3088:                            out.printin(tagHandlerVar);
3089:                            out.print(".");
3090:                            out.print("setDynamicAttribute(");
3091:                            String uri = attrs[i].getURI();
3092:                            if ("".equals(uri) || (uri == null)) {
3093:                                out.print("null");
3094:                            } else {
3095:                                out.print("\"" + attrs[i].getURI() + "\"");
3096:                            }
3097:                            out.print(", \"");
3098:                            out.print(attrs[i].getLocalName());
3099:                            out.print("\", ");
3100:                            out.print(attrValue);
3101:                            out.println(");");
3102:                        } else {
3103:                            out.printin(tagHandlerVar);
3104:                            out.print(".");
3105:                            out.print(handlerInfo.getSetterMethod(
3106:                                    attrs[i].getLocalName()).getName());
3107:                            out.print("(");
3108:                            out.print(attrValue);
3109:                            out.println(");");
3110:                        }
3111:                    }
3112:                }
3113:
3114:                /*
3115:                 * @param c The target class to which to coerce the given string @param
3116:                 * s The string value @param attrName The name of the attribute whose
3117:                 * value is being supplied @param propEditorClass The property editor
3118:                 * for the given attribute @param isNamedAttribute true if the given
3119:                 * attribute is a named attribute (that is, specified using the
3120:                 * jsp:attribute standard action), and false otherwise
3121:                 */
3122:                private String convertString(Class c, String s,
3123:                        String attrName, Class propEditorClass,
3124:                        boolean isNamedAttribute) throws JasperException {
3125:
3126:                    String quoted = s;
3127:                    if (!isNamedAttribute) {
3128:                        quoted = quote(s);
3129:                    }
3130:
3131:                    if (propEditorClass != null) {
3132:                        String className = JspUtil.getCanonicalName(c);
3133:                        return "("
3134:                                + className
3135:                                + ")org.apache.jasper.runtime.JspRuntimeLibrary.getValueFromBeanInfoPropertyEditor("
3136:                                + className + ".class, \"" + attrName + "\", "
3137:                                + quoted + ", "
3138:                                + JspUtil.getCanonicalName(propEditorClass)
3139:                                + ".class)";
3140:                    } else if (c == String.class) {
3141:                        return quoted;
3142:                    } else if (c == boolean.class) {
3143:                        return JspUtil.coerceToPrimitiveBoolean(s,
3144:                                isNamedAttribute);
3145:                    } else if (c == Boolean.class) {
3146:                        return JspUtil.coerceToBoolean(s, isNamedAttribute);
3147:                    } else if (c == byte.class) {
3148:                        return JspUtil.coerceToPrimitiveByte(s,
3149:                                isNamedAttribute);
3150:                    } else if (c == Byte.class) {
3151:                        return JspUtil.coerceToByte(s, isNamedAttribute);
3152:                    } else if (c == char.class) {
3153:                        return JspUtil.coerceToChar(s, isNamedAttribute);
3154:                    } else if (c == Character.class) {
3155:                        return JspUtil.coerceToCharacter(s, isNamedAttribute);
3156:                    } else if (c == double.class) {
3157:                        return JspUtil.coerceToPrimitiveDouble(s,
3158:                                isNamedAttribute);
3159:                    } else if (c == Double.class) {
3160:                        return JspUtil.coerceToDouble(s, isNamedAttribute);
3161:                    } else if (c == float.class) {
3162:                        return JspUtil.coerceToPrimitiveFloat(s,
3163:                                isNamedAttribute);
3164:                    } else if (c == Float.class) {
3165:                        return JspUtil.coerceToFloat(s, isNamedAttribute);
3166:                    } else if (c == int.class) {
3167:                        return JspUtil.coerceToInt(s, isNamedAttribute);
3168:                    } else if (c == Integer.class) {
3169:                        return JspUtil.coerceToInteger(s, isNamedAttribute);
3170:                    } else if (c == short.class) {
3171:                        return JspUtil.coerceToPrimitiveShort(s,
3172:                                isNamedAttribute);
3173:                    } else if (c == Short.class) {
3174:                        return JspUtil.coerceToShort(s, isNamedAttribute);
3175:                    } else if (c == long.class) {
3176:                        return JspUtil.coerceToPrimitiveLong(s,
3177:                                isNamedAttribute);
3178:                    } else if (c == Long.class) {
3179:                        return JspUtil.coerceToLong(s, isNamedAttribute);
3180:                    } else if (c == Object.class) {
3181:                        return "new String(" + quoted + ")";
3182:                    } else {
3183:                        String className = JspUtil.getCanonicalName(c);
3184:                        return "("
3185:                                + className
3186:                                + ")org.apache.jasper.runtime.JspRuntimeLibrary.getValueFromPropertyEditorManager("
3187:                                + className + ".class, \"" + attrName + "\", "
3188:                                + quoted + ")";
3189:                    }
3190:                }
3191:
3192:                /*
3193:                 * Converts the scope string representation, whose possible values are
3194:                 * "page", "request", "session", and "application", to the corresponding
3195:                 * scope constant.
3196:                 */
3197:                private String getScopeConstant(String scope) {
3198:                    String scopeName = "PageContext.PAGE_SCOPE"; // Default to page
3199:
3200:                    if ("request".equals(scope)) {
3201:                        scopeName = "PageContext.REQUEST_SCOPE";
3202:                    } else if ("session".equals(scope)) {
3203:                        scopeName = "PageContext.SESSION_SCOPE";
3204:                    } else if ("application".equals(scope)) {
3205:                        scopeName = "PageContext.APPLICATION_SCOPE";
3206:                    }
3207:
3208:                    return scopeName;
3209:                }
3210:
3211:                /**
3212:                 * Generates anonymous JspFragment inner class which is passed as an
3213:                 * argument to SimpleTag.setJspBody().
3214:                 */
3215:                private void generateJspFragment(Node n, String tagHandlerVar)
3216:                        throws JasperException {
3217:                    // XXX - A possible optimization here would be to check to see
3218:                    // if the only child of the parent node is TemplateText. If so,
3219:                    // we know there won't be any parameters, etc, so we can
3220:                    // generate a low-overhead JspFragment that just echoes its
3221:                    // body. The implementation of this fragment can come from
3222:                    // the org.apache.jasper.runtime package as a support class.
3223:                    FragmentHelperClass.Fragment fragment = fragmentHelperClass
3224:                            .openFragment(n, tagHandlerVar, methodNesting);
3225:                    ServletWriter outSave = out;
3226:                    out = fragment.getGenBuffer().getOut();
3227:                    String tmpParent = parent;
3228:                    parent = "_jspx_parent";
3229:                    boolean isSimpleTagParentSave = isSimpleTagParent;
3230:                    isSimpleTagParent = true;
3231:                    boolean tmpIsFragment = isFragment;
3232:                    isFragment = true;
3233:                    String pushBodyCountVarSave = pushBodyCountVar;
3234:                    if (pushBodyCountVar != null) {
3235:                        // Use a fixed name for push body count, to simplify code gen
3236:                        pushBodyCountVar = "_jspx_push_body_count";
3237:                    }
3238:                    visitBody(n);
3239:                    out = outSave;
3240:                    parent = tmpParent;
3241:                    isSimpleTagParent = isSimpleTagParentSave;
3242:                    isFragment = tmpIsFragment;
3243:                    pushBodyCountVar = pushBodyCountVarSave;
3244:                    fragmentHelperClass.closeFragment(fragment, methodNesting);
3245:                    // XXX - Need to change pageContext to jspContext if
3246:                    // we're not in a place where pageContext is defined (e.g.
3247:                    // in a fragment or in a tag file.
3248:                    out.print("new " + fragmentHelperClass.getClassName()
3249:                            + "( " + fragment.getId()
3250:                            + ", _jspx_page_context, " + tagHandlerVar + ", "
3251:                            + pushBodyCountVar + ")");
3252:                }
3253:
3254:                /**
3255:                 * Generate the code required to obtain the runtime value of the given
3256:                 * named attribute.
3257:                 * 
3258:                 * @return The name of the temporary variable the result is stored in.
3259:                 */
3260:                public String generateNamedAttributeValue(Node.NamedAttribute n)
3261:                        throws JasperException {
3262:
3263:                    String varName = n.getTemporaryVariableName();
3264:
3265:                    // If the only body element for this named attribute node is
3266:                    // template text, we need not generate an extra call to
3267:                    // pushBody and popBody. Maybe we can further optimize
3268:                    // here by getting rid of the temporary variable, but in
3269:                    // reality it looks like javac does this for us.
3270:                    Node.Nodes body = n.getBody();
3271:                    if (body != null) {
3272:                        boolean templateTextOptimization = false;
3273:                        if (body.size() == 1) {
3274:                            Node bodyElement = body.getNode(0);
3275:                            if (bodyElement instanceof  Node.TemplateText) {
3276:                                templateTextOptimization = true;
3277:                                out
3278:                                        .printil("String "
3279:                                                + varName
3280:                                                + " = "
3281:                                                + quote(new String(
3282:                                                        ((Node.TemplateText) bodyElement)
3283:                                                                .getText()))
3284:                                                + ";");
3285:                            }
3286:                        }
3287:
3288:                        // XXX - Another possible optimization would be for
3289:                        // lone EL expressions (no need to pushBody here either).
3290:
3291:                        if (!templateTextOptimization) {
3292:                            out.printil("out = _jspx_page_context.pushBody();");
3293:                            visitBody(n);
3294:                            out.printil("String " + varName + " = "
3295:                                    + "((javax.servlet.jsp.tagext.BodyContent)"
3296:                                    + "out).getString();");
3297:                            out.printil("out = _jspx_page_context.popBody();");
3298:                        }
3299:                    } else {
3300:                        // Empty body must be treated as ""
3301:                        out.printil("String " + varName + " = \"\";");
3302:                    }
3303:
3304:                    return varName;
3305:                }
3306:
3307:                /**
3308:                 * Similar to generateNamedAttributeValue, but create a JspFragment
3309:                 * instead.
3310:                 * 
3311:                 * @param n
3312:                 *            The parent node of the named attribute
3313:                 * @param tagHandlerVar
3314:                 *            The variable the tag handler is stored in, so the fragment
3315:                 *            knows its parent tag.
3316:                 * @return The name of the temporary variable the fragment is stored in.
3317:                 */
3318:                public String generateNamedAttributeJspFragment(
3319:                        Node.NamedAttribute n, String tagHandlerVar)
3320:                        throws JasperException {
3321:                    String varName = n.getTemporaryVariableName();
3322:
3323:                    out.printin("javax.servlet.jsp.tagext.JspFragment "
3324:                            + varName + " = ");
3325:                    generateJspFragment(n, tagHandlerVar);
3326:                    out.println(";");
3327:
3328:                    return varName;
3329:                }
3330:            }
3331:
3332:            private static void generateLocalVariables(ServletWriter out, Node n)
3333:                    throws JasperException {
3334:                Node.ChildInfo ci;
3335:                if (n instanceof  Node.CustomTag) {
3336:                    ci = ((Node.CustomTag) n).getChildInfo();
3337:                } else if (n instanceof  Node.JspBody) {
3338:                    ci = ((Node.JspBody) n).getChildInfo();
3339:                } else if (n instanceof  Node.NamedAttribute) {
3340:                    ci = ((Node.NamedAttribute) n).getChildInfo();
3341:                } else {
3342:                    // Cannot access err since this method is static, but at
3343:                    // least flag an error.
3344:                    throw new JasperException("Unexpected Node Type");
3345:                    // err.getString(
3346:                    // "jsp.error.internal.unexpected_node_type" ) );
3347:                }
3348:
3349:                if (ci.hasUseBean()) {
3350:                    out
3351:                            .printil("HttpSession session = _jspx_page_context.getSession();");
3352:                    out
3353:                            .printil("ServletContext application = _jspx_page_context.getServletContext();");
3354:                }
3355:                if (ci.hasUseBean() || ci.hasIncludeAction()
3356:                        || ci.hasSetProperty() || ci.hasParamAction()) {
3357:                    out
3358:                            .printil("HttpServletRequest request = (HttpServletRequest)_jspx_page_context.getRequest();");
3359:                }
3360:                if (ci.hasIncludeAction()) {
3361:                    out
3362:                            .printil("HttpServletResponse response = (HttpServletResponse)_jspx_page_context.getResponse();");
3363:                }
3364:            }
3365:
3366:            /**
3367:             * Common part of postamble, shared by both servlets and tag files.
3368:             */
3369:            private void genCommonPostamble() {
3370:                // Append any methods that were generated in the buffer.
3371:                for (int i = 0; i < methodsBuffered.size(); i++) {
3372:                    GenBuffer methodBuffer = (GenBuffer) methodsBuffered.get(i);
3373:                    methodBuffer.adjustJavaLines(out.getJavaLine() - 1);
3374:                    out.printMultiLn(methodBuffer.toString());
3375:                }
3376:
3377:                // Append the helper class
3378:                if (fragmentHelperClass.isUsed()) {
3379:                    fragmentHelperClass.generatePostamble();
3380:                    fragmentHelperClass.adjustJavaLines(out.getJavaLine() - 1);
3381:                    out.printMultiLn(fragmentHelperClass.toString());
3382:                }
3383:
3384:                // Append char array declarations
3385:                if (charArrayBuffer != null) {
3386:                    out.printMultiLn(charArrayBuffer.toString());
3387:                }
3388:
3389:                // Close the class definition
3390:                out.popIndent();
3391:                out.printil("}");
3392:            }
3393:
3394:            /**
3395:             * Generates the ending part of the static portion of the servlet.
3396:             */
3397:            private void generatePostamble(Node.Nodes page) {
3398:                out.popIndent();
3399:                out.printil("} catch (Throwable t) {");
3400:                out.pushIndent();
3401:                out.printil("if (!(t instanceof SkipPageException)){");
3402:                out.pushIndent();
3403:                out.printil("out = _jspx_out;");
3404:                out.printil("if (out != null && out.getBufferSize() != 0)");
3405:                out.pushIndent();
3406:                out
3407:                        .printil("try { out.clearBuffer(); } catch (java.io.IOException e) {}");
3408:                out.popIndent();
3409:
3410:                out
3411:                        .printil("if (_jspx_page_context != null) _jspx_page_context.handlePageException(t);");
3412:                out.popIndent();
3413:                out.printil("}");
3414:                out.popIndent();
3415:                out.printil("} finally {");
3416:                out.pushIndent();
3417:
3418:                out
3419:                        .printil("_jspxFactory.releasePageContext(_jspx_page_context);");
3420:
3421:                out.popIndent();
3422:                out.printil("}");
3423:
3424:                // Close the service method
3425:                out.popIndent();
3426:                out.printil("}");
3427:
3428:                // Generated methods, helper classes, etc.
3429:                genCommonPostamble();
3430:            }
3431:
3432:            /**
3433:             * Constructor.
3434:             */
3435:            Generator(ServletWriter out, Compiler compiler) {
3436:                this .out = out;
3437:                methodsBuffered = new ArrayList();
3438:                charArrayBuffer = null;
3439:                err = compiler.getErrorDispatcher();
3440:                ctxt = compiler.getCompilationContext();
3441:                fragmentHelperClass = new FragmentHelperClass(ctxt
3442:                        .getServletClassName()
3443:                        + "Helper");
3444:                pageInfo = compiler.getPageInfo();
3445:
3446:                /*
3447:                 * Temporary hack. If a JSP page uses the "extends" attribute of the
3448:                 * page directive, the _jspInit() method of the generated servlet class
3449:                 * will not be called (it is only called for those generated servlets
3450:                 * that extend HttpJspBase, the default), causing the tag handler pools
3451:                 * not to be initialized and resulting in a NPE. The JSP spec needs to
3452:                 * clarify whether containers can override init() and destroy(). For
3453:                 * now, we just disable tag pooling for pages that use "extends".
3454:                 */
3455:                if (pageInfo.getExtends(false) == null) {
3456:                    isPoolingEnabled = ctxt.getOptions().isPoolingEnabled();
3457:                } else {
3458:                    isPoolingEnabled = false;
3459:                }
3460:                beanInfo = pageInfo.getBeanRepository();
3461:                breakAtLF = ctxt.getOptions().getMappedFile();
3462:                if (isPoolingEnabled) {
3463:                    tagHandlerPoolNames = new Vector();
3464:                }
3465:            }
3466:
3467:            /**
3468:             * The main entry for Generator.
3469:             * 
3470:             * @param out
3471:             *            The servlet output writer
3472:             * @param compiler
3473:             *            The compiler
3474:             * @param page
3475:             *            The input page
3476:             */
3477:            public static void generate(ServletWriter out, Compiler compiler,
3478:                    Node.Nodes page) throws JasperException {
3479:
3480:                Generator gen = new Generator(out, compiler);
3481:
3482:                if (gen.isPoolingEnabled) {
3483:                    gen.compileTagHandlerPoolList(page);
3484:                }
3485:                if (gen.ctxt.isTagFile()) {
3486:                    JasperTagInfo tagInfo = (JasperTagInfo) gen.ctxt
3487:                            .getTagInfo();
3488:                    gen.generateTagHandlerPreamble(tagInfo, page);
3489:
3490:                    if (gen.ctxt.isPrototypeMode()) {
3491:                        return;
3492:                    }
3493:
3494:                    gen.generateXmlProlog(page);
3495:                    gen.fragmentHelperClass.generatePreamble();
3496:                    page.visit(gen.new GenerateVisitor(gen.ctxt.isTagFile(),
3497:                            out, gen.methodsBuffered, gen.fragmentHelperClass,
3498:                            gen.ctxt.getClassLoader(), tagInfo));
3499:                    gen.generateTagHandlerPostamble(tagInfo);
3500:                } else {
3501:                    gen.generatePreamble(page);
3502:                    gen.generateXmlProlog(page);
3503:                    gen.fragmentHelperClass.generatePreamble();
3504:                    page.visit(gen.new GenerateVisitor(gen.ctxt.isTagFile(),
3505:                            out, gen.methodsBuffered, gen.fragmentHelperClass,
3506:                            gen.ctxt.getClassLoader(), null));
3507:                    gen.generatePostamble(page);
3508:                }
3509:            }
3510:
3511:            /*
3512:             * Generates tag handler preamble.
3513:             */
3514:            private void generateTagHandlerPreamble(JasperTagInfo tagInfo,
3515:                    Node.Nodes tag) throws JasperException {
3516:
3517:                // Generate package declaration
3518:                String className = tagInfo.getTagClassName();
3519:                int lastIndex = className.lastIndexOf('.');
3520:                if (lastIndex != -1) {
3521:                    String pkgName = className.substring(0, lastIndex);
3522:                    genPreamblePackage(pkgName);
3523:                    className = className.substring(lastIndex + 1);
3524:                }
3525:
3526:                // Generate imports
3527:                genPreambleImports();
3528:
3529:                // Generate class declaration
3530:                out.printin("public final class ");
3531:                out.println(className);
3532:                out
3533:                        .printil("    extends javax.servlet.jsp.tagext.SimpleTagSupport");
3534:                out
3535:                        .printin("    implements org.apache.jasper.runtime.JspSourceDependent");
3536:                if (tagInfo.hasDynamicAttributes()) {
3537:                    out.println(",");
3538:                    out
3539:                            .printin("               javax.servlet.jsp.tagext.DynamicAttributes");
3540:                }
3541:                out.println(" {");
3542:                out.println();
3543:                out.pushIndent();
3544:
3545:                /*
3546:                 * Class body begins here
3547:                 */
3548:                generateDeclarations(tag);
3549:
3550:                // Static initializations here
3551:                genPreambleStaticInitializers();
3552:
3553:                out.printil("private JspContext jspContext;");
3554:
3555:                // Declare writer used for storing result of fragment/body invocation
3556:                // if 'varReader' or 'var' attribute is specified
3557:                out.printil("private java.io.Writer _jspx_sout;");
3558:
3559:                // Class variable declarations
3560:                genPreambleClassVariableDeclarations(tagInfo.getTagName());
3561:
3562:                generateSetJspContext(tagInfo);
3563:
3564:                // Tag-handler specific declarations
3565:                generateTagHandlerAttributes(tagInfo);
3566:                if (tagInfo.hasDynamicAttributes())
3567:                    generateSetDynamicAttribute();
3568:
3569:                // Methods here
3570:                genPreambleMethods();
3571:
3572:                // Now the doTag() method
3573:                out
3574:                        .printil("public void doTag() throws JspException, java.io.IOException {");
3575:
3576:                if (ctxt.isPrototypeMode()) {
3577:                    out.printil("}");
3578:                    out.popIndent();
3579:                    out.printil("}");
3580:                    return;
3581:                }
3582:
3583:                out.pushIndent();
3584:
3585:                /*
3586:                 * According to the spec, 'pageContext' must not be made available as an
3587:                 * implicit object in tag files. Declare _jspx_page_context, so we can
3588:                 * share the code generator with JSPs.
3589:                 */
3590:                out
3591:                        .printil("PageContext _jspx_page_context = (PageContext)jspContext;");
3592:
3593:                // Declare implicit objects.
3594:                out
3595:                        .printil("HttpServletRequest request = "
3596:                                + "(HttpServletRequest) _jspx_page_context.getRequest();");
3597:                out
3598:                        .printil("HttpServletResponse response = "
3599:                                + "(HttpServletResponse) _jspx_page_context.getResponse();");
3600:                out
3601:                        .printil("HttpSession session = _jspx_page_context.getSession();");
3602:                out
3603:                        .printil("ServletContext application = _jspx_page_context.getServletContext();");
3604:                out
3605:                        .printil("ServletConfig config = _jspx_page_context.getServletConfig();");
3606:                out.printil("JspWriter out = jspContext.getOut();");
3607:                out.printil("_jspInit(config);");
3608:
3609:                // set current JspContext on ELContext
3610:                out
3611:                        .printil("jspContext.getELContext().putContext(JspContext.class,jspContext);");
3612:
3613:                generatePageScopedVariables(tagInfo);
3614:
3615:                declareTemporaryScriptingVars(tag);
3616:                out.println();
3617:
3618:                out.printil("try {");
3619:                out.pushIndent();
3620:            }
3621:
3622:            private void generateTagHandlerPostamble(TagInfo tagInfo) {
3623:                out.popIndent();
3624:
3625:                // Have to catch Throwable because a classic tag handler
3626:                // helper method is declared to throw Throwable.
3627:                out.printil("} catch( Throwable t ) {");
3628:                out.pushIndent();
3629:                out.printil("if( t instanceof SkipPageException )");
3630:                out.printil("    throw (SkipPageException) t;");
3631:                out.printil("if( t instanceof java.io.IOException )");
3632:                out.printil("    throw (java.io.IOException) t;");
3633:                out.printil("if( t instanceof IllegalStateException )");
3634:                out.printil("    throw (IllegalStateException) t;");
3635:                out.printil("if( t instanceof JspException )");
3636:                out.printil("    throw (JspException) t;");
3637:                out.printil("throw new JspException(t);");
3638:                out.popIndent();
3639:                out.printil("} finally {");
3640:                out.pushIndent();
3641:
3642:                // handle restoring VariableMapper
3643:                TagAttributeInfo[] attrInfos = tagInfo.getAttributes();
3644:                for (int i = 0; i < attrInfos.length; i++) {
3645:                    if (attrInfos[i].isDeferredMethod()
3646:                            || attrInfos[i].isDeferredValue()) {
3647:                        out.printin("_el_variablemapper.setVariable(");
3648:                        out.print(quote(attrInfos[i].getName()));
3649:                        out.print(",_el_ve");
3650:                        out.print(i);
3651:                        out.println(");");
3652:                    }
3653:                }
3654:
3655:                // restore nested JspContext on ELContext
3656:                out
3657:                        .printil("jspContext.getELContext().putContext(JspContext.class,super.getJspContext());");
3658:
3659:                out
3660:                        .printil("((org.apache.jasper.runtime.JspContextWrapper) jspContext).syncEndTagFile();");
3661:                if (isPoolingEnabled && !tagHandlerPoolNames.isEmpty()) {
3662:                    out.printil("_jspDestroy();");
3663:                }
3664:                out.popIndent();
3665:                out.printil("}");
3666:
3667:                // Close the doTag method
3668:                out.popIndent();
3669:                out.printil("}");
3670:
3671:                // Generated methods, helper classes, etc.
3672:                genCommonPostamble();
3673:            }
3674:
3675:            /**
3676:             * Generates declarations for tag handler attributes, and defines the getter
3677:             * and setter methods for each.
3678:             */
3679:            private void generateTagHandlerAttributes(TagInfo tagInfo)
3680:                    throws JasperException {
3681:
3682:                if (tagInfo.hasDynamicAttributes()) {
3683:                    out
3684:                            .printil("private java.util.HashMap _jspx_dynamic_attrs = new java.util.HashMap();");
3685:                }
3686:
3687:                // Declare attributes
3688:                TagAttributeInfo[] attrInfos = tagInfo.getAttributes();
3689:                for (int i = 0; i < attrInfos.length; i++) {
3690:                    out.printin("private ");
3691:                    if (attrInfos[i].isFragment()) {
3692:                        out.print("javax.servlet.jsp.tagext.JspFragment ");
3693:                    } else {
3694:                        out.print(JspUtil.toJavaSourceType(attrInfos[i]
3695:                                .getTypeName()));
3696:                        out.print(" ");
3697:                    }
3698:                    out.print(attrInfos[i].getName());
3699:                    out.println(";");
3700:                }
3701:                out.println();
3702:
3703:                // Define attribute getter and setter methods
3704:                if (attrInfos != null) {
3705:                    for (int i = 0; i < attrInfos.length; i++) {
3706:                        // getter method
3707:                        out.printin("public ");
3708:                        if (attrInfos[i].isFragment()) {
3709:                            out.print("javax.servlet.jsp.tagext.JspFragment ");
3710:                        } else {
3711:                            out.print(JspUtil.toJavaSourceType(attrInfos[i]
3712:                                    .getTypeName()));
3713:                            out.print(" ");
3714:                        }
3715:                        out.print(toGetterMethod(attrInfos[i].getName()));
3716:                        out.println(" {");
3717:                        out.pushIndent();
3718:                        out.printin("return this.");
3719:                        out.print(attrInfos[i].getName());
3720:                        out.println(";");
3721:                        out.popIndent();
3722:                        out.printil("}");
3723:                        out.println();
3724:
3725:                        // setter method
3726:                        out.printin("public void ");
3727:                        out.print(toSetterMethodName(attrInfos[i].getName()));
3728:                        if (attrInfos[i].isFragment()) {
3729:                            out.print("(javax.servlet.jsp.tagext.JspFragment ");
3730:                        } else {
3731:                            out.print("(");
3732:                            out.print(JspUtil.toJavaSourceType(attrInfos[i]
3733:                                    .getTypeName()));
3734:                            out.print(" ");
3735:                        }
3736:                        out.print(attrInfos[i].getName());
3737:                        out.println(") {");
3738:                        out.pushIndent();
3739:                        out.printin("this.");
3740:                        out.print(attrInfos[i].getName());
3741:                        out.print(" = ");
3742:                        out.print(attrInfos[i].getName());
3743:                        out.println(";");
3744:                        if (ctxt.isTagFile()) {
3745:                            // Tag files should also set jspContext attributes
3746:                            out.printin("jspContext.setAttribute(\"");
3747:                            out.print(attrInfos[i].getName());
3748:                            out.print("\", ");
3749:                            out.print(attrInfos[i].getName());
3750:                            out.println(");");
3751:                        }
3752:                        out.popIndent();
3753:                        out.printil("}");
3754:                        out.println();
3755:                    }
3756:                }
3757:            }
3758:
3759:            /*
3760:             * Generate setter for JspContext so we can create a wrapper and store both
3761:             * the original and the wrapper. We need the wrapper to mask the page
3762:             * context from the tag file and simulate a fresh page context. We need the
3763:             * original to do things like sync AT_BEGIN and AT_END scripting variables.
3764:             */
3765:            private void generateSetJspContext(TagInfo tagInfo) {
3766:
3767:                boolean nestedSeen = false;
3768:                boolean atBeginSeen = false;
3769:                boolean atEndSeen = false;
3770:
3771:                // Determine if there are any aliases
3772:                boolean aliasSeen = false;
3773:                TagVariableInfo[] tagVars = tagInfo.getTagVariableInfos();
3774:                for (int i = 0; i < tagVars.length; i++) {
3775:                    if (tagVars[i].getNameFromAttribute() != null
3776:                            && tagVars[i].getNameGiven() != null) {
3777:                        aliasSeen = true;
3778:                        break;
3779:                    }
3780:                }
3781:
3782:                if (aliasSeen) {
3783:                    out
3784:                            .printil("public void setJspContext(JspContext ctx, java.util.Map aliasMap) {");
3785:                } else {
3786:                    out.printil("public void setJspContext(JspContext ctx) {");
3787:                }
3788:                out.pushIndent();
3789:                out.printil("super.setJspContext(ctx);");
3790:                out.printil("java.util.ArrayList _jspx_nested = null;");
3791:                out.printil("java.util.ArrayList _jspx_at_begin = null;");
3792:                out.printil("java.util.ArrayList _jspx_at_end = null;");
3793:
3794:                for (int i = 0; i < tagVars.length; i++) {
3795:
3796:                    switch (tagVars[i].getScope()) {
3797:                    case VariableInfo.NESTED:
3798:                        if (!nestedSeen) {
3799:                            out
3800:                                    .printil("_jspx_nested = new java.util.ArrayList();");
3801:                            nestedSeen = true;
3802:                        }
3803:                        out.printin("_jspx_nested.add(");
3804:                        break;
3805:
3806:                    case VariableInfo.AT_BEGIN:
3807:                        if (!atBeginSeen) {
3808:                            out
3809:                                    .printil("_jspx_at_begin = new java.util.ArrayList();");
3810:                            atBeginSeen = true;
3811:                        }
3812:                        out.printin("_jspx_at_begin.add(");
3813:                        break;
3814:
3815:                    case VariableInfo.AT_END:
3816:                        if (!atEndSeen) {
3817:                            out
3818:                                    .printil("_jspx_at_end = new java.util.ArrayList();");
3819:                            atEndSeen = true;
3820:                        }
3821:                        out.printin("_jspx_at_end.add(");
3822:                        break;
3823:                    } // switch
3824:
3825:                    out.print(quote(tagVars[i].getNameGiven()));
3826:                    out.println(");");
3827:                }
3828:                if (aliasSeen) {
3829:                    out
3830:                            .printil("this.jspContext = new org.apache.jasper.runtime.JspContextWrapper(ctx, _jspx_nested, _jspx_at_begin, _jspx_at_end, aliasMap);");
3831:                } else {
3832:                    out
3833:                            .printil("this.jspContext = new org.apache.jasper.runtime.JspContextWrapper(ctx, _jspx_nested, _jspx_at_begin, _jspx_at_end, null);");
3834:                }
3835:                out.popIndent();
3836:                out.printil("}");
3837:                out.println();
3838:                out.printil("public JspContext getJspContext() {");
3839:                out.pushIndent();
3840:                out.printil("return this.jspContext;");
3841:                out.popIndent();
3842:                out.printil("}");
3843:            }
3844:
3845:            /*
3846:             * Generates implementation of
3847:             * javax.servlet.jsp.tagext.DynamicAttributes.setDynamicAttribute() method,
3848:             * which saves each dynamic attribute that is passed in so that a scoped
3849:             * variable can later be created for it.
3850:             */
3851:            public void generateSetDynamicAttribute() {
3852:                out
3853:                        .printil("public void setDynamicAttribute(String uri, String localName, Object value) throws JspException {");
3854:                out.pushIndent();
3855:                /*
3856:                 * According to the spec, only dynamic attributes with no uri are to be
3857:                 * present in the Map; all other dynamic attributes are ignored.
3858:                 */
3859:                out.printil("if (uri == null)");
3860:                out.pushIndent();
3861:                out.printil("_jspx_dynamic_attrs.put(localName, value);");
3862:                out.popIndent();
3863:                out.popIndent();
3864:                out.printil("}");
3865:            }
3866:
3867:            /*
3868:             * Creates a page-scoped variable for each declared tag attribute. Also, if
3869:             * the tag accepts dynamic attributes, a page-scoped variable is made
3870:             * available for each dynamic attribute that was passed in.
3871:             */
3872:            private void generatePageScopedVariables(JasperTagInfo tagInfo) {
3873:
3874:                // "normal" attributes
3875:                TagAttributeInfo[] attrInfos = tagInfo.getAttributes();
3876:                boolean variableMapperVar = false;
3877:                for (int i = 0; i < attrInfos.length; i++) {
3878:                    String attrName = attrInfos[i].getName();
3879:
3880:                    // handle assigning deferred vars to VariableMapper, storing
3881:                    // previous values under '_el_ve[i]' for later re-assignment
3882:                    if (attrInfos[i].isDeferredValue()
3883:                            || attrInfos[i].isDeferredMethod()) {
3884:
3885:                        // we need to scope the modified VariableMapper for consistency and performance
3886:                        if (!variableMapperVar) {
3887:                            out
3888:                                    .printil("javax.el.VariableMapper _el_variablemapper = jspContext.getELContext().getVariableMapper();");
3889:                            variableMapperVar = true;
3890:                        }
3891:
3892:                        out.printin("javax.el.ValueExpression _el_ve");
3893:                        out.print(i);
3894:                        out.print(" = _el_variablemapper.setVariable(");
3895:                        out.print(quote(attrName));
3896:                        out.print(',');
3897:                        if (attrInfos[i].isDeferredMethod()) {
3898:                            out.print(VAR_EXPRESSIONFACTORY);
3899:                            out.print(".createValueExpression(");
3900:                            out.print(toGetterMethod(attrName));
3901:                            out.print(",javax.el.MethodExpression.class)");
3902:                        } else {
3903:                            out.print(toGetterMethod(attrName));
3904:                        }
3905:                        out.println(");");
3906:                    } else {
3907:                        out.printil("if( " + toGetterMethod(attrName)
3908:                                + " != null ) ");
3909:                        out.pushIndent();
3910:                        out.printin("_jspx_page_context.setAttribute(");
3911:                        out.print(quote(attrName));
3912:                        out.print(", ");
3913:                        out.print(toGetterMethod(attrName));
3914:                        out.println(");");
3915:                        out.popIndent();
3916:                    }
3917:                }
3918:
3919:                // Expose the Map containing dynamic attributes as a page-scoped var
3920:                if (tagInfo.hasDynamicAttributes()) {
3921:                    out.printin("_jspx_page_context.setAttribute(\"");
3922:                    out.print(tagInfo.getDynamicAttributesMapName());
3923:                    out.print("\", _jspx_dynamic_attrs);");
3924:                }
3925:            }
3926:
3927:            /*
3928:             * Generates the getter method for the given attribute name.
3929:             */
3930:            private String toGetterMethod(String attrName) {
3931:                char[] attrChars = attrName.toCharArray();
3932:                attrChars[0] = Character.toUpperCase(attrChars[0]);
3933:                return "get" + new String(attrChars) + "()";
3934:            }
3935:
3936:            /*
3937:             * Generates the setter method name for the given attribute name.
3938:             */
3939:            private String toSetterMethodName(String attrName) {
3940:                char[] attrChars = attrName.toCharArray();
3941:                attrChars[0] = Character.toUpperCase(attrChars[0]);
3942:                return "set" + new String(attrChars);
3943:            }
3944:
3945:            /**
3946:             * Class storing the result of introspecting a custom tag handler.
3947:             */
3948:            private static class TagHandlerInfo {
3949:
3950:                private Hashtable methodMaps;
3951:
3952:                private Hashtable propertyEditorMaps;
3953:
3954:                private Class tagHandlerClass;
3955:
3956:                /**
3957:                 * Constructor.
3958:                 * 
3959:                 * @param n
3960:                 *            The custom tag whose tag handler class is to be
3961:                 *            introspected
3962:                 * @param tagHandlerClass
3963:                 *            Tag handler class
3964:                 * @param err
3965:                 *            Error dispatcher
3966:                 */
3967:                TagHandlerInfo(Node n, Class tagHandlerClass,
3968:                        ErrorDispatcher err) throws JasperException {
3969:                    this .tagHandlerClass = tagHandlerClass;
3970:                    this .methodMaps = new Hashtable();
3971:                    this .propertyEditorMaps = new Hashtable();
3972:
3973:                    try {
3974:                        BeanInfo tagClassInfo = Introspector
3975:                                .getBeanInfo(tagHandlerClass);
3976:                        PropertyDescriptor[] pd = tagClassInfo
3977:                                .getPropertyDescriptors();
3978:                        for (int i = 0; i < pd.length; i++) {
3979:                            /*
3980:                             * FIXME: should probably be checking for things like
3981:                             * pageContext, bodyContent, and parent here -akv
3982:                             */
3983:                            if (pd[i].getWriteMethod() != null) {
3984:                                methodMaps.put(pd[i].getName(), pd[i]
3985:                                        .getWriteMethod());
3986:                            }
3987:                            if (pd[i].getPropertyEditorClass() != null)
3988:                                propertyEditorMaps.put(pd[i].getName(), pd[i]
3989:                                        .getPropertyEditorClass());
3990:                        }
3991:                    } catch (IntrospectionException ie) {
3992:                        err.jspError(n, "jsp.error.introspect.taghandler",
3993:                                tagHandlerClass.getName(), ie);
3994:                    }
3995:                }
3996:
3997:                /**
3998:                 * XXX
3999:                 */
4000:                public Method getSetterMethod(String attrName) {
4001:                    return (Method) methodMaps.get(attrName);
4002:                }
4003:
4004:                /**
4005:                 * XXX
4006:                 */
4007:                public Class getPropertyEditorClass(String attrName) {
4008:                    return (Class) propertyEditorMaps.get(attrName);
4009:                }
4010:
4011:                /**
4012:                 * XXX
4013:                 */
4014:                public Class getTagHandlerClass() {
4015:                    return tagHandlerClass;
4016:                }
4017:            }
4018:
4019:            /**
4020:             * A class for generating codes to a buffer. Included here are some support
4021:             * for tracking source to Java lines mapping.
4022:             */
4023:            private static class GenBuffer {
4024:
4025:                /*
4026:                 * For a CustomTag, the codes that are generated at the beginning of the
4027:                 * tag may not be in the same buffer as those for the body of the tag.
4028:                 * Two fields are used here to keep this straight. For codes that do not
4029:                 * corresponds to any JSP lines, they should be null.
4030:                 */
4031:                private Node node;
4032:
4033:                private Node.Nodes body;
4034:
4035:                private java.io.CharArrayWriter charWriter;
4036:
4037:                protected ServletWriter out;
4038:
4039:                GenBuffer() {
4040:                    this (null, null);
4041:                }
4042:
4043:                GenBuffer(Node n, Node.Nodes b) {
4044:                    node = n;
4045:                    body = b;
4046:                    if (body != null) {
4047:                        body.setGeneratedInBuffer(true);
4048:                    }
4049:                    charWriter = new java.io.CharArrayWriter();
4050:                    out = new ServletWriter(new java.io.PrintWriter(charWriter));
4051:                }
4052:
4053:                public ServletWriter getOut() {
4054:                    return out;
4055:                }
4056:
4057:                public String toString() {
4058:                    return charWriter.toString();
4059:                }
4060:
4061:                /**
4062:                 * Adjust the Java Lines. This is necessary because the Java lines
4063:                 * stored with the nodes are relative the beginning of this buffer and
4064:                 * need to be adjusted when this buffer is inserted into the source.
4065:                 */
4066:                public void adjustJavaLines(final int offset) {
4067:
4068:                    if (node != null) {
4069:                        adjustJavaLine(node, offset);
4070:                    }
4071:
4072:                    if (body != null) {
4073:                        try {
4074:                            body.visit(new Node.Visitor() {
4075:
4076:                                public void doVisit(Node n) {
4077:                                    adjustJavaLine(n, offset);
4078:                                }
4079:
4080:                                public void visit(Node.CustomTag n)
4081:                                        throws JasperException {
4082:                                    Node.Nodes b = n.getBody();
4083:                                    if (b != null && !b.isGeneratedInBuffer()) {
4084:                                        // Don't adjust lines for the nested tags that
4085:                                        // are also generated in buffers, because the
4086:                                        // adjustments will be done elsewhere.
4087:                                        b.visit(this );
4088:                                    }
4089:                                }
4090:                            });
4091:                        } catch (JasperException ex) {
4092:                        }
4093:                    }
4094:                }
4095:
4096:                private static void adjustJavaLine(Node n, int offset) {
4097:                    if (n.getBeginJavaLine() > 0) {
4098:                        n.setBeginJavaLine(n.getBeginJavaLine() + offset);
4099:                        n.setEndJavaLine(n.getEndJavaLine() + offset);
4100:                    }
4101:                }
4102:            }
4103:
4104:            /**
4105:             * Keeps track of the generated Fragment Helper Class
4106:             */
4107:            private static class FragmentHelperClass {
4108:
4109:                private static class Fragment {
4110:                    private GenBuffer genBuffer;
4111:
4112:                    private int id;
4113:
4114:                    public Fragment(int id, Node node) {
4115:                        this .id = id;
4116:                        genBuffer = new GenBuffer(null, node.getBody());
4117:                    }
4118:
4119:                    public GenBuffer getGenBuffer() {
4120:                        return this .genBuffer;
4121:                    }
4122:
4123:                    public int getId() {
4124:                        return this .id;
4125:                    }
4126:                }
4127:
4128:                // True if the helper class should be generated.
4129:                private boolean used = false;
4130:
4131:                private ArrayList fragments = new ArrayList();
4132:
4133:                private String className;
4134:
4135:                // Buffer for entire helper class
4136:                private GenBuffer classBuffer = new GenBuffer();
4137:
4138:                public FragmentHelperClass(String className) {
4139:                    this .className = className;
4140:                }
4141:
4142:                public String getClassName() {
4143:                    return this .className;
4144:                }
4145:
4146:                public boolean isUsed() {
4147:                    return this .used;
4148:                }
4149:
4150:                public void generatePreamble() {
4151:                    ServletWriter out = this .classBuffer.getOut();
4152:                    out.println();
4153:                    out.pushIndent();
4154:                    // Note: cannot be static, as we need to reference things like
4155:                    // _jspx_meth_*
4156:                    out.printil("private class " + className);
4157:                    out.printil("    extends "
4158:                            + "org.apache.jasper.runtime.JspFragmentHelper");
4159:                    out.printil("{");
4160:                    out.pushIndent();
4161:                    out
4162:                            .printil("private javax.servlet.jsp.tagext.JspTag _jspx_parent;");
4163:                    out.printil("private int[] _jspx_push_body_count;");
4164:                    out.println();
4165:                    out.printil("public " + className
4166:                            + "( int discriminator, JspContext jspContext, "
4167:                            + "javax.servlet.jsp.tagext.JspTag _jspx_parent, "
4168:                            + "int[] _jspx_push_body_count ) {");
4169:                    out.pushIndent();
4170:                    out
4171:                            .printil("super( discriminator, jspContext, _jspx_parent );");
4172:                    out.printil("this._jspx_parent = _jspx_parent;");
4173:                    out
4174:                            .printil("this._jspx_push_body_count = _jspx_push_body_count;");
4175:                    out.popIndent();
4176:                    out.printil("}");
4177:                }
4178:
4179:                public Fragment openFragment(Node parent, String tagHandlerVar,
4180:                        int methodNesting) throws JasperException {
4181:                    Fragment result = new Fragment(fragments.size(), parent);
4182:                    fragments.add(result);
4183:                    this .used = true;
4184:                    parent.setInnerClassName(className);
4185:
4186:                    ServletWriter out = result.getGenBuffer().getOut();
4187:                    out.pushIndent();
4188:                    out.pushIndent();
4189:                    // XXX - Returns boolean because if a tag is invoked from
4190:                    // within this fragment, the Generator sometimes might
4191:                    // generate code like "return true". This is ignored for now,
4192:                    // meaning only the fragment is skipped. The JSR-152
4193:                    // expert group is currently discussing what to do in this case.
4194:                    // See comment in closeFragment()
4195:                    if (methodNesting > 0) {
4196:                        out.printin("public boolean invoke");
4197:                    } else {
4198:                        out.printin("public void invoke");
4199:                    }
4200:                    out.println(result.getId() + "( " + "JspWriter out ) ");
4201:                    out.pushIndent();
4202:                    // Note: Throwable required because methods like _jspx_meth_*
4203:                    // throw Throwable.
4204:                    out.printil("throws Throwable");
4205:                    out.popIndent();
4206:                    out.printil("{");
4207:                    out.pushIndent();
4208:                    generateLocalVariables(out, parent);
4209:
4210:                    return result;
4211:                }
4212:
4213:                public void closeFragment(Fragment fragment, int methodNesting) {
4214:                    ServletWriter out = fragment.getGenBuffer().getOut();
4215:                    // XXX - See comment in openFragment()
4216:                    if (methodNesting > 0) {
4217:                        out.printil("return false;");
4218:                    } else {
4219:                        out.printil("return;");
4220:                    }
4221:                    out.popIndent();
4222:                    out.printil("}");
4223:                }
4224:
4225:                public void generatePostamble() {
4226:                    ServletWriter out = this .classBuffer.getOut();
4227:                    // Generate all fragment methods:
4228:                    for (int i = 0; i < fragments.size(); i++) {
4229:                        Fragment fragment = (Fragment) fragments.get(i);
4230:                        fragment.getGenBuffer().adjustJavaLines(
4231:                                out.getJavaLine() - 1);
4232:                        out.printMultiLn(fragment.getGenBuffer().toString());
4233:                    }
4234:
4235:                    // Generate postamble:
4236:                    out.printil("public void invoke( java.io.Writer writer )");
4237:                    out.pushIndent();
4238:                    out.printil("throws JspException");
4239:                    out.popIndent();
4240:                    out.printil("{");
4241:                    out.pushIndent();
4242:                    out.printil("JspWriter out = null;");
4243:                    out.printil("if( writer != null ) {");
4244:                    out.pushIndent();
4245:                    out.printil("out = this.jspContext.pushBody(writer);");
4246:                    out.popIndent();
4247:                    out.printil("} else {");
4248:                    out.pushIndent();
4249:                    out.printil("out = this.jspContext.getOut();");
4250:                    out.popIndent();
4251:                    out.printil("}");
4252:                    out.printil("try {");
4253:                    out.pushIndent();
4254:                    out
4255:                            .printil("this.jspContext.getELContext().putContext(JspContext.class,this.jspContext);");
4256:                    out.printil("switch( this.discriminator ) {");
4257:                    out.pushIndent();
4258:                    for (int i = 0; i < fragments.size(); i++) {
4259:                        out.printil("case " + i + ":");
4260:                        out.pushIndent();
4261:                        out.printil("invoke" + i + "( out );");
4262:                        out.printil("break;");
4263:                        out.popIndent();
4264:                    }
4265:                    out.popIndent();
4266:                    out.printil("}"); // switch
4267:                    out.popIndent();
4268:                    out.printil("}"); // try
4269:                    out.printil("catch( Throwable e ) {");
4270:                    out.pushIndent();
4271:                    out.printil("if (e instanceof SkipPageException)");
4272:                    out.printil("    throw (SkipPageException) e;");
4273:                    out.printil("throw new JspException( e );");
4274:                    out.popIndent();
4275:                    out.printil("}"); // catch
4276:                    out.printil("finally {");
4277:                    out.pushIndent();
4278:
4279:                    out.printil("if( writer != null ) {");
4280:                    out.pushIndent();
4281:                    out.printil("this.jspContext.popBody();");
4282:                    out.popIndent();
4283:                    out.printil("}");
4284:
4285:                    out.popIndent();
4286:                    out.printil("}"); // finally
4287:                    out.popIndent();
4288:                    out.printil("}"); // invoke method
4289:                    out.popIndent();
4290:                    out.printil("}"); // helper class
4291:                    out.popIndent();
4292:                }
4293:
4294:                public String toString() {
4295:                    return classBuffer.toString();
4296:                }
4297:
4298:                public void adjustJavaLines(int offset) {
4299:                    for (int i = 0; i < fragments.size(); i++) {
4300:                        Fragment fragment = (Fragment) fragments.get(i);
4301:                        fragment.getGenBuffer().adjustJavaLines(offset);
4302:                    }
4303:                }
4304:            }
4305:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.