1 17 package org.apache.jasper.compiler; 18 19 import java.io.CharArrayWriter ; 20 import java.io.FileNotFoundException ; 21 import java.io.IOException ; 22 import java.io.InputStream ; 23 24 import java.util.Iterator ; 25 import java.util.List ; 26 import java.util.jar.JarFile ; 27 28 import javax.servlet.jsp.tagext.TagFileInfo ; 29 import javax.servlet.jsp.tagext.TagInfo ; 30 import javax.servlet.jsp.tagext.TagLibraryInfo ; 31 import javax.xml.parsers.SAXParser ; 32 import javax.xml.parsers.SAXParserFactory ; 33 34 import org.apache.jasper.JasperException; 35 import org.apache.jasper.JspCompilationContext; 36 import org.xml.sax.Attributes ; 37 import org.xml.sax.InputSource ; 38 import org.xml.sax.Locator ; 39 import org.xml.sax.SAXException ; 40 import org.xml.sax.SAXParseException ; 41 import org.xml.sax.XMLReader ; 42 import org.xml.sax.ext.LexicalHandler ; 43 import org.xml.sax.helpers.AttributesImpl ; 44 import org.xml.sax.helpers.DefaultHandler ; 45 46 53 54 class JspDocumentParser 55 extends DefaultHandler 56 implements LexicalHandler , TagConstants { 57 58 private static final String JSP_VERSION = "version"; 59 private static final String LEXICAL_HANDLER_PROPERTY = 60 "http://xml.org/sax/properties/lexical-handler"; 61 private static final String JSP_URI = "http://java.sun.com/JSP/Page"; 62 63 private static final EnableDTDValidationException ENABLE_DTD_VALIDATION_EXCEPTION = 64 new EnableDTDValidationException( 65 "jsp.error.enable_dtd_validation", 66 null); 67 68 private ParserController parserController; 69 private JspCompilationContext ctxt; 70 private PageInfo pageInfo; 71 private String path; 72 private StringBuffer charBuffer; 73 74 private Node current; 76 77 82 private Node scriptlessBodyNode; 83 84 private Locator locator; 85 86 private Mark startMark; 97 98 private boolean inDTD; 100 101 private boolean isValidating; 102 103 private ErrorDispatcher err; 104 private boolean isTagFile; 105 private boolean directivesOnly; 106 private boolean isTop; 107 108 private int tagDependentNesting = 0; 110 private boolean tagDependentPending = false; 113 114 117 public JspDocumentParser( 118 ParserController pc, 119 String path, 120 boolean isTagFile, 121 boolean directivesOnly) { 122 this.parserController = pc; 123 this.ctxt = pc.getJspCompilationContext(); 124 this.pageInfo = pc.getCompiler().getPageInfo(); 125 this.err = pc.getCompiler().getErrorDispatcher(); 126 this.path = path; 127 this.isTagFile = isTagFile; 128 this.directivesOnly = directivesOnly; 129 this.isTop = true; 130 } 131 132 137 public static Node.Nodes parse( 138 ParserController pc, 139 String path, 140 JarFile jarFile, 141 Node parent, 142 boolean isTagFile, 143 boolean directivesOnly, 144 String pageEnc, 145 String jspConfigPageEnc, 146 boolean isEncodingSpecifiedInProlog, 147 boolean isBomPresent) 148 throws JasperException { 149 150 JspDocumentParser jspDocParser = 151 new JspDocumentParser(pc, path, isTagFile, directivesOnly); 152 Node.Nodes pageNodes = null; 153 154 try { 155 156 Node.Root dummyRoot = new Node.Root(null, parent, true); 158 dummyRoot.setPageEncoding(pageEnc); 159 dummyRoot.setJspConfigPageEncoding(jspConfigPageEnc); 160 dummyRoot.setIsEncodingSpecifiedInProlog( 161 isEncodingSpecifiedInProlog); 162 dummyRoot.setIsBomPresent(isBomPresent); 163 jspDocParser.current = dummyRoot; 164 if (parent == null) { 165 jspDocParser.addInclude( 166 dummyRoot, 167 jspDocParser.pageInfo.getIncludePrelude()); 168 } else { 169 jspDocParser.isTop = false; 170 } 171 172 SAXParser saxParser = getSAXParser(false, jspDocParser); 174 InputStream inStream = null; 175 try { 176 inStream = JspUtil.getInputStream(path, jarFile, 177 jspDocParser.ctxt, 178 jspDocParser.err); 179 saxParser.parse(new InputSource (inStream), jspDocParser); 180 } catch (EnableDTDValidationException e) { 181 saxParser = getSAXParser(true, jspDocParser); 182 jspDocParser.isValidating = true; 183 if (inStream != null) { 184 try { 185 inStream.close(); 186 } catch (Exception any) { 187 } 188 } 189 inStream = JspUtil.getInputStream(path, jarFile, 190 jspDocParser.ctxt, 191 jspDocParser.err); 192 saxParser.parse(new InputSource (inStream), jspDocParser); 193 } finally { 194 if (inStream != null) { 195 try { 196 inStream.close(); 197 } catch (Exception any) { 198 } 199 } 200 } 201 202 if (parent == null) { 203 jspDocParser.addInclude( 204 dummyRoot, 205 jspDocParser.pageInfo.getIncludeCoda()); 206 } 207 208 pageNodes = new Node.Nodes(dummyRoot); 210 211 } catch (IOException ioe) { 212 jspDocParser.err.jspError("jsp.error.data.file.read", path, ioe); 213 } catch (SAXParseException e) { 214 jspDocParser.err.jspError 215 (new Mark(jspDocParser.ctxt, path, e.getLineNumber(), 216 e.getColumnNumber()), 217 e.getMessage()); 218 } catch (Exception e) { 219 jspDocParser.err.jspError(e); 220 } 221 222 return pageNodes; 223 } 224 225 231 private void addInclude(Node parent, List files) throws SAXException { 232 if (files != null) { 233 Iterator iter = files.iterator(); 234 while (iter.hasNext()) { 235 String file = (String )iter.next(); 236 AttributesImpl attrs = new AttributesImpl (); 237 attrs.addAttribute("", "file", "file", "CDATA", file); 238 239 Node includeDir = 241 new Node.IncludeDirective(attrs, null, parent); 243 processIncludeDirective(file, includeDir); 244 } 245 } 246 } 247 248 261 public void startElement( 262 String uri, 263 String localName, 264 String qName, 265 Attributes attrs) 266 throws SAXException { 267 268 AttributesImpl taglibAttrs = null; 269 AttributesImpl nonTaglibAttrs = null; 270 AttributesImpl nonTaglibXmlnsAttrs = null; 271 272 processChars(); 273 274 checkPrefixes(uri, qName, attrs); 275 276 if (directivesOnly && 277 !(JSP_URI.equals(uri) && localName.startsWith(DIRECTIVE_ACTION))) { 278 return; 279 } 280 281 if (JSP_URI.equals(uri) && TEXT_ACTION.equals(current.getLocalName())) { 283 throw new SAXParseException ( 284 Localizer.getMessage("jsp.error.text.has_subelement"), 285 locator); 286 } 287 288 startMark = new Mark(ctxt, path, locator.getLineNumber(), 289 locator.getColumnNumber()); 290 291 if (attrs != null) { 292 296 boolean isTaglib = false; 297 for (int i = attrs.getLength() - 1; i >= 0; i--) { 298 isTaglib = false; 299 String attrQName = attrs.getQName(i); 300 if (!attrQName.startsWith("xmlns")) { 301 if (nonTaglibAttrs == null) { 302 nonTaglibAttrs = new AttributesImpl (); 303 } 304 nonTaglibAttrs.addAttribute( 305 attrs.getURI(i), 306 attrs.getLocalName(i), 307 attrs.getQName(i), 308 attrs.getType(i), 309 attrs.getValue(i)); 310 } else { 311 if (attrQName.startsWith("xmlns:jsp")) { 312 isTaglib = true; 313 } else { 314 String attrUri = attrs.getValue(i); 315 isTaglib = pageInfo.hasTaglib(attrUri); 318 } 319 if (isTaglib) { 320 if (taglibAttrs == null) { 321 taglibAttrs = new AttributesImpl (); 322 } 323 taglibAttrs.addAttribute( 324 attrs.getURI(i), 325 attrs.getLocalName(i), 326 attrs.getQName(i), 327 attrs.getType(i), 328 attrs.getValue(i)); 329 } else { 330 if (nonTaglibXmlnsAttrs == null) { 331 nonTaglibXmlnsAttrs = new AttributesImpl (); 332 } 333 nonTaglibXmlnsAttrs.addAttribute( 334 attrs.getURI(i), 335 attrs.getLocalName(i), 336 attrs.getQName(i), 337 attrs.getType(i), 338 attrs.getValue(i)); 339 } 340 } 341 } 342 } 343 344 Node node = null; 345 346 if (tagDependentPending && JSP_URI.equals(uri) && 347 localName.equals(BODY_ACTION)) { 348 tagDependentPending = false; 349 tagDependentNesting++; 350 current = 351 parseStandardAction( 352 qName, 353 localName, 354 nonTaglibAttrs, 355 nonTaglibXmlnsAttrs, 356 taglibAttrs, 357 startMark, 358 current); 359 return; 360 } 361 362 if (tagDependentPending && JSP_URI.equals(uri) && 363 localName.equals(ATTRIBUTE_ACTION)) { 364 current = 365 parseStandardAction( 366 qName, 367 localName, 368 nonTaglibAttrs, 369 nonTaglibXmlnsAttrs, 370 taglibAttrs, 371 startMark, 372 current); 373 return; 374 } 375 376 if (tagDependentPending) { 377 tagDependentPending = false; 378 tagDependentNesting++; 379 } 380 381 if (tagDependentNesting > 0) { 382 node = 383 new Node.UninterpretedTag( 384 qName, 385 localName, 386 nonTaglibAttrs, 387 nonTaglibXmlnsAttrs, 388 taglibAttrs, 389 startMark, 390 current); 391 } else if (JSP_URI.equals(uri)) { 392 node = 393 parseStandardAction( 394 qName, 395 localName, 396 nonTaglibAttrs, 397 nonTaglibXmlnsAttrs, 398 taglibAttrs, 399 startMark, 400 current); 401 } else { 402 node = 403 parseCustomAction( 404 qName, 405 localName, 406 uri, 407 nonTaglibAttrs, 408 nonTaglibXmlnsAttrs, 409 taglibAttrs, 410 startMark, 411 current); 412 if (node == null) { 413 node = 414 new Node.UninterpretedTag( 415 qName, 416 localName, 417 nonTaglibAttrs, 418 nonTaglibXmlnsAttrs, 419 taglibAttrs, 420 startMark, 421 current); 422 } else { 423 String bodyType = getBodyType((Node.CustomTag) node); 425 426 if (scriptlessBodyNode == null 427 && bodyType.equalsIgnoreCase(TagInfo.BODY_CONTENT_SCRIPTLESS)) { 428 scriptlessBodyNode = node; 429 } 430 else if (TagInfo.BODY_CONTENT_TAG_DEPENDENT.equalsIgnoreCase(bodyType)) { 431 tagDependentPending = true; 432 } 433 } 434 } 435 436 current = node; 437 } 438 439 455 public void characters(char[] buf, int offset, int len) { 456 457 if (charBuffer == null) { 458 charBuffer = new StringBuffer (); 459 } 460 charBuffer.append(buf, offset, len); 461 } 462 463 private void processChars() throws SAXException { 464 465 if (charBuffer == null || directivesOnly) { 466 return; 467 } 468 469 477 boolean isAllSpace = true; 478 if (!(current instanceof Node.JspText) 479 && !(current instanceof Node.NamedAttribute)) { 480 for (int i = 0; i < charBuffer.length(); i++) { 481 if (!(charBuffer.charAt(i) == ' ' 482 || charBuffer.charAt(i) == '\n' 483 || charBuffer.charAt(i) == '\r' 484 || charBuffer.charAt(i) == '\t')) { 485 isAllSpace = false; 486 break; 487 } 488 } 489 } 490 491 if (!isAllSpace && tagDependentPending) { 492 tagDependentPending = false; 493 tagDependentNesting++; 494 } 495 496 if (tagDependentNesting > 0) { 497 if (charBuffer.length() > 0) { 498 new Node.TemplateText(charBuffer.toString(), startMark, current); 499 } 500 startMark = new Mark(ctxt, path, locator.getLineNumber(), 501 locator.getColumnNumber()); 502 charBuffer = null; 503 return; 504 } 505 506 if ((current instanceof Node.JspText) 507 || (current instanceof Node.NamedAttribute) 508 || !isAllSpace) { 509 510 int line = startMark.getLineNumber(); 511 int column = startMark.getColumnNumber(); 512 513 CharArrayWriter ttext = new CharArrayWriter (); 514 int lastCh = 0, elType = 0; 515 for (int i = 0; i < charBuffer.length(); i++) { 516 517 int ch = charBuffer.charAt(i); 518 if (ch == '\n') { 519 column = 1; 520 line++; 521 } else { 522 column++; 523 } 524 if ((lastCh == '$' || lastCh == '#') && ch == '{') { 525 elType = lastCh; 526 if (ttext.size() > 0) { 527 new Node.TemplateText( 528 ttext.toString(), 529 startMark, 530 current); 531 ttext = new CharArrayWriter (); 532 startMark = new Mark(ctxt, path, line, column - 2); 535 } 536 i++; 538 boolean singleQ = false; 539 boolean doubleQ = false; 540 lastCh = 0; 541 for (;; i++) { 542 if (i >= charBuffer.length()) { 543 throw new SAXParseException ( 544 Localizer.getMessage( 545 "jsp.error.unterminated", 546 (char) elType + "{"), 547 locator); 548 549 } 550 ch = charBuffer.charAt(i); 551 if (ch == '\n') { 552 column = 1; 553 line++; 554 } else { 555 column++; 556 } 557 if (lastCh == '\\' && (singleQ || doubleQ)) { 558 ttext.write(ch); 559 lastCh = 0; 560 continue; 561 } 562 if (ch == '}') { 563 new Node.ELExpression((char) elType, 564 ttext.toString(), 565 startMark, 566 current); 567 ttext = new CharArrayWriter (); 568 startMark = new Mark(ctxt, path, line, column); 569 break; 570 } 571 if (ch == '"') 572 doubleQ = !doubleQ; 573 else if (ch == '\'') 574 singleQ = !singleQ; 575 576 ttext.write(ch); 577 lastCh = ch; 578 } 579 } else if (lastCh == '\\' && (ch == '$' || ch == '#')) { 580 ttext.write(ch); 581 ch = 0; } else { 583 if (lastCh == '$' || lastCh == '#' || lastCh == '\\') { 584 ttext.write(lastCh); 585 } 586 if (ch != '$' && ch != '#' && ch != '\\') { 587 ttext.write(ch); 588 } 589 } 590 lastCh = ch; 591 } 592 if (lastCh == '$' || lastCh == '#' || lastCh == '\\') { 593 ttext.write(lastCh); 594 } 595 if (ttext.size() > 0) { 596 new Node.TemplateText(ttext.toString(), startMark, current); 597 } 598 } 599 startMark = new Mark(ctxt, path, locator.getLineNumber(), 600 locator.getColumnNumber()); 601 602 charBuffer = null; 603 } 604 605 608 public void endElement(String uri, String localName, String qName) 609 throws SAXException { 610 611 processChars(); 612 613 if (directivesOnly && 614 !(JSP_URI.equals(uri) && localName.startsWith(DIRECTIVE_ACTION))) { 615 return; 616 } 617 618 if (current instanceof Node.NamedAttribute) { 619 boolean isTrim = ((Node.NamedAttribute)current).isTrim(); 620 Node.Nodes subElems = ((Node.NamedAttribute)current).getBody(); 621 for (int i = 0; subElems != null && i < subElems.size(); i++) { 622 Node subElem = subElems.getNode(i); 623 if (!(subElem instanceof Node.TemplateText)) { 624 continue; 625 } 626 if (i == 0) { 636 if (isTrim) { 637 ((Node.TemplateText)subElem).ltrim(); 638 } 639 } else if (i == subElems.size() - 1) { 640 if (isTrim) { 641 ((Node.TemplateText)subElem).rtrim(); 642 } 643 } else { 644 if (((Node.TemplateText)subElem).isAllSpace()) { 645 subElems.remove(subElem); 646 } 647 } 648 } 649 } else if (current instanceof Node.ScriptingElement) { 650 checkScriptingBody((Node.ScriptingElement)current); 651 } 652 653 if ( isTagDependent(current)) { 654 tagDependentNesting--; 655 } 656 657 if (scriptlessBodyNode != null 658 && current.equals(scriptlessBodyNode)) { 659 scriptlessBodyNode = null; 660 } 661 662 if (current.getParent() != null) { 663 current = current.getParent(); 664 } 665 } 666 667 672 public void setDocumentLocator(Locator locator) { 673 this.locator = locator; 674 } 675 676 679 public void comment(char[] buf, int offset, int len) throws SAXException { 680 681 processChars(); 683 if (!inDTD) { 685 startMark = 686 new Mark( 687 ctxt, 688 path, 689 locator.getLineNumber(), 690 locator.getColumnNumber()); 691 new Node.Comment(new String (buf, offset, len), startMark, current); 692 } 693 } 694 695 698 public void startCDATA() throws SAXException { 699 700 processChars(); startMark = new Mark(ctxt, path, locator.getLineNumber(), 702 locator.getColumnNumber()); 703 } 704 705 708 public void endCDATA() throws SAXException { 709 processChars(); } 711 712 715 public void startEntity(String name) throws SAXException { 716 } 718 719 722 public void endEntity(String name) throws SAXException { 723 } 725 726 729 public void startDTD(String name, String publicId, String systemId) 730 throws SAXException { 731 if (!isValidating) { 732 fatalError(ENABLE_DTD_VALIDATION_EXCEPTION); 733 } 734 735 inDTD = true; 736 } 737 738 741 public void endDTD() throws SAXException { 742 inDTD = false; 743 } 744 745 748 public void fatalError(SAXParseException e) throws SAXException { 749 throw e; 750 } 751 752 755 public void error(SAXParseException e) throws SAXException { 756 throw e; 757 } 758 759 762 public void startPrefixMapping(String prefix, String uri) 763 throws SAXException { 764 TagLibraryInfo taglibInfo; 765 766 if (directivesOnly && !(JSP_URI.equals(uri))) { 767 return; 768 } 769 770 try { 771 taglibInfo = getTaglibInfo(prefix, uri); 772 } catch (JasperException je) { 773 throw new SAXParseException ( 774 Localizer.getMessage("jsp.error.could.not.add.taglibraries"), 775 locator, 776 je); 777 } 778 779 if (taglibInfo != null) { 780 if (pageInfo.getTaglib(uri) == null) { 781 pageInfo.addTaglib(uri, taglibInfo); 782 } 783 pageInfo.pushPrefixMapping(prefix, uri); 784 } else { 785 pageInfo.pushPrefixMapping(prefix, null); 786 } 787 } 788 789 792 public void endPrefixMapping(String prefix) throws SAXException { 793 794 if (directivesOnly) { 795 String uri = pageInfo.getURI(prefix); 796 if (!JSP_URI.equals(uri)) { 797 return; 798 } 799 } 800 801 pageInfo.popPrefixMapping(prefix); 802 } 803 804 807 private Node parseStandardAction( 808 String qName, 809 String localName, 810 Attributes nonTaglibAttrs, 811 Attributes nonTaglibXmlnsAttrs, 812 Attributes taglibAttrs, 813 Mark start, 814 Node parent) 815 throws SAXException { 816 817 Node node = null; 818 819 if (localName.equals(ROOT_ACTION)) { 820 if (!(current instanceof Node.Root)) { 821 throw new SAXParseException ( 822 Localizer.getMessage("jsp.error.nested_jsproot"), 823 locator); 824 } 825 node = 826 new Node.JspRoot( 827 qName, 828 nonTaglibAttrs, 829 nonTaglibXmlnsAttrs, 830 taglibAttrs, 831 start, 832 current); 833 if (isTop) { 834 pageInfo.setHasJspRoot(true); 835 } 836 } else if (localName.equals(PAGE_DIRECTIVE_ACTION)) { 837 if (isTagFile) { 838 throw new SAXParseException ( 839 Localizer.getMessage( 840 "jsp.error.action.istagfile", 841 localName), 842 locator); 843 } 844 node = 845 new Node.PageDirective( 846 qName, 847 nonTaglibAttrs, 848 nonTaglibXmlnsAttrs, 849 taglibAttrs, 850 start, 851 current); 852 String imports = nonTaglibAttrs.getValue("import"); 853 if (imports != null) { 855 ((Node.PageDirective)node).addImport(imports); 856 } 857 } else if (localName.equals(INCLUDE_DIRECTIVE_ACTION)) { 858 node = 859 new Node.IncludeDirective( 860 qName, 861 nonTaglibAttrs, 862 nonTaglibXmlnsAttrs, 863 taglibAttrs, 864 start, 865 current); 866 processIncludeDirective(nonTaglibAttrs.getValue("file"), node); 867 } else if (localName.equals(DECLARATION_ACTION)) { 868 if (scriptlessBodyNode != null) { 869 throw new SAXParseException ( 872 Localizer.getMessage( 873 "jsp.error.no.scriptlets", 874 localName), 875 locator); 876 } 877 node = 878 new Node.Declaration( 879 qName, 880 nonTaglibXmlnsAttrs, 881 taglibAttrs, 882 start, 883 current); 884 } else if (localName.equals(SCRIPTLET_ACTION)) { 885 if (scriptlessBodyNode != null) { 886 throw new SAXParseException ( 889 Localizer.getMessage( 890 "jsp.error.no.scriptlets", 891 localName), 892 locator); 893 } 894 node = 895 new Node.Scriptlet( 896 qName, 897 nonTaglibXmlnsAttrs, 898 taglibAttrs, 899 start, 900 current); 901 } else if (localName.equals(EXPRESSION_ACTION)) { 902 if (scriptlessBodyNode != null) { 903 throw new SAXParseException ( 906 Localizer.getMessage( 907 "jsp.error.no.scriptlets", 908 localName), 909 locator); 910 } 911 node = 912 new Node.Expression( 913 qName, 914 nonTaglibXmlnsAttrs, 915 taglibAttrs, 916 start, 917 current); 918 } else if (localName.equals(USE_BEAN_ACTION)) { 919 node = 920 new Node.UseBean( 921 qName, 922 nonTaglibAttrs, 923 nonTaglibXmlnsAttrs, 924 taglibAttrs, 925 start, 926 current); 927 } else if (localName.equals(SET_PROPERTY_ACTION)) { 928 node = 929 new Node.SetProperty( 930 qName, 931 nonTaglibAttrs, 932 nonTaglibXmlnsAttrs, 933 taglibAttrs, 934 start, 935 current); 936 } else if (localName.equals(GET_PROPERTY_ACTION)) { 937 node = 938 new Node.GetProperty( 939 qName, 940 nonTaglibAttrs, 941 nonTaglibXmlnsAttrs, 942 taglibAttrs, 943 start, 944 current); 945 } else if (localName.equals(INCLUDE_ACTION)) { 946 node = 947 new Node.IncludeAction( 948 qName, 949 nonTaglibAttrs, 950 nonTaglibXmlnsAttrs, 951 taglibAttrs, 952 start, 953 current); 954 } else if (localName.equals(FORWARD_ACTION)) { 955 node = 956 new Node.ForwardAction( 957 qName, 958 nonTaglibAttrs, 959 nonTaglibXmlnsAttrs, 960 taglibAttrs, 961 start, 962 current); 963 } else if (localName.equals(PARAM_ACTION)) { 964 node = 965 new Node.ParamAction( 966 qName, 967 nonTaglibAttrs, 968 nonTaglibXmlnsAttrs, 969 taglibAttrs, 970 start, 971 current); 972 } else if (localName.equals(PARAMS_ACTION)) { 973 node = 974 new Node.ParamsAction( 975 qName, 976 nonTaglibXmlnsAttrs, 977 taglibAttrs, 978 start, 979 current); 980 } else if (localName.equals(PLUGIN_ACTION)) { 981 node = 982 new Node.PlugIn( 983 qName, 984 nonTaglibAttrs, 985 nonTaglibXmlnsAttrs, 986 taglibAttrs, 987 start, 988 current); 989 } else if (localName.equals(TEXT_ACTION)) { 990 node = 991 new Node.JspText( 992 qName, 993 nonTaglibXmlnsAttrs, 994 taglibAttrs, 995 start, 996 current); 997 } else if (localName.equals(BODY_ACTION)) { 998 node = 999 new Node.JspBody( 1000 qName, 1001 nonTaglibXmlnsAttrs, 1002 taglibAttrs, 1003 start, 1004 current); 1005 } else if (localName.equals(ATTRIBUTE_ACTION)) { 1006 node = 1007 new Node.NamedAttribute( 1008 qName, 1009 nonTaglibAttrs, 1010 nonTaglibXmlnsAttrs, 1011 taglibAttrs, 1012 start, 1013 current); 1014 } else if (localName.equals(OUTPUT_ACTION)) { 1015 node = 1016 new Node.JspOutput( 1017 qName, 1018 nonTaglibAttrs, 1019 nonTaglibXmlnsAttrs, 1020 taglibAttrs, 1021 start, 1022 current); 1023 } else if (localName.equals(TAG_DIRECTIVE_ACTION)) { 1024 if (!isTagFile) { 1025 throw new SAXParseException ( 1026 Localizer.getMessage( 1027 "jsp.error.action.isnottagfile", 1028 localName), 1029 locator); 1030 } 1031 node = 1032 new Node.TagDirective( 1033 qName, 1034 nonTaglibAttrs, 1035 nonTaglibXmlnsAttrs, 1036 taglibAttrs, 1037 start, 1038 current); 1039 String imports = nonTaglibAttrs.getValue("import"); 1040 if (imports != null) { 1042 ((Node.TagDirective)node).addImport(imports); 1043 } 1044 } else if (localName.equals(ATTRIBUTE_DIRECTIVE_ACTION)) { 1045 if (!isTagFile) { 1046 throw new SAXParseException ( 1047 Localizer.getMessage( 1048 "jsp.error.action.isnottagfile", 1049 localName), 1050 locator); 1051 } 1052 node = 1053 new Node.AttributeDirective( 1054 qName, 1055 nonTaglibAttrs, 1056 nonTaglibXmlnsAttrs, 1057 taglibAttrs, 1058 start, 1059 current); 1060 } else if (localName.equals(VARIABLE_DIRECTIVE_ACTION)) { 1061 if (!isTagFile) { 1062 throw new SAXParseException ( 1063 Localizer.getMessage( 1064 "jsp.error.action.isnottagfile", 1065 localName), 1066 locator); 1067 } 1068 node = 1069 new Node.VariableDirective( 1070 qName, 1071 nonTaglibAttrs, 1072 nonTaglibXmlnsAttrs, 1073 taglibAttrs, 1074 start, 1075 current); 1076 } else if (localName.equals(INVOKE_ACTION)) { 1077 if (!isTagFile) { 1078 throw new SAXParseException ( 1079 Localizer.getMessage( 1080 "jsp.error.action.isnottagfile", 1081 localName), 1082 locator); 1083 } 1084 node = 1085 new Node.InvokeAction( 1086 qName, 1087 nonTaglibAttrs, 1088 nonTaglibXmlnsAttrs, 1089 taglibAttrs, 1090 start, 1091 current); 1092 } else if (localName.equals(DOBODY_ACTION)) { 1093 if (!isTagFile) { 1094 throw new SAXParseException ( 1095 Localizer.getMessage( 1096 "jsp.error.action.isnottagfile", 1097 localName), 1098 locator); 1099 } 1100 node = 1101 new Node.DoBodyAction( 1102 qName, 1103 nonTaglibAttrs, 1104 nonTaglibXmlnsAttrs, 1105 taglibAttrs, 1106 start, 1107 current); 1108 } else if (localName.equals(ELEMENT_ACTION)) { 1109 node = 1110 new Node.JspElement( 1111 qName, 1112 nonTaglibAttrs, 1113 nonTaglibXmlnsAttrs, 1114 taglibAttrs, 1115 start, 1116 current); 1117 } else if (localName.equals(FALLBACK_ACTION)) { 1118 node = 1119 new Node.FallBackAction( 1120 qName, 1121 nonTaglibXmlnsAttrs, 1122 taglibAttrs, 1123 start, 1124 current); 1125 } else { 1126 throw new SAXParseException ( 1127 Localizer.getMessage( 1128 "jsp.error.xml.badStandardAction", 1129 localName), 1130 locator); 1131 } 1132 1133 return node; 1134 } 1135 1136 1140 private Node parseCustomAction( 1141 String qName, 1142 String localName, 1143 String uri, 1144 Attributes nonTaglibAttrs, 1145 Attributes nonTaglibXmlnsAttrs, 1146 Attributes taglibAttrs, 1147 Mark start, 1148 Node parent) 1149 throws SAXException { 1150 1151 TagLibraryInfo tagLibInfo = pageInfo.getTaglib(uri); 1153 if (tagLibInfo == null) { 1154 return null; 1155 } 1156 1157 TagInfo tagInfo = tagLibInfo.getTag(localName); 1158 TagFileInfo tagFileInfo = tagLibInfo.getTagFile(localName); 1159 if (tagInfo == null && tagFileInfo == null) { 1160 throw new SAXException ( 1161 Localizer.getMessage("jsp.error.xml.bad_tag", localName, uri)); 1162 } 1163 Class tagHandlerClass = null; 1164 if (tagInfo != null) { 1165 String handlerClassName = tagInfo.getTagClassName(); 1166 try { 1167 tagHandlerClass = 1168 ctxt.getClassLoader().loadClass(handlerClassName); 1169 } catch (Exception e) { 1170 throw new SAXException ( 1171 Localizer.getMessage("jsp.error.loadclass.taghandler", 1172 handlerClassName, 1173 qName), 1174 e); 1175 } 1176 } 1177 1178 String prefix = ""; 1179 int colon = qName.indexOf(':'); 1180 if (colon != -1) { 1181 prefix = qName.substring(0, colon); 1182 } 1183 1184 Node.CustomTag ret = null; 1185 if (tagInfo != null) { 1186 ret = 1187 new Node.CustomTag( 1188 qName, 1189 prefix, 1190 localName, 1191 uri, 1192 nonTaglibAttrs, 1193 nonTaglibXmlnsAttrs, 1194 taglibAttrs, 1195 start, 1196 parent, 1197 tagInfo, 1198 tagHandlerClass); 1199 } else { 1200 ret = 1201 new Node.CustomTag( 1202 qName, 1203 prefix, 1204 localName, 1205 uri, 1206 nonTaglibAttrs, 1207 nonTaglibXmlnsAttrs, 1208 taglibAttrs, 1209 start, 1210 parent, 1211 tagFileInfo); 1212 } 1213 1214 return ret; 1215 } 1216 1217 1226 private TagLibraryInfo getTaglibInfo(String prefix, String uri) 1227 throws JasperException { 1228 1229 TagLibraryInfo result = null; 1230 1231 if (uri.startsWith(URN_JSPTAGDIR)) { 1232 String tagdir = uri.substring(URN_JSPTAGDIR.length()); 1234 result = 1235 new ImplicitTagLibraryInfo( 1236 ctxt, 1237 parserController, 1238 pageInfo, 1239 prefix, 1240 tagdir, 1241 err); 1242 } else { 1243 boolean isPlainUri = false; 1245 if (uri.startsWith(URN_JSPTLD)) { 1246 uri = uri.substring(URN_JSPTLD.length()); 1248 } else { 1249 isPlainUri = true; 1250 } 1251 1252 String [] location = ctxt.getTldLocation(uri); 1253 if (location != null || !isPlainUri) { 1254 if (ctxt.getOptions().isCaching()) { 1255 result = (TagLibraryInfoImpl) ctxt.getOptions().getCache().get(uri); 1256 } 1257 if (result == null) { 1258 1264 result = 1265 new TagLibraryInfoImpl( 1266 ctxt, 1267 parserController, 1268 pageInfo, 1269 prefix, 1270 uri, 1271 location, 1272 err); 1273 if (ctxt.getOptions().isCaching()) { 1274 ctxt.getOptions().getCache().put(uri, result); 1275 } 1276 } 1277 } 1278 } 1279 1280 return result; 1281 } 1282 1283 1291 private void checkScriptingBody(Node.ScriptingElement scriptingElem) 1292 throws SAXException { 1293 Node.Nodes body = scriptingElem.getBody(); 1294 if (body != null) { 1295 int size = body.size(); 1296 for (int i = 0; i < size; i++) { 1297 Node n = body.getNode(i); 1298 if (!(n instanceof Node.TemplateText)) { 1299 String elemType = SCRIPTLET_ACTION; 1300 if (scriptingElem instanceof Node.Declaration) 1301 elemType = DECLARATION_ACTION; 1302 if (scriptingElem instanceof Node.Expression) 1303 elemType = EXPRESSION_ACTION; 1304 String msg = 1305 Localizer.getMessage( 1306 "jsp.error.parse.xml.scripting.invalid.body", 1307 elemType); 1308 throw new SAXException (msg); 1309 } 1310 } 1311 } 1312 } 1313 1314 1321 private void processIncludeDirective(String fname, Node parent) 1322 throws SAXException { 1323 1324 if (fname == null) { 1325 return; 1326 } 1327 1328 try { 1329 parserController.parse(fname, parent, null); 1330 } catch (FileNotFoundException fnfe) { 1331 throw new SAXParseException ( 1332 Localizer.getMessage("jsp.error.file.not.found", fname), 1333 locator, 1334 fnfe); 1335 } catch (Exception e) { 1336 throw new SAXException (e); 1337 } 1338 } 1339 1340 1349 private void checkPrefixes(String uri, String qName, Attributes attrs) { 1350 1351 checkPrefix(uri, qName); 1352 1353 int len = attrs.getLength(); 1354 for (int i = 0; i < len; i++) { 1355 checkPrefix(attrs.getURI(i), attrs.getQName(i)); 1356 } 1357 } 1358 1359 1367 private void checkPrefix(String uri, String qName) { 1368 1369 int index = qName.indexOf(':'); 1370 if (index != -1) { 1371 String prefix = qName.substring(0, index); 1372 pageInfo.addPrefix(prefix); 1373 if ("jsp".equals(prefix) && !JSP_URI.equals(uri)) { 1374 pageInfo.setIsJspPrefixHijacked(true); 1375 } 1376 } 1377 } 1378 1379 1388 private static SAXParser getSAXParser( 1389 boolean validating, 1390 JspDocumentParser jspDocParser) 1391 throws Exception { 1392 1393 SAXParserFactory factory = SAXParserFactory.newInstance(); 1394 factory.setNamespaceAware(true); 1395 1396 factory.setFeature( 1398 "http://xml.org/sax/features/namespace-prefixes", 1399 true); 1400 factory.setValidating(validating); 1401 1405 SAXParser saxParser = factory.newSAXParser(); 1407 XMLReader xmlReader = saxParser.getXMLReader(); 1408 xmlReader.setProperty(LEXICAL_HANDLER_PROPERTY, jspDocParser); 1409 xmlReader.setErrorHandler(jspDocParser); 1410 1411 return saxParser; 1412 } 1413 1414 1418 private static class EnableDTDValidationException 1419 extends SAXParseException { 1420 1421 EnableDTDValidationException(String message, Locator loc) { 1422 super(message, loc); 1423 } 1424 } 1425 1426 private static String getBodyType(Node.CustomTag custom) { 1427 1428 if (custom.getTagInfo() != null) { 1429 return custom.getTagInfo().getBodyContent(); 1430 } 1431 1432 return custom.getTagFileInfo().getTagInfo().getBodyContent(); 1433 } 1434 1435 private boolean isTagDependent(Node n) { 1436 1437 if (n instanceof Node.CustomTag) { 1438 String bodyType = getBodyType((Node.CustomTag) n); 1439 return 1440 TagInfo.BODY_CONTENT_TAG_DEPENDENT.equalsIgnoreCase(bodyType); 1441 } 1442 return false; 1443 } 1444} 1445 | Popular Tags |