1 56 57 package org.jdom.input; 58 59 import java.io.*; 60 import java.lang.reflect.*; 61 import java.net.*; 62 import java.util.*; 63 64 import org.jdom.*; 65 66 import org.xml.sax.*; 67 import org.xml.sax.helpers.XMLReaderFactory ; 68 69 89 public class SAXBuilder { 90 91 private static final String CVS_ID = 92 "@(#) $RCSfile: SAXBuilder.java,v $ $Revision: 1.91 $ $Date: 2004/12/11 02:17:58 $ $Name: $"; 93 94 98 private static final String DEFAULT_SAX_DRIVER = 99 "org.apache.xerces.parsers.SAXParser"; 100 101 102 private boolean validate; 103 104 105 private boolean expand = true; 106 107 108 private String saxDriverClass; 109 110 111 private ErrorHandler saxErrorHandler = null; 112 113 114 private EntityResolver saxEntityResolver = null; 115 116 117 private DTDHandler saxDTDHandler = null; 118 119 120 private XMLFilter saxXMLFilter = null; 121 122 123 private JDOMFactory factory = new DefaultJDOMFactory(); 124 125 126 private boolean ignoringWhite = false; 127 128 129 private boolean ignoringBoundaryWhite = false; 130 131 132 private HashMap features = new HashMap(5); 133 134 135 private HashMap properties = new HashMap(5); 136 137 141 private boolean reuseParser = true; 142 143 144 private XMLReader saxParser = null; 145 146 151 public SAXBuilder() { 152 this(false); 153 } 154 155 164 public SAXBuilder(boolean validate) { 165 this.validate = validate; 166 } 167 168 175 public SAXBuilder(String saxDriverClass) { 176 this(saxDriverClass, false); 177 } 178 179 189 public SAXBuilder(String saxDriverClass, boolean validate) { 190 this.saxDriverClass = saxDriverClass; 191 this.validate = validate; 192 } 193 194 199 public String getDriverClass() { 200 return saxDriverClass; 201 } 202 203 207 public JDOMFactory getFactory() { 208 return factory; 209 } 210 211 217 public void setFactory(JDOMFactory factory) { 218 this.factory = factory; 219 } 220 221 226 public boolean getValidation() { 227 return validate; 228 } 229 230 236 public void setValidation(boolean validate) { 237 this.validate = validate; 238 } 239 240 244 public ErrorHandler getErrorHandler() { 245 return saxErrorHandler; 246 } 247 248 253 public void setErrorHandler(ErrorHandler errorHandler) { 254 saxErrorHandler = errorHandler; 255 } 256 257 262 public EntityResolver getEntityResolver() { 263 return saxEntityResolver; 264 } 265 266 271 public void setEntityResolver(EntityResolver entityResolver) { 272 saxEntityResolver = entityResolver; 273 } 274 275 280 public DTDHandler getDTDHandler() { 281 return saxDTDHandler; 282 } 283 284 289 public void setDTDHandler(DTDHandler dtdHandler) { 290 saxDTDHandler = dtdHandler; 291 } 292 293 298 public XMLFilter getXMLFilter() { 299 return saxXMLFilter; 300 } 301 302 307 public void setXMLFilter(XMLFilter xmlFilter) { 308 saxXMLFilter = xmlFilter; 309 } 310 311 318 public boolean getIgnoringElementContentWhitespace() { 319 return ignoringWhite; 320 } 321 322 333 public void setIgnoringElementContentWhitespace(boolean ignoringWhite) { 334 this.ignoringWhite = ignoringWhite; 335 } 336 337 346 public boolean getIgnoringBoundaryWhitespace() { 347 return ignoringBoundaryWhite; 348 } 349 350 366 public void setIgnoringBoundaryWhitespace(boolean ignoringBoundaryWhite) { 367 this.ignoringBoundaryWhite = ignoringBoundaryWhite; 368 } 369 370 377 public boolean getReuseParser() { 378 return reuseParser; 379 } 380 381 393 public void setReuseParser(boolean reuseParser) { 394 this.reuseParser = reuseParser; 395 this.saxParser = null; 396 } 397 398 413 public void setFeature(String name, boolean value) { 414 features.put(name, new Boolean (value)); 416 } 417 418 433 public void setProperty(String name, Object value) { 434 properties.put(name, value); 436 } 437 438 448 public Document build(InputSource in) 449 throws JDOMException, IOException { 450 SAXHandler contentHandler = null; 451 452 try { 453 contentHandler = createContentHandler(); 455 configureContentHandler(contentHandler); 456 457 XMLReader parser = this.saxParser; 458 if (parser == null) { 459 parser = createParser(); 461 462 if (saxXMLFilter != null) { 464 XMLFilter root = saxXMLFilter; 466 while (root.getParent() instanceof XMLFilter) { 467 root = (XMLFilter)root.getParent(); 468 } 469 root.setParent(parser); 470 471 parser = saxXMLFilter; 473 } 474 475 configureParser(parser, contentHandler); 477 478 if (reuseParser == true) { 479 this.saxParser = parser; 480 } 481 } 482 else { 483 configureParser(parser, contentHandler); 486 } 487 488 parser.parse(in); 490 491 return contentHandler.getDocument(); 492 } 493 catch (SAXParseException e) { 494 Document doc = contentHandler.getDocument(); 495 if (doc.hasRootElement() == false) { 496 doc = null; 497 } 498 499 String systemId = e.getSystemId(); 500 if (systemId != null) { 501 throw new JDOMParseException("Error on line " + 502 e.getLineNumber() + " of document " + systemId, e, doc); 503 } else { 504 throw new JDOMParseException("Error on line " + 505 e.getLineNumber(), e, doc); 506 } 507 } 508 catch (SAXException e) { 509 throw new JDOMParseException("Error in building: " + 510 e.getMessage(), e, contentHandler.getDocument()); 511 } 512 finally { 513 contentHandler = null; 517 } 518 } 519 520 525 protected SAXHandler createContentHandler() { 526 SAXHandler contentHandler = new SAXHandler(factory); 527 return contentHandler; 528 } 529 530 538 protected void configureContentHandler(SAXHandler contentHandler) { 539 contentHandler.setExpandEntities(expand); 541 contentHandler.setIgnoringElementContentWhitespace(ignoringWhite); 542 contentHandler.setIgnoringBoundaryWhitespace(ignoringBoundaryWhite); 543 } 544 545 557 protected XMLReader createParser() throws JDOMException { 558 XMLReader parser = null; 559 if (saxDriverClass != null) { 560 try { 562 parser = XMLReaderFactory.createXMLReader(saxDriverClass); 563 564 setFeaturesAndProperties(parser, true); 566 } 567 catch (SAXException e) { 568 throw new JDOMException("Could not load " + saxDriverClass, e); 569 } 570 } else { 571 try { 576 Class factoryClass = 578 Class.forName("org.jdom.input.JAXPParserFactory"); 579 580 Method createParser = 581 factoryClass.getMethod("createParser", 582 new Class [] { boolean.class, Map.class, Map.class }); 583 584 parser = (XMLReader)createParser.invoke(null, 586 new Object [] { new Boolean (validate), 587 features, properties }); 588 589 setFeaturesAndProperties(parser, false); 591 } 592 catch (JDOMException e) { 593 throw e; 594 } 595 catch (NoClassDefFoundError e) { 596 } 601 catch (Exception e) { 602 } 604 } 605 606 if (parser == null) { 609 try { 610 parser = XMLReaderFactory.createXMLReader(DEFAULT_SAX_DRIVER); 611 saxDriverClass = parser.getClass().getName(); 613 614 setFeaturesAndProperties(parser, true); 616 } 617 catch (SAXException e) { 618 throw new JDOMException("Could not load default SAX parser: " 619 + DEFAULT_SAX_DRIVER, e); 620 } 621 } 622 623 return parser; 624 } 625 626 637 protected void configureParser(XMLReader parser, SAXHandler contentHandler) 638 throws JDOMException { 639 640 642 parser.setContentHandler(contentHandler); 643 644 if (saxEntityResolver != null) { 645 parser.setEntityResolver(saxEntityResolver); 646 } 647 648 if (saxDTDHandler != null) { 649 parser.setDTDHandler(saxDTDHandler); 650 } else { 651 parser.setDTDHandler(contentHandler); 652 } 653 654 if (saxErrorHandler != null) { 655 parser.setErrorHandler(saxErrorHandler); 656 } else { 657 parser.setErrorHandler(new BuilderErrorHandler()); 658 } 659 660 boolean lexicalReporting = false; 662 try { 663 parser.setProperty("http://xml.org/sax/handlers/LexicalHandler", 664 contentHandler); 665 lexicalReporting = true; 666 } catch (SAXNotSupportedException e) { 667 } catch (SAXNotRecognizedException e) { 669 } 671 672 if (!lexicalReporting) { 674 try { 675 parser.setProperty( 676 "http://xml.org/sax/properties/lexical-handler", 677 contentHandler); 678 lexicalReporting = true; 679 } catch (SAXNotSupportedException e) { 680 } catch (SAXNotRecognizedException e) { 682 } 684 } 685 686 if (!expand) { 688 try { 689 parser.setProperty( 690 "http://xml.org/sax/properties/declaration-handler", 691 contentHandler); 692 } catch (SAXNotSupportedException e) { 693 } catch (SAXNotRecognizedException e) { 695 } 697 } 698 } 699 700 private void setFeaturesAndProperties(XMLReader parser, 701 boolean coreFeatures) 702 throws JDOMException { 703 Iterator iter = features.keySet().iterator(); 705 while (iter.hasNext()) { 706 String name = (String )iter.next(); 707 Boolean value = (Boolean )features.get(name); 708 internalSetFeature(parser, name, value.booleanValue(), name); 709 } 710 711 iter = properties.keySet().iterator(); 713 while (iter.hasNext()) { 714 String name = (String )iter.next(); 715 internalSetProperty(parser, name, properties.get(name), name); 716 } 717 718 if (coreFeatures) { 719 try { 721 internalSetFeature(parser, 722 "http://xml.org/sax/features/validation", 723 validate, "Validation"); 724 } catch (JDOMException e) { 725 if (validate) 729 throw e; 730 } 731 732 internalSetFeature(parser, 734 "http://xml.org/sax/features/namespaces", 735 true, "Namespaces"); 736 internalSetFeature(parser, 737 "http://xml.org/sax/features/namespace-prefixes", 738 true, "Namespace prefixes"); 739 } 740 741 try { 749 if (parser.getFeature("http://xml.org/sax/features/external-general-entities") != expand) { 750 parser.setFeature("http://xml.org/sax/features/external-general-entities", expand); 751 } 752 } 753 catch (SAXNotRecognizedException e) { } 754 catch (SAXNotSupportedException e) { } 755 } 756 757 761 private void internalSetFeature(XMLReader parser, String feature, 762 boolean value, String displayName) throws JDOMException { 763 try { 764 parser.setFeature(feature, value); 765 } catch (SAXNotSupportedException e) { 766 throw new JDOMException( 767 displayName + " feature not supported for SAX driver " + parser.getClass().getName()); 768 } catch (SAXNotRecognizedException e) { 769 throw new JDOMException( 770 displayName + " feature not recognized for SAX driver " + parser.getClass().getName()); 771 } 772 } 773 774 780 private void internalSetProperty(XMLReader parser, String property, 781 Object value, String displayName) throws JDOMException { 782 try { 783 parser.setProperty(property, value); 784 } catch (SAXNotSupportedException e) { 785 throw new JDOMException( 786 displayName + " property not supported for SAX driver " + parser.getClass().getName()); 787 } catch (SAXNotRecognizedException e) { 788 throw new JDOMException( 789 displayName + " property not recognized for SAX driver " + parser.getClass().getName()); 790 } 791 } 792 793 805 public Document build(InputStream in) 806 throws JDOMException, IOException { 807 return build(new InputSource(in)); 808 } 809 810 822 public Document build(File file) 823 throws JDOMException, IOException { 824 try { 825 URL url = fileToURL(file); 826 return build(url); 827 } catch (MalformedURLException e) { 828 throw new JDOMException("Error in building", e); 829 } 830 } 831 832 844 public Document build(URL url) 845 throws JDOMException, IOException { 846 String systemID = url.toExternalForm(); 847 return build(new InputSource(systemID)); 848 } 849 850 863 public Document build(InputStream in, String systemId) 864 throws JDOMException, IOException { 865 866 InputSource src = new InputSource(in); 867 src.setSystemId(systemId); 868 return build(src); 869 } 870 871 886 public Document build(Reader characterStream) 887 throws JDOMException, IOException { 888 return build(new InputSource(characterStream)); 889 } 890 891 907 public Document build(Reader characterStream, String systemId) 908 throws JDOMException, IOException { 909 910 InputSource src = new InputSource(characterStream); 911 src.setSystemId(systemId); 912 return build(src); 913 } 914 915 926 public Document build(String systemId) 927 throws JDOMException, IOException { 928 return build(new InputSource(systemId)); 929 } 930 931 954 960 private static URL fileToURL(File file) throws MalformedURLException { 961 StringBuffer buffer = new StringBuffer (); 962 String path = file.getAbsolutePath(); 963 964 if (File.separatorChar != '/') { 966 path = path.replace(File.separatorChar, '/'); 967 } 968 969 if (!path.startsWith("/")) { 971 buffer.append('/'); 972 } 973 974 int len = path.length(); 976 for (int i = 0; i < len; i++) { 977 char c = path.charAt(i); 978 if (c == ' ') 979 buffer.append("%20"); 980 else if (c == '#') 981 buffer.append("%23"); 982 else if (c == '%') 983 buffer.append("%25"); 984 else if (c == '&') 985 buffer.append("%26"); 986 else if (c == ';') 987 buffer.append("%3B"); 988 else if (c == '<') 989 buffer.append("%3C"); 990 else if (c == '=') 991 buffer.append("%3D"); 992 else if (c == '>') 993 buffer.append("%3E"); 994 else if (c == '?') 995 buffer.append("%3F"); 996 else if (c == '~') 997 buffer.append("%7E"); 998 else 999 buffer.append(c); 1000 } 1001 1002 if (!path.endsWith("/") && file.isDirectory()) { 1004 buffer.append('/'); 1005 } 1006 1007 return new URL("file", "", buffer.toString()); 1009 } 1010 1011 1017 public boolean getExpandEntities() { 1018 return expand; 1019 } 1020 1021 1044 public void setExpandEntities(boolean expand) { 1045 this.expand = expand; 1046 } 1047} 1048 | Popular Tags |