1 16 17 package org.apache.commons.jelly; 18 19 import java.io.IOException ; 20 import java.io.OutputStream ; 21 import java.io.UnsupportedEncodingException ; 22 import java.io.Writer ; 23 import java.util.ArrayList ; 24 import java.util.HashMap ; 25 import java.util.Iterator ; 26 import java.util.List ; 27 import java.util.Map ; 28 29 import org.apache.commons.logging.Log; 30 import org.apache.commons.logging.LogFactory; 31 import org.dom4j.io.XMLWriter; 32 import org.xml.sax.Attributes ; 33 import org.xml.sax.ContentHandler ; 34 import org.xml.sax.Locator ; 35 import org.xml.sax.SAXException ; 36 import org.xml.sax.XMLReader ; 37 import org.xml.sax.ext.LexicalHandler ; 38 import org.xml.sax.helpers.AttributesImpl ; 39 import org.xml.sax.helpers.DefaultHandler ; 40 41 48 49 public class XMLOutput implements ContentHandler , LexicalHandler { 50 51 protected static final String [] LEXICAL_HANDLER_NAMES = 52 { 53 "http://xml.org/sax/properties/lexical-handler", 54 "http://xml.org/sax/handlers/LexicalHandler" }; 55 56 57 private static final Attributes EMPTY_ATTRIBUTES = new AttributesImpl (); 58 59 60 private static final Log log = LogFactory.getLog(XMLOutput.class); 61 62 63 private static final boolean DEFAULT_ESCAPE_TEXT = false; 64 65 66 private ContentHandler contentHandler; 67 68 69 private LexicalHandler lexicalHandler; 70 71 72 private NamespaceStack namespaceStack = new NamespaceStack(); 73 74 public XMLOutput() { 75 } 76 77 81 public XMLOutput(ContentHandler contentHandler) { 82 this.contentHandler = contentHandler; 83 if (contentHandler instanceof LexicalHandler ) { 85 this.lexicalHandler = (LexicalHandler ) contentHandler; 86 } 87 } 88 89 94 public XMLOutput( 95 ContentHandler contentHandler, 96 LexicalHandler lexicalHandler) { 97 this.contentHandler = contentHandler; 98 this.lexicalHandler = lexicalHandler; 99 } 100 101 public String toString() { 102 return super.toString() 103 + "[contentHandler=" 104 + contentHandler 105 + ";lexicalHandler=" 106 + lexicalHandler 107 + "]"; 108 } 109 110 117 public void close() throws IOException { 118 } 119 120 125 public void flush() throws IOException { 126 if (contentHandler instanceof XMLWriter) { 127 ((XMLWriter)contentHandler).flush(); 128 } else if (contentHandler instanceof XMLOutput) { 129 ((XMLOutput)contentHandler).flush(); 130 } 131 } 132 133 136 139 public static XMLOutput createXMLOutput(XMLReader xmlReader) { 140 XMLOutput output = new XMLOutput(xmlReader.getContentHandler()); 141 142 for (int i = 0; i < LEXICAL_HANDLER_NAMES.length; i++) { 144 try { 145 Object value = xmlReader.getProperty(LEXICAL_HANDLER_NAMES[i]); 146 if (value instanceof LexicalHandler ) { 147 output.setLexicalHandler((LexicalHandler ) value); 148 break; 149 } 150 } catch (Exception e) { 151 if (log.isDebugEnabled()) { 153 log.debug("error setting lexical handler properties", e); 154 } 155 } 156 } 157 return output; 158 } 159 160 164 public static XMLOutput createXMLOutput(Writer writer) { 165 return createXMLOutput(writer, DEFAULT_ESCAPE_TEXT); 166 } 167 168 176 public static XMLOutput createXMLOutput(Writer writer, boolean escapeText) { 177 XMLWriter xmlWriter = new XMLWriter(writer); 178 xmlWriter.setEscapeText(escapeText); 179 return createXMLOutput(xmlWriter); 180 } 181 182 186 public static XMLOutput createXMLOutput(OutputStream out) throws UnsupportedEncodingException { 187 return createXMLOutput(out, DEFAULT_ESCAPE_TEXT); 188 } 189 190 200 public static XMLOutput createXMLOutput(OutputStream out, boolean escapeText) 201 throws UnsupportedEncodingException { 202 XMLWriter xmlWriter = new XMLWriter(out); 203 xmlWriter.setEscapeText(escapeText); 204 return createXMLOutput(xmlWriter); 205 } 206 207 214 public static XMLOutput createDummyXMLOutput() { 215 return new XMLOutput(new DefaultHandler ()); 216 } 217 218 221 226 public void write(String text) throws SAXException { 227 char[] ch = text.toCharArray(); 228 characters(ch, 0, ch.length); 229 } 230 231 235 public void writeCDATA(String text) throws SAXException { 236 startCDATA(); 237 char[] ch = text.toCharArray(); 238 characters(ch, 0, ch.length); 239 endCDATA(); 240 } 241 242 245 public void writeComment(String text) throws SAXException { 246 char[] ch = text.toCharArray(); 247 comment(ch, 0, ch.length); 248 } 249 250 254 public void startElement(String localName) throws SAXException { 255 startElement("", localName, localName, EMPTY_ATTRIBUTES); 256 } 257 258 262 public void startElement(String localName, Attributes attributes) throws SAXException { 263 startElement("", localName, localName, attributes); 264 } 265 266 270 public void endElement(String localName) throws SAXException { 271 endElement("", localName, localName); 272 } 273 274 275 278 303 public void setDocumentLocator(Locator locator) { 304 contentHandler.setDocumentLocator(locator); 305 } 306 307 318 public void startDocument() throws SAXException { 319 contentHandler.startDocument(); 320 } 321 322 335 public void endDocument() throws SAXException { 336 contentHandler.endDocument(); 337 } 338 339 377 public void startPrefixMapping(String prefix, String uri) throws SAXException { 378 namespaceStack.pushNamespace(prefix, uri); 379 } 382 383 399 public void endPrefixMapping(String prefix) throws SAXException { 400 } 403 404 466 public void startElement( 467 String uri, 468 String localName, 469 String qName, 470 Attributes atts) 471 throws SAXException { 472 473 int idx = qName.indexOf(':'); 474 String attNsPrefix = ""; 475 if (idx >= 0) { 476 attNsPrefix = qName.substring(0, idx); 477 } 478 namespaceStack.pushNamespace(attNsPrefix, uri); 479 for (int i = 0; i < atts.getLength(); i++) { 480 String attQName = atts.getQName(i); 481 idx = attQName.indexOf(':'); 484 if (idx >= 0) { 485 attNsPrefix = attQName.substring(0, idx); 486 String attUri = atts.getURI(i); 487 namespaceStack.pushNamespace(attNsPrefix, attUri); 488 } 489 } 490 491 contentHandler.startElement(uri, localName, qName, atts); 492 namespaceStack.increaseLevel(); 494 } 495 496 517 public void endElement(String uri, String localName, String qName) 518 throws SAXException { 519 contentHandler.endElement(uri, localName, qName); 520 namespaceStack.decreaseLevel(); 522 namespaceStack.popNamespaces(); 523 } 524 525 568 public void characters(char[] ch, int start, int length) throws SAXException { 569 contentHandler.characters(ch, start, length); 570 } 571 572 596 public void ignorableWhitespace(char[] ch, int start, int length) 597 throws SAXException { 598 contentHandler.ignorableWhitespace(ch, start, length); 599 } 600 601 623 public void processingInstruction(String target, String data) 624 throws SAXException { 625 contentHandler.processingInstruction(target, data); 626 } 627 628 653 public void skippedEntity(String name) throws SAXException { 654 contentHandler.skippedEntity(name); 655 } 656 657 658 661 699 public void startDTD(String name, String publicId, String systemId) 700 throws SAXException { 701 if (lexicalHandler != null) { 702 lexicalHandler.startDTD(name, publicId, systemId); 703 } 704 } 705 706 716 public void endDTD() throws SAXException { 717 if (lexicalHandler != null) { 718 lexicalHandler.endDTD(); 719 } 720 } 721 722 771 public void startEntity(String name) throws SAXException { 772 if (lexicalHandler != null) { 773 lexicalHandler.startEntity(name); 774 } 775 } 776 777 784 public void endEntity(String name) throws SAXException { 785 if (lexicalHandler != null) { 786 lexicalHandler.endEntity(name); 787 } 788 } 789 790 801 public void startCDATA() throws SAXException { 802 if (lexicalHandler != null) { 803 lexicalHandler.startCDATA(); 804 } 805 } 806 807 813 public void endCDATA() throws SAXException { 814 if (lexicalHandler != null) { 815 lexicalHandler.endCDATA(); 816 } 817 } 818 819 833 public void comment(char ch[], int start, int length) throws SAXException { 834 if (lexicalHandler != null) { 835 lexicalHandler.comment(ch, start, length); 836 } 837 } 838 839 847 public void objectData(Object object) throws SAXException { 848 if(contentHandler instanceof XMLOutput) 849 ((XMLOutput) contentHandler).objectData(object); 850 else { 851 if(object!=null) { 852 String output=object.toString(); 853 write(output); 854 } else { 855 write("null"); 857 } 858 } 859 } 860 861 866 public ContentHandler getContentHandler() { 867 return contentHandler; 868 } 869 870 876 public void setContentHandler(ContentHandler contentHandler) { 877 if (contentHandler == null) { 878 throw new NullPointerException ("ContentHandler cannot be null!"); 879 } 880 this.contentHandler = contentHandler; 881 } 882 883 886 public LexicalHandler getLexicalHandler() { 887 return lexicalHandler; 888 } 889 890 896 public void setLexicalHandler(LexicalHandler lexicalHandler) { 897 this.lexicalHandler = lexicalHandler; 898 } 899 900 905 protected static XMLOutput createXMLOutput(final XMLWriter xmlWriter) { 906 XMLOutput answer = new XMLOutput() { 907 public void close() throws IOException { 908 xmlWriter.close(); 909 } 910 }; 911 answer.setContentHandler(xmlWriter); 912 answer.setLexicalHandler(xmlWriter); 913 return answer; 914 } 915 916 private final class NamespaceStack { 917 918 private List nsStack; 919 920 private NamespaceStack() { 921 this.nsStack = new ArrayList (); 922 this.nsStack.add(new HashMap ()); 923 } 924 925 private boolean isRootNodeDefaultNs(String prefix, String uri) { 926 return ("".equals(prefix) && "".equals(uri) && nsStack.size() == 1); 927 } 928 929 public void pushNamespace(String prefix, String uri) throws SAXException { 930 Map prefixUriMap; 931 932 if (prefix == null) { 933 prefix = ""; 934 } 935 if (uri == null) { 936 uri = ""; 937 } 938 939 if ("xml".equals(prefix)) { 940 return; 943 } 944 945 946 boolean isNew = true; 950 for (Iterator iter = nsStack.iterator(); iter.hasNext();) { 951 prefixUriMap = (Map ) iter.next(); 952 if (prefixUriMap.containsKey(prefix)) { 953 if (uri.equals(prefixUriMap.get(prefix))) { 954 isNew = false; 957 } 958 break; 961 } 962 } 963 964 if (isNew) { 965 prefixUriMap = (Map ) nsStack.get(0); if (prefixUriMap.containsKey(prefix)) { 970 if (!uri.equals(prefixUriMap.get(prefix))) { 971 throw new SAXException ("Cannot set same prefix to diferent URI in same node: trying to add prefix \"" 972 + prefix + "\" for uri \""+uri+"\" whereas the declared ones are " + prefixUriMap); 973 } 974 } else { 975 prefixUriMap.put(prefix, uri); 976 977 if (!isRootNodeDefaultNs(prefix, uri)) { 980 contentHandler.startPrefixMapping(prefix, uri); 982 } 983 } 984 } 985 } 986 987 public void popNamespaces() throws SAXException { 988 Map prefixUriMap = (Map )nsStack.get(0); 989 for (Iterator iter = prefixUriMap.keySet().iterator();iter.hasNext();) { 990 String prefix = (String )iter.next(); 991 String uri = (String ) prefixUriMap.get(prefix); 992 iter.remove(); 993 994 if (!isRootNodeDefaultNs(prefix, uri)) { 997 contentHandler.endPrefixMapping(prefix); 999 } 1000 } 1001 } 1002 1003 public void popNamespace(String prefix) throws SAXException { 1004 Map prefixUriMap = (Map )nsStack.get(0); 1005 1006 if (prefix == null) { 1007 prefix = ""; 1008 } 1009 1010 if ("xml".equals(prefix)) { 1011 return; 1014 } 1015 1016 if (prefixUriMap.containsKey(prefix)) { 1017 String uri = (String ) prefixUriMap.get(prefix); 1018 prefixUriMap.remove(prefix); 1019 if (!isRootNodeDefaultNs(prefix, uri)) { 1022 contentHandler.endPrefixMapping(prefix); 1024 } 1025 } 1029 } 1030 1031 public void decreaseLevel() { 1032 nsStack.remove(0); 1033 } 1034 1035 public void increaseLevel() { 1036 nsStack.add(0, new HashMap ()); 1037 } 1038 } 1039} 1040
| Popular Tags
|