1 18 package org.apache.batik.dom.util; 19 20 import java.io.IOException ; 21 import java.io.InputStream ; 22 import java.io.InterruptedIOException ; 23 import java.io.Reader ; 24 import java.util.Iterator ; 25 import java.util.LinkedList ; 26 import java.util.List ; 27 28 import org.w3c.dom.DOMImplementation ; 29 import org.w3c.dom.Document ; 30 import org.w3c.dom.Element ; 31 import org.w3c.dom.Node ; 32 33 import org.xml.sax.Attributes ; 34 import org.xml.sax.ErrorHandler ; 35 import org.xml.sax.InputSource ; 36 import org.xml.sax.Locator ; 37 import org.xml.sax.SAXException ; 38 import org.xml.sax.SAXParseException ; 39 import org.xml.sax.XMLReader ; 40 import org.xml.sax.ext.LexicalHandler ; 41 import org.xml.sax.helpers.DefaultHandler ; 42 import org.xml.sax.helpers.XMLReaderFactory ; 43 44 import org.apache.batik.util.HaltingThread; 45 46 53 public class SAXDocumentFactory 54 extends DefaultHandler 55 implements LexicalHandler , 56 DocumentFactory { 57 58 61 protected DOMImplementation implementation; 62 63 66 protected String parserClassName; 67 68 71 protected Document document; 72 73 76 protected DocumentDescriptor documentDescriptor; 77 78 81 protected boolean createDocumentDescriptor; 82 83 86 protected Node currentNode; 87 88 91 protected Locator locator; 92 93 96 protected StringBuffer stringBuffer = new StringBuffer (); 97 101 protected boolean stringContent; 102 103 106 protected boolean inDTD; 107 108 111 protected boolean inCDATA; 112 113 116 protected boolean isValidating; 117 118 121 protected HashTableStack namespaces; 122 123 126 protected ErrorHandler errorHandler; 127 128 protected interface PreInfo { 129 public Node createNode(Document doc); 130 } 131 132 static class ProcessingInstructionInfo implements PreInfo { 133 public String target, data; 134 public ProcessingInstructionInfo(String target, String data) { 135 this.target = target; 136 this.data = data; 137 } 138 public Node createNode(Document doc) { 139 return doc.createProcessingInstruction(target, data); 140 } 141 } 142 143 static class CommentInfo implements PreInfo { 144 public String comment; 145 public CommentInfo(String comment) { 146 this.comment = comment; 147 } 148 public Node createNode(Document doc) { 149 return doc.createComment(comment); 150 } 151 } 152 153 static class CDataInfo implements PreInfo { 154 public String cdata; 155 public CDataInfo(String cdata) { 156 this.cdata = cdata; 157 } 158 public Node createNode(Document doc) { 159 return doc.createCDATASection(cdata); 160 } 161 } 162 163 static class TextInfo implements PreInfo { 164 public String text; 165 public TextInfo(String text) { 166 this.text = text; 167 } 168 public Node createNode(Document doc) { 169 return doc.createTextNode(text); 170 } 171 } 172 173 177 protected List preInfo; 178 179 185 public SAXDocumentFactory(DOMImplementation impl, 186 String parser) { 187 implementation = impl; 188 parserClassName = parser; 189 } 190 191 197 public SAXDocumentFactory(DOMImplementation impl, 198 String parser, 199 boolean dd) { 200 implementation = impl; 201 parserClassName = parser; 202 createDocumentDescriptor = dd; 203 } 204 205 212 public Document createDocument(String ns, String root, String uri) 213 throws IOException { 214 return createDocument(ns, root, uri, new InputSource (uri)); 215 } 216 217 222 public Document createDocument(String uri) 223 throws IOException { 224 return createDocument(new InputSource (uri)); 225 } 226 227 235 public Document createDocument(String ns, String root, String uri, 236 InputStream is) throws IOException { 237 InputSource inp = new InputSource (is); 238 inp.setSystemId(uri); 239 return createDocument(ns, root, uri, inp); 240 } 241 242 248 public Document createDocument(String uri, InputStream is) 249 throws IOException { 250 InputSource inp = new InputSource (is); 251 inp.setSystemId(uri); 252 return createDocument(inp); 253 } 254 255 263 public Document createDocument(String ns, String root, String uri, 264 Reader r) throws IOException { 265 InputSource inp = new InputSource (r); 266 inp.setSystemId(uri); 267 return createDocument(ns, root, uri, inp); 268 } 269 270 278 public Document createDocument(String ns, String root, String uri, 279 XMLReader r) throws IOException { 280 r.setContentHandler(this); 281 r.setDTDHandler(this); 282 r.setEntityResolver(this); 283 try { 284 r.parse(uri); 285 } catch (SAXException e) { 286 Exception ex = e.getException(); 287 if (ex != null && ex instanceof InterruptedIOException ) { 288 throw (InterruptedIOException ) ex; 289 } 290 throw new IOException (e.getMessage()); 291 } 292 currentNode = null; 293 Document ret = document; 294 document = null; 295 return ret; 296 } 297 298 304 public Document createDocument(String uri, Reader r) throws IOException { 305 InputSource inp = new InputSource (r); 306 inp.setSystemId(uri); 307 return createDocument(inp); 308 } 309 310 318 protected Document createDocument(String ns, String root, String uri, 319 InputSource is) 320 throws IOException { 321 Document ret = createDocument(is); 322 Element docElem = ret.getDocumentElement(); 323 324 String lname = root; 325 String nsURI = ns; 326 if (ns == null) { 327 int idx = lname.indexOf(':'); 328 String nsp = (idx == -1 || idx == lname.length()-1) 329 ? "" 330 : lname.substring(0, idx); 331 nsURI = namespaces.get(nsp); 332 if (idx != -1 && idx != lname.length()-1) { 333 lname = lname.substring(idx+1); 334 } 335 } 336 337 338 String docElemNS = docElem.getNamespaceURI(); 339 if ((docElemNS != nsURI) && 340 ((docElemNS == null) || (!docElemNS.equals(nsURI)))) 341 throw new IOException 342 ("Root element namespace does not match that requested:\n" + 343 "Requested: " + nsURI + "\n" + 344 "Found: " + docElemNS); 345 346 if (docElemNS != null) { 347 if (!docElem.getLocalName().equals(lname)) 348 throw new IOException 349 ("Root element does not match that requested:\n" + 350 "Requested: " + lname + "\n" + 351 "Found: " + docElem.getLocalName()); 352 } else { 353 if (!docElem.getNodeName().equals(lname)) 354 throw new IOException 355 ("Root element does not match that requested:\n" + 356 "Requested: " + lname + "\n" + 357 "Found: " + docElem.getNodeName()); 358 } 359 360 return ret; 361 } 362 363 364 369 protected Document createDocument(InputSource is) 370 throws IOException { 371 try { 372 XMLReader parser = 373 XMLReaderFactory.createXMLReader(parserClassName); 374 375 parser.setContentHandler(this); 376 parser.setDTDHandler(this); 377 parser.setEntityResolver(this); 378 parser.setErrorHandler((errorHandler == null) ? 379 this : errorHandler); 380 381 parser.setFeature("http://xml.org/sax/features/namespaces", 382 true); 383 parser.setFeature("http://xml.org/sax/features/namespace-prefixes", 384 true); 385 parser.setFeature("http://xml.org/sax/features/validation", 386 isValidating); 387 parser.setProperty("http://xml.org/sax/properties/lexical-handler", 388 this); 389 parser.parse(is); 390 } catch (SAXException e) { 391 Exception ex = e.getException(); 392 if (ex != null && ex instanceof InterruptedIOException ) { 393 throw (InterruptedIOException )ex; 394 } 395 throw new IOException (e.getMessage()); 396 } 397 398 currentNode = null; 399 Document ret = document; 400 document = null; 401 locator = null; 402 return ret; 403 } 404 405 410 public DocumentDescriptor getDocumentDescriptor() { 411 return documentDescriptor; 412 } 413 414 418 public void setDocumentLocator(Locator l) { 419 locator = l; 420 } 421 422 429 public void setValidating(boolean isValidating) { 430 this.isValidating = isValidating; 431 } 432 433 437 public boolean isValidating() { 438 return isValidating; 439 } 440 441 444 public void setErrorHandler(ErrorHandler eh) { 445 errorHandler = eh; 446 } 447 448 public DOMImplementation getDOMImplementation(String ver) { 449 return implementation; 450 } 451 452 456 public void fatalError(SAXParseException ex) throws SAXException { 457 throw ex; 458 } 459 460 464 public void error(SAXParseException ex) throws SAXException { 465 throw ex; 466 } 467 468 472 public void warning(SAXParseException ex) throws SAXException { 473 } 474 475 479 public void startDocument() throws SAXException { 480 preInfo = new LinkedList (); 481 namespaces = new HashTableStack(); 482 namespaces.put("xml", XMLSupport.XML_NAMESPACE_URI); 483 namespaces.put("xmlns", XMLSupport.XMLNS_NAMESPACE_URI); 484 namespaces.put("", null); 485 486 inDTD = false; 487 inCDATA = false; 488 currentNode = null; 489 document = null; 490 491 stringBuffer.setLength(0); 492 stringContent = false; 493 494 if (createDocumentDescriptor) { 495 documentDescriptor = new DocumentDescriptor(); 496 } else { 497 documentDescriptor = null; 498 } 499 } 500 501 505 public void startElement(String uri, 506 String localName, 507 String rawName, 508 Attributes attributes) throws SAXException { 509 if (HaltingThread.hasBeenHalted()) { 511 throw new SAXException (new InterruptedIOException ()); 512 } 513 514 int len = attributes.getLength(); 516 namespaces.push(); 517 String version = null; 518 for (int i = 0; i < len; i++) { 519 String aname = attributes.getQName(i); 520 int slen = aname.length(); 521 if (slen < 5) 522 continue; 523 if (aname.equals("version")) { 524 version = attributes.getValue(i); 525 continue; 526 } 527 if (!aname.startsWith("xmlns")) 528 continue; 529 if (slen == 5) { 530 String ns = attributes.getValue(i); 531 if (ns.length() == 0) 532 ns = null; 533 namespaces.put("", ns); 534 } else if (aname.charAt(5) == ':') { 535 String ns = attributes.getValue(i); 536 if (ns.length() == 0) { 537 ns = null; 538 } 539 namespaces.put(aname.substring(6), ns); 540 } 541 } 542 543 appendStringData(); 545 546 Element e; 548 int idx = rawName.indexOf(':'); 549 String nsp = (idx == -1 || idx == rawName.length()-1) 550 ? "" 551 : rawName.substring(0, idx); 552 String nsURI = namespaces.get(nsp); 553 if (currentNode == null) { 554 implementation = getDOMImplementation(version); 555 document = implementation.createDocument(nsURI, rawName, null); 556 Iterator i = preInfo.iterator(); 557 currentNode = e = document.getDocumentElement(); 558 while (i.hasNext()) { 559 PreInfo pi = (PreInfo)i.next(); 560 Node n = pi.createNode(document); 561 document.insertBefore(n, e); 562 } 563 preInfo = null; 564 } else { 565 e = document.createElementNS(nsURI, rawName); 566 currentNode.appendChild(e); 567 currentNode = e; 568 } 569 570 if (createDocumentDescriptor && locator != null) { 572 documentDescriptor.setLocationLine(e, locator.getLineNumber()); 573 } 574 575 for (int i = 0; i < len; i++) { 577 String aname = attributes.getQName(i); 578 if (aname.equals("xmlns")) { 579 e.setAttributeNS(XMLSupport.XMLNS_NAMESPACE_URI, 580 aname, 581 attributes.getValue(i)); 582 } else { 583 idx = aname.indexOf(':'); 584 nsURI = (idx == -1) 585 ? null 586 : namespaces.get(aname.substring(0, idx)); 587 e.setAttributeNS(nsURI, aname, attributes.getValue(i)); 588 } 589 } 590 } 591 592 596 public void endElement(String uri, String localName, String rawName) 597 throws SAXException { 598 appendStringData(); 600 if (currentNode != null) 601 currentNode = currentNode.getParentNode(); 602 namespaces.pop(); 603 } 604 605 public void appendStringData() { 606 if (!stringContent) return; 607 608 String str = stringBuffer.toString(); 609 stringBuffer.setLength(0); stringContent = false; 611 if (currentNode == null) { 612 if (inCDATA) preInfo.add(new CDataInfo(str)); 613 else preInfo.add(new TextInfo(str)); 614 } else { 615 Node n; 616 if (inCDATA) n = document.createCDATASection(str); 617 else n = document.createTextNode(str); 618 currentNode.appendChild(n); 619 } 620 } 621 622 626 public void characters(char ch[], int start, int length) 627 throws SAXException { 628 stringBuffer.append(ch, start, length); 629 stringContent = true; 630 } 631 632 633 637 public void ignorableWhitespace(char[] ch, 638 int start, 639 int length) 640 throws SAXException { 641 stringBuffer.append(ch, start, length); 642 stringContent = true; 643 } 644 645 649 public void processingInstruction(String target, String data) 650 throws SAXException { 651 if (inDTD) 652 return; 653 654 appendStringData(); 656 if (currentNode == null) 657 preInfo.add(new ProcessingInstructionInfo(target, data)); 658 else 659 currentNode.appendChild 660 (document.createProcessingInstruction(target, data)); 661 } 662 663 665 669 public void startDTD(String name, String publicId, String systemId) 670 throws SAXException { 671 appendStringData(); inDTD = true; 673 } 674 675 678 public void endDTD() throws SAXException { 679 inDTD = false; 680 } 681 682 686 public void startEntity(String name) throws SAXException { 687 } 688 689 693 public void endEntity(String name) throws SAXException { 694 } 695 696 700 public void startCDATA() throws SAXException { 701 appendStringData(); inCDATA = true; 703 stringContent = true; } 705 706 710 public void endCDATA() throws SAXException { 711 appendStringData(); inCDATA = false; 713 } 714 715 719 public void comment(char ch[], int start, int length) throws SAXException { 720 if (inDTD) return; 721 appendStringData(); 722 723 String str = new String (ch, start, length); 724 if (currentNode == null) { 725 preInfo.add(new CommentInfo(str)); 726 } else { 727 currentNode.appendChild(document.createComment(str)); 728 } 729 } 730 } 731 | Popular Tags |