| 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 &nb
|