Source Code Cross Referenced for Validator.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.lang.reflect.Method;
0021:        import java.util.ArrayList;
0022:        import java.util.HashMap;
0023:        import java.util.Hashtable;
0024:        import java.util.Iterator;
0025:
0026:        import javax.el.ELException;
0027:        import javax.el.ExpressionFactory;
0028:        import javax.el.FunctionMapper;
0029:        import javax.servlet.jsp.tagext.FunctionInfo;
0030:        import javax.servlet.jsp.tagext.JspFragment;
0031:        import javax.servlet.jsp.tagext.PageData;
0032:        import javax.servlet.jsp.tagext.TagAttributeInfo;
0033:        import javax.servlet.jsp.tagext.TagData;
0034:        import javax.servlet.jsp.tagext.TagExtraInfo;
0035:        import javax.servlet.jsp.tagext.TagInfo;
0036:        import javax.servlet.jsp.tagext.TagLibraryInfo;
0037:        import javax.servlet.jsp.tagext.ValidationMessage;
0038:
0039:        import org.apache.el.lang.ELSupport;
0040:        import org.apache.jasper.Constants;
0041:        import org.apache.jasper.JasperException;
0042:        import org.apache.jasper.el.ELContextImpl;
0043:        import org.xml.sax.Attributes;
0044:
0045:        /**
0046:         * Performs validation on the page elements. Attributes are checked for
0047:         * mandatory presence, entry value validity, and consistency. As a side effect,
0048:         * some page global value (such as those from page direcitves) are stored, for
0049:         * later use.
0050:         * 
0051:         * @author Kin-man Chung
0052:         * @author Jan Luehe
0053:         * @author Shawn Bayern
0054:         * @author Mark Roth
0055:         */
0056:        class Validator {
0057:
0058:            /**
0059:             * A visitor to validate and extract page directive info
0060:             */
0061:            static class DirectiveVisitor extends Node.Visitor {
0062:
0063:                private PageInfo pageInfo;
0064:
0065:                private ErrorDispatcher err;
0066:
0067:                private static final JspUtil.ValidAttribute[] pageDirectiveAttrs = {
0068:                        new JspUtil.ValidAttribute("language"),
0069:                        new JspUtil.ValidAttribute("extends"),
0070:                        new JspUtil.ValidAttribute("import"),
0071:                        new JspUtil.ValidAttribute("session"),
0072:                        new JspUtil.ValidAttribute("buffer"),
0073:                        new JspUtil.ValidAttribute("autoFlush"),
0074:                        new JspUtil.ValidAttribute("isThreadSafe"),
0075:                        new JspUtil.ValidAttribute("info"),
0076:                        new JspUtil.ValidAttribute("errorPage"),
0077:                        new JspUtil.ValidAttribute("isErrorPage"),
0078:                        new JspUtil.ValidAttribute("contentType"),
0079:                        new JspUtil.ValidAttribute("pageEncoding"),
0080:                        new JspUtil.ValidAttribute("isELIgnored"),
0081:                        new JspUtil.ValidAttribute(
0082:                                "deferredSyntaxAllowedAsLiteral"),
0083:                        new JspUtil.ValidAttribute("trimDirectiveWhitespaces") };
0084:
0085:                private boolean pageEncodingSeen = false;
0086:
0087:                /*
0088:                 * Constructor
0089:                 */
0090:                DirectiveVisitor(Compiler compiler) throws JasperException {
0091:                    this .pageInfo = compiler.getPageInfo();
0092:                    this .err = compiler.getErrorDispatcher();
0093:                }
0094:
0095:                public void visit(Node.IncludeDirective n)
0096:                        throws JasperException {
0097:                    // Since pageDirectiveSeen flag only applies to the Current page
0098:                    // save it here and restore it after the file is included.
0099:                    boolean pageEncodingSeenSave = pageEncodingSeen;
0100:                    pageEncodingSeen = false;
0101:                    visitBody(n);
0102:                    pageEncodingSeen = pageEncodingSeenSave;
0103:                }
0104:
0105:                public void visit(Node.PageDirective n) throws JasperException {
0106:
0107:                    JspUtil.checkAttributes("Page directive", n,
0108:                            pageDirectiveAttrs, err);
0109:
0110:                    // JSP.2.10.1
0111:                    Attributes attrs = n.getAttributes();
0112:                    for (int i = 0; attrs != null && i < attrs.getLength(); i++) {
0113:                        String attr = attrs.getQName(i);
0114:                        String value = attrs.getValue(i);
0115:
0116:                        if ("language".equals(attr)) {
0117:                            if (pageInfo.getLanguage(false) == null) {
0118:                                pageInfo.setLanguage(value, n, err, true);
0119:                            } else if (!pageInfo.getLanguage(false).equals(
0120:                                    value)) {
0121:                                err.jspError(n,
0122:                                        "jsp.error.page.conflict.language",
0123:                                        pageInfo.getLanguage(false), value);
0124:                            }
0125:                        } else if ("extends".equals(attr)) {
0126:                            if (pageInfo.getExtends(false) == null) {
0127:                                pageInfo.setExtends(value, n);
0128:                            } else if (!pageInfo.getExtends(false)
0129:                                    .equals(value)) {
0130:                                err.jspError(n,
0131:                                        "jsp.error.page.conflict.extends",
0132:                                        pageInfo.getExtends(false), value);
0133:                            }
0134:                        } else if ("contentType".equals(attr)) {
0135:                            if (pageInfo.getContentType() == null) {
0136:                                pageInfo.setContentType(value);
0137:                            } else if (!pageInfo.getContentType().equals(value)) {
0138:                                err.jspError(n,
0139:                                        "jsp.error.page.conflict.contenttype",
0140:                                        pageInfo.getContentType(), value);
0141:                            }
0142:                        } else if ("session".equals(attr)) {
0143:                            if (pageInfo.getSession() == null) {
0144:                                pageInfo.setSession(value, n, err);
0145:                            } else if (!pageInfo.getSession().equals(value)) {
0146:                                err.jspError(n,
0147:                                        "jsp.error.page.conflict.session",
0148:                                        pageInfo.getSession(), value);
0149:                            }
0150:                        } else if ("buffer".equals(attr)) {
0151:                            if (pageInfo.getBufferValue() == null) {
0152:                                pageInfo.setBufferValue(value, n, err);
0153:                            } else if (!pageInfo.getBufferValue().equals(value)) {
0154:                                err.jspError(n,
0155:                                        "jsp.error.page.conflict.buffer",
0156:                                        pageInfo.getBufferValue(), value);
0157:                            }
0158:                        } else if ("autoFlush".equals(attr)) {
0159:                            if (pageInfo.getAutoFlush() == null) {
0160:                                pageInfo.setAutoFlush(value, n, err);
0161:                            } else if (!pageInfo.getAutoFlush().equals(value)) {
0162:                                err.jspError(n,
0163:                                        "jsp.error.page.conflict.autoflush",
0164:                                        pageInfo.getAutoFlush(), value);
0165:                            }
0166:                        } else if ("isThreadSafe".equals(attr)) {
0167:                            if (pageInfo.getIsThreadSafe() == null) {
0168:                                pageInfo.setIsThreadSafe(value, n, err);
0169:                            } else if (!pageInfo.getIsThreadSafe()
0170:                                    .equals(value)) {
0171:                                err.jspError(n,
0172:                                        "jsp.error.page.conflict.isthreadsafe",
0173:                                        pageInfo.getIsThreadSafe(), value);
0174:                            }
0175:                        } else if ("isELIgnored".equals(attr)) {
0176:                            if (pageInfo.getIsELIgnored() == null) {
0177:                                pageInfo.setIsELIgnored(value, n, err, true);
0178:                            } else if (!pageInfo.getIsELIgnored().equals(value)) {
0179:                                err.jspError(n,
0180:                                        "jsp.error.page.conflict.iselignored",
0181:                                        pageInfo.getIsELIgnored(), value);
0182:                            }
0183:                        } else if ("isErrorPage".equals(attr)) {
0184:                            if (pageInfo.getIsErrorPage() == null) {
0185:                                pageInfo.setIsErrorPage(value, n, err);
0186:                            } else if (!pageInfo.getIsErrorPage().equals(value)) {
0187:                                err.jspError(n,
0188:                                        "jsp.error.page.conflict.iserrorpage",
0189:                                        pageInfo.getIsErrorPage(), value);
0190:                            }
0191:                        } else if ("errorPage".equals(attr)) {
0192:                            if (pageInfo.getErrorPage() == null) {
0193:                                pageInfo.setErrorPage(value);
0194:                            } else if (!pageInfo.getErrorPage().equals(value)) {
0195:                                err.jspError(n,
0196:                                        "jsp.error.page.conflict.errorpage",
0197:                                        pageInfo.getErrorPage(), value);
0198:                            }
0199:                        } else if ("info".equals(attr)) {
0200:                            if (pageInfo.getInfo() == null) {
0201:                                pageInfo.setInfo(value);
0202:                            } else if (!pageInfo.getInfo().equals(value)) {
0203:                                err.jspError(n, "jsp.error.page.conflict.info",
0204:                                        pageInfo.getInfo(), value);
0205:                            }
0206:                        } else if ("pageEncoding".equals(attr)) {
0207:                            if (pageEncodingSeen)
0208:                                err.jspError(n,
0209:                                        "jsp.error.page.multi.pageencoding");
0210:                            // 'pageEncoding' can occur at most once per file
0211:                            pageEncodingSeen = true;
0212:                            String actual = comparePageEncodings(value, n);
0213:                            n.getRoot().setPageEncoding(actual);
0214:                        } else if ("deferredSyntaxAllowedAsLiteral"
0215:                                .equals(attr)) {
0216:                            if (pageInfo.getDeferredSyntaxAllowedAsLiteral() == null) {
0217:                                pageInfo.setDeferredSyntaxAllowedAsLiteral(
0218:                                        value, n, err, true);
0219:                            } else if (!pageInfo
0220:                                    .getDeferredSyntaxAllowedAsLiteral()
0221:                                    .equals(value)) {
0222:                                err
0223:                                        .jspError(
0224:                                                n,
0225:                                                "jsp.error.page.conflict.deferredsyntaxallowedasliteral",
0226:                                                pageInfo
0227:                                                        .getDeferredSyntaxAllowedAsLiteral(),
0228:                                                value);
0229:                            }
0230:                        } else if ("trimDirectiveWhitespaces".equals(attr)) {
0231:                            if (pageInfo.getTrimDirectiveWhitespaces() == null) {
0232:                                pageInfo.setTrimDirectiveWhitespaces(value, n,
0233:                                        err, true);
0234:                            } else if (!pageInfo.getTrimDirectiveWhitespaces()
0235:                                    .equals(value)) {
0236:                                err
0237:                                        .jspError(
0238:                                                n,
0239:                                                "jsp.error.page.conflict.trimdirectivewhitespaces",
0240:                                                pageInfo
0241:                                                        .getTrimDirectiveWhitespaces(),
0242:                                                value);
0243:                            }
0244:                        }
0245:                    }
0246:
0247:                    // Check for bad combinations
0248:                    if (pageInfo.getBuffer() == 0 && !pageInfo.isAutoFlush())
0249:                        err.jspError(n, "jsp.error.page.badCombo");
0250:
0251:                    // Attributes for imports for this node have been processed by
0252:                    // the parsers, just add them to pageInfo.
0253:                    pageInfo.addImports(n.getImports());
0254:                }
0255:
0256:                public void visit(Node.TagDirective n) throws JasperException {
0257:                    // Note: Most of the validation is done in TagFileProcessor
0258:                    // when it created a TagInfo object from the
0259:                    // tag file in which the directive appeared.
0260:
0261:                    // This method does additional processing to collect page info
0262:
0263:                    Attributes attrs = n.getAttributes();
0264:                    for (int i = 0; attrs != null && i < attrs.getLength(); i++) {
0265:                        String attr = attrs.getQName(i);
0266:                        String value = attrs.getValue(i);
0267:
0268:                        if ("language".equals(attr)) {
0269:                            if (pageInfo.getLanguage(false) == null) {
0270:                                pageInfo.setLanguage(value, n, err, false);
0271:                            } else if (!pageInfo.getLanguage(false).equals(
0272:                                    value)) {
0273:                                err.jspError(n,
0274:                                        "jsp.error.tag.conflict.language",
0275:                                        pageInfo.getLanguage(false), value);
0276:                            }
0277:                        } else if ("isELIgnored".equals(attr)) {
0278:                            if (pageInfo.getIsELIgnored() == null) {
0279:                                pageInfo.setIsELIgnored(value, n, err, false);
0280:                            } else if (!pageInfo.getIsELIgnored().equals(value)) {
0281:                                err.jspError(n,
0282:                                        "jsp.error.tag.conflict.iselignored",
0283:                                        pageInfo.getIsELIgnored(), value);
0284:                            }
0285:                        } else if ("pageEncoding".equals(attr)) {
0286:                            if (pageEncodingSeen)
0287:                                err.jspError(n,
0288:                                        "jsp.error.tag.multi.pageencoding");
0289:                            pageEncodingSeen = true;
0290:                            compareTagEncodings(value, n);
0291:                            n.getRoot().setPageEncoding(value);
0292:                        } else if ("deferredSyntaxAllowedAsLiteral"
0293:                                .equals(attr)) {
0294:                            if (pageInfo.getDeferredSyntaxAllowedAsLiteral() == null) {
0295:                                pageInfo.setDeferredSyntaxAllowedAsLiteral(
0296:                                        value, n, err, false);
0297:                            } else if (!pageInfo
0298:                                    .getDeferredSyntaxAllowedAsLiteral()
0299:                                    .equals(value)) {
0300:                                err
0301:                                        .jspError(
0302:                                                n,
0303:                                                "jsp.error.tag.conflict.deferredsyntaxallowedasliteral",
0304:                                                pageInfo
0305:                                                        .getDeferredSyntaxAllowedAsLiteral(),
0306:                                                value);
0307:                            }
0308:                        } else if ("trimDirectiveWhitespaces".equals(attr)) {
0309:                            if (pageInfo.getTrimDirectiveWhitespaces() == null) {
0310:                                pageInfo.setTrimDirectiveWhitespaces(value, n,
0311:                                        err, false);
0312:                            } else if (!pageInfo.getTrimDirectiveWhitespaces()
0313:                                    .equals(value)) {
0314:                                err
0315:                                        .jspError(
0316:                                                n,
0317:                                                "jsp.error.tag.conflict.trimdirectivewhitespaces",
0318:                                                pageInfo
0319:                                                        .getTrimDirectiveWhitespaces(),
0320:                                                value);
0321:                            }
0322:                        }
0323:                    }
0324:
0325:                    // Attributes for imports for this node have been processed by
0326:                    // the parsers, just add them to pageInfo.
0327:                    pageInfo.addImports(n.getImports());
0328:                }
0329:
0330:                public void visit(Node.AttributeDirective n)
0331:                        throws JasperException {
0332:                    // Do nothing, since this attribute directive has already been
0333:                    // validated by TagFileProcessor when it created a TagInfo object
0334:                    // from the tag file in which the directive appeared
0335:                }
0336:
0337:                public void visit(Node.VariableDirective n)
0338:                        throws JasperException {
0339:                    // Do nothing, since this variable directive has already been
0340:                    // validated by TagFileProcessor when it created a TagInfo object
0341:                    // from the tag file in which the directive appeared
0342:                }
0343:
0344:                /*
0345:                 * Compares page encodings specified in various places, and throws
0346:                 * exception in case of page encoding mismatch.
0347:                 * 
0348:                 * @param pageDirEnc The value of the pageEncoding attribute of the page
0349:                 * directive @param pageDir The page directive node
0350:                 * 
0351:                 * @throws JasperException in case of page encoding mismatch
0352:                 */
0353:                private String comparePageEncodings(String pageDirEnc,
0354:                        Node.PageDirective pageDir) throws JasperException {
0355:
0356:                    Node.Root root = pageDir.getRoot();
0357:                    String configEnc = root.getJspConfigPageEncoding();
0358:
0359:                    /*
0360:                     * Compare the 'pageEncoding' attribute of the page directive with
0361:                     * the encoding specified in the JSP config element whose URL
0362:                     * pattern matches this page. Treat "UTF-16", "UTF-16BE", and
0363:                     * "UTF-16LE" as identical.
0364:                     */
0365:                    if (configEnc != null) {
0366:                        if (!pageDirEnc.equals(configEnc)
0367:                                && (!pageDirEnc.startsWith("UTF-16") || !configEnc
0368:                                        .startsWith("UTF-16"))) {
0369:                            err
0370:                                    .jspError(
0371:                                            pageDir,
0372:                                            "jsp.error.config_pagedir_encoding_mismatch",
0373:                                            configEnc, pageDirEnc);
0374:                        } else {
0375:                            return configEnc;
0376:                        }
0377:                    }
0378:
0379:                    /*
0380:                     * Compare the 'pageEncoding' attribute of the page directive with
0381:                     * the encoding specified in the XML prolog (only for XML syntax,
0382:                     * and only if JSP document contains XML prolog with encoding
0383:                     * declaration). Treat "UTF-16", "UTF-16BE", and "UTF-16LE" as
0384:                     * identical.
0385:                     */
0386:                    if ((root.isXmlSyntax() && root
0387:                            .isEncodingSpecifiedInProlog())
0388:                            || root.isBomPresent()) {
0389:                        String pageEnc = root.getPageEncoding();
0390:                        if (!pageDirEnc.equals(pageEnc)
0391:                                && (!pageDirEnc.startsWith("UTF-16") || !pageEnc
0392:                                        .startsWith("UTF-16"))) {
0393:                            err
0394:                                    .jspError(
0395:                                            pageDir,
0396:                                            "jsp.error.prolog_pagedir_encoding_mismatch",
0397:                                            pageEnc, pageDirEnc);
0398:                        } else {
0399:                            return pageEnc;
0400:                        }
0401:                    }
0402:
0403:                    return pageDirEnc;
0404:                }
0405:
0406:                /*
0407:                 * Compares page encodings specified in various places, and throws
0408:                 * exception in case of page encoding mismatch.
0409:                 * 
0410:                 * @param pageDirEnc The value of the pageEncoding attribute of the page
0411:                 * directive @param pageDir The page directive node
0412:                 * 
0413:                 * @throws JasperException in case of page encoding mismatch
0414:                 */
0415:                private void compareTagEncodings(String pageDirEnc,
0416:                        Node.TagDirective pageDir) throws JasperException {
0417:
0418:                    Node.Root root = pageDir.getRoot();
0419:
0420:                    /*
0421:                     * Compare the 'pageEncoding' attribute of the page directive with
0422:                     * the encoding specified in the XML prolog (only for XML syntax,
0423:                     * and only if JSP document contains XML prolog with encoding
0424:                     * declaration). Treat "UTF-16", "UTF-16BE", and "UTF-16LE" as
0425:                     * identical.
0426:                     */
0427:                    if ((root.isXmlSyntax() && root
0428:                            .isEncodingSpecifiedInProlog())
0429:                            || root.isBomPresent()) {
0430:                        String pageEnc = root.getPageEncoding();
0431:                        if (!pageDirEnc.equals(pageEnc)
0432:                                && (!pageDirEnc.startsWith("UTF-16") || !pageEnc
0433:                                        .startsWith("UTF-16"))) {
0434:                            err
0435:                                    .jspError(
0436:                                            pageDir,
0437:                                            "jsp.error.prolog_pagedir_encoding_mismatch",
0438:                                            pageEnc, pageDirEnc);
0439:                        }
0440:                    }
0441:                }
0442:
0443:            }
0444:
0445:            /**
0446:             * A visitor for validating nodes other than page directives
0447:             */
0448:            static class ValidateVisitor extends Node.Visitor {
0449:
0450:                private PageInfo pageInfo;
0451:
0452:                private ErrorDispatcher err;
0453:
0454:                private TagInfo tagInfo;
0455:
0456:                private ClassLoader loader;
0457:
0458:                private final StringBuffer buf = new StringBuffer(32);
0459:
0460:                private static final JspUtil.ValidAttribute[] jspRootAttrs = {
0461:                        new JspUtil.ValidAttribute("xsi:schemaLocation"),
0462:                        new JspUtil.ValidAttribute("version", true) };
0463:
0464:                private static final JspUtil.ValidAttribute[] includeDirectiveAttrs = { new JspUtil.ValidAttribute(
0465:                        "file", true) };
0466:
0467:                private static final JspUtil.ValidAttribute[] taglibDirectiveAttrs = {
0468:                        new JspUtil.ValidAttribute("uri"),
0469:                        new JspUtil.ValidAttribute("tagdir"),
0470:                        new JspUtil.ValidAttribute("prefix", true) };
0471:
0472:                private static final JspUtil.ValidAttribute[] includeActionAttrs = {
0473:                        new JspUtil.ValidAttribute("page", true, true),
0474:                        new JspUtil.ValidAttribute("flush") };
0475:
0476:                private static final JspUtil.ValidAttribute[] paramActionAttrs = {
0477:                        new JspUtil.ValidAttribute("name", true),
0478:                        new JspUtil.ValidAttribute("value", true, true) };
0479:
0480:                private static final JspUtil.ValidAttribute[] forwardActionAttrs = { new JspUtil.ValidAttribute(
0481:                        "page", true, true) };
0482:
0483:                private static final JspUtil.ValidAttribute[] getPropertyAttrs = {
0484:                        new JspUtil.ValidAttribute("name", true),
0485:                        new JspUtil.ValidAttribute("property", true) };
0486:
0487:                private static final JspUtil.ValidAttribute[] setPropertyAttrs = {
0488:                        new JspUtil.ValidAttribute("name", true),
0489:                        new JspUtil.ValidAttribute("property", true),
0490:                        new JspUtil.ValidAttribute("value", false, true),
0491:                        new JspUtil.ValidAttribute("param") };
0492:
0493:                private static final JspUtil.ValidAttribute[] useBeanAttrs = {
0494:                        new JspUtil.ValidAttribute("id", true),
0495:                        new JspUtil.ValidAttribute("scope"),
0496:                        new JspUtil.ValidAttribute("class"),
0497:                        new JspUtil.ValidAttribute("type"),
0498:                        new JspUtil.ValidAttribute("beanName", false, true) };
0499:
0500:                private static final JspUtil.ValidAttribute[] plugInAttrs = {
0501:                        new JspUtil.ValidAttribute("type", true),
0502:                        new JspUtil.ValidAttribute("code", true),
0503:                        new JspUtil.ValidAttribute("codebase"),
0504:                        new JspUtil.ValidAttribute("align"),
0505:                        new JspUtil.ValidAttribute("archive"),
0506:                        new JspUtil.ValidAttribute("height", false, true),
0507:                        new JspUtil.ValidAttribute("hspace"),
0508:                        new JspUtil.ValidAttribute("jreversion"),
0509:                        new JspUtil.ValidAttribute("name"),
0510:                        new JspUtil.ValidAttribute("vspace"),
0511:                        new JspUtil.ValidAttribute("width", false, true),
0512:                        new JspUtil.ValidAttribute("nspluginurl"),
0513:                        new JspUtil.ValidAttribute("iepluginurl") };
0514:
0515:                private static final JspUtil.ValidAttribute[] attributeAttrs = {
0516:                        new JspUtil.ValidAttribute("name", true),
0517:                        new JspUtil.ValidAttribute("trim") };
0518:
0519:                private static final JspUtil.ValidAttribute[] invokeAttrs = {
0520:                        new JspUtil.ValidAttribute("fragment", true),
0521:                        new JspUtil.ValidAttribute("var"),
0522:                        new JspUtil.ValidAttribute("varReader"),
0523:                        new JspUtil.ValidAttribute("scope") };
0524:
0525:                private static final JspUtil.ValidAttribute[] doBodyAttrs = {
0526:                        new JspUtil.ValidAttribute("var"),
0527:                        new JspUtil.ValidAttribute("varReader"),
0528:                        new JspUtil.ValidAttribute("scope") };
0529:
0530:                private static final JspUtil.ValidAttribute[] jspOutputAttrs = {
0531:                        new JspUtil.ValidAttribute("omit-xml-declaration"),
0532:                        new JspUtil.ValidAttribute("doctype-root-element"),
0533:                        new JspUtil.ValidAttribute("doctype-public"),
0534:                        new JspUtil.ValidAttribute("doctype-system") };
0535:
0536:                /*
0537:                 * Constructor
0538:                 */
0539:                ValidateVisitor(Compiler compiler) {
0540:                    this .pageInfo = compiler.getPageInfo();
0541:                    this .err = compiler.getErrorDispatcher();
0542:                    this .tagInfo = compiler.getCompilationContext()
0543:                            .getTagInfo();
0544:                    this .loader = compiler.getCompilationContext()
0545:                            .getClassLoader();
0546:                }
0547:
0548:                public void visit(Node.JspRoot n) throws JasperException {
0549:                    JspUtil.checkAttributes("Jsp:root", n, jspRootAttrs, err);
0550:                    String version = n.getTextAttribute("version");
0551:                    if (!version.equals("1.2") && !version.equals("2.0")
0552:                            && !version.equals("2.1")) {
0553:                        err.jspError(n, "jsp.error.jsproot.version.invalid",
0554:                                version);
0555:                    }
0556:                    visitBody(n);
0557:                }
0558:
0559:                public void visit(Node.IncludeDirective n)
0560:                        throws JasperException {
0561:                    JspUtil.checkAttributes("Include directive", n,
0562:                            includeDirectiveAttrs, err);
0563:                    visitBody(n);
0564:                }
0565:
0566:                public void visit(Node.TaglibDirective n)
0567:                        throws JasperException {
0568:                    JspUtil.checkAttributes("Taglib directive", n,
0569:                            taglibDirectiveAttrs, err);
0570:                    // Either 'uri' or 'tagdir' attribute must be specified
0571:                    String uri = n.getAttributeValue("uri");
0572:                    String tagdir = n.getAttributeValue("tagdir");
0573:                    if (uri == null && tagdir == null) {
0574:                        err.jspError(n,
0575:                                "jsp.error.taglibDirective.missing.location");
0576:                    }
0577:                    if (uri != null && tagdir != null) {
0578:                        err
0579:                                .jspError(n,
0580:                                        "jsp.error.taglibDirective.both_uri_and_tagdir");
0581:                    }
0582:                }
0583:
0584:                public void visit(Node.ParamAction n) throws JasperException {
0585:                    JspUtil.checkAttributes("Param action", n,
0586:                            paramActionAttrs, err);
0587:                    // make sure the value of the 'name' attribute is not a
0588:                    // request-time expression
0589:                    throwErrorIfExpression(n, "name", "jsp:param");
0590:                    n.setValue(getJspAttribute(null, "value", null, null, n
0591:                            .getAttributeValue("value"),
0592:                            java.lang.String.class, n, false));
0593:                    visitBody(n);
0594:                }
0595:
0596:                public void visit(Node.ParamsAction n) throws JasperException {
0597:                    // Make sure we've got at least one nested jsp:param
0598:                    Node.Nodes subElems = n.getBody();
0599:                    if (subElems == null) {
0600:                        err.jspError(n, "jsp.error.params.emptyBody");
0601:                    }
0602:                    visitBody(n);
0603:                }
0604:
0605:                public void visit(Node.IncludeAction n) throws JasperException {
0606:                    JspUtil.checkAttributes("Include action", n,
0607:                            includeActionAttrs, err);
0608:                    n.setPage(getJspAttribute(null, "page", null, null, n
0609:                            .getAttributeValue("page"), java.lang.String.class,
0610:                            n, false));
0611:                    visitBody(n);
0612:                };
0613:
0614:                public void visit(Node.ForwardAction n) throws JasperException {
0615:                    JspUtil.checkAttributes("Forward", n, forwardActionAttrs,
0616:                            err);
0617:                    n.setPage(getJspAttribute(null, "page", null, null, n
0618:                            .getAttributeValue("page"), java.lang.String.class,
0619:                            n, false));
0620:                    visitBody(n);
0621:                }
0622:
0623:                public void visit(Node.GetProperty n) throws JasperException {
0624:                    JspUtil.checkAttributes("GetProperty", n, getPropertyAttrs,
0625:                            err);
0626:                }
0627:
0628:                public void visit(Node.SetProperty n) throws JasperException {
0629:                    JspUtil.checkAttributes("SetProperty", n, setPropertyAttrs,
0630:                            err);
0631:                    String property = n.getTextAttribute("property");
0632:                    String param = n.getTextAttribute("param");
0633:                    String value = n.getAttributeValue("value");
0634:
0635:                    n.setValue(getJspAttribute(null, "value", null, null,
0636:                            value, java.lang.Object.class, n, false));
0637:
0638:                    boolean valueSpecified = n.getValue() != null;
0639:
0640:                    if ("*".equals(property)) {
0641:                        if (param != null || valueSpecified)
0642:                            err.jspError(n, "jsp.error.setProperty.invalid");
0643:
0644:                    } else if (param != null && valueSpecified) {
0645:                        err.jspError(n, "jsp.error.setProperty.invalid");
0646:                    }
0647:
0648:                    visitBody(n);
0649:                }
0650:
0651:                public void visit(Node.UseBean n) throws JasperException {
0652:                    JspUtil.checkAttributes("UseBean", n, useBeanAttrs, err);
0653:
0654:                    String name = n.getTextAttribute("id");
0655:                    String scope = n.getTextAttribute("scope");
0656:                    JspUtil.checkScope(scope, n, err);
0657:                    String className = n.getTextAttribute("class");
0658:                    String type = n.getTextAttribute("type");
0659:                    BeanRepository beanInfo = pageInfo.getBeanRepository();
0660:
0661:                    if (className == null && type == null)
0662:                        err.jspError(n, "jsp.error.usebean.missingType");
0663:
0664:                    if (beanInfo.checkVariable(name))
0665:                        err.jspError(n, "jsp.error.usebean.duplicate");
0666:
0667:                    if ("session".equals(scope) && !pageInfo.isSession())
0668:                        err.jspError(n, "jsp.error.usebean.noSession");
0669:
0670:                    Node.JspAttribute jattr = getJspAttribute(null, "beanName",
0671:                            null, null, n.getAttributeValue("beanName"),
0672:                            java.lang.String.class, n, false);
0673:                    n.setBeanName(jattr);
0674:                    if (className != null && jattr != null)
0675:                        err.jspError(n, "jsp.error.usebean.notBoth");
0676:
0677:                    if (className == null)
0678:                        className = type;
0679:
0680:                    beanInfo.addBean(n, name, className, scope);
0681:
0682:                    visitBody(n);
0683:                }
0684:
0685:                public void visit(Node.PlugIn n) throws JasperException {
0686:                    JspUtil.checkAttributes("Plugin", n, plugInAttrs, err);
0687:
0688:                    throwErrorIfExpression(n, "type", "jsp:plugin");
0689:                    throwErrorIfExpression(n, "code", "jsp:plugin");
0690:                    throwErrorIfExpression(n, "codebase", "jsp:plugin");
0691:                    throwErrorIfExpression(n, "align", "jsp:plugin");
0692:                    throwErrorIfExpression(n, "archive", "jsp:plugin");
0693:                    throwErrorIfExpression(n, "hspace", "jsp:plugin");
0694:                    throwErrorIfExpression(n, "jreversion", "jsp:plugin");
0695:                    throwErrorIfExpression(n, "name", "jsp:plugin");
0696:                    throwErrorIfExpression(n, "vspace", "jsp:plugin");
0697:                    throwErrorIfExpression(n, "nspluginurl", "jsp:plugin");
0698:                    throwErrorIfExpression(n, "iepluginurl", "jsp:plugin");
0699:
0700:                    String type = n.getTextAttribute("type");
0701:                    if (type == null)
0702:                        err.jspError(n, "jsp.error.plugin.notype");
0703:                    if (!type.equals("bean") && !type.equals("applet"))
0704:                        err.jspError(n, "jsp.error.plugin.badtype");
0705:                    if (n.getTextAttribute("code") == null)
0706:                        err.jspError(n, "jsp.error.plugin.nocode");
0707:
0708:                    Node.JspAttribute width = getJspAttribute(null, "width",
0709:                            null, null, n.getAttributeValue("width"),
0710:                            java.lang.String.class, n, false);
0711:                    n.setWidth(width);
0712:
0713:                    Node.JspAttribute height = getJspAttribute(null, "height",
0714:                            null, null, n.getAttributeValue("height"),
0715:                            java.lang.String.class, n, false);
0716:                    n.setHeight(height);
0717:
0718:                    visitBody(n);
0719:                }
0720:
0721:                public void visit(Node.NamedAttribute n) throws JasperException {
0722:                    JspUtil
0723:                            .checkAttributes("Attribute", n, attributeAttrs,
0724:                                    err);
0725:                    visitBody(n);
0726:                }
0727:
0728:                public void visit(Node.JspBody n) throws JasperException {
0729:                    visitBody(n);
0730:                }
0731:
0732:                public void visit(Node.Declaration n) throws JasperException {
0733:                    if (pageInfo.isScriptingInvalid()) {
0734:                        err.jspError(n.getStart(), "jsp.error.no.scriptlets");
0735:                    }
0736:                }
0737:
0738:                public void visit(Node.Expression n) throws JasperException {
0739:                    if (pageInfo.isScriptingInvalid()) {
0740:                        err.jspError(n.getStart(), "jsp.error.no.scriptlets");
0741:                    }
0742:                }
0743:
0744:                public void visit(Node.Scriptlet n) throws JasperException {
0745:                    if (pageInfo.isScriptingInvalid()) {
0746:                        err.jspError(n.getStart(), "jsp.error.no.scriptlets");
0747:                    }
0748:                }
0749:
0750:                public void visit(Node.ELExpression n) throws JasperException {
0751:                    // exit if we are ignoring EL all together
0752:                    if (pageInfo.isELIgnored())
0753:                        return;
0754:
0755:                    // JSP.2.2 - '#{' not allowed in template text
0756:                    if (n.getType() == '#') {
0757:                        if (!pageInfo.isDeferredSyntaxAllowedAsLiteral()
0758:                                && (tagInfo == null || ((tagInfo != null) && !(tagInfo
0759:                                        .getTagLibrary().getRequiredVersion()
0760:                                        .equals("2.0") || tagInfo
0761:                                        .getTagLibrary().getRequiredVersion()
0762:                                        .equals("1.2"))))) {
0763:                            err.jspError(n, "jsp.error.el.template.deferred");
0764:                        } else {
0765:                            return;
0766:                        }
0767:                    }
0768:
0769:                    // build expression
0770:                    StringBuffer expr = this .getBuffer();
0771:                    expr.append(n.getType()).append('{').append(n.getText())
0772:                            .append('}');
0773:                    ELNode.Nodes el = ELParser.parse(expr.toString());
0774:
0775:                    // validate/prepare expression
0776:                    prepareExpression(el, n, expr.toString());
0777:
0778:                    // store it
0779:                    n.setEL(el);
0780:                }
0781:
0782:                public void visit(Node.UninterpretedTag n)
0783:                        throws JasperException {
0784:                    if (n.getNamedAttributeNodes().size() != 0) {
0785:                        err.jspError(n, "jsp.error.namedAttribute.invalidUse");
0786:                    }
0787:
0788:                    Attributes attrs = n.getAttributes();
0789:                    if (attrs != null) {
0790:                        int attrSize = attrs.getLength();
0791:                        Node.JspAttribute[] jspAttrs = new Node.JspAttribute[attrSize];
0792:                        for (int i = 0; i < attrSize; i++) {
0793:                            jspAttrs[i] = getJspAttribute(null, attrs
0794:                                    .getQName(i), attrs.getURI(i), attrs
0795:                                    .getLocalName(i), attrs.getValue(i),
0796:                                    java.lang.Object.class, n, false);
0797:                        }
0798:                        n.setJspAttributes(jspAttrs);
0799:                    }
0800:
0801:                    visitBody(n);
0802:                }
0803:
0804:                public void visit(Node.CustomTag n) throws JasperException {
0805:
0806:                    TagInfo tagInfo = n.getTagInfo();
0807:                    if (tagInfo == null) {
0808:                        err.jspError(n, "jsp.error.missing.tagInfo", n
0809:                                .getQName());
0810:                    }
0811:
0812:                    /*
0813:                     * The bodyconet of a SimpleTag cannot be JSP.
0814:                     */
0815:                    if (n.implements SimpleTag()
0816:                            && tagInfo.getBodyContent().equalsIgnoreCase(
0817:                                    TagInfo.BODY_CONTENT_JSP)) {
0818:                        err.jspError(n, "jsp.error.simpletag.badbodycontent",
0819:                                tagInfo.getTagClassName());
0820:                    }
0821:
0822:                    /*
0823:                     * If the tag handler declares in the TLD that it supports dynamic
0824:                     * attributes, it also must implement the DynamicAttributes
0825:                     * interface.
0826:                     */
0827:                    if (tagInfo.hasDynamicAttributes()
0828:                            && !n.implements DynamicAttributes()) {
0829:                        err.jspError(n,
0830:                                "jsp.error.dynamic.attributes.not.implemented",
0831:                                n.getQName());
0832:                    }
0833:
0834:                    /*
0835:                     * Make sure all required attributes are present, either as
0836:                     * attributes or named attributes (<jsp:attribute>). Also make sure
0837:                     * that the same attribute is not specified in both attributes or
0838:                     * named attributes.
0839:                     */
0840:                    TagAttributeInfo[] tldAttrs = tagInfo.getAttributes();
0841:                    String customActionUri = n.getURI();
0842:                    Attributes attrs = n.getAttributes();
0843:                    int attrsSize = (attrs == null) ? 0 : attrs.getLength();
0844:                    for (int i = 0; i < tldAttrs.length; i++) {
0845:                        String attr = null;
0846:                        if (attrs != null) {
0847:                            attr = attrs.getValue(tldAttrs[i].getName());
0848:                            if (attr == null) {
0849:                                attr = attrs.getValue(customActionUri,
0850:                                        tldAttrs[i].getName());
0851:                            }
0852:                        }
0853:                        Node.NamedAttribute na = n
0854:                                .getNamedAttributeNode(tldAttrs[i].getName());
0855:
0856:                        if (tldAttrs[i].isRequired() && attr == null
0857:                                && na == null) {
0858:                            err.jspError(n, "jsp.error.missing_attribute",
0859:                                    tldAttrs[i].getName(), n.getLocalName());
0860:                        }
0861:                        if (attr != null && na != null) {
0862:                            err.jspError(n,
0863:                                    "jsp.error.duplicate.name.jspattribute",
0864:                                    tldAttrs[i].getName());
0865:                        }
0866:                    }
0867:
0868:                    Node.Nodes naNodes = n.getNamedAttributeNodes();
0869:                    int jspAttrsSize = naNodes.size() + attrsSize;
0870:                    Node.JspAttribute[] jspAttrs = null;
0871:                    if (jspAttrsSize > 0) {
0872:                        jspAttrs = new Node.JspAttribute[jspAttrsSize];
0873:                    }
0874:                    Hashtable<String, Object> tagDataAttrs = new Hashtable<String, Object>(
0875:                            attrsSize);
0876:
0877:                    checkXmlAttributes(n, jspAttrs, tagDataAttrs);
0878:                    checkNamedAttributes(n, jspAttrs, attrsSize, tagDataAttrs);
0879:
0880:                    TagData tagData = new TagData(tagDataAttrs);
0881:
0882:                    // JSP.C1: It is a (translation time) error for an action that
0883:                    // has one or more variable subelements to have a TagExtraInfo
0884:                    // class that returns a non-null object.
0885:                    TagExtraInfo tei = tagInfo.getTagExtraInfo();
0886:                    if (tei != null && tei.getVariableInfo(tagData) != null
0887:                            && tei.getVariableInfo(tagData).length > 0
0888:                            && tagInfo.getTagVariableInfos().length > 0) {
0889:                        err.jspError("jsp.error.non_null_tei_and_var_subelems",
0890:                                n.getQName());
0891:                    }
0892:
0893:                    n.setTagData(tagData);
0894:                    n.setJspAttributes(jspAttrs);
0895:
0896:                    visitBody(n);
0897:                }
0898:
0899:                public void visit(Node.JspElement n) throws JasperException {
0900:
0901:                    Attributes attrs = n.getAttributes();
0902:                    if (attrs == null) {
0903:                        err.jspError(n, "jsp.error.jspelement.missing.name");
0904:                    }
0905:                    int xmlAttrLen = attrs.getLength();
0906:
0907:                    Node.Nodes namedAttrs = n.getNamedAttributeNodes();
0908:
0909:                    // XML-style 'name' attribute, which is mandatory, must not be
0910:                    // included in JspAttribute array
0911:                    int jspAttrSize = xmlAttrLen - 1 + namedAttrs.size();
0912:
0913:                    Node.JspAttribute[] jspAttrs = new Node.JspAttribute[jspAttrSize];
0914:                    int jspAttrIndex = 0;
0915:
0916:                    // Process XML-style attributes
0917:                    for (int i = 0; i < xmlAttrLen; i++) {
0918:                        if ("name".equals(attrs.getLocalName(i))) {
0919:                            n.setNameAttribute(getJspAttribute(null, attrs
0920:                                    .getQName(i), attrs.getURI(i), attrs
0921:                                    .getLocalName(i), attrs.getValue(i),
0922:                                    java.lang.String.class, n, false));
0923:                        } else {
0924:                            if (jspAttrIndex < jspAttrSize) {
0925:                                jspAttrs[jspAttrIndex++] = getJspAttribute(
0926:                                        null, attrs.getQName(i), attrs
0927:                                                .getURI(i), attrs
0928:                                                .getLocalName(i), attrs
0929:                                                .getValue(i),
0930:                                        java.lang.Object.class, n, false);
0931:                            }
0932:                        }
0933:                    }
0934:                    if (n.getNameAttribute() == null) {
0935:                        err.jspError(n, "jsp.error.jspelement.missing.name");
0936:                    }
0937:
0938:                    // Process named attributes
0939:                    for (int i = 0; i < namedAttrs.size(); i++) {
0940:                        Node.NamedAttribute na = (Node.NamedAttribute) namedAttrs
0941:                                .getNode(i);
0942:                        jspAttrs[jspAttrIndex++] = new Node.JspAttribute(na,
0943:                                null, false);
0944:                    }
0945:
0946:                    n.setJspAttributes(jspAttrs);
0947:
0948:                    visitBody(n);
0949:                }
0950:
0951:                public void visit(Node.JspOutput n) throws JasperException {
0952:                    JspUtil.checkAttributes("jsp:output", n, jspOutputAttrs,
0953:                            err);
0954:
0955:                    if (n.getBody() != null) {
0956:                        err.jspError(n, "jsp.error.jspoutput.nonemptybody");
0957:                    }
0958:
0959:                    String omitXmlDecl = n
0960:                            .getAttributeValue("omit-xml-declaration");
0961:                    String doctypeName = n
0962:                            .getAttributeValue("doctype-root-element");
0963:                    String doctypePublic = n
0964:                            .getAttributeValue("doctype-public");
0965:                    String doctypeSystem = n
0966:                            .getAttributeValue("doctype-system");
0967:
0968:                    String omitXmlDeclOld = pageInfo.getOmitXmlDecl();
0969:                    String doctypeNameOld = pageInfo.getDoctypeName();
0970:                    String doctypePublicOld = pageInfo.getDoctypePublic();
0971:                    String doctypeSystemOld = pageInfo.getDoctypeSystem();
0972:
0973:                    if (omitXmlDecl != null && omitXmlDeclOld != null
0974:                            && !omitXmlDecl.equals(omitXmlDeclOld)) {
0975:                        err.jspError(n, "jsp.error.jspoutput.conflict",
0976:                                "omit-xml-declaration", omitXmlDeclOld,
0977:                                omitXmlDecl);
0978:                    }
0979:
0980:                    if (doctypeName != null && doctypeNameOld != null
0981:                            && !doctypeName.equals(doctypeNameOld)) {
0982:                        err.jspError(n, "jsp.error.jspoutput.conflict",
0983:                                "doctype-root-element", doctypeNameOld,
0984:                                doctypeName);
0985:                    }
0986:
0987:                    if (doctypePublic != null && doctypePublicOld != null
0988:                            && !doctypePublic.equals(doctypePublicOld)) {
0989:                        err.jspError(n, "jsp.error.jspoutput.conflict",
0990:                                "doctype-public", doctypePublicOld,
0991:                                doctypePublic);
0992:                    }
0993:
0994:                    if (doctypeSystem != null && doctypeSystemOld != null
0995:                            && !doctypeSystem.equals(doctypeSystemOld)) {
0996:                        err.jspError(n, "jsp.error.jspoutput.conflict",
0997:                                "doctype-system", doctypeSystemOld,
0998:                                doctypeSystem);
0999:                    }
1000:
1001:                    if (doctypeName == null && doctypeSystem != null
1002:                            || doctypeName != null && doctypeSystem == null) {
1003:                        err
1004:                                .jspError(n,
1005:                                        "jsp.error.jspoutput.doctypenamesystem");
1006:                    }
1007:
1008:                    if (doctypePublic != null && doctypeSystem == null) {
1009:                        err.jspError(n,
1010:                                "jsp.error.jspoutput.doctypepulicsystem");
1011:                    }
1012:
1013:                    if (omitXmlDecl != null) {
1014:                        pageInfo.setOmitXmlDecl(omitXmlDecl);
1015:                    }
1016:                    if (doctypeName != null) {
1017:                        pageInfo.setDoctypeName(doctypeName);
1018:                    }
1019:                    if (doctypeSystem != null) {
1020:                        pageInfo.setDoctypeSystem(doctypeSystem);
1021:                    }
1022:                    if (doctypePublic != null) {
1023:                        pageInfo.setDoctypePublic(doctypePublic);
1024:                    }
1025:                }
1026:
1027:                public void visit(Node.InvokeAction n) throws JasperException {
1028:
1029:                    JspUtil.checkAttributes("Invoke", n, invokeAttrs, err);
1030:
1031:                    String scope = n.getTextAttribute("scope");
1032:                    JspUtil.checkScope(scope, n, err);
1033:
1034:                    String var = n.getTextAttribute("var");
1035:                    String varReader = n.getTextAttribute("varReader");
1036:                    if (scope != null && var == null && varReader == null) {
1037:                        err.jspError(n, "jsp.error.missing_var_or_varReader");
1038:                    }
1039:                    if (var != null && varReader != null) {
1040:                        err.jspError(n, "jsp.error.var_and_varReader");
1041:                    }
1042:                }
1043:
1044:                public void visit(Node.DoBodyAction n) throws JasperException {
1045:
1046:                    JspUtil.checkAttributes("DoBody", n, doBodyAttrs, err);
1047:
1048:                    String scope = n.getTextAttribute("scope");
1049:                    JspUtil.checkScope(scope, n, err);
1050:
1051:                    String var = n.getTextAttribute("var");
1052:                    String varReader = n.getTextAttribute("varReader");
1053:                    if (scope != null && var == null && varReader == null) {
1054:                        err.jspError(n, "jsp.error.missing_var_or_varReader");
1055:                    }
1056:                    if (var != null && varReader != null) {
1057:                        err.jspError(n, "jsp.error.var_and_varReader");
1058:                    }
1059:                }
1060:
1061:                /*
1062:                 * Make sure the given custom action does not have any invalid
1063:                 * attributes.
1064:                 * 
1065:                 * A custom action and its declared attributes always belong to the same
1066:                 * namespace, which is identified by the prefix name of the custom tag
1067:                 * invocation. For example, in this invocation:
1068:                 * 
1069:                 * <my:test a="1" b="2" c="3"/>, the action
1070:                 * 
1071:                 * "test" and its attributes "a", "b", and "c" all belong to the
1072:                 * namespace identified by the prefix "my". The above invocation would
1073:                 * be equivalent to:
1074:                 * 
1075:                 * <my:test my:a="1" my:b="2" my:c="3"/>
1076:                 * 
1077:                 * An action attribute may have a prefix different from that of the
1078:                 * action invocation only if the underlying tag handler supports dynamic
1079:                 * attributes, in which case the attribute with the different prefix is
1080:                 * considered a dynamic attribute.
1081:                 */
1082:                private void checkXmlAttributes(Node.CustomTag n,
1083:                        Node.JspAttribute[] jspAttrs,
1084:                        Hashtable<String, Object> tagDataAttrs)
1085:                        throws JasperException {
1086:
1087:                    TagInfo tagInfo = n.getTagInfo();
1088:                    if (tagInfo == null) {
1089:                        err.jspError(n, "jsp.error.missing.tagInfo", n
1090:                                .getQName());
1091:                    }
1092:                    TagAttributeInfo[] tldAttrs = tagInfo.getAttributes();
1093:                    Attributes attrs = n.getAttributes();
1094:
1095:                    boolean checkDeferred = !pageInfo
1096:                            .isDeferredSyntaxAllowedAsLiteral()
1097:                            && !(tagInfo.getTagLibrary().getRequiredVersion()
1098:                                    .equals("2.0") || tagInfo.getTagLibrary()
1099:                                    .getRequiredVersion().equals("1.2"));
1100:
1101:                    for (int i = 0; attrs != null && i < attrs.getLength(); i++) {
1102:                        boolean found = false;
1103:
1104:                        boolean runtimeExpression = ((n.getRoot().isXmlSyntax() && attrs
1105:                                .getValue(i).startsWith("%=")) || (!n.getRoot()
1106:                                .isXmlSyntax() && attrs.getValue(i).startsWith(
1107:                                "<%=")));
1108:                        boolean elExpression = false;
1109:                        boolean deferred = false;
1110:                        boolean deferredValueIsLiteral = false;
1111:
1112:                        ELNode.Nodes el = null;
1113:                        if (!runtimeExpression) {
1114:                            el = ELParser.parse(attrs.getValue(i));
1115:                            Iterator<ELNode> nodes = el.iterator();
1116:                            while (nodes.hasNext()) {
1117:                                ELNode node = nodes.next();
1118:                                if (node instanceof  ELNode.Root) {
1119:                                    if (((ELNode.Root) node).getType() == '$') {
1120:                                        elExpression = true;
1121:                                    } else if (checkDeferred
1122:                                            && ((ELNode.Root) node).getType() == '#') {
1123:                                        elExpression = true;
1124:                                        deferred = true;
1125:                                        if (pageInfo.isELIgnored()) {
1126:                                            deferredValueIsLiteral = true;
1127:                                        }
1128:                                    }
1129:                                }
1130:                            }
1131:                        }
1132:
1133:                        boolean expression = runtimeExpression
1134:                                || (elExpression && (!pageInfo.isELIgnored() || (!"true"
1135:                                        .equalsIgnoreCase(pageInfo
1136:                                                .getIsELIgnored())
1137:                                        && checkDeferred && deferred)));
1138:
1139:                        for (int j = 0; tldAttrs != null && j < tldAttrs.length; j++) {
1140:                            if (attrs.getLocalName(i).equals(
1141:                                    tldAttrs[j].getName())
1142:                                    && (attrs.getURI(i) == null
1143:                                            || attrs.getURI(i).length() == 0 || attrs
1144:                                            .getURI(i).equals(n.getURI()))) {
1145:
1146:                                if (tldAttrs[j].canBeRequestTime()
1147:                                        || tldAttrs[j].isDeferredMethod()
1148:                                        || tldAttrs[j].isDeferredValue()) { // JSP 2.1
1149:
1150:                                    if (!expression) {
1151:
1152:                                        if (deferredValueIsLiteral
1153:                                                && !pageInfo
1154:                                                        .isDeferredSyntaxAllowedAsLiteral()) {
1155:                                            err
1156:                                                    .jspError(
1157:                                                            n,
1158:                                                            "jsp.error.attribute.custom.non_rt_with_expr",
1159:                                                            tldAttrs[j]
1160:                                                                    .getName());
1161:                                        }
1162:
1163:                                        String expectedType = null;
1164:                                        if (tldAttrs[j].isDeferredMethod()) {
1165:                                            // The String litteral must be castable to what is declared as type
1166:                                            // for the attribute
1167:                                            String m = tldAttrs[j]
1168:                                                    .getMethodSignature();
1169:                                            if (m != null) {
1170:                                                int rti = m.trim().indexOf(' ');
1171:                                                if (rti > 0) {
1172:                                                    expectedType = m.substring(
1173:                                                            0, rti).trim();
1174:                                                }
1175:                                            } else {
1176:                                                expectedType = "java.lang.Object";
1177:                                            }
1178:                                        }
1179:                                        if (tldAttrs[j].isDeferredValue()) {
1180:                                            // The String litteral must be castable to what is declared as type
1181:                                            // for the attribute
1182:                                            expectedType = tldAttrs[j]
1183:                                                    .getExpectedTypeName();
1184:                                        }
1185:                                        if (expectedType != null) {
1186:                                            Class expectedClass = String.class;
1187:                                            try {
1188:                                                expectedClass = JspUtil
1189:                                                        .toClass(expectedType,
1190:                                                                loader);
1191:                                            } catch (ClassNotFoundException e) {
1192:                                                err
1193:                                                        .jspError(
1194:                                                                n,
1195:                                                                "jsp.error.unknown_attribute_type",
1196:                                                                tldAttrs[j]
1197:                                                                        .getName(),
1198:                                                                expectedType);
1199:                                            }
1200:                                            // Check casting
1201:                                            try {
1202:                                                ELSupport.checkType(attrs
1203:                                                        .getValue(i),
1204:                                                        expectedClass);
1205:                                            } catch (Exception e) {
1206:                                                err
1207:                                                        .jspError(
1208:                                                                n,
1209:                                                                "jsp.error.coerce_to_type",
1210:                                                                tldAttrs[j]
1211:                                                                        .getName(),
1212:                                                                expectedType,
1213:                                                                attrs
1214:                                                                        .getValue(i));
1215:                                            }
1216:                                        }
1217:
1218:                                        jspAttrs[i] = new Node.JspAttribute(
1219:                                                tldAttrs[j], attrs.getQName(i),
1220:                                                attrs.getURI(i), attrs
1221:                                                        .getLocalName(i), attrs
1222:                                                        .getValue(i), false,
1223:                                                null, false);
1224:                                    } else {
1225:
1226:                                        if (deferred
1227:                                                && !tldAttrs[j]
1228:                                                        .isDeferredMethod()
1229:                                                && !tldAttrs[j]
1230:                                                        .isDeferredValue()) {
1231:                                            // No deferred expressions allowed for this attribute
1232:                                            err
1233:                                                    .jspError(
1234:                                                            n,
1235:                                                            "jsp.error.attribute.custom.non_rt_with_expr",
1236:                                                            tldAttrs[j]
1237:                                                                    .getName());
1238:                                        }
1239:                                        if (!deferred
1240:                                                && !tldAttrs[j]
1241:                                                        .canBeRequestTime()) {
1242:                                            // Only deferred expressions are allowed for this attribute
1243:                                            err
1244:                                                    .jspError(
1245:                                                            n,
1246:                                                            "jsp.error.attribute.custom.non_rt_with_expr",
1247:                                                            tldAttrs[j]
1248:                                                                    .getName());
1249:                                        }
1250:
1251:                                        Class expectedType = String.class;
1252:                                        try {
1253:                                            String typeStr = tldAttrs[j]
1254:                                                    .getTypeName();
1255:                                            if (tldAttrs[j].isFragment()) {
1256:                                                expectedType = JspFragment.class;
1257:                                            } else if (typeStr != null) {
1258:                                                expectedType = JspUtil.toClass(
1259:                                                        typeStr, loader);
1260:                                            }
1261:                                            if (elExpression) {
1262:                                                // El expression
1263:                                                validateFunctions(el, n);
1264:                                                jspAttrs[i] = new Node.JspAttribute(
1265:                                                        tldAttrs[j], attrs
1266:                                                                .getQName(i),
1267:                                                        attrs.getURI(i),
1268:                                                        attrs.getLocalName(i),
1269:                                                        attrs.getValue(i),
1270:                                                        false, el, false);
1271:                                                ELContextImpl ctx = new ELContextImpl();
1272:                                                ctx
1273:                                                        .setFunctionMapper(getFunctionMapper(el));
1274:                                                try {
1275:                                                    jspAttrs[i]
1276:                                                            .validateEL(
1277:                                                                    this .pageInfo
1278:                                                                            .getExpressionFactory(),
1279:                                                                    ctx);
1280:                                                } catch (ELException e) {
1281:                                                    this .err
1282:                                                            .jspError(
1283:                                                                    n
1284:                                                                            .getStart(),
1285:                                                                    "jsp.error.invalid.expression",
1286:                                                                    attrs
1287:                                                                            .getValue(i),
1288:                                                                    e
1289:                                                                            .toString());
1290:                                                }
1291:                                            } else {
1292:                                                // Runtime expression
1293:                                                jspAttrs[i] = getJspAttribute(
1294:                                                        tldAttrs[j], attrs
1295:                                                                .getQName(i),
1296:                                                        attrs.getURI(i),
1297:                                                        attrs.getLocalName(i),
1298:                                                        attrs.getValue(i),
1299:                                                        expectedType, n, false);
1300:                                            }
1301:                                        } catch (ClassNotFoundException e) {
1302:                                            err
1303:                                                    .jspError(
1304:                                                            n,
1305:                                                            "jsp.error.unknown_attribute_type",
1306:                                                            tldAttrs[j]
1307:                                                                    .getName(),
1308:                                                            tldAttrs[j]
1309:                                                                    .getTypeName());
1310:                                        }
1311:                                    }
1312:
1313:                                } else {
1314:                                    // Attribute does not accept any expressions.
1315:                                    // Make sure its value does not contain any.
1316:                                    if (expression) {
1317:                                        err
1318:                                                .jspError(
1319:                                                        n,
1320:                                                        "jsp.error.attribute.custom.non_rt_with_expr",
1321:                                                        tldAttrs[j].getName());
1322:                                    }
1323:                                    jspAttrs[i] = new Node.JspAttribute(
1324:                                            tldAttrs[j], attrs.getQName(i),
1325:                                            attrs.getURI(i), attrs
1326:                                                    .getLocalName(i), attrs
1327:                                                    .getValue(i), false, null,
1328:                                            false);
1329:                                }
1330:                                if (expression) {
1331:                                    tagDataAttrs.put(attrs.getQName(i),
1332:                                            TagData.REQUEST_TIME_VALUE);
1333:                                } else {
1334:                                    tagDataAttrs.put(attrs.getQName(i), attrs
1335:                                            .getValue(i));
1336:                                }
1337:                                found = true;
1338:                                break;
1339:                            }
1340:                        }
1341:                        if (!found) {
1342:                            if (tagInfo.hasDynamicAttributes()) {
1343:                                jspAttrs[i] = getJspAttribute(null, attrs
1344:                                        .getQName(i), attrs.getURI(i), attrs
1345:                                        .getLocalName(i), attrs.getValue(i),
1346:                                        java.lang.Object.class, n, true);
1347:                            } else {
1348:                                err.jspError(n, "jsp.error.bad_attribute",
1349:                                        attrs.getQName(i), n.getLocalName());
1350:                            }
1351:                        }
1352:                    }
1353:                }
1354:
1355:                /*
1356:                 * Make sure the given custom action does not have any invalid named
1357:                 * attributes
1358:                 */
1359:                private void checkNamedAttributes(Node.CustomTag n,
1360:                        Node.JspAttribute[] jspAttrs, int start,
1361:                        Hashtable<String, Object> tagDataAttrs)
1362:                        throws JasperException {
1363:
1364:                    TagInfo tagInfo = n.getTagInfo();
1365:                    if (tagInfo == null) {
1366:                        err.jspError(n, "jsp.error.missing.tagInfo", n
1367:                                .getQName());
1368:                    }
1369:                    TagAttributeInfo[] tldAttrs = tagInfo.getAttributes();
1370:                    Node.Nodes naNodes = n.getNamedAttributeNodes();
1371:
1372:                    for (int i = 0; i < naNodes.size(); i++) {
1373:                        Node.NamedAttribute na = (Node.NamedAttribute) naNodes
1374:                                .getNode(i);
1375:                        boolean found = false;
1376:                        for (int j = 0; j < tldAttrs.length; j++) {
1377:                            /*
1378:                             * See above comment about namespace matches. For named
1379:                             * attributes, we use the prefix instead of URI as the match
1380:                             * criterion, because in the case of a JSP document, we'd
1381:                             * have to keep track of which namespaces are in scope when
1382:                             * parsing a named attribute, in order to determine the URI
1383:                             * that the prefix of the named attribute's name matches to.
1384:                             */
1385:                            String attrPrefix = na.getPrefix();
1386:                            if (na.getLocalName().equals(tldAttrs[j].getName())
1387:                                    && (attrPrefix == null
1388:                                            || attrPrefix.length() == 0 || attrPrefix
1389:                                            .equals(n.getPrefix()))) {
1390:                                jspAttrs[start + i] = new Node.JspAttribute(na,
1391:                                        tldAttrs[j], false);
1392:                                NamedAttributeVisitor nav = null;
1393:                                if (na.getBody() != null) {
1394:                                    nav = new NamedAttributeVisitor();
1395:                                    na.getBody().visit(nav);
1396:                                }
1397:                                if (nav != null && nav.hasDynamicContent()) {
1398:                                    tagDataAttrs.put(na.getName(),
1399:                                            TagData.REQUEST_TIME_VALUE);
1400:                                } else {
1401:                                    tagDataAttrs
1402:                                            .put(na.getName(), na.getText());
1403:                                }
1404:                                found = true;
1405:                                break;
1406:                            }
1407:                        }
1408:                        if (!found) {
1409:                            if (tagInfo.hasDynamicAttributes()) {
1410:                                jspAttrs[start + i] = new Node.JspAttribute(na,
1411:                                        null, true);
1412:                            } else {
1413:                                err.jspError(n, "jsp.error.bad_attribute", na
1414:                                        .getName(), n.getLocalName());
1415:                            }
1416:                        }
1417:                    }
1418:                }
1419:
1420:                /**
1421:                 * Preprocess attributes that can be expressions. Expression delimiters
1422:                 * are stripped.
1423:                 * <p>
1424:                 * If value is null, checks if there are any NamedAttribute subelements
1425:                 * in the tree node, and if so, constructs a JspAttribute out of a child
1426:                 * NamedAttribute node.
1427:                 */
1428:                private Node.JspAttribute getJspAttribute(TagAttributeInfo tai,
1429:                        String qName, String uri, String localName,
1430:                        String value, Class expectedType, Node n,
1431:                        boolean dynamic) throws JasperException {
1432:
1433:                    Node.JspAttribute result = null;
1434:
1435:                    // XXX Is it an error to see "%=foo%" in non-Xml page?
1436:                    // (We won't see "<%=foo%> in xml page because '<' is not a
1437:                    // valid attribute value in xml).
1438:
1439:                    if (value != null) {
1440:                        if (n.getRoot().isXmlSyntax() && value.startsWith("%=")) {
1441:                            result = new Node.JspAttribute(tai, qName, uri,
1442:                                    localName, value.substring(2, value
1443:                                            .length() - 1), true, null, dynamic);
1444:                        } else if (!n.getRoot().isXmlSyntax()
1445:                                && value.startsWith("<%=")) {
1446:                            result = new Node.JspAttribute(tai, qName, uri,
1447:                                    localName, value.substring(3, value
1448:                                            .length() - 2), true, null, dynamic);
1449:                        } else {
1450:                            // The attribute can contain expressions but is not a
1451:                            // scriptlet expression; thus, we want to run it through
1452:                            // the expression interpreter
1453:
1454:                            // validate expression syntax if string contains
1455:                            // expression(s)
1456:                            ELNode.Nodes el = ELParser.parse(value);
1457:
1458:                            boolean deferred = false;
1459:                            Iterator<ELNode> nodes = el.iterator();
1460:                            while (nodes.hasNext()) {
1461:                                ELNode node = nodes.next();
1462:                                if (node instanceof  ELNode.Root) {
1463:                                    if (((ELNode.Root) node).getType() == '#') {
1464:                                        deferred = true;
1465:                                    }
1466:                                }
1467:                            }
1468:
1469:                            if (el.containsEL()
1470:                                    && !pageInfo.isELIgnored()
1471:                                    && ((!pageInfo
1472:                                            .isDeferredSyntaxAllowedAsLiteral() && deferred) || !deferred)) {
1473:
1474:                                validateFunctions(el, n);
1475:
1476:                                result = new Node.JspAttribute(tai, qName, uri,
1477:                                        localName, value, false, el, dynamic);
1478:
1479:                                ELContextImpl ctx = new ELContextImpl();
1480:                                ctx.setFunctionMapper(getFunctionMapper(el));
1481:
1482:                                try {
1483:                                    result.validateEL(this .pageInfo
1484:                                            .getExpressionFactory(), ctx);
1485:                                } catch (ELException e) {
1486:                                    this .err.jspError(n.getStart(),
1487:                                            "jsp.error.invalid.expression",
1488:                                            value, e.toString());
1489:                                }
1490:
1491:                            } else {
1492:                                value = value.replace(Constants.ESC, '$');
1493:                                result = new Node.JspAttribute(tai, qName, uri,
1494:                                        localName, value, false, null, dynamic);
1495:                            }
1496:                        }
1497:                    } else {
1498:                        // Value is null. Check for any NamedAttribute subnodes
1499:                        // that might contain the value for this attribute.
1500:                        // Otherwise, the attribute wasn't found so we return null.
1501:
1502:                        Node.NamedAttribute namedAttributeNode = n
1503:                                .getNamedAttributeNode(qName);
1504:                        if (namedAttributeNode != null) {
1505:                            result = new Node.JspAttribute(namedAttributeNode,
1506:                                    tai, dynamic);
1507:                        }
1508:                    }
1509:
1510:                    return result;
1511:                }
1512:
1513:                /*
1514:                 * Return an empty StringBuffer [not thread-safe]
1515:                 */
1516:                private StringBuffer getBuffer() {
1517:                    this .buf.setLength(0);
1518:                    return this .buf;
1519:                }
1520:
1521:                /*
1522:                 * Checks to see if the given attribute value represents a runtime or EL
1523:                 * expression.
1524:                 */
1525:                private boolean isExpression(Node n, String value,
1526:                        boolean checkDeferred) {
1527:
1528:                    boolean runtimeExpression = ((n.getRoot().isXmlSyntax() && value
1529:                            .startsWith("%=")) || (!n.getRoot().isXmlSyntax() && value
1530:                            .startsWith("<%=")));
1531:                    boolean elExpression = false;
1532:
1533:                    if (!runtimeExpression && !pageInfo.isELIgnored()) {
1534:                        Iterator<ELNode> nodes = ELParser.parse(value)
1535:                                .iterator();
1536:                        while (nodes.hasNext()) {
1537:                            ELNode node = nodes.next();
1538:                            if (node instanceof  ELNode.Root) {
1539:                                if (((ELNode.Root) node).getType() == '$') {
1540:                                    elExpression = true;
1541:                                } else if (checkDeferred
1542:                                        && !pageInfo
1543:                                                .isDeferredSyntaxAllowedAsLiteral()
1544:                                        && ((ELNode.Root) node).getType() == '#') {
1545:                                    elExpression = true;
1546:                                }
1547:                            }
1548:                        }
1549:                    }
1550:
1551:                    return runtimeExpression || elExpression;
1552:
1553:                }
1554:
1555:                /*
1556:                 * Throws exception if the value of the attribute with the given name in
1557:                 * the given node is given as an RT or EL expression, but the spec
1558:                 * requires a static value.
1559:                 */
1560:                private void throwErrorIfExpression(Node n, String attrName,
1561:                        String actionName) throws JasperException {
1562:                    if (n.getAttributes() != null
1563:                            && n.getAttributes().getValue(attrName) != null
1564:                            && isExpression(n, n.getAttributes().getValue(
1565:                                    attrName), true)) {
1566:                        err
1567:                                .jspError(
1568:                                        n,
1569:                                        "jsp.error.attribute.standard.non_rt_with_expr",
1570:                                        attrName, actionName);
1571:                    }
1572:                }
1573:
1574:                private static class NamedAttributeVisitor extends Node.Visitor {
1575:                    private boolean hasDynamicContent;
1576:
1577:                    public void doVisit(Node n) throws JasperException {
1578:                        if (!(n instanceof  Node.JspText)
1579:                                && !(n instanceof  Node.TemplateText)) {
1580:                            hasDynamicContent = true;
1581:                        }
1582:                        visitBody(n);
1583:                    }
1584:
1585:                    public boolean hasDynamicContent() {
1586:                        return hasDynamicContent;
1587:                    }
1588:                }
1589:
1590:                private String findUri(String prefix, Node n) {
1591:
1592:                    for (Node p = n; p != null; p = p.getParent()) {
1593:                        Attributes attrs = p.getTaglibAttributes();
1594:                        if (attrs == null) {
1595:                            continue;
1596:                        }
1597:                        for (int i = 0; i < attrs.getLength(); i++) {
1598:                            String name = attrs.getQName(i);
1599:                            int k = name.indexOf(':');
1600:                            if (prefix == null && k < 0) {
1601:                                // prefix not specified and a default ns found
1602:                                return attrs.getValue(i);
1603:                            }
1604:                            if (prefix != null && k >= 0
1605:                                    && prefix.equals(name.substring(k + 1))) {
1606:                                return attrs.getValue(i);
1607:                            }
1608:                        }
1609:                    }
1610:                    return null;
1611:                }
1612:
1613:                /**
1614:                 * Validate functions in EL expressions
1615:                 */
1616:                private void validateFunctions(ELNode.Nodes el, Node n)
1617:                        throws JasperException {
1618:
1619:                    class FVVisitor extends ELNode.Visitor {
1620:
1621:                        Node n;
1622:
1623:                        FVVisitor(Node n) {
1624:                            this .n = n;
1625:                        }
1626:
1627:                        public void visit(ELNode.Function func)
1628:                                throws JasperException {
1629:                            String prefix = func.getPrefix();
1630:                            String function = func.getName();
1631:                            String uri = null;
1632:
1633:                            if (n.getRoot().isXmlSyntax()) {
1634:                                uri = findUri(prefix, n);
1635:                            } else if (prefix != null) {
1636:                                uri = pageInfo.getURI(prefix);
1637:                            }
1638:
1639:                            if (uri == null) {
1640:                                if (prefix == null) {
1641:                                    err.jspError(n,
1642:                                            "jsp.error.noFunctionPrefix",
1643:                                            function);
1644:                                } else {
1645:                                    err
1646:                                            .jspError(
1647:                                                    n,
1648:                                                    "jsp.error.attribute.invalidPrefix",
1649:                                                    prefix);
1650:                                }
1651:                            }
1652:                            TagLibraryInfo taglib = pageInfo.getTaglib(uri);
1653:                            FunctionInfo funcInfo = null;
1654:                            if (taglib != null) {
1655:                                funcInfo = taglib.getFunction(function);
1656:                            }
1657:                            if (funcInfo == null) {
1658:                                err.jspError(n, "jsp.error.noFunction",
1659:                                        function);
1660:                            }
1661:                            // Skip TLD function uniqueness check. Done by Schema ?
1662:                            func.setUri(uri);
1663:                            func.setFunctionInfo(funcInfo);
1664:                            processSignature(func);
1665:                        }
1666:                    }
1667:
1668:                    el.visit(new FVVisitor(n));
1669:                }
1670:
1671:                private void prepareExpression(ELNode.Nodes el, Node n,
1672:                        String expr) throws JasperException {
1673:                    validateFunctions(el, n);
1674:
1675:                    // test it out
1676:                    ELContextImpl ctx = new ELContextImpl();
1677:                    ctx.setFunctionMapper(this .getFunctionMapper(el));
1678:                    ExpressionFactory ef = this .pageInfo.getExpressionFactory();
1679:                    try {
1680:                        ef.createValueExpression(ctx, expr, Object.class);
1681:                    } catch (ELException e) {
1682:
1683:                    }
1684:                }
1685:
1686:                private void processSignature(ELNode.Function func)
1687:                        throws JasperException {
1688:                    func.setMethodName(getMethod(func));
1689:                    func.setParameters(getParameters(func));
1690:                }
1691:
1692:                /**
1693:                 * Get the method name from the signature.
1694:                 */
1695:                private String getMethod(ELNode.Function func)
1696:                        throws JasperException {
1697:                    FunctionInfo funcInfo = func.getFunctionInfo();
1698:                    String signature = funcInfo.getFunctionSignature();
1699:
1700:                    int start = signature.indexOf(' ');
1701:                    if (start < 0) {
1702:                        err.jspError("jsp.error.tld.fn.invalid.signature", func
1703:                                .getPrefix(), func.getName());
1704:                    }
1705:                    int end = signature.indexOf('(');
1706:                    if (end < 0) {
1707:                        err
1708:                                .jspError(
1709:                                        "jsp.error.tld.fn.invalid.signature.parenexpected",
1710:                                        func.getPrefix(), func.getName());
1711:                    }
1712:                    return signature.substring(start + 1, end).trim();
1713:                }
1714:
1715:                /**
1716:                 * Get the parameters types from the function signature.
1717:                 * 
1718:                 * @return An array of parameter class names
1719:                 */
1720:                private String[] getParameters(ELNode.Function func)
1721:                        throws JasperException {
1722:                    FunctionInfo funcInfo = func.getFunctionInfo();
1723:                    String signature = funcInfo.getFunctionSignature();
1724:                    ArrayList<String> params = new ArrayList<String>();
1725:                    // Signature is of the form
1726:                    // <return-type> S <method-name S? '('
1727:                    // < <arg-type> ( ',' <arg-type> )* )? ')'
1728:                    int start = signature.indexOf('(') + 1;
1729:                    boolean lastArg = false;
1730:                    while (true) {
1731:                        int p = signature.indexOf(',', start);
1732:                        if (p < 0) {
1733:                            p = signature.indexOf(')', start);
1734:                            if (p < 0) {
1735:                                err.jspError(
1736:                                        "jsp.error.tld.fn.invalid.signature",
1737:                                        func.getPrefix(), func.getName());
1738:                            }
1739:                            lastArg = true;
1740:                        }
1741:                        String arg = signature.substring(start, p).trim();
1742:                        if (!"".equals(arg)) {
1743:                            params.add(arg);
1744:                        }
1745:                        if (lastArg) {
1746:                            break;
1747:                        }
1748:                        start = p + 1;
1749:                    }
1750:                    return (String[]) params.toArray(new String[params.size()]);
1751:                }
1752:
1753:                private FunctionMapper getFunctionMapper(ELNode.Nodes el)
1754:                        throws JasperException {
1755:
1756:                    class ValidateFunctionMapper extends FunctionMapper {
1757:
1758:                        private HashMap<String, Method> fnmap = new HashMap<String, Method>();
1759:
1760:                        public void mapFunction(String fnQName, Method method) {
1761:                            fnmap.put(fnQName, method);
1762:                        }
1763:
1764:                        public Method resolveFunction(String prefix,
1765:                                String localName) {
1766:                            return this .fnmap.get(prefix + ":" + localName);
1767:                        }
1768:                    }
1769:
1770:                    class MapperELVisitor extends ELNode.Visitor {
1771:                        ValidateFunctionMapper fmapper;
1772:
1773:                        MapperELVisitor(ValidateFunctionMapper fmapper) {
1774:                            this .fmapper = fmapper;
1775:                        }
1776:
1777:                        public void visit(ELNode.Function n)
1778:                                throws JasperException {
1779:
1780:                            Class c = null;
1781:                            Method method = null;
1782:                            try {
1783:                                c = loader.loadClass(n.getFunctionInfo()
1784:                                        .getFunctionClass());
1785:                            } catch (ClassNotFoundException e) {
1786:                                err.jspError(
1787:                                        "jsp.error.function.classnotfound", n
1788:                                                .getFunctionInfo()
1789:                                                .getFunctionClass(), n
1790:                                                .getPrefix()
1791:                                                + ':' + n.getName(), e
1792:                                                .getMessage());
1793:                            }
1794:                            String paramTypes[] = n.getParameters();
1795:                            int size = paramTypes.length;
1796:                            Class params[] = new Class[size];
1797:                            int i = 0;
1798:                            try {
1799:                                for (i = 0; i < size; i++) {
1800:                                    params[i] = JspUtil.toClass(paramTypes[i],
1801:                                            loader);
1802:                                }
1803:                                method = c.getDeclaredMethod(n.getMethodName(),
1804:                                        params);
1805:                            } catch (ClassNotFoundException e) {
1806:                                err.jspError(
1807:                                        "jsp.error.signature.classnotfound",
1808:                                        paramTypes[i], n.getPrefix() + ':'
1809:                                                + n.getName(), e.getMessage());
1810:                            } catch (NoSuchMethodException e) {
1811:                                err.jspError("jsp.error.noFunctionMethod", n
1812:                                        .getMethodName(), n.getName(), c
1813:                                        .getName());
1814:                            }
1815:                            fmapper.mapFunction(n.getPrefix() + ':'
1816:                                    + n.getName(), method);
1817:                        }
1818:                    }
1819:
1820:                    ValidateFunctionMapper fmapper = new ValidateFunctionMapper();
1821:                    el.visit(new MapperELVisitor(fmapper));
1822:                    return fmapper;
1823:                }
1824:            } // End of ValidateVisitor
1825:
1826:            /**
1827:             * A visitor for validating TagExtraInfo classes of all tags
1828:             */
1829:            static class TagExtraInfoVisitor extends Node.Visitor {
1830:
1831:                private ErrorDispatcher err;
1832:
1833:                /*
1834:                 * Constructor
1835:                 */
1836:                TagExtraInfoVisitor(Compiler compiler) {
1837:                    this .err = compiler.getErrorDispatcher();
1838:                }
1839:
1840:                public void visit(Node.CustomTag n) throws JasperException {
1841:                    TagInfo tagInfo = n.getTagInfo();
1842:                    if (tagInfo == null) {
1843:                        err.jspError(n, "jsp.error.missing.tagInfo", n
1844:                                .getQName());
1845:                    }
1846:
1847:                    ValidationMessage[] errors = tagInfo.validate(n
1848:                            .getTagData());
1849:                    if (errors != null && errors.length != 0) {
1850:                        StringBuffer errMsg = new StringBuffer();
1851:                        errMsg.append("<h3>");
1852:                        errMsg.append(Localizer.getMessage(
1853:                                "jsp.error.tei.invalid.attributes", n
1854:                                        .getQName()));
1855:                        errMsg.append("</h3>");
1856:                        for (int i = 0; i < errors.length; i++) {
1857:                            errMsg.append("<p>");
1858:                            if (errors[i].getId() != null) {
1859:                                errMsg.append(errors[i].getId());
1860:                                errMsg.append(": ");
1861:                            }
1862:                            errMsg.append(errors[i].getMessage());
1863:                            errMsg.append("</p>");
1864:                        }
1865:
1866:                        err.jspError(n, errMsg.toString());
1867:                    }
1868:
1869:                    visitBody(n);
1870:                }
1871:            }
1872:
1873:            public static void validate(Compiler compiler, Node.Nodes page)
1874:                    throws JasperException {
1875:
1876:                /*
1877:                 * Visit the page/tag directives first, as they are global to the page
1878:                 * and are position independent.
1879:                 */
1880:                page.visit(new DirectiveVisitor(compiler));
1881:
1882:                // Determine the default output content type
1883:                PageInfo pageInfo = compiler.getPageInfo();
1884:                String contentType = pageInfo.getContentType();
1885:
1886:                if (contentType == null || contentType.indexOf("charset=") < 0) {
1887:                    boolean isXml = page.getRoot().isXmlSyntax();
1888:                    String defaultType;
1889:                    if (contentType == null) {
1890:                        defaultType = isXml ? "text/xml" : "text/html";
1891:                    } else {
1892:                        defaultType = contentType;
1893:                    }
1894:
1895:                    String charset = null;
1896:                    if (isXml) {
1897:                        charset = "UTF-8";
1898:                    } else {
1899:                        if (!page.getRoot().isDefaultPageEncoding()) {
1900:                            charset = page.getRoot().getPageEncoding();
1901:                        }
1902:                    }
1903:
1904:                    if (charset != null) {
1905:                        pageInfo.setContentType(defaultType + ";charset="
1906:                                + charset);
1907:                    } else {
1908:                        pageInfo.setContentType(defaultType);
1909:                    }
1910:                }
1911:
1912:                /*
1913:                 * Validate all other nodes. This validation step includes checking a
1914:                 * custom tag's mandatory and optional attributes against information in
1915:                 * the TLD (first validation step for custom tags according to
1916:                 * JSP.10.5).
1917:                 */
1918:                page.visit(new ValidateVisitor(compiler));
1919:
1920:                /*
1921:                 * Invoke TagLibraryValidator classes of all imported tags (second
1922:                 * validation step for custom tags according to JSP.10.5).
1923:                 */
1924:                validateXmlView(new PageDataImpl(page, compiler), compiler);
1925:
1926:                /*
1927:                 * Invoke TagExtraInfo method isValid() for all imported tags (third
1928:                 * validation step for custom tags according to JSP.10.5).
1929:                 */
1930:                page.visit(new TagExtraInfoVisitor(compiler));
1931:
1932:            }
1933:
1934:            // *********************************************************************
1935:            // Private (utility) methods
1936:
1937:            /**
1938:             * Validate XML view against the TagLibraryValidator classes of all imported
1939:             * tag libraries.
1940:             */
1941:            private static void validateXmlView(PageData xmlView,
1942:                    Compiler compiler) throws JasperException {
1943:
1944:                StringBuffer errMsg = null;
1945:                ErrorDispatcher errDisp = compiler.getErrorDispatcher();
1946:
1947:                for (Iterator iter = compiler.getPageInfo().getTaglibs()
1948:                        .iterator(); iter.hasNext();) {
1949:
1950:                    Object o = iter.next();
1951:                    if (!(o instanceof  TagLibraryInfoImpl))
1952:                        continue;
1953:                    TagLibraryInfoImpl tli = (TagLibraryInfoImpl) o;
1954:
1955:                    ValidationMessage[] errors = tli.validate(xmlView);
1956:                    if ((errors != null) && (errors.length != 0)) {
1957:                        if (errMsg == null) {
1958:                            errMsg = new StringBuffer();
1959:                        }
1960:                        errMsg.append("<h3>");
1961:                        errMsg.append(Localizer.getMessage(
1962:                                "jsp.error.tlv.invalid.page", tli
1963:                                        .getShortName(), compiler.getPageInfo()
1964:                                        .getJspFile()));
1965:                        errMsg.append("</h3>");
1966:                        for (int i = 0; i < errors.length; i++) {
1967:                            if (errors[i] != null) {
1968:                                errMsg.append("<p>");
1969:                                errMsg.append(errors[i].getId());
1970:                                errMsg.append(": ");
1971:                                errMsg.append(errors[i].getMessage());
1972:                                errMsg.append("</p>");
1973:                            }
1974:                        }
1975:                    }
1976:                }
1977:
1978:                if (errMsg != null) {
1979:                    errDisp.jspError(errMsg.toString());
1980:                }
1981:            }
1982:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.