1 17 18 package org.apache.jasper.compiler; 19 20 import java.lang.reflect.Method ; 21 import java.util.ArrayList ; 22 import java.util.HashMap ; 23 import java.util.Hashtable ; 24 import java.util.Iterator ; 25 26 import javax.el.ELException; 27 import javax.el.ExpressionFactory; 28 import javax.el.FunctionMapper; 29 import javax.servlet.jsp.tagext.FunctionInfo ; 30 import javax.servlet.jsp.tagext.JspFragment ; 31 import javax.servlet.jsp.tagext.PageData ; 32 import javax.servlet.jsp.tagext.TagAttributeInfo ; 33 import javax.servlet.jsp.tagext.TagData ; 34 import javax.servlet.jsp.tagext.TagExtraInfo ; 35 import javax.servlet.jsp.tagext.TagInfo ; 36 import javax.servlet.jsp.tagext.TagLibraryInfo ; 37 import javax.servlet.jsp.tagext.ValidationMessage ; 38 39 import org.apache.el.lang.ELSupport; 40 import org.apache.jasper.Constants; 41 import org.apache.jasper.JasperException; 42 import org.apache.jasper.el.ELContextImpl; 43 import org.xml.sax.Attributes ; 44 45 56 class Validator { 57 58 61 static class DirectiveVisitor extends Node.Visitor { 62 63 private PageInfo pageInfo; 64 65 private ErrorDispatcher err; 66 67 private static final JspUtil.ValidAttribute[] pageDirectiveAttrs = { 68 new JspUtil.ValidAttribute("language"), 69 new JspUtil.ValidAttribute("extends"), 70 new JspUtil.ValidAttribute("import"), 71 new JspUtil.ValidAttribute("session"), 72 new JspUtil.ValidAttribute("buffer"), 73 new JspUtil.ValidAttribute("autoFlush"), 74 new JspUtil.ValidAttribute("isThreadSafe"), 75 new JspUtil.ValidAttribute("info"), 76 new JspUtil.ValidAttribute("errorPage"), 77 new JspUtil.ValidAttribute("isErrorPage"), 78 new JspUtil.ValidAttribute("contentType"), 79 new JspUtil.ValidAttribute("pageEncoding"), 80 new JspUtil.ValidAttribute("isELIgnored"), 81 new JspUtil.ValidAttribute("deferredSyntaxAllowedAsLiteral"), 82 new JspUtil.ValidAttribute("trimDirectiveWhitespaces") 83 }; 84 85 private boolean pageEncodingSeen = false; 86 87 90 DirectiveVisitor(Compiler compiler) throws JasperException { 91 this.pageInfo = compiler.getPageInfo(); 92 this.err = compiler.getErrorDispatcher(); 93 } 94 95 public void visit(Node.IncludeDirective n) throws JasperException { 96 boolean pageEncodingSeenSave = pageEncodingSeen; 99 pageEncodingSeen = false; 100 visitBody(n); 101 pageEncodingSeen = pageEncodingSeenSave; 102 } 103 104 public void visit(Node.PageDirective n) throws JasperException { 105 106 JspUtil.checkAttributes("Page directive", n, pageDirectiveAttrs, 107 err); 108 109 Attributes attrs = n.getAttributes(); 111 for (int i = 0; attrs != null && i < attrs.getLength(); i++) { 112 String attr = attrs.getQName(i); 113 String value = attrs.getValue(i); 114 115 if ("language".equals(attr)) { 116 if (pageInfo.getLanguage(false) == null) { 117 pageInfo.setLanguage(value, n, err, true); 118 } else if (!pageInfo.getLanguage(false).equals(value)) { 119 err.jspError(n, "jsp.error.page.conflict.language", 120 pageInfo.getLanguage(false), value); 121 } 122 } else if ("extends".equals(attr)) { 123 if (pageInfo.getExtends(false) == null) { 124 pageInfo.setExtends(value, n); 125 } else if (!pageInfo.getExtends(false).equals(value)) { 126 err.jspError(n, "jsp.error.page.conflict.extends", 127 pageInfo.getExtends(false), value); 128 } 129 } else if ("contentType".equals(attr)) { 130 if (pageInfo.getContentType() == null) { 131 pageInfo.setContentType(value); 132 } else if (!pageInfo.getContentType().equals(value)) { 133 err.jspError(n, "jsp.error.page.conflict.contenttype", 134 pageInfo.getContentType(), value); 135 } 136 } else if ("session".equals(attr)) { 137 if (pageInfo.getSession() == null) { 138 pageInfo.setSession(value, n, err); 139 } else if (!pageInfo.getSession().equals(value)) { 140 err.jspError(n, "jsp.error.page.conflict.session", 141 pageInfo.getSession(), value); 142 } 143 } else if ("buffer".equals(attr)) { 144 if (pageInfo.getBufferValue() == null) { 145 pageInfo.setBufferValue(value, n, err); 146 } else if (!pageInfo.getBufferValue().equals(value)) { 147 err.jspError(n, "jsp.error.page.conflict.buffer", 148 pageInfo.getBufferValue(), value); 149 } 150 } else if ("autoFlush".equals(attr)) { 151 if (pageInfo.getAutoFlush() == null) { 152 pageInfo.setAutoFlush(value, n, err); 153 } else if (!pageInfo.getAutoFlush().equals(value)) { 154 err.jspError(n, "jsp.error.page.conflict.autoflush", 155 pageInfo.getAutoFlush(), value); 156 } 157 } else if ("isThreadSafe".equals(attr)) { 158 if (pageInfo.getIsThreadSafe() == null) { 159 pageInfo.setIsThreadSafe(value, n, err); 160 } else if (!pageInfo.getIsThreadSafe().equals(value)) { 161 err.jspError(n, "jsp.error.page.conflict.isthreadsafe", 162 pageInfo.getIsThreadSafe(), value); 163 } 164 } else if ("isELIgnored".equals(attr)) { 165 if (pageInfo.getIsELIgnored() == null) { 166 pageInfo.setIsELIgnored(value, n, err, true); 167 } else if (!pageInfo.getIsELIgnored().equals(value)) { 168 err.jspError(n, "jsp.error.page.conflict.iselignored", 169 pageInfo.getIsELIgnored(), value); 170 } 171 } else if ("isErrorPage".equals(attr)) { 172 if (pageInfo.getIsErrorPage() == null) { 173 pageInfo.setIsErrorPage(value, n, err); 174 } else if (!pageInfo.getIsErrorPage().equals(value)) { 175 err.jspError(n, "jsp.error.page.conflict.iserrorpage", 176 pageInfo.getIsErrorPage(), value); 177 } 178 } else if ("errorPage".equals(attr)) { 179 if (pageInfo.getErrorPage() == null) { 180 pageInfo.setErrorPage(value); 181 } else if (!pageInfo.getErrorPage().equals(value)) { 182 err.jspError(n, "jsp.error.page.conflict.errorpage", 183 pageInfo.getErrorPage(), value); 184 } 185 } else if ("info".equals(attr)) { 186 if (pageInfo.getInfo() == null) { 187 pageInfo.setInfo(value); 188 } else if (!pageInfo.getInfo().equals(value)) { 189 err.jspError(n, "jsp.error.page.conflict.info", 190 pageInfo.getInfo(), value); 191 } 192 } else if ("pageEncoding".equals(attr)) { 193 if (pageEncodingSeen) 194 err.jspError(n, "jsp.error.page.multi.pageencoding"); 195 pageEncodingSeen = true; 197 String actual = comparePageEncodings(value, n); 198 n.getRoot().setPageEncoding(actual); 199 } else if ("deferredSyntaxAllowedAsLiteral".equals(attr)) { 200 if (pageInfo.getDeferredSyntaxAllowedAsLiteral() == null) { 201 pageInfo.setDeferredSyntaxAllowedAsLiteral(value, n, 202 err, true); 203 } else if (!pageInfo.getDeferredSyntaxAllowedAsLiteral() 204 .equals(value)) { 205 err 206 .jspError( 207 n, 208 "jsp.error.page.conflict.deferredsyntaxallowedasliteral", 209 pageInfo 210 .getDeferredSyntaxAllowedAsLiteral(), 211 value); 212 } 213 } else if ("trimDirectiveWhitespaces".equals(attr)) { 214 if (pageInfo.getTrimDirectiveWhitespaces() == null) { 215 pageInfo.setTrimDirectiveWhitespaces(value, n, err, 216 true); 217 } else if (!pageInfo.getTrimDirectiveWhitespaces().equals( 218 value)) { 219 err 220 .jspError( 221 n, 222 "jsp.error.page.conflict.trimdirectivewhitespaces", 223 pageInfo.getTrimDirectiveWhitespaces(), 224 value); 225 } 226 } 227 } 228 229 if (pageInfo.getBuffer() == 0 && !pageInfo.isAutoFlush()) 231 err.jspError(n, "jsp.error.page.badCombo"); 232 233 pageInfo.addImports(n.getImports()); 236 } 237 238 public void visit(Node.TagDirective n) throws JasperException { 239 243 245 Attributes attrs = n.getAttributes(); 246 for (int i = 0; attrs != null && i < attrs.getLength(); i++) { 247 String attr = attrs.getQName(i); 248 String value = attrs.getValue(i); 249 250 if ("language".equals(attr)) { 251 if (pageInfo.getLanguage(false) == null) { 252 pageInfo.setLanguage(value, n, err, false); 253 } else if (!pageInfo.getLanguage(false).equals(value)) { 254 err.jspError(n, "jsp.error.tag.conflict.language", 255 pageInfo.getLanguage(false), value); 256 } 257 } else if ("isELIgnored".equals(attr)) { 258 if (pageInfo.getIsELIgnored() == null) { 259 pageInfo.setIsELIgnored(value, n, err, false); 260 } else if (!pageInfo.getIsELIgnored().equals(value)) { 261 err.jspError(n, "jsp.error.tag.conflict.iselignored", 262 pageInfo.getIsELIgnored(), value); 263 } 264 } else if ("pageEncoding".equals(attr)) { 265 if (pageEncodingSeen) 266 err.jspError(n, "jsp.error.tag.multi.pageencoding"); 267 pageEncodingSeen = true; 268 compareTagEncodings(value, n); 269 n.getRoot().setPageEncoding(value); 270 } else if ("deferredSyntaxAllowedAsLiteral".equals(attr)) { 271 if (pageInfo.getDeferredSyntaxAllowedAsLiteral() == null) { 272 pageInfo.setDeferredSyntaxAllowedAsLiteral(value, n, 273 err, false); 274 } else if (!pageInfo.getDeferredSyntaxAllowedAsLiteral() 275 .equals(value)) { 276 err 277 .jspError( 278 n, 279 "jsp.error.tag.conflict.deferredsyntaxallowedasliteral", 280 pageInfo 281 .getDeferredSyntaxAllowedAsLiteral(), 282 value); 283 } 284 } else if ("trimDirectiveWhitespaces".equals(attr)) { 285 if (pageInfo.getTrimDirectiveWhitespaces() == null) { 286 pageInfo.setTrimDirectiveWhitespaces(value, n, err, 287 false); 288 } else if (!pageInfo.getTrimDirectiveWhitespaces().equals( 289 value)) { 290 err 291 .jspError( 292 n, 293 "jsp.error.tag.conflict.trimdirectivewhitespaces", 294 pageInfo.getTrimDirectiveWhitespaces(), 295 value); 296 } 297 } 298 } 299 300 pageInfo.addImports(n.getImports()); 303 } 304 305 public void visit(Node.AttributeDirective n) throws JasperException { 306 } 310 311 public void visit(Node.VariableDirective n) throws JasperException { 312 } 316 317 326 private String comparePageEncodings(String pageDirEnc, 327 Node.PageDirective pageDir) throws JasperException { 328 329 Node.Root root = pageDir.getRoot(); 330 String configEnc = root.getJspConfigPageEncoding(); 331 332 338 if (configEnc != null) { 339 if (!pageDirEnc.equals(configEnc) 340 && (!pageDirEnc.startsWith("UTF-16") || !configEnc 341 .startsWith("UTF-16"))) { 342 err.jspError(pageDir, 343 "jsp.error.config_pagedir_encoding_mismatch", 344 configEnc, pageDirEnc); 345 } else { 346 return configEnc; 347 } 348 } 349 350 357 if ((root.isXmlSyntax() && root.isEncodingSpecifiedInProlog()) || root.isBomPresent()) { 358 String pageEnc = root.getPageEncoding(); 359 if (!pageDirEnc.equals(pageEnc) 360 && (!pageDirEnc.startsWith("UTF-16") || !pageEnc 361 .startsWith("UTF-16"))) { 362 err.jspError(pageDir, 363 "jsp.error.prolog_pagedir_encoding_mismatch", 364 pageEnc, pageDirEnc); 365 } else { 366 return pageEnc; 367 } 368 } 369 370 return pageDirEnc; 371 } 372 373 382 private void compareTagEncodings(String pageDirEnc, 383 Node.TagDirective pageDir) throws JasperException { 384 385 Node.Root root = pageDir.getRoot(); 386 387 394 if ((root.isXmlSyntax() && root.isEncodingSpecifiedInProlog()) || root.isBomPresent()) { 395 String pageEnc = root.getPageEncoding(); 396 if (!pageDirEnc.equals(pageEnc) 397 && (!pageDirEnc.startsWith("UTF-16") || !pageEnc 398 .startsWith("UTF-16"))) { 399 err.jspError(pageDir, 400 "jsp.error.prolog_pagedir_encoding_mismatch", 401 pageEnc, pageDirEnc); 402 } 403 } 404 } 405 406 } 407 408 411 static class ValidateVisitor extends Node.Visitor { 412 413 private PageInfo pageInfo; 414 415 private ErrorDispatcher err; 416 417 private TagInfo tagInfo; 418 419 private ClassLoader loader; 420 421 private final StringBuffer buf = new StringBuffer (32); 422 423 private static final JspUtil.ValidAttribute[] jspRootAttrs = { 424 new JspUtil.ValidAttribute("xsi:schemaLocation"), 425 new JspUtil.ValidAttribute("version", true) }; 426 427 private static final JspUtil.ValidAttribute[] includeDirectiveAttrs = { new JspUtil.ValidAttribute( 428 "file", true) }; 429 430 private static final JspUtil.ValidAttribute[] taglibDirectiveAttrs = { 431 new JspUtil.ValidAttribute("uri"), 432 new JspUtil.ValidAttribute("tagdir"), 433 new JspUtil.ValidAttribute("prefix", true) }; 434 435 private static final JspUtil.ValidAttribute[] includeActionAttrs = { 436 new JspUtil.ValidAttribute("page", true, true), 437 new JspUtil.ValidAttribute("flush") }; 438 439 private static final JspUtil.ValidAttribute[] paramActionAttrs = { 440 new JspUtil.ValidAttribute("name", true), 441 new JspUtil.ValidAttribute("value", true, true) }; 442 443 private static final JspUtil.ValidAttribute[] forwardActionAttrs = { new JspUtil.ValidAttribute( 444 "page", true, true) }; 445 446 private static final JspUtil.ValidAttribute[] getPropertyAttrs = { 447 new JspUtil.ValidAttribute("name", true), 448 new JspUtil.ValidAttribute("property", true) }; 449 450 private static final JspUtil.ValidAttribute[] setPropertyAttrs = { 451 new JspUtil.ValidAttribute("name", true), 452 new JspUtil.ValidAttribute("property", true), 453 new JspUtil.ValidAttribute("value", false, true), 454 new JspUtil.ValidAttribute("param") }; 455 456 private static final JspUtil.ValidAttribute[] useBeanAttrs = { 457 new JspUtil.ValidAttribute("id", true), 458 new JspUtil.ValidAttribute("scope"), 459 new JspUtil.ValidAttribute("class"), 460 new JspUtil.ValidAttribute("type"), 461 new JspUtil.ValidAttribute("beanName", false, true) }; 462 463 private static final JspUtil.ValidAttribute[] plugInAttrs = { 464 new JspUtil.ValidAttribute("type", true), 465 new JspUtil.ValidAttribute("code", true), 466 new JspUtil.ValidAttribute("codebase"), 467 new JspUtil.ValidAttribute("align"), 468 new JspUtil.ValidAttribute("archive"), 469 new JspUtil.ValidAttribute("height", false, true), 470 new JspUtil.ValidAttribute("hspace"), 471 new JspUtil.ValidAttribute("jreversion"), 472 new JspUtil.ValidAttribute("name"), 473 new JspUtil.ValidAttribute("vspace"), 474 new JspUtil.ValidAttribute("width", false, true), 475 new JspUtil.ValidAttribute("nspluginurl"), 476 new JspUtil.ValidAttribute("iepluginurl") }; 477 478 private static final JspUtil.ValidAttribute[] attributeAttrs = { 479 new JspUtil.ValidAttribute("name", true), 480 new JspUtil.ValidAttribute("trim") }; 481 482 private static final JspUtil.ValidAttribute[] invokeAttrs = { 483 new JspUtil.ValidAttribute("fragment", true), 484 new JspUtil.ValidAttribute("var"), 485 new JspUtil.ValidAttribute("varReader"), 486 new JspUtil.ValidAttribute("scope") }; 487 488 private static final JspUtil.ValidAttribute[] doBodyAttrs = { 489 new JspUtil.ValidAttribute("var"), 490 new JspUtil.ValidAttribute("varReader"), 491 new JspUtil.ValidAttribute("scope") }; 492 493 private static final JspUtil.ValidAttribute[] jspOutputAttrs = { 494 new JspUtil.ValidAttribute("omit-xml-declaration"), 495 new JspUtil.ValidAttribute("doctype-root-element"), 496 new JspUtil.ValidAttribute("doctype-public"), 497 new JspUtil.ValidAttribute("doctype-system") }; 498 499 502 ValidateVisitor(Compiler compiler) { 503 this.pageInfo = compiler.getPageInfo(); 504 this.err = compiler.getErrorDispatcher(); 505 this.tagInfo = compiler.getCompilationContext().getTagInfo(); 506 this.loader = compiler.getCompilationContext().getClassLoader(); 507 } 508 509 public void visit(Node.JspRoot n) throws JasperException { 510 JspUtil.checkAttributes("Jsp:root", n, jspRootAttrs, err); 511 String version = n.getTextAttribute("version"); 512 if (!version.equals("1.2") && !version.equals("2.0")) { 513 err.jspError(n, "jsp.error.jsproot.version.invalid", version); 514 } 515 visitBody(n); 516 } 517 518 public void visit(Node.IncludeDirective n) throws JasperException { 519 JspUtil.checkAttributes("Include directive", n, 520 includeDirectiveAttrs, err); 521 visitBody(n); 522 } 523 524 public void visit(Node.TaglibDirective n) throws JasperException { 525 JspUtil.checkAttributes("Taglib directive", n, 526 taglibDirectiveAttrs, err); 527 String uri = n.getAttributeValue("uri"); 529 String tagdir = n.getAttributeValue("tagdir"); 530 if (uri == null && tagdir == null) { 531 err.jspError(n, "jsp.error.taglibDirective.missing.location"); 532 } 533 if (uri != null && tagdir != null) { 534 err 535 .jspError(n, 536 "jsp.error.taglibDirective.both_uri_and_tagdir"); 537 } 538 } 539 540 public void visit(Node.ParamAction n) throws JasperException { 541 JspUtil.checkAttributes("Param action", n, paramActionAttrs, err); 542 throwErrorIfExpression(n, "name", "jsp:param"); 545 n.setValue(getJspAttribute(null, "value", null, null, n 546 .getAttributeValue("value"), java.lang.String .class, n, 547 false)); 548 visitBody(n); 549 } 550 551 public void visit(Node.ParamsAction n) throws JasperException { 552 Node.Nodes subElems = n.getBody(); 554 if (subElems == null) { 555 err.jspError(n, "jsp.error.params.emptyBody"); 556 } 557 visitBody(n); 558 } 559 560 public void visit(Node.IncludeAction n) throws JasperException { 561 JspUtil.checkAttributes("Include action", n, includeActionAttrs, 562 err); 563 n.setPage(getJspAttribute(null, "page", null, null, n 564 .getAttributeValue("page"), java.lang.String .class, n, 565 false)); 566 visitBody(n); 567 }; 568 569 public void visit(Node.ForwardAction n) throws JasperException { 570 JspUtil.checkAttributes("Forward", n, forwardActionAttrs, err); 571 n.setPage(getJspAttribute(null, "page", null, null, n 572 .getAttributeValue("page"), java.lang.String .class, n, 573 false)); 574 visitBody(n); 575 } 576 577 public void visit(Node.GetProperty n) throws JasperException { 578 JspUtil.checkAttributes("GetProperty", n, getPropertyAttrs, err); 579 } 580 581 public void visit(Node.SetProperty n) throws JasperException { 582 JspUtil.checkAttributes("SetProperty", n, setPropertyAttrs, err); 583 String property = n.getTextAttribute("property"); 584 String param = n.getTextAttribute("param"); 585 String value = n.getAttributeValue("value"); 586 587 n.setValue(getJspAttribute(null, "value", null, null, value, 588 java.lang.Object .class, n, false)); 589 590 boolean valueSpecified = n.getValue() != null; 591 592 if ("*".equals(property)) { 593 if (param != null || valueSpecified) 594 err.jspError(n, "jsp.error.setProperty.invalid"); 595 596 } else if (param != null && valueSpecified) { 597 err.jspError(n, "jsp.error.setProperty.invalid"); 598 } 599 600 visitBody(n); 601 } 602 603 public void visit(Node.UseBean n) throws JasperException { 604 JspUtil.checkAttributes("UseBean", n, useBeanAttrs, err); 605 606 String name = n.getTextAttribute("id"); 607 String scope = n.getTextAttribute("scope"); 608 JspUtil.checkScope(scope, n, err); 609 String className = n.getTextAttribute("class"); 610 String type = n.getTextAttribute("type"); 611 BeanRepository beanInfo = pageInfo.getBeanRepository(); 612 613 if (className == null && type == null) 614 err.jspError(n, "jsp.error.usebean.missingType"); 615 616 if (beanInfo.checkVariable(name)) 617 err.jspError(n, "jsp.error.usebean.duplicate"); 618 619 if ("session".equals(scope) && !pageInfo.isSession()) 620 err.jspError(n, "jsp.error.usebean.noSession"); 621 622 Node.JspAttribute jattr = getJspAttribute(null, "beanName", null, 623 null, n.getAttributeValue("beanName"), 624 java.lang.String .class, n, false); 625 n.setBeanName(jattr); 626 if (className != null && jattr != null) 627 err.jspError(n, "jsp.error.usebean.notBoth"); 628 629 if (className == null) 630 className = type; 631 632 beanInfo.addBean(n, name, className, scope); 633 634 visitBody(n); 635 } 636 637 public void visit(Node.PlugIn n) throws JasperException { 638 JspUtil.checkAttributes("Plugin", n, plugInAttrs, err); 639 640 throwErrorIfExpression(n, "type", "jsp:plugin"); 641 throwErrorIfExpression(n, "code", "jsp:plugin"); 642 throwErrorIfExpression(n, "codebase", "jsp:plugin"); 643 throwErrorIfExpression(n, "align", "jsp:plugin"); 644 throwErrorIfExpression(n, "archive", "jsp:plugin"); 645 throwErrorIfExpression(n, "hspace", "jsp:plugin"); 646 throwErrorIfExpression(n, "jreversion", "jsp:plugin"); 647 throwErrorIfExpression(n, "name", "jsp:plugin"); 648 throwErrorIfExpression(n, "vspace", "jsp:plugin"); 649 throwErrorIfExpression(n, "nspluginurl", "jsp:plugin"); 650 throwErrorIfExpression(n, "iepluginurl", "jsp:plugin"); 651 652 String type = n.getTextAttribute("type"); 653 if (type == null) 654 err.jspError(n, "jsp.error.plugin.notype"); 655 if (!type.equals("bean") && !type.equals("applet")) 656 err.jspError(n, "jsp.error.plugin.badtype"); 657 if (n.getTextAttribute("code") == null) 658 err.jspError(n, "jsp.error.plugin.nocode"); 659 660 Node.JspAttribute width = getJspAttribute(null, "width", null, 661 null, n.getAttributeValue("width"), java.lang.String .class, 662 n, false); 663 n.setWidth(width); 664 665 Node.JspAttribute height = getJspAttribute(null, "height", null, 666 null, n.getAttributeValue("height"), 667 java.lang.String .class, n, false); 668 n.setHeight(height); 669 670 visitBody(n); 671 } 672 673 public void visit(Node.NamedAttribute n) throws JasperException { 674 JspUtil.checkAttributes("Attribute", n, attributeAttrs, err); 675 visitBody(n); 676 } 677 678 public void visit(Node.JspBody n) throws JasperException { 679 visitBody(n); 680 } 681 682 public void visit(Node.Declaration n) throws JasperException { 683 if (pageInfo.isScriptingInvalid()) { 684 err.jspError(n.getStart(), "jsp.error.no.scriptlets"); 685 } 686 } 687 688 public void visit(Node.Expression n) throws JasperException { 689 if (pageInfo.isScriptingInvalid()) { 690 err.jspError(n.getStart(), "jsp.error.no.scriptlets"); 691 } 692 } 693 694 public void visit(Node.Scriptlet n) throws JasperException { 695 if (pageInfo.isScriptingInvalid()) { 696 err.jspError(n.getStart(), "jsp.error.no.scriptlets"); 697 } 698 } 699 700 public void visit(Node.ELExpression n) throws JasperException { 701 if (pageInfo.isELIgnored()) 703 return; 704 705 if (n.getType() == '#') { 707 if (!pageInfo.isDeferredSyntaxAllowedAsLiteral() 708 && (tagInfo == null 709 || ((tagInfo != null) && !tagInfo.getTagLibrary().getRequiredVersion().equals("2.0")))) { 710 err.jspError(n, "jsp.error.el.template.deferred"); 711 } else { 712 return; 713 } 714 } 715 716 StringBuffer expr = this.getBuffer(); 718 expr.append(n.getType()).append('{').append(n.getText()) 719 .append('}'); 720 ELNode.Nodes el = ELParser.parse(expr.toString()); 721 722 prepareExpression(el, n, expr.toString()); 724 725 n.setEL(el); 727 } 728 729 public void visit(Node.UninterpretedTag n) throws JasperException { 730 if (n.getNamedAttributeNodes().size() != 0) { 731 err.jspError(n, "jsp.error.namedAttribute.invalidUse"); 732 } 733 734 Attributes attrs = n.getAttributes(); 735 if (attrs != null) { 736 int attrSize = attrs.getLength(); 737 Node.JspAttribute[] jspAttrs = new Node.JspAttribute[attrSize]; 738 for (int i = 0; i < attrSize; i++) { 739 jspAttrs[i] = getJspAttribute(null, attrs.getQName(i), 740 attrs.getURI(i), attrs.getLocalName(i), attrs 741 .getValue(i), java.lang.Object .class, n, 742 false); 743 } 744 n.setJspAttributes(jspAttrs); 745 } 746 747 visitBody(n); 748 } 749 750 public void visit(Node.CustomTag n) throws JasperException { 751 752 TagInfo tagInfo = n.getTagInfo(); 753 if (tagInfo == null) { 754 err.jspError(n, "jsp.error.missing.tagInfo", n.getQName()); 755 } 756 757 760 if (n.implementsSimpleTag() 761 && tagInfo.getBodyContent().equalsIgnoreCase( 762 TagInfo.BODY_CONTENT_JSP)) { 763 err.jspError(n, "jsp.error.simpletag.badbodycontent", tagInfo 764 .getTagClassName()); 765 } 766 767 772 if (tagInfo.hasDynamicAttributes() 773 && !n.implementsDynamicAttributes()) { 774 err.jspError(n, "jsp.error.dynamic.attributes.not.implemented", 775 n.getQName()); 776 } 777 778 784 TagAttributeInfo [] tldAttrs = tagInfo.getAttributes(); 785 String customActionUri = n.getURI(); 786 Attributes attrs = n.getAttributes(); 787 int attrsSize = (attrs == null) ? 0 : attrs.getLength(); 788 for (int i = 0; i < tldAttrs.length; i++) { 789 String attr = null; 790 if (attrs != null) { 791 attr = attrs.getValue(tldAttrs[i].getName()); 792 if (attr == null) { 793 attr = attrs.getValue(customActionUri, tldAttrs[i] 794 .getName()); 795 } 796 } 797 Node.NamedAttribute na = n.getNamedAttributeNode(tldAttrs[i] 798 .getName()); 799 800 if (tldAttrs[i].isRequired() && attr == null && na == null) { 801 err.jspError(n, "jsp.error.missing_attribute", tldAttrs[i] 802 .getName(), n.getLocalName()); 803 } 804 if (attr != null && na != null) { 805 err.jspError(n, "jsp.error.duplicate.name.jspattribute", 806 tldAttrs[i].getName()); 807 } 808 } 809 810 Node.Nodes naNodes = n.getNamedAttributeNodes(); 811 int jspAttrsSize = naNodes.size() + attrsSize; 812 Node.JspAttribute[] jspAttrs = null; 813 if (jspAttrsSize > 0) { 814 jspAttrs = new Node.JspAttribute[jspAttrsSize]; 815 } 816 Hashtable <String , Object > tagDataAttrs = new Hashtable <String , Object >(attrsSize); 817 818 checkXmlAttributes(n, jspAttrs, tagDataAttrs); 819 checkNamedAttributes(n, jspAttrs, attrsSize, tagDataAttrs); 820 821 TagData tagData = new TagData (tagDataAttrs); 822 823 TagExtraInfo tei = tagInfo.getTagExtraInfo(); 827 if (tei != null && tei.getVariableInfo(tagData) != null 828 && tei.getVariableInfo(tagData).length > 0 829 && tagInfo.getTagVariableInfos().length > 0) { 830 err.jspError("jsp.error.non_null_tei_and_var_subelems", n 831 .getQName()); 832 } 833 834 n.setTagData(tagData); 835 n.setJspAttributes(jspAttrs); 836 837 visitBody(n); 838 } 839 840 public void visit(Node.JspElement n) throws JasperException { 841 842 Attributes attrs = n.getAttributes(); 843 if (attrs == null) { 844 err.jspError(n, "jsp.error.jspelement.missing.name"); 845 } 846 int xmlAttrLen = attrs.getLength(); 847 848 Node.Nodes namedAttrs = n.getNamedAttributeNodes(); 849 850 int jspAttrSize = xmlAttrLen - 1 + namedAttrs.size(); 853 854 Node.JspAttribute[] jspAttrs = new Node.JspAttribute[jspAttrSize]; 855 int jspAttrIndex = 0; 856 857 for (int i = 0; i < xmlAttrLen; i++) { 859 if ("name".equals(attrs.getLocalName(i))) { 860 n.setNameAttribute(getJspAttribute(null, attrs.getQName(i), 861 attrs.getURI(i), attrs.getLocalName(i), attrs 862 .getValue(i), java.lang.String .class, n, 863 false)); 864 } else { 865 if (jspAttrIndex < jspAttrSize) { 866 jspAttrs[jspAttrIndex++] = getJspAttribute(null, attrs 867 .getQName(i), attrs.getURI(i), attrs 868 .getLocalName(i), attrs.getValue(i), 869 java.lang.Object .class, n, false); 870 } 871 } 872 } 873 if (n.getNameAttribute() == null) { 874 err.jspError(n, "jsp.error.jspelement.missing.name"); 875 } 876 877 for (int i = 0; i < namedAttrs.size(); i++) { 879 Node.NamedAttribute na = (Node.NamedAttribute) namedAttrs 880 .getNode(i); 881 jspAttrs[jspAttrIndex++] = new Node.JspAttribute(na, null, 882 false); 883 } 884 885 n.setJspAttributes(jspAttrs); 886 887 visitBody(n); 888 } 889 890 public void visit(Node.JspOutput n) throws JasperException { 891 JspUtil.checkAttributes("jsp:output", n, jspOutputAttrs, err); 892 893 if (n.getBody() != null) { 894 err.jspError(n, "jsp.error.jspoutput.nonemptybody"); 895 } 896 897 String omitXmlDecl = n.getAttributeValue("omit-xml-declaration"); 898 String doctypeName = n.getAttributeValue("doctype-root-element"); 899 String doctypePublic = n.getAttributeValue("doctype-public"); 900 String doctypeSystem = n.getAttributeValue("doctype-system"); 901 902 String omitXmlDeclOld = pageInfo.getOmitXmlDecl(); 903 String doctypeNameOld = pageInfo.getDoctypeName(); 904 String doctypePublicOld = pageInfo.getDoctypePublic(); 905 String doctypeSystemOld = pageInfo.getDoctypeSystem(); 906 907 if (omitXmlDecl != null && omitXmlDeclOld != null 908 && !omitXmlDecl.equals(omitXmlDeclOld)) { 909 err.jspError(n, "jsp.error.jspoutput.conflict", 910 "omit-xml-declaration", omitXmlDeclOld, omitXmlDecl); 911 } 912 913 if (doctypeName != null && doctypeNameOld != null 914 && !doctypeName.equals(doctypeNameOld)) { 915 err.jspError(n, "jsp.error.jspoutput.conflict", 916 "doctype-root-element", doctypeNameOld, doctypeName); 917 } 918 919 if (doctypePublic != null && doctypePublicOld != null 920 && !doctypePublic.equals(doctypePublicOld)) { 921 err.jspError(n, "jsp.error.jspoutput.conflict", 922 "doctype-public", doctypePublicOld, doctypePublic); 923 } 924 925 if (doctypeSystem != null && doctypeSystemOld != null 926 && !doctypeSystem.equals(doctypeSystemOld)) { 927 err.jspError(n, "jsp.error.jspoutput.conflict", 928 "doctype-system", doctypeSystemOld, doctypeSystem); 929 } 930 931 if (doctypeName == null && doctypeSystem != null 932 || doctypeName != null && doctypeSystem == null) { 933 err.jspError(n, "jsp.error.jspoutput.doctypenamesystem"); 934 } 935 936 if (doctypePublic != null && doctypeSystem == null) { 937 err.jspError(n, "jsp.error.jspoutput.doctypepulicsystem"); 938 } 939 940 if (omitXmlDecl != null) { 941 pageInfo.setOmitXmlDecl(omitXmlDecl); 942 } 943 if (doctypeName != null) { 944 pageInfo.setDoctypeName(doctypeName); 945 } 946 if (doctypeSystem != null) { 947 pageInfo.setDoctypeSystem(doctypeSystem); 948 } 949 if (doctypePublic != null) { 950 pageInfo.setDoctypePublic(doctypePublic); 951 } 952 } 953 954 public void visit(Node.InvokeAction n) throws JasperException { 955 956 JspUtil.checkAttributes("Invoke", n, invokeAttrs, err); 957 958 String scope = n.getTextAttribute("scope"); 959 JspUtil.checkScope(scope, n, err); 960 961 String var = n.getTextAttribute("var"); 962 String varReader = n.getTextAttribute("varReader"); 963 if (scope != null && var == null && varReader == null) { 964 err.jspError(n, "jsp.error.missing_var_or_varReader"); 965 } 966 if (var != null && varReader != null) { 967 err.jspError(n, "jsp.error.var_and_varReader"); 968 } 969 } 970 971 public void visit(Node.DoBodyAction n) throws JasperException { 972 973 JspUtil.checkAttributes("DoBody", n, doBodyAttrs, err); 974 975 String scope = n.getTextAttribute("scope"); 976 JspUtil.checkScope(scope, n, err); 977 978 String var = n.getTextAttribute("var"); 979 String varReader = n.getTextAttribute("varReader"); 980 if (scope != null && var == null && varReader == null) { 981 err.jspError(n, "jsp.error.missing_var_or_varReader"); 982 } 983 if (var != null && varReader != null) { 984 err.jspError(n, "jsp.error.var_and_varReader"); 985 } 986 } 987 988 1009 private void checkXmlAttributes(Node.CustomTag n, 1010 Node.JspAttribute[] jspAttrs, Hashtable <String , Object > tagDataAttrs) 1011 throws JasperException { 1012 1013 TagInfo tagInfo = n.getTagInfo(); 1014 if (tagInfo == null) { 1015 err.jspError(n, "jsp.error.missing.tagInfo", n.getQName()); 1016 } 1017 TagAttributeInfo [] tldAttrs = tagInfo.getAttributes(); 1018 Attributes attrs = n.getAttributes(); 1019 1020 for (int i = 0; attrs != null && i < attrs.getLength(); i++) { 1021 boolean found = false; 1022 for (int j = 0; tldAttrs != null && j < tldAttrs.length; j++) { 1023 if (attrs.getLocalName(i).equals(tldAttrs[j].getName()) 1024 && (attrs.getURI(i) == null 1025 || attrs.getURI(i).length() == 0 || attrs 1026 .getURI(i).equals(n.getURI()))) { 1027 boolean checkDeferred = !tagInfo.getTagLibrary().getRequiredVersion().equals("2.0"); 1028 boolean deferred = false; 1029 boolean deferredValueIsLiteral = false; 1030 boolean expression = isExpression(n, attrs.getValue(i), checkDeferred); 1031 if (checkDeferred && attrs.getValue(i).indexOf("#{") != -1) { 1032 deferred = true; 1033 if (pageInfo.isELIgnored()) { 1034 deferredValueIsLiteral = true; 1035 } 1036 } 1037 1038 if (tldAttrs[j].canBeRequestTime() 1039 || tldAttrs[j].isDeferredMethod() || tldAttrs[j].isDeferredValue()) { 1041 if (!expression) { 1042 1043 if (deferredValueIsLiteral && !pageInfo.isDeferredSyntaxAllowedAsLiteral()) { 1044 err.jspError(n, "jsp.error.attribute.custom.non_rt_with_expr", 1045 tldAttrs[j].getName()); 1046 } 1047 1048 String expectedType = null; 1049 if (tldAttrs[j].isDeferredMethod()) { 1050 String m = tldAttrs[j].getMethodSignature(); 1053 if (m != null) { 1054 int rti = m.trim().indexOf(' '); 1055 if (rti > 0) { 1056 expectedType = m.substring(0, rti).trim(); 1057 } 1058 } else { 1059 expectedType = "java.lang.Object"; 1060 } 1061 } 1062 if (tldAttrs[j].isDeferredValue()) { 1063 expectedType = tldAttrs[j].getExpectedTypeName(); 1066 } 1067 if (expectedType != null) { 1068 Class expectedClass = String .class; 1069 try { 1070 expectedClass = JspUtil.toClass(expectedType, loader); 1071 } catch (ClassNotFoundException e) { 1072 err.jspError 1073 (n, "jsp.error.unknown_attribute_type", 1074 tldAttrs[j].getName(), expectedType); 1075 } 1076 try { 1078 ELSupport.coerceToType(attrs.getValue(i), expectedClass); 1079 } catch (Exception e) { 1080 err.jspError 1081 (n, "jsp.error.coerce_to_type", 1082 tldAttrs[j].getName(), expectedType, attrs.getValue(i)); 1083 } 1084 } 1085 1086 jspAttrs[i] = new Node.JspAttribute(tldAttrs[j], 1087 attrs.getQName(i), attrs.getURI(i), attrs 1088 .getLocalName(i), 1089 attrs.getValue(i), false, null, false); 1090 } else { 1091 1092 if (deferred && !tldAttrs[j].isDeferredMethod() && !tldAttrs[j].isDeferredValue()) { 1093 err.jspError(n, "jsp.error.attribute.custom.non_rt_with_expr", 1095 tldAttrs[j].getName()); 1096 } 1097 if (!deferred && !tldAttrs[j].canBeRequestTime()) { 1098 err.jspError(n, "jsp.error.attribute.custom.non_rt_with_expr", 1100 tldAttrs[j].getName()); 1101 } 1102 1103 Class expectedType = String .class; 1104 try { 1105 String typeStr = tldAttrs[j].getTypeName(); 1106 if (tldAttrs[j].isFragment()) { 1107 expectedType = JspFragment .class; 1108 } else if (typeStr != null) { 1109 expectedType = JspUtil.toClass(typeStr, 1110 loader); 1111 } 1112 jspAttrs[i] = getJspAttribute(tldAttrs[j], 1113 attrs.getQName(i), attrs.getURI(i), 1114 attrs.getLocalName(i), attrs 1115 .getValue(i), expectedType, n, 1116 false); 1117 } catch (ClassNotFoundException e) { 1118 err.jspError 1119 (n, "jsp.error.unknown_attribute_type", 1120 tldAttrs[j].getName(), tldAttrs[j].getTypeName()); 1121 } 1122 } 1123 1124 } else { 1125 if (expression) { 1128 err.jspError(n, "jsp.error.attribute.custom.non_rt_with_expr", 1129 tldAttrs[j].getName()); 1130 } 1131 jspAttrs[i] = new Node.JspAttribute(tldAttrs[j], 1132 attrs.getQName(i), attrs.getURI(i), attrs 1133 .getLocalName(i), 1134 attrs.getValue(i), false, null, false); 1135 } 1136 if (jspAttrs[i].isExpression()) { 1137 tagDataAttrs.put(attrs.getQName(i), 1138 TagData.REQUEST_TIME_VALUE); 1139 } else { 1140 tagDataAttrs.put(attrs.getQName(i), attrs 1141 .getValue(i)); 1142 } 1143 found = true; 1144 break; 1145 } 1146 } 1147 if (!found) { 1148 if (tagInfo.hasDynamicAttributes()) { 1149 jspAttrs[i] = getJspAttribute(null, attrs.getQName(i), 1150 attrs.getURI(i), attrs.getLocalName(i), attrs 1151 .getValue(i), java.lang.Object .class, 1152 n, true); 1153 } else { 1154 err.jspError(n, "jsp.error.bad_attribute", attrs 1155 .getQName(i), n.getLocalName()); 1156 } 1157 } 1158 } 1159 } 1160 1161 1165 private void checkNamedAttributes(Node.CustomTag n, 1166 Node.JspAttribute[] jspAttrs, int start, 1167 Hashtable <String , Object > tagDataAttrs) 1168 throws JasperException { 1169 1170 TagInfo tagInfo = n.getTagInfo(); 1171 if (tagInfo == null) { 1172 err.jspError(n, "jsp.error.missing.tagInfo", n.getQName()); 1173 } 1174 TagAttributeInfo [] tldAttrs = tagInfo.getAttributes(); 1175 Node.Nodes naNodes = n.getNamedAttributeNodes(); 1176 1177 for (int i = 0; i < naNodes.size(); i++) { 1178 Node.NamedAttribute na = (Node.NamedAttribute) naNodes 1179 .getNode(i); 1180 boolean found = false; 1181 for (int j = 0; j < tldAttrs.length; j++) { 1182 1190 String attrPrefix = na.getPrefix(); 1191 if (na.getLocalName().equals(tldAttrs[j].getName()) 1192 && (attrPrefix == null || attrPrefix.length() == 0 || attrPrefix 1193 .equals(n.getPrefix()))) { 1194 jspAttrs[start + i] = new Node.JspAttribute(na, 1195 tldAttrs[j], false); 1196 NamedAttributeVisitor nav = null; 1197 if (na.getBody() != null) { 1198 nav = new NamedAttributeVisitor(); 1199 na.getBody().visit(nav); 1200 } 1201 if (nav != null && nav.hasDynamicContent()) { 1202 tagDataAttrs.put(na.getName(), 1203 TagData.REQUEST_TIME_VALUE); 1204 } else { 1205 tagDataAttrs.put(na.getName(), na.getText()); 1206 } 1207 found = true; 1208 break; 1209 } 1210 } 1211 if (!found) { 1212 if (tagInfo.hasDynamicAttributes()) { 1213 jspAttrs[start + i] = new Node.JspAttribute(na, null, 1214 true); 1215 } else { 1216 err.jspError(n, "jsp.error.bad_attribute", 1217 na.getName(), n.getLocalName()); 1218 } 1219 } 1220 } 1221 } 1222 1223 1231 private Node.JspAttribute getJspAttribute(TagAttributeInfo tai, 1232 String qName, String uri, String localName, String value, 1233 Class expectedType, Node n, boolean dynamic) 1234 throws JasperException { 1235 1236 Node.JspAttribute result = null; 1237 1238 1242 if (value != null) { 1243 if (n.getRoot().isXmlSyntax() && value.startsWith("%=")) { 1244 result = new Node.JspAttribute(tai, qName, uri, localName, 1245 value.substring(2, value.length() - 1), true, null, 1246 dynamic); 1247 } else if (!n.getRoot().isXmlSyntax() 1248 && value.startsWith("<%=")) { 1249 result = new Node.JspAttribute(tai, qName, uri, localName, 1250 value.substring(3, value.length() - 2), true, null, 1251 dynamic); 1252 } else { 1253 1257 ELNode.Nodes el = ELParser.parse(value); 1260 1261 boolean deferred = false; 1262 Iterator <ELNode> nodes = el.iterator(); 1263 while (nodes.hasNext()) { 1264 ELNode node = nodes.next(); 1265 if (node instanceof ELNode.Root) { 1266 if (((ELNode.Root) node).getType() == '#') { 1267 deferred = true; 1268 } 1269 } 1270 } 1271 1272 if (el.containsEL() && !pageInfo.isELIgnored() 1273 && ((!pageInfo.isDeferredSyntaxAllowedAsLiteral() && deferred) 1274 || !deferred)) { 1275 1276 validateFunctions(el, n); 1277 1278 result = new Node.JspAttribute(tai, qName, uri, 1279 localName, value, false, el, dynamic); 1280 1281 ELContextImpl ctx = new ELContextImpl(); 1282 ctx.setFunctionMapper(getFunctionMapper(el)); 1283 1284 try { 1285 result.validateEL(this.pageInfo 1286 .getExpressionFactory(), ctx); 1287 } catch (ELException e) { 1288 this.err.jspError(n.getStart(), 1289 "jsp.error.invalid.expression", value, e 1290 .toString()); 1291 } 1292 1293 } else { 1294 value = value.replace(Constants.ESC, '$'); 1295 result = new Node.JspAttribute(tai, qName, uri, 1296 localName, value, false, null, dynamic); 1297 } 1298 } 1299 } else { 1300 1304 Node.NamedAttribute namedAttributeNode = n 1305 .getNamedAttributeNode(qName); 1306 if (namedAttributeNode != null) { 1307 result = new Node.JspAttribute(namedAttributeNode, tai, 1308 dynamic); 1309 } 1310 } 1311 1312 return result; 1313 } 1314 1315 1318 private StringBuffer getBuffer() { 1319 this.buf.setLength(0); 1320 return this.buf; 1321 } 1322 1323 1327 private boolean isExpression(Node n, String value, boolean checkDeferred) { 1328 if ((n.getRoot().isXmlSyntax() && value.startsWith("%=")) 1329 || (!n.getRoot().isXmlSyntax() && value.startsWith("<%=")) 1330 || (value.indexOf("${") != -1 && !pageInfo.isELIgnored()) 1331 || (checkDeferred && value.indexOf("#{") != -1 && !pageInfo.isELIgnored() 1332 && !pageInfo.isDeferredSyntaxAllowedAsLiteral())) 1333 return true; 1334 else 1335 return false; 1336 } 1337 1338 1343 private void throwErrorIfExpression(Node n, String attrName, 1344 String actionName) throws JasperException { 1345 if (n.getAttributes() != null 1346 && n.getAttributes().getValue(attrName) != null 1347 && isExpression(n, n.getAttributes().getValue(attrName), true)) { 1348 err.jspError(n, 1349 "jsp.error.attribute.standard.non_rt_with_expr", 1350 attrName, actionName); 1351 } 1352 } 1353 1354 private static class NamedAttributeVisitor extends Node.Visitor { 1355 private boolean hasDynamicContent; 1356 1357 public void doVisit(Node n) throws JasperException { 1358 if (!(n instanceof Node.JspText) 1359 && !(n instanceof Node.TemplateText)) { 1360 hasDynamicContent = true; 1361 } 1362 visitBody(n); 1363 } 1364 1365 public boolean hasDynamicContent() { 1366 return hasDynamicContent; 1367 } 1368 } 1369 1370 private String findUri(String prefix, Node n) { 1371 1372 for (Node p = n; p != null; p = p.getParent()) { 1373 Attributes attrs = p.getTaglibAttributes(); 1374 if (attrs == null) { 1375 continue; 1376 } 1377 for (int i = 0; i < attrs.getLength(); i++) { 1378 String name = attrs.getQName(i); 1379 int k = name.indexOf(':'); 1380 if (prefix == null && k < 0) { 1381 return attrs.getValue(i); 1383 } 1384 if (prefix != null && k >= 0 1385 && prefix.equals(name.substring(k + 1))) { 1386 return attrs.getValue(i); 1387 } 1388 } 1389 } 1390 return null; 1391 } 1392 1393 1396 private void validateFunctions(ELNode.Nodes el, Node n) 1397 throws JasperException { 1398 1399 class FVVisitor extends ELNode.Visitor { 1400 1401 Node n; 1402 1403 FVVisitor(Node n) { 1404 this.n = n; 1405 } 1406 1407 public void visit(ELNode.Function func) throws JasperException { 1408 String prefix = func.getPrefix(); 1409 String function = func.getName(); 1410 String uri = null; 1411 1412 if (n.getRoot().isXmlSyntax()) { 1413 uri = findUri(prefix, n); 1414 } else if (prefix != null) { 1415 uri = pageInfo.getURI(prefix); 1416 } 1417 1418 if (uri == null) { 1419 if (prefix == null) { 1420 err.jspError(n, "jsp.error.noFunctionPrefix", 1421 function); 1422 } else { 1423 err 1424 .jspError( 1425 n, 1426 "jsp.error.attribute.invalidPrefix", 1427 prefix); 1428 } 1429 } 1430 TagLibraryInfo taglib = pageInfo.getTaglib(uri); 1431 FunctionInfo funcInfo = null; 1432 if (taglib != null) { 1433 funcInfo = taglib.getFunction(function); 1434 } 1435 if (funcInfo == null) { 1436 err.jspError(n, "jsp.error.noFunction", function); 1437 } 1438 func.setUri(uri); 1440 func.setFunctionInfo(funcInfo); 1441 processSignature(func); 1442 } 1443 } 1444 1445 el.visit(new FVVisitor(n)); 1446 } 1447 1448 private void prepareExpression(ELNode.Nodes el, Node n, String expr) 1449 throws JasperException { 1450 validateFunctions(el, n); 1451 1452 ELContextImpl ctx = new ELContextImpl(); 1454 ctx.setFunctionMapper(this.getFunctionMapper(el)); 1455 ExpressionFactory ef = this.pageInfo.getExpressionFactory(); 1456 try { 1457 ef.createValueExpression(ctx, expr, Object .class); 1458 } catch (ELException e) { 1459 1460 } 1461 } 1462 1463 private void processSignature(ELNode.Function func) 1464 throws JasperException { 1465 func.setMethodName(getMethod(func)); 1466 func.setParameters(getParameters(func)); 1467 } 1468 1469 1472 private String getMethod(ELNode.Function func) throws JasperException { 1473 FunctionInfo funcInfo = func.getFunctionInfo(); 1474 String signature = funcInfo.getFunctionSignature(); 1475 1476 int start = signature.indexOf(' '); 1477 if (start < 0) { 1478 err.jspError("jsp.error.tld.fn.invalid.signature", func 1479 .getPrefix(), func.getName()); 1480 } 1481 int end = signature.indexOf('('); 1482 if (end < 0) { 1483 err.jspError( 1484 "jsp.error.tld.fn.invalid.signature.parenexpected", 1485 func.getPrefix(), func.getName()); 1486 } 1487 return signature.substring(start + 1, end).trim(); 1488 } 1489 1490 1495 private String [] getParameters(ELNode.Function func) 1496 throws JasperException { 1497 FunctionInfo funcInfo = func.getFunctionInfo(); 1498 String signature = funcInfo.getFunctionSignature(); 1499 ArrayList <String > params = new ArrayList <String >(); 1500 int start = signature.indexOf('(') + 1; 1504 boolean lastArg = false; 1505 while (true) { 1506 int p = signature.indexOf(',', start); 1507 if (p < 0) { 1508 p = signature.indexOf(')', start); 1509 if (p < 0) { 1510 err.jspError("jsp.error.tld.fn.invalid.signature", func 1511 .getPrefix(), func.getName()); 1512 } 1513 lastArg = true; 1514 } 1515 String arg = signature.substring(start, p).trim(); 1516 if (!"".equals(arg)) { 1517 params.add(arg); 1518 } 1519 if (lastArg) { 1520 break; 1521 } 1522 start = p + 1; 1523 } 1524 return (String []) params.toArray(new String [params.size()]); 1525 } 1526 1527 private FunctionMapper getFunctionMapper(ELNode.Nodes el) 1528 throws JasperException { 1529 1530 class ValidateFunctionMapper extends FunctionMapper { 1531 1532 private HashMap <String , Method > fnmap = new HashMap <String , Method >(); 1533 1534 public void mapFunction(String fnQName, Method method) { 1535 fnmap.put(fnQName, method); 1536 } 1537 1538 public Method resolveFunction(String prefix, String localName) { 1539 return this.fnmap.get(prefix + ":" + localName); 1540 } 1541 } 1542 1543 class MapperELVisitor extends ELNode.Visitor { 1544 ValidateFunctionMapper fmapper; 1545 1546 MapperELVisitor(ValidateFunctionMapper fmapper) { 1547 this.fmapper = fmapper; 1548 } 1549 1550 public void visit(ELNode.Function n) throws JasperException { 1551 1552 Class c = null; 1553 Method method = null; 1554 try { 1555 c = loader.loadClass(n.getFunctionInfo() 1556 .getFunctionClass()); 1557 } catch (ClassNotFoundException e) { 1558 err.jspError("jsp.error.function.classnotfound", n 1559 .getFunctionInfo().getFunctionClass(), n 1560 .getPrefix() 1561 + ':' + n.getName(), e.getMessage()); 1562 } 1563 String paramTypes[] = n.getParameters(); 1564 int size = paramTypes.length; 1565 Class params[] = new Class [size]; 1566 int i = 0; 1567 try { 1568 for (i = 0; i < size; i++) { 1569 params[i] = JspUtil.toClass(paramTypes[i], loader); 1570 } 1571 method = c.getDeclaredMethod(n.getMethodName(), params); 1572 } catch (ClassNotFoundException e) { 1573 err.jspError("jsp.error.signature.classnotfound", 1574 paramTypes[i], n.getPrefix() + ':' 1575 + n.getName(), e.getMessage()); 1576 } catch (NoSuchMethodException e) { 1577 err.jspError("jsp.error.noFunctionMethod", n 1578 .getMethodName(), n.getName(), c.getName()); 1579 } 1580 fmapper.mapFunction(n.getPrefix() + ':' + n.getName(), 1581 method); 1582 } 1583 } 1584 1585 ValidateFunctionMapper fmapper = new ValidateFunctionMapper(); 1586 el.visit(new MapperELVisitor(fmapper)); 1587 return fmapper; 1588 } 1589 } 1591 1594 static class TagExtraInfoVisitor extends Node.Visitor { 1595 1596 private ErrorDispatcher err; 1597 1598 1601 TagExtraInfoVisitor(Compiler compiler) { 1602 this.err = compiler.getErrorDispatcher(); 1603 } 1604 1605 public void visit(Node.CustomTag n) throws JasperException { 1606 TagInfo tagInfo = n.getTagInfo(); 1607 if (tagInfo == null) { 1608 err.jspError(n, "jsp.error.missing.tagInfo", n.getQName()); 1609 } 1610 1611 ValidationMessage [] errors = tagInfo.validate(n.getTagData()); 1612 if (errors != null && errors.length != 0) { 1613 StringBuffer errMsg = new StringBuffer (); 1614 errMsg.append("<h3>"); 1615 errMsg.append(Localizer.getMessage( 1616 "jsp.error.tei.invalid.attributes", n.getQName())); 1617 errMsg.append("</h3>"); 1618 for (int i = 0; i < errors.length; i++) { 1619 errMsg.append("<p>"); 1620 if (errors[i].getId() != null) { 1621 errMsg.append(errors[i].getId()); 1622 errMsg.append(": "); 1623 } 1624 errMsg.append(errors[i].getMessage()); 1625 errMsg.append("</p>"); 1626 } 1627 1628 err.jspError(n, errMsg.toString()); 1629 } 1630 1631 visitBody(n); 1632 } 1633 } 1634 1635 public static void validate(Compiler compiler, Node.Nodes page) 1636 throws JasperException { 1637 1638 1642 page.visit(new DirectiveVisitor(compiler)); 1643 1644 PageInfo pageInfo = compiler.getPageInfo(); 1646 String contentType = pageInfo.getContentType(); 1647 1648 if (contentType == null || contentType.indexOf("charset=") < 0) { 1649 boolean isXml = page.getRoot().isXmlSyntax(); 1650 String defaultType; 1651 if (contentType == null) { 1652 defaultType = isXml ? "text/xml" : "text/html"; 1653 } else { 1654 defaultType = contentType; 1655 } 1656 1657 String charset = null; 1658 if (isXml) { 1659 charset = "UTF-8"; 1660 } else { 1661 if (!page.getRoot().isDefaultPageEncoding()) { 1662 charset = page.getRoot().getPageEncoding(); 1663 } 1664 } 1665 1666 if (charset != null) { 1667 pageInfo.setContentType(defaultType + ";charset=" + charset); 1668 } else { 1669 pageInfo.setContentType(defaultType); 1670 } 1671 } 1672 1673 1679 page.visit(new ValidateVisitor(compiler)); 1680 1681 1685 validateXmlView(new PageDataImpl(page, compiler), compiler); 1686 1687 1691 page.visit(new TagExtraInfoVisitor(compiler)); 1692 1693 } 1694 1695 1698 1702 private static void validateXmlView(PageData xmlView, Compiler compiler) 1703 throws JasperException { 1704 1705 StringBuffer errMsg = null; 1706 ErrorDispatcher errDisp = compiler.getErrorDispatcher(); 1707 1708 for (Iterator iter = compiler.getPageInfo().getTaglibs().iterator(); iter 1709 .hasNext();) { 1710 1711 Object o = iter.next(); 1712 if (!(o instanceof TagLibraryInfoImpl)) 1713 continue; 1714 TagLibraryInfoImpl tli = (TagLibraryInfoImpl) o; 1715 1716 ValidationMessage [] errors = tli.validate(xmlView); 1717 if ((errors != null) && (errors.length != 0)) { 1718 if (errMsg == null) { 1719 errMsg = new StringBuffer (); 1720 } 1721 errMsg.append("<h3>"); 1722 errMsg.append(Localizer.getMessage( 1723 "jsp.error.tlv.invalid.page", tli.getShortName(), 1724 compiler.getPageInfo().getJspFile())); 1725 errMsg.append("</h3>"); 1726 for (int i = 0; i < errors.length; i++) { 1727 if (errors[i] != null) { 1728 errMsg.append("<p>"); 1729 errMsg.append(errors[i].getId()); 1730 errMsg.append(": "); 1731 errMsg.append(errors[i].getMessage()); 1732 errMsg.append("</p>"); 1733 } 1734 } 1735 } 1736 } 1737 1738 if (errMsg != null) { 1739 errDisp.jspError(errMsg.toString()); 1740 } 1741 } 1742} 1743 | Popular Tags |