1 package com.thoughtworks.xstream.io.xml; 2 3 import com.thoughtworks.xstream.XStream; 4 import com.thoughtworks.xstream.io.HierarchicalStreamWriter; 5 import com.thoughtworks.xstream.io.StreamException; 6 import org.xml.sax.ContentHandler ; 7 import org.xml.sax.DTDHandler ; 8 import org.xml.sax.EntityResolver ; 9 import org.xml.sax.ErrorHandler ; 10 import org.xml.sax.InputSource ; 11 import org.xml.sax.SAXException ; 12 import org.xml.sax.SAXNotRecognizedException ; 13 import org.xml.sax.SAXNotSupportedException ; 14 import org.xml.sax.XMLReader ; 15 import org.xml.sax.helpers.AttributesImpl ; 16 17 import java.util.ArrayList ; 18 import java.util.Collections ; 19 import java.util.HashMap ; 20 import java.util.Iterator ; 21 import java.util.LinkedList ; 22 import java.util.List ; 23 import java.util.Map ; 24 25 50 public final class SaxWriter implements HierarchicalStreamWriter, XMLReader { 51 57 public final static String CONFIGURED_XSTREAM_PROPERTY = 58 "http://com.thoughtworks.xstream/sax/property/configured-xstream"; 59 60 68 public final static String SOURCE_OBJECT_LIST_PROPERTY = 69 "http://com.thoughtworks.xstream/sax/property/source-object-list"; 70 71 75 78 private EntityResolver entityResolver = null; 79 80 83 private DTDHandler dtdHandler = null; 84 85 88 private ContentHandler contentHandler = null; 89 90 93 private ErrorHandler errorHandler = null; 94 95 103 private Map features = new HashMap (); 104 105 108 private final Map properties = new HashMap (); 109 110 private final boolean includeEnclosingDocument; 111 112 public SaxWriter(boolean includeEnclosingDocument) { 113 this.includeEnclosingDocument = includeEnclosingDocument; 114 } 115 116 public SaxWriter() { 117 this(true); 118 } 119 120 124 148 public void setFeature(String name, boolean value) 149 throws SAXNotRecognizedException { 150 if ((name.equals("http://xml.org/sax/features/namespaces")) || 151 (name.equals("http://xml.org/sax/features/namespace-prefixes"))) { 152 this.features.put(name, new Boolean (value)); 153 } else { 154 throw new SAXNotRecognizedException (name); 155 } 156 } 157 158 185 public boolean getFeature(String name) 186 throws SAXNotRecognizedException { 187 if ((name.equals("http://xml.org/sax/features/namespaces")) || 188 (name.equals("http://xml.org/sax/features/namespace-prefixes"))) { 189 Boolean value = (Boolean ) (this.features.get(name)); 190 191 if (value == null) { 192 value = Boolean.FALSE; 193 } 194 return value.booleanValue(); 195 } else { 196 throw new SAXNotRecognizedException (name); 197 } 198 } 199 200 231 public void setProperty(String name, Object value) 232 throws SAXNotRecognizedException , 233 SAXNotSupportedException { 234 if (name.equals(CONFIGURED_XSTREAM_PROPERTY)) { 235 if (!(value instanceof XStream)) { 236 throw new SAXNotSupportedException ("Value for property \"" + 237 CONFIGURED_XSTREAM_PROPERTY + 238 "\" must be a non-null XStream object"); 239 } 240 } else if (name.equals(SOURCE_OBJECT_LIST_PROPERTY)) { 241 if (value instanceof List ) { 242 List list = (List ) value; 243 244 if (list.isEmpty()) { 245 throw new SAXNotSupportedException ("Value for property \"" + 246 SOURCE_OBJECT_LIST_PROPERTY + 247 "\" shall not be an empty list"); 248 } else { 249 value = Collections.unmodifiableList(new ArrayList (list)); 252 } 253 } else { 254 throw new SAXNotSupportedException ("Value for property \"" + 255 SOURCE_OBJECT_LIST_PROPERTY + 256 "\" must be a non-null List object"); 257 } 258 } else { 259 throw new SAXNotRecognizedException (name); 260 } 261 this.properties.put(name, value); 262 } 263 264 287 public Object getProperty(String name) 288 throws SAXNotRecognizedException { 289 if ((name.equals(CONFIGURED_XSTREAM_PROPERTY)) || 290 (name.equals(SOURCE_OBJECT_LIST_PROPERTY))) { 291 return this.properties.get(name); 292 } else { 293 throw new SAXNotRecognizedException (name); 294 } 295 } 296 297 301 316 public void setEntityResolver(EntityResolver resolver) { 317 if (resolver == null) { 318 throw new NullPointerException ("resolver"); 319 } 320 this.entityResolver = resolver; 321 return; 322 } 323 324 331 public EntityResolver getEntityResolver() { 332 return this.entityResolver; 333 } 334 335 350 public void setDTDHandler(DTDHandler handler) { 351 if (handler == null) { 352 throw new NullPointerException ("handler"); 353 } 354 this.dtdHandler = handler; 355 return; 356 } 357 358 365 public DTDHandler getDTDHandler() { 366 return this.dtdHandler; 367 } 368 369 385 public void setContentHandler(ContentHandler handler) { 386 if (handler == null) { 387 throw new NullPointerException ("handler"); 388 } 389 this.contentHandler = handler; 390 return; 391 } 392 393 400 public ContentHandler getContentHandler() { 401 return this.contentHandler; 402 } 403 404 422 public void setErrorHandler(ErrorHandler handler) { 423 if (handler == null) { 424 throw new NullPointerException ("handler"); 425 } 426 this.errorHandler = handler; 427 return; 428 } 429 430 437 public ErrorHandler getErrorHandler() { 438 return this.errorHandler; 439 } 440 441 445 471 public void parse(String systemId) throws SAXException { 472 this.parse(); 473 } 474 475 513 public void parse(InputSource input) throws SAXException { 514 this.parse(); 515 } 516 517 524 private void parse() throws SAXException { 525 XStream xstream = (XStream) (this.properties.get(CONFIGURED_XSTREAM_PROPERTY)); 526 if (xstream == null) { 527 xstream = new XStream(); 528 } 529 530 List source = (List ) (this.properties.get(SOURCE_OBJECT_LIST_PROPERTY)); 531 if ((source == null) || (source.isEmpty())) { 532 throw new SAXException ("Missing or empty source object list. Setting property \"" + 533 SOURCE_OBJECT_LIST_PROPERTY + "\" is mandatory"); 534 } 535 536 try { 537 this.startDocument(true); 538 for (Iterator i = source.iterator(); i.hasNext();) { 539 xstream.marshal(i.next(), this); 540 } 541 this.endDocument(true); 542 } catch (StreamException e) { 543 if (e.getCause() instanceof SAXException ) { 544 throw (SAXException ) (e.getCause()); 545 } else { 546 throw new SAXException (e); 547 } 548 } 549 } 550 551 552 556 private int depth = 0; 557 private List elementStack = new LinkedList (); 558 private char[] buffer = new char[128]; 559 private boolean startTagInProgress = false; 560 private final AttributesImpl attributeList = new AttributesImpl (); 561 562 public void startNode(String name) { 563 try { 564 if (this.depth != 0) { 565 this.flushStartTag(); 566 } else if (includeEnclosingDocument) { 567 this.startDocument(false); 568 } 569 this.elementStack.add(0, name); 570 571 this.startTagInProgress = true; 572 this.depth++; 573 } catch (SAXException e) { 574 throw new StreamException(e); 575 } 576 } 577 578 public void addAttribute(String name, String value) { 579 if (this.startTagInProgress) { 580 this.attributeList.addAttribute("", name, name, "CDATA", value); 581 } else { 582 throw new StreamException(new IllegalStateException ("No startElement being processed")); 583 } 584 } 585 586 public void setValue(String text) { 587 try { 588 this.flushStartTag(); 589 590 int lg = text.length(); 591 if (lg > buffer.length) { 592 buffer = new char[lg]; 593 } 594 text.getChars(0, lg, buffer, 0); 595 596 this.contentHandler.characters(buffer, 0, lg); 597 } catch (SAXException e) { 598 throw new StreamException(e); 599 } 600 } 601 602 public void endNode() { 603 try { 604 this.flushStartTag(); 605 606 String tagName = (String ) (this.elementStack.remove(0)); 607 608 this.contentHandler.endElement("", tagName, tagName); 609 610 this.depth--; 611 if (this.depth == 0 && includeEnclosingDocument) { 612 this.endDocument(false); 613 } 614 } catch (SAXException e) { 615 throw new StreamException(e); 616 } 617 } 618 619 628 private void startDocument(boolean multiObjectMode) throws SAXException { 629 if (this.depth == 0) { 630 this.contentHandler.startDocument(); 632 633 if (multiObjectMode) { 634 this.depth++; 637 } 638 } 639 } 640 641 650 private void endDocument(boolean multiObjectMode) throws SAXException { 651 if ((this.depth == 0) || ((this.depth == 1) && (multiObjectMode))) { 652 this.contentHandler.endDocument(); 653 this.depth = 0; 654 } 655 } 656 657 663 private void flushStartTag() throws SAXException { 664 if (this.startTagInProgress) { 665 String tagName = (String ) (this.elementStack.get(0)); 666 667 this.contentHandler.startElement("", tagName, 668 tagName, this.attributeList); 669 this.attributeList.clear(); 670 this.startTagInProgress = false; 671 } 672 } 673 674 public void flush() { 675 } 677 678 public void close() { 679 } 681 682 public HierarchicalStreamWriter underlyingWriter() { 683 return this; 684 } 685 } 686 687 | Popular Tags |