1 28 29 package com.caucho.xml2; 30 31 import com.caucho.server.util.CauchoSystem; 32 import com.caucho.util.L10N; 33 import com.caucho.vfs.Path; 34 import com.caucho.vfs.ReadStream; 35 import com.caucho.vfs.Vfs; 36 import com.caucho.vfs.VfsStream; 37 38 import org.w3c.dom.Document ; 39 import org.xml.sax.*; 40 import org.xml.sax.ext.LexicalHandler ; 41 42 import javax.xml.parsers.DocumentBuilderFactory ; 43 import java.io.FileNotFoundException ; 44 import java.io.IOException ; 45 import java.io.InputStream ; 46 import java.util.Hashtable ; 47 import java.util.Locale ; 48 import java.util.logging.Logger ; 49 50 abstract public class AbstractParser implements XMLReader, Parser 51 { 52 static final Logger log = Logger.getLogger(AbstractParser.class.getName()); 53 static final L10N L = new L10N(AbstractParser.class); 54 55 static Hashtable <String ,String > _attrTypes = new Hashtable <String ,String >(); 56 static Entities _xmlEntities = new XmlEntities(); 57 58 boolean _isCoalescing = true; 59 60 boolean _optionalTags = true; 61 boolean _skipWhitespace; 62 boolean _skipComments; 63 boolean _strictComments; 64 boolean _strictAttributes; 65 boolean _entitiesAsText = false; 66 boolean _expandEntities = true; 67 boolean _strictCharacters; 68 boolean _strictXml; 69 boolean _singleTopElement; 70 71 boolean _isNamespaceAware = true; 72 boolean _isNamespacePrefixes = true; 73 boolean _isSAXNamespaces = false; 74 75 boolean _isXmlnsPrefix; 76 boolean _isXmlnsAttribute; 77 78 boolean _isValidating = false; 79 80 boolean _isStaticEncoding = false; 81 String _defaultEncoding = "UTF-8"; 82 83 ContentHandler _contentHandler; 85 EntityResolver _entityResolver; 86 DTDHandler _dtdHandler; 87 LexicalHandler _lexicalHandler; 88 ErrorHandler _errorHandler; 89 Locale _locale; 90 91 Entities _entities; 92 QDocument _owner; 93 QDocumentType _dtd; 94 95 DOMBuilder _builder; 96 97 Path _searchPath; 98 99 String _publicId; 100 String _systemId; 101 String _filename; 102 int _line = 1; 103 104 107 AbstractParser() 108 { 109 this(null); 110 } 111 112 118 AbstractParser(QDocumentType dtd) 119 { 120 if (dtd == null) 121 dtd = new QDocumentType(null); 122 _dtd = dtd; 123 124 _entities = _xmlEntities; 125 } 126 127 void clear() 128 { 129 _isCoalescing = true; 130 131 _isNamespaceAware = true; 132 _isSAXNamespaces = false; 133 _isNamespacePrefixes = false; 134 _optionalTags = true; 135 _skipWhitespace = false; 136 _skipComments = false; 137 _strictComments = false; 138 _strictAttributes = false; 139 _entitiesAsText = false; 140 _expandEntities = true; 141 _strictCharacters = false; 142 _strictXml = false; 143 _singleTopElement = false; 144 145 _defaultEncoding = "UTF-8"; 146 _isStaticEncoding = false; 147 } 148 149 void init() 150 { 151 156 _isXmlnsPrefix = _isNamespaceAware || _isNamespacePrefixes; 157 _isXmlnsAttribute = _isNamespacePrefixes || ! _isNamespaceAware; 158 } 159 160 163 public void setOwner(QDocument doc) 164 { 165 _owner = doc; 166 } 167 168 171 public void setConfig(DocumentBuilderFactory factory) 172 { 173 if (_builder == null) 174 _builder = new DOMBuilder(); 175 176 _isCoalescing = factory.isCoalescing(); 177 setExpandEntities(factory.isExpandEntityReferences()); 178 setSkipComments(factory.isIgnoringComments()); 179 setSkipWhitespace(factory.isIgnoringElementContentWhitespace()); 180 setNamespaceAware(factory.isNamespaceAware()); 181 setNamespacePrefixes(false); 182 setValidating(factory.isValidating()); 183 } 184 185 public void setEntitiesAsText(boolean entitiesAsText) 186 { 187 _entitiesAsText = entitiesAsText; 188 } 189 190 public boolean getEntitiesAsText() 191 { 192 return _entitiesAsText; 193 } 194 195 public void setExpandEntities(boolean expandEntities) 196 { 197 _expandEntities = expandEntities; 198 } 199 200 204 public void setSkipComments(boolean skipComments) 205 { 206 _skipComments = skipComments; 207 } 208 209 212 public void setSkipWhitespace(boolean skipWhitespace) 213 { 214 _skipWhitespace = skipWhitespace; 215 } 216 217 220 public boolean isCoalescing() 221 { 222 return _isCoalescing; 223 } 224 225 228 public void setCoalescing(boolean isCoalescing) 229 { 230 _isCoalescing = isCoalescing; 231 } 232 233 236 public boolean isValidating() 237 { 238 return _isValidating; 239 } 240 241 244 public void setValidating(boolean isValidating) 245 { 246 _isValidating = isValidating; 247 } 248 249 252 public boolean isNamespaceAware() 253 { 254 return _isNamespaceAware; 255 } 256 257 260 public void setNamespaceAware(boolean isNamespaceAware) 261 { 262 _isNamespaceAware = isNamespaceAware; 263 } 264 265 268 public boolean isSAXNamespaces() 269 { 270 return _isSAXNamespaces; 271 } 272 273 276 public void setSAXNamespaces(boolean isNamespaces) 277 { 278 _isSAXNamespaces = isNamespaces; 279 } 280 281 284 public boolean isNamespacePrefixes() 285 { 286 return _isNamespacePrefixes; 287 } 288 289 292 public void setNamespacePrefixes(boolean isNamespaces) 293 { 294 _isNamespacePrefixes = isNamespaces; 295 } 296 297 public boolean getSkipComments() 298 { 299 return _skipComments; 300 } 301 302 307 public void setDefaultEncoding(String encoding) 308 { 309 _defaultEncoding = encoding; 310 } 311 312 315 public String getDefaultEncoding() 316 { 317 return _defaultEncoding; 318 } 319 320 public Object getProperty(String name) 321 throws SAXNotRecognizedException 322 { 323 if (name.equals("http://xml.org/sax/properties/lexical-handler")) 324 return _lexicalHandler; 325 else if (name.equals("http://xml.org/sax/properties/dom-node")) 326 return null; 327 else if (name.equals("http://xml.org/sax/properties/xml-string")) 328 return null; 329 else 330 throw new SAXNotRecognizedException(name); 331 } 332 333 public void setProperty(String name, Object obj) 334 throws SAXNotSupportedException 335 { 336 if (name.equals("http://xml.org/sax/properties/lexical-handler")) 337 _lexicalHandler = (LexicalHandler ) obj; 338 else if (name.equals("http://xml.org/sax/handlers/LexicalHandler")) 339 _lexicalHandler = (LexicalHandler ) obj; 340 else 341 throw new SAXNotSupportedException(name); 342 } 343 344 public boolean getFeature(String name) 345 throws SAXNotRecognizedException 346 { 347 if (name.equals("http://xml.org/sax/features/namespaces")) 348 return _isSAXNamespaces; 349 else if (name.equals("http://xml.org/sax/features/namespace-prefixes")) 350 return _isNamespacePrefixes; 351 else if (name.equals("http://xml.org/sax/features/string-interning")) 352 return true; 353 else if (name.equals("http://xml.org/sax/features/validation")) 354 return _isValidating; 355 else if (name.equals("http://xml.org/sax/features/external-general-entities")) 356 return true; 357 else if (name.equals("http://xml.org/sax/features/external-parameter-entities")) 358 return false; 359 else if (name.equals("http://caucho.com/xml/features/skip-comments")) 360 return _skipComments; 361 else 362 throw new SAXNotRecognizedException(name); 363 } 364 365 public void setFeature(String name, boolean value) 366 throws SAXNotSupportedException 367 { 368 if (name.equals("http://xml.org/sax/features/namespaces")) { 369 _isNamespaceAware = value; 370 } 371 else if (name.equals("http://xml.org/sax/features/namespace-prefixes")) { 372 _isNamespacePrefixes = value; 375 _isNamespaceAware = true; 376 } 377 else if (name.equals("http://caucho.com/xml/features/skip-comments")) { 378 _skipComments = value; 379 } 380 else if (name.equals("http://xml.org/sax/features/validation")) 381 _isValidating = value; 382 else 383 throw new SAXNotSupportedException(name); 384 } 385 386 public void setLexicalHandler(LexicalHandler handler) 387 { 388 _lexicalHandler = handler; 389 } 390 391 396 public void setEntityResolver(EntityResolver resolver) 397 { 398 _entityResolver = resolver; 399 } 400 401 406 public EntityResolver getEntityResolver() 407 { 408 return _entityResolver; 409 } 410 411 public void setDTDHandler(DTDHandler handler) 412 { 413 _dtdHandler = handler; 414 } 415 416 public DTDHandler getDTDHandler() 417 { 418 return _dtdHandler; 419 } 420 421 public void setContentHandler(ContentHandler handler) 422 { 423 _contentHandler = handler; 424 } 425 426 public ContentHandler getContentHandler() 427 { 428 return _contentHandler; 429 } 430 431 436 public void setDocumentHandler(DocumentHandler handler) 437 { 438 if (handler == null) 439 _contentHandler = null; 440 else 441 _contentHandler = new ContentHandlerAdapter(handler); 442 } 443 444 public void setErrorHandler(ErrorHandler handler) 445 { 446 _errorHandler = handler; 447 } 448 449 public ErrorHandler getErrorHandler() 450 { 451 return _errorHandler; 452 } 453 454 public void setLocale(Locale locale) 455 { 456 _locale = locale; 457 } 458 459 464 public void parse(InputSource source) 465 throws IOException , SAXException 466 { 467 init(); 468 469 if (_searchPath == null) { 470 if (source.getSystemId() != null) 471 _searchPath = Vfs.lookup(source.getSystemId()).getParent(); 472 } 473 474 _systemId = source.getSystemId(); 475 _publicId = source.getPublicId(); 476 ReadStream stream; 477 String encoding = null; 478 479 if (source.getByteStream() != null) { 480 stream = Vfs.openRead(source.getByteStream()); 481 encoding = source.getEncoding(); 482 } 483 else if (source.getCharacterStream() != null) { 484 encoding = "UTF-8"; 485 _isStaticEncoding = true; 486 stream = Vfs.openRead(source.getCharacterStream()); 487 } 488 else if (source.getSystemId() != null) { 489 InputStream is = openStream(source.getSystemId(), 490 source.getPublicId(), 491 null, 492 true); 493 stream = Vfs.openRead(is); 494 encoding = source.getEncoding(); 495 } 496 else 497 throw new FileNotFoundException (L.l("invalid InputSource")); 498 499 if (encoding != null) 500 stream.setEncoding(encoding); 501 502 try { 503 parseInt(stream); 504 } finally { 505 stream.close(); 506 } 507 } 508 509 514 public void parse(InputStream is) 515 throws IOException , SAXException 516 { 517 init(); 518 519 _systemId = "stream"; 520 521 if (is instanceof ReadStream) { 522 Path path = ((ReadStream) is).getPath(); 523 _systemId = path.getURL(); 524 _filename = path.getUserPath(); 525 526 if (_searchPath != null) { 527 } 528 else if (path != null) 529 _searchPath = path.getParent(); 530 531 parseInt((ReadStream) is); 532 } 533 else { 534 ReadStream rs = VfsStream.openRead(is); 535 try { 536 parseInt(rs); 537 } finally { 538 if (rs != is) 539 rs.close(); 540 } 541 } 542 } 543 544 549 public void parse(InputStream is, String systemId) 550 throws IOException , SAXException 551 { 552 init(); 553 554 parseImpl(is, systemId); 555 } 556 557 562 public void parseImpl(InputStream is, String systemId) 563 throws IOException , SAXException 564 { 565 if (is instanceof ReadStream) { 566 Path path = ((ReadStream) is).getPath(); 567 568 if (_searchPath != null) { 569 } 570 else if (path != null) { 571 _searchPath = path.getParent(); 572 if (systemId != null) 573 _searchPath = _searchPath.lookup(systemId).getParent(); 574 } 575 else if (systemId != null) 576 _searchPath = Vfs.lookup(systemId).getParent(); 577 578 if (systemId == null) { 579 systemId = path.getURL(); 580 _filename = ((ReadStream) is).getUserPath(); 581 } 582 else 583 _filename = systemId; 584 585 _systemId = systemId; 586 587 parseInt((ReadStream) is); 588 } 589 else { 590 if (systemId == null) { 591 _systemId = "anonymous.xml"; 592 } 593 else { 594 _searchPath = Vfs.lookup(systemId).getParent(); 595 _systemId = systemId; 596 } 597 598 ReadStream rs = VfsStream.openRead(is); 599 try { 600 parseInt(rs); 601 } finally { 602 if (rs != is) 603 rs.close(); 604 } 605 } 606 } 607 608 613 public void parse(String systemId) 614 throws IOException , SAXException 615 { 616 InputStream is = openTopStream(systemId, null); 617 try { 618 parse(is); 619 } finally { 620 is.close(); 621 } 622 } 623 624 627 public void parse(Path path) 628 throws IOException , SAXException 629 { 630 init(); 631 632 if (_searchPath == null) 633 _searchPath = path.getParent(); 634 635 ReadStream is = path.openRead(); 636 try { 637 parseInt(is); 638 } finally { 639 is.close(); 640 } 641 } 642 643 648 public void parseString(String string) 649 throws IOException , SAXException 650 { 651 init(); 652 653 ReadStream is = Vfs.openString(string); 654 655 try { 656 parseInt(is); 657 } finally { 658 is.close(); 659 } 660 } 661 662 667 public Document parseDocument(InputSource source) 668 throws IOException , SAXException 669 { 670 init(); 671 672 QDocument doc = new QDocument(); 673 674 if (_builder == null) 675 _builder = new DOMBuilder(); 676 677 _builder.init(doc); 678 setOwner(doc); 679 680 doc.setSystemId(source.getSystemId()); 681 _builder.setSystemId(source.getSystemId()); 682 _builder.setStrictXML(_strictXml); 683 _builder.setCoalescing(_isCoalescing); 684 _builder.setSkipWhitespace(_skipWhitespace); 685 _contentHandler = _builder; 686 687 parse(source); 688 689 return doc; 690 } 691 692 697 public Document parseDocument(String systemId) 698 throws IOException , SAXException 699 { 700 InputStream is = openTopStream(systemId, null); 701 try { 702 return parseDocument(is); 703 } finally { 704 is.close(); 705 } 706 } 707 708 713 public Document parseDocument(Path path) 714 throws IOException , SAXException 715 { 716 if (_searchPath == null) 717 _searchPath = path.getParent(); 718 719 ReadStream is = path.openRead(); 720 try { 721 return parseDocument(is); 722 } finally { 723 is.close(); 724 } 725 } 726 727 734 public Document parseDocument(InputStream is) 735 throws IOException , SAXException 736 { 737 return parseDocument(is, null); 738 } 739 740 748 public Document parseDocument(InputStream is, String systemId) 749 throws IOException , SAXException 750 { 751 init(); 752 753 QDocument doc = new QDocument(); 754 parseDocument(doc, is, systemId); 755 756 return doc; 757 } 758 759 public void parseDocument(QDocument doc, InputStream is, String systemId) 760 throws IOException , SAXException 761 { 762 _owner = doc; 763 764 if (_builder == null) 765 _builder = new DOMBuilder(); 766 767 _builder.init(_owner); 768 _builder.setSystemId(systemId); 769 _builder.setCoalescing(_isCoalescing); 770 _builder.setSkipWhitespace(_skipWhitespace); 771 _contentHandler = _builder; 772 773 parseImpl(is, systemId); 774 } 775 776 781 public Document parseDocumentString(String string) 782 throws IOException , SAXException 783 { 784 ReadStream is = Vfs.openString(string); 785 786 try { 787 _isStaticEncoding = true; 788 return parseDocument(is); 789 } finally { 790 is.close(); 791 } 792 } 793 794 797 public InputStream openStream(String systemId, String publicId) 798 throws IOException , SAXException 799 { 800 return openStream(systemId, publicId, _entityResolver, false); 801 } 802 803 806 public InputStream openTopStream(String systemId, String publicId) 807 throws IOException , SAXException 808 { 809 return openStream(systemId, publicId, _entityResolver, true); 810 } 811 812 815 public InputStream openStream(String systemId, String publicId, 816 EntityResolver entityResolver) 817 throws IOException , SAXException 818 { 819 return openStream(systemId, publicId, entityResolver, false); 820 } 821 822 825 protected InputStream openStream(String systemId, String publicId, 826 EntityResolver entityResolver, 827 boolean isTop) 828 throws IOException , SAXException 829 { 830 int colon = systemId.indexOf(':'); 831 int slash = systemId.indexOf('/'); 832 833 boolean isAbsolute = colon > 0 && (colon < slash || slash < 0); 834 835 if (slash == 0 || ! isAbsolute) { 836 Path pwd; 837 838 if (_searchPath != null) 839 pwd = _searchPath; 840 else 841 pwd = Vfs.lookup(systemId).getParent(); 842 843 String newId = pwd.lookup(systemId).getURL(); 844 if (! newId.startsWith("error:")) 845 systemId = newId; 846 else { 847 int tail = _systemId.lastIndexOf('/'); 848 if (tail >= 0) 849 systemId = _systemId.substring(0, tail + 1) + systemId; 850 } 851 } 852 853 if (entityResolver != null) { 855 InputSource source = entityResolver.resolveEntity(publicId, systemId); 856 857 if (source != null) { 858 _filename = systemId; 859 _systemId = systemId; 860 861 return openSource(source); 862 } 863 } 864 865 int ch; 866 if (CauchoSystem.isWindows() && systemId.startsWith("file:") && 867 systemId.length() > 7 && systemId.charAt(6) == ':' && 868 (((ch = systemId.charAt(5)) >= 'a' && ch <= 'z') || 869 ch >= 'A' && ch <= 'Z')) { 870 colon = 1; 871 isAbsolute = false; 872 systemId = "/" + systemId.substring(5); 873 } 874 875 if (! isTop && 876 isAbsolute && ! systemId.startsWith("file:") && 877 ! systemId.startsWith("jar:") && 878 ! (colon == 1 && CauchoSystem.isWindows())) { 879 throw new RemoteURLException(L.l("URL `{0}' was not opened because it is a remote URL. Any URL scheme other than file: must be handled by a custom entity resolver.", 880 systemId)); 881 } 882 else if (_searchPath != null) { 883 return _searchPath.lookup(systemId).openRead(); 884 } 885 else 886 return Vfs.lookup(systemId).openRead(); 887 } 888 889 892 protected InputStream openSource(InputSource source) 893 throws IOException , SAXException 894 { 895 if (source.getByteStream() != null) { 896 return source.getByteStream(); 897 } 898 else if (source.getCharacterStream() != null) { 899 return Vfs.openRead(source.getCharacterStream()); 900 } 901 else if (source.getSystemId() != null) { 902 return Vfs.openRead(source.getSystemId()); 903 } 904 else 905 throw new FileNotFoundException (L.l("invalid InputSource {0}", source)); 906 } 907 908 915 abstract Document parseInt(ReadStream is) 916 throws IOException , SAXException; 917 918 static { 919 _attrTypes.put("CDATA", "CDATA"); 920 _attrTypes.put("ID", "ID"); 921 _attrTypes.put("IDREF", "IDREF"); 922 _attrTypes.put("IDREFS", "IDREFS"); 923 _attrTypes.put("ENTITY", "ENTITY"); 924 _attrTypes.put("ENTITIES", "ENTITIES"); 925 _attrTypes.put("NMTOKEN", "NMTOKEN"); 926 _attrTypes.put("NMTOKENS", "NMTOKENS"); 927 } 928 } 929 | Popular Tags |