1 13 14 30 31 package org.dom4j.io.aelfred; 32 33 import org.xml.sax.*; 34 import org.xml.sax.ext.DeclHandler ; 35 import org.xml.sax.ext.LexicalHandler ; 36 import org.xml.sax.helpers.NamespaceSupport ; 37 38 import java.io.IOException ; 39 import java.io.InputStreamReader ; 40 import java.util.*; 41 42 43 45 107 final public class SAXDriver 108 implements Locator, Attributes, XMLReader, Parser, AttributeList 109 { 110 private final DefaultHandler base = new DefaultHandler (); 111 private XmlParser parser; 112 113 private EntityResolver entityResolver = base; 114 private ContentHandler contentHandler = base; 115 private DTDHandler dtdHandler = base; 116 private ErrorHandler errorHandler = base; 117 private DeclHandler declHandler = base; 118 private LexicalHandler lexicalHandler = base; 119 120 private String elementName = null; 121 private ArrayList entityStack = new ArrayList (); 122 123 private ArrayList attributeNames = new ArrayList (); 124 private ArrayList attributeNamespaces = new ArrayList (); 125 private ArrayList attributeLocalNames = new ArrayList (); 126 private ArrayList attributeValues = new ArrayList (); 127 128 private boolean namespaces = true; 129 private boolean xmlNames = false; 130 private boolean nspending = false; 133 private int attributeCount = 0; 134 private String nsTemp [] = new String [3]; 135 private NamespaceSupport prefixStack = new NamespaceSupport (); 136 137 private HashMap features; 138 private HashMap properties; 139 140 141 145 146 public SAXDriver () {} 147 148 149 153 158 public void setLocale (Locale locale) 159 throws SAXException 160 { 161 if ("en".equals (locale.getLanguage ())) 162 return ; 163 164 throw new SAXException ("AElfred only supports English locales."); 165 } 166 167 168 172 public EntityResolver getEntityResolver () 173 { 174 return entityResolver; 175 } 176 177 181 public void setEntityResolver (EntityResolver resolver) 182 { 183 if (resolver == null) 184 resolver = base; 185 this.entityResolver = resolver; 186 } 187 188 189 193 public DTDHandler getDTDHandler () 194 { 195 return dtdHandler; 196 } 197 198 202 public void setDTDHandler (DTDHandler handler) 203 { 204 if (handler == null) 205 handler = base; 206 this.dtdHandler = handler; 207 } 208 209 210 222 public void setDocumentHandler (DocumentHandler handler) 223 { 224 contentHandler = new Adapter (handler); 225 xmlNames = true; 226 } 227 228 232 public ContentHandler getContentHandler () 233 { 234 return contentHandler; 235 } 236 237 243 public void setContentHandler (ContentHandler handler) 244 { 245 if (handler == null) 246 handler = base; 247 contentHandler = handler; 248 } 249 250 254 public void setErrorHandler (ErrorHandler handler) 255 { 256 if (handler == null) 257 handler = base; 258 this.errorHandler = handler; 259 } 260 261 265 public ErrorHandler getErrorHandler () 266 { 267 return errorHandler; 268 } 269 270 271 287 288 public void parse (InputSource source) throws SAXException, IOException 289 { 290 synchronized (base) { 291 parser = new XmlParser (); 292 parser.setHandler (this); 293 294 try { 295 String systemId = source.getSystemId (); 296 297 301 if (systemId != null) 302 entityStack.add (systemId); 303 else 304 entityStack.add ("illegal:unknown system ID"); 305 306 parser.doParse (systemId, 307 source.getPublicId (), 308 source.getCharacterStream (), 309 source.getByteStream (), 310 source.getEncoding ()); 311 } catch (SAXException e) { 312 throw e; 313 } catch (IOException e) { 314 throw e; 315 } catch (RuntimeException e) { 316 throw e; 317 } catch (Exception e) { 318 throw new SAXException (e.getMessage (), e); 319 } finally { 320 contentHandler.endDocument (); 321 entityStack.clear (); 322 } 323 } 324 } 325 326 327 331 332 public void parse (String systemId) throws SAXException, IOException 333 { 334 parse (new InputSource (systemId)); 335 } 336 337 static final String FEATURE = "http://xml.org/sax/features/"; 341 static final String HANDLER = "http://xml.org/sax/properties/"; 342 343 349 public boolean getFeature (String featureId) 350 throws SAXNotRecognizedException 351 { 352 if ((FEATURE + "validation").equals (featureId)) 353 return false; 354 355 if ((FEATURE + "external-general-entities").equals (featureId) 357 || (FEATURE + "external-parameter-entities") 358 .equals (featureId)) 359 return true; 360 361 if ((FEATURE + "namespace-prefixes").equals (featureId)) 363 return xmlNames; 364 365 if ((FEATURE + "namespaces").equals (featureId)) 367 return namespaces; 368 369 371 if ((FEATURE + "string-interning").equals (featureId)) 373 return true; 374 375 if (features != null && features.containsKey (featureId)) 376 return ((Boolean )features.get (featureId)).booleanValue (); 377 378 throw new SAXNotRecognizedException (featureId); 379 } 380 381 387 public Object getProperty (String propertyId) 388 throws SAXNotRecognizedException 389 { 390 if ((HANDLER + "declaration-handler").equals (propertyId)) 391 return declHandler; 392 393 if ((HANDLER + "lexical-handler").equals (propertyId)) 394 return lexicalHandler; 395 396 if (properties != null && properties.containsKey (propertyId)) 397 return properties.get (propertyId); 398 399 throw new SAXNotRecognizedException (propertyId); 401 } 402 403 408 public void setFeature (String featureId, boolean state) 409 throws SAXNotRecognizedException, SAXNotSupportedException 410 { 411 boolean value; 412 413 try { 414 value = getFeature (featureId); 416 417 if (state == value) 418 return; 419 420 if ((FEATURE + "namespace-prefixes").equals (featureId)) { 421 xmlNames = state; 423 return; 424 } 425 426 if ((FEATURE + "namespaces").equals (featureId)) { 427 if (true) { 429 namespaces = state; 430 return; 431 } 432 } 434 435 if (features == null || !features.containsKey (featureId)) 437 throw new SAXNotSupportedException (featureId); 438 439 } catch (SAXNotRecognizedException e) { 440 if (features == null) 442 features = new HashMap (5); 443 } 444 445 features.put (featureId, 447 state 448 ? Boolean.TRUE 449 : Boolean.FALSE); 450 } 451 452 456 public void setProperty (String propertyId, Object property) 457 throws SAXNotRecognizedException, SAXNotSupportedException 458 { 459 Object value; 460 461 try { 462 value = getProperty (propertyId); 464 465 if ((HANDLER + "declaration-handler").equals (propertyId)) { 466 if (property == null) 467 declHandler = base; 468 else if (! (property instanceof DeclHandler )) 469 throw new SAXNotSupportedException (propertyId); 470 else 471 declHandler = (DeclHandler ) property; 472 return ; 473 } 474 475 if ((HANDLER + "lexical-handler").equals (propertyId)) { 476 if (property == null) 477 lexicalHandler = base; 478 else if (! (property instanceof LexicalHandler )) 479 throw new SAXNotSupportedException (propertyId); 480 else 481 lexicalHandler = (LexicalHandler ) property; 482 return ; 483 } 484 485 if (properties == null || !properties.containsKey (propertyId)) 487 throw new SAXNotSupportedException (propertyId); 488 489 } catch (SAXNotRecognizedException e) { 490 if (properties == null) 492 properties = new HashMap (5); 493 } 494 495 properties.put (propertyId, property); 497 } 498 499 500 506 510 void startDocument () throws SAXException 511 { 512 contentHandler.setDocumentLocator (this); 513 contentHandler.startDocument (); 514 attributeNames.clear (); 515 attributeValues.clear (); 516 } 517 518 void endDocument () throws SAXException 519 { 520 } 523 524 Object resolveEntity (String publicId, String systemId) 525 throws SAXException, IOException 526 { 527 InputSource source = entityResolver.resolveEntity (publicId, 528 systemId); 529 530 if (source == null) { 531 return null; 532 } else if (source.getCharacterStream () != null) { 533 return source.getCharacterStream (); 534 } else if (source.getByteStream () != null) { 535 if (source.getEncoding () == null) 536 return source.getByteStream (); 537 else try { 538 return new InputStreamReader ( 539 source.getByteStream (), 540 source.getEncoding () 541 ); 542 } catch (IOException e) { 543 return source.getByteStream (); 544 } 545 } else { 546 return source.getSystemId (); 547 } 548 } 552 553 554 void startExternalEntity (String systemId) 555 throws SAXException 556 { 557 entityStack.add (systemId); 558 } 559 560 void endExternalEntity (String systemId) 561 throws SAXException 562 { 563 entityStack.remove ( entityStack.size() - 1 ); 564 } 565 566 void doctypeDecl (String name, String publicId, String systemId) 567 throws SAXException 568 { 569 lexicalHandler.startDTD (name, publicId, systemId); 570 571 574 } 578 579 void endDoctype () throws SAXException 580 { 581 586 deliverDTDEvents (); 587 lexicalHandler.endDTD (); 588 } 589 590 591 void attribute (String aname, String value, boolean isSpecified) 592 throws SAXException 593 { 594 if (attributeCount++ == 0) { 595 if (namespaces) 596 prefixStack.pushContext (); 597 } 598 599 if (value != null) { 602 if (namespaces) { 603 int index = aname.indexOf (':'); 604 605 if (index > 0) { 607 if (index == 5 && aname.startsWith ("xmlns")) { 609 String prefix = aname.substring (index + 1); 610 611 if (value.length () == 0) { 612 errorHandler.error (new SAXParseException ( 613 "missing URI in namespace decl attribute: " 614 + aname, 615 this)); 616 } else { 617 prefixStack.declarePrefix (prefix, value); 618 contentHandler.startPrefixMapping (prefix, value); 619 } 620 if (!xmlNames) 621 return; 622 nsTemp [0] = ""; 623 nsTemp [1] = aname; 624 625 } else { 627 if (prefixStack.processName (aname, nsTemp, true) 628 == null) { 629 nsTemp[0] = ""; 631 nsTemp[1] = aname; nspending = true; 633 } } 642 643 } else { 645 if ("xmlns".equals (aname)) { 647 prefixStack.declarePrefix ("", value); 648 contentHandler.startPrefixMapping ("", value); 649 if (!xmlNames) 650 return; 651 } 652 nsTemp [0] = ""; 653 nsTemp [1] = aname; 654 } 655 } else 656 nsTemp [0] = nsTemp [1] = ""; 657 658 attributeNamespaces.add (nsTemp [0]); 659 attributeLocalNames.add (nsTemp [1]); 660 attributeNames.add (aname); 661 attributeValues.add (value); 663 } 664 } 665 666 void startElement (String elname) 667 throws SAXException 668 { 669 ContentHandler handler = contentHandler; 670 671 683 if (attributeCount == 0) 684 prefixStack.pushContext (); 685 686 elementName = elname; 688 if (namespaces) { 689 if (attributeCount > 0 && nspending) { 692 for (int i=0; i<attributeLocalNames.size(); i++) { 693 String aname = (String )attributeLocalNames.get(i); 694 if (aname.indexOf(':')>0) { 695 696 if (prefixStack.processName (aname, nsTemp, true) == null) { 697 errorHandler.error (new SAXParseException ( 698 "undeclared name prefix in: " + aname, 699 this)); 700 } else { 701 attributeNamespaces.set(i, nsTemp[0]); 702 attributeLocalNames.set(i, nsTemp[1]); 703 } 704 } 705 } 706 } 707 709 if (prefixStack.processName (elname, nsTemp, false) == null) { 710 errorHandler.error (new SAXParseException ( 711 "undeclared name prefix in: " + elname, 712 this)); 713 nsTemp [0] = nsTemp [1] = ""; 714 } 715 716 handler.startElement (nsTemp [0], nsTemp [1], elname, this); 717 } else 718 handler.startElement ("", "", elname, this); 719 721 if (attributeCount != 0) { 723 attributeNames.clear (); 724 attributeNamespaces.clear (); 725 attributeLocalNames.clear (); 726 attributeValues.clear (); 727 attributeCount = 0; 728 } 729 nspending = false; 730 } 731 732 void endElement (String elname) 733 throws SAXException 734 { 735 ContentHandler handler = contentHandler; 736 737 handler.endElement ("", "", elname); 738 739 if (!namespaces) 740 return; 741 742 Enumeration prefixes = prefixStack.getDeclaredPrefixes (); 743 744 while (prefixes.hasMoreElements ()) 745 handler.endPrefixMapping ((String ) prefixes.nextElement ()); 746 prefixStack.popContext (); 747 } 748 749 void startCDATA () 750 throws SAXException 751 { 752 lexicalHandler.startCDATA (); 753 } 754 755 void charData (char ch[], int start, int length) 756 throws SAXException 757 { 758 contentHandler.characters (ch, start, length); 759 } 760 761 void endCDATA () 762 throws SAXException 763 { 764 lexicalHandler.endCDATA (); 765 } 766 767 void ignorableWhitespace (char ch[], int start, int length) 768 throws SAXException 769 { 770 contentHandler.ignorableWhitespace (ch, start, length); 771 } 772 773 void processingInstruction (String target, String data) 774 throws SAXException 775 { 776 780 contentHandler.processingInstruction (target, data); 781 } 782 783 void comment (char ch[], int start, int length) 784 throws SAXException 785 { 786 790 if (lexicalHandler != base) 791 lexicalHandler.comment (ch, start, length); 792 } 793 794 void error (String message, String url, int line, int column) 796 throws SAXException 797 { 798 SAXParseException fatal; 799 800 fatal = new SAXParseException (message, null, url, line, column); 801 errorHandler.fatalError (fatal); 802 803 throw fatal; 805 } 806 807 808 private void deliverDTDEvents () 812 throws SAXException 813 { 814 String ename; 815 String nname; 816 String publicId; 817 String systemId; 818 819 if (dtdHandler != base) { 821 Iterator notationNames = parser.declaredNotations (); 822 823 while (notationNames.hasNext ()) { 824 nname = (String ) notationNames.next (); 825 publicId = parser.getNotationPublicId (nname); 826 systemId = parser.getNotationSystemId (nname); 827 dtdHandler.notationDecl (nname, publicId, systemId); 828 } 829 } 830 831 if (dtdHandler != base || declHandler != base) { 833 Iterator entityNames = parser.declaredEntities (); 834 int type; 835 836 while (entityNames.hasNext ()) { 837 ename = (String ) entityNames.next (); 838 type = parser.getEntityType (ename); 839 840 if (ename.charAt (0) == '%') 841 continue; 842 843 if (type == XmlParser.ENTITY_NDATA) { 845 publicId = parser.getEntityPublicId (ename); 846 systemId = parser.getEntitySystemId (ename); 847 nname = parser.getEntityNotationName (ename); 848 dtdHandler.unparsedEntityDecl (ename, 849 publicId, systemId, nname); 850 851 } 853 else if (type == XmlParser.ENTITY_TEXT) { 854 publicId = parser.getEntityPublicId (ename); 855 systemId = parser.getEntitySystemId (ename); 856 declHandler.externalEntityDecl (ename, 857 publicId, systemId); 858 859 } 861 else if (type == XmlParser.ENTITY_INTERNAL) { 862 if ("lt".equals (ename) || "gt".equals (ename) 865 || "quot".equals (ename) 866 || "apos".equals (ename) 867 || "amp".equals (ename)) 868 continue; 869 declHandler.internalEntityDecl (ename, 870 parser.getEntityValue (ename)); 871 } 872 } 873 } 874 875 if (declHandler != base) { 877 Iterator elementNames = parser.declaredElements (); 878 Iterator attNames; 879 880 while (elementNames.hasNext ()) { 881 String model = null; 882 883 ename = (String ) elementNames.next (); 884 switch (parser.getElementContentType (ename)) { 885 case XmlParser.CONTENT_ANY: 886 model = "ANY"; 887 break; 888 case XmlParser.CONTENT_EMPTY: 889 model = "EMPTY"; 890 break; 891 case XmlParser.CONTENT_MIXED: 892 case XmlParser.CONTENT_ELEMENTS: 893 model = parser.getElementContentModel (ename); 894 break; 895 case XmlParser.CONTENT_UNDECLARED: 896 default: 897 model = null; 898 break; 899 } 900 if (model != null) 901 declHandler.elementDecl (ename, model); 902 903 attNames = parser.declaredAttributes (ename); 904 while (attNames != null && attNames.hasNext ()) { 905 String aname = (String ) attNames.next (); 906 String type; 907 String valueDefault; 908 String value; 909 910 switch (parser.getAttributeType (ename, aname)) { 911 case XmlParser.ATTRIBUTE_CDATA: 912 type = "CDATA"; 913 break; 914 case XmlParser.ATTRIBUTE_ENTITY: 915 type = "ENTITY"; 916 break; 917 case XmlParser.ATTRIBUTE_ENTITIES: 918 type = "ENTITIES"; 919 break; 920 case XmlParser.ATTRIBUTE_ENUMERATED: 921 type = parser.getAttributeIterator (ename, aname); 922 break; 923 case XmlParser.ATTRIBUTE_ID: 924 type = "ID"; 925 break; 926 case XmlParser.ATTRIBUTE_IDREF: 927 type = "IDREF"; 928 break; 929 case XmlParser.ATTRIBUTE_IDREFS: 930 type = "IDREFS"; 931 break; 932 case XmlParser.ATTRIBUTE_NMTOKEN: 933 type = "NMTOKEN"; 934 break; 935 case XmlParser.ATTRIBUTE_NMTOKENS: 936 type = "NMTOKENS"; 937 break; 938 939 case XmlParser.ATTRIBUTE_NOTATION: 944 type = "NOTATION"; 945 break; 946 947 default: 948 errorHandler.fatalError (new SAXParseException ( 949 "internal error, att type", this)); 950 type = null; 951 } 952 953 switch (parser.getAttributeDefaultValueType ( 954 ename, aname)) { 955 case XmlParser.ATTRIBUTE_DEFAULT_IMPLIED: 956 valueDefault = "#IMPLIED"; 957 break; 958 case XmlParser.ATTRIBUTE_DEFAULT_REQUIRED: 959 valueDefault = "#REQUIRED"; 960 break; 961 case XmlParser.ATTRIBUTE_DEFAULT_FIXED: 962 valueDefault = "#FIXED"; 963 break; 964 case XmlParser.ATTRIBUTE_DEFAULT_SPECIFIED: 965 valueDefault = null; 966 break; 967 968 default: 969 errorHandler.fatalError (new SAXParseException ( 970 "internal error, att default", this)); 971 valueDefault = null; 972 } 973 974 value = parser.getAttributeDefaultValue (ename, aname); 975 976 declHandler.attributeDecl (ename, aname, 977 type, valueDefault, value); 978 } 979 } 980 } 981 } 982 983 984 988 992 public int getLength () 993 { 994 return attributeNames.size (); 995 } 996 997 1000 public String getURI (int index) 1001 { 1002 return (String ) (attributeNamespaces.get (index)); 1003 } 1004 1005 1008 public String getLocalName (int index) 1009 { 1010 return (String ) (attributeLocalNames.get (index)); 1011 } 1012 1013 1016 public String getQName (int i) 1017 { 1018 return (String ) (attributeNames.get (i)); 1019 } 1020 1021 1024 public String getName (int i) 1025 { 1026 return (String ) (attributeNames.get (i)); 1027 } 1028 1029 1033 public String getType (int i) 1034 { 1035 switch (parser.getAttributeType (elementName, getQName (i))) { 1036 1037 case XmlParser.ATTRIBUTE_UNDECLARED: 1038 case XmlParser.ATTRIBUTE_CDATA: 1039 return "CDATA"; 1040 case XmlParser.ATTRIBUTE_ID: 1041 return "ID"; 1042 case XmlParser.ATTRIBUTE_IDREF: 1043 return "IDREF"; 1044 case XmlParser.ATTRIBUTE_IDREFS: 1045 return "IDREFS"; 1046 case XmlParser.ATTRIBUTE_ENTITY: 1047 return "ENTITY"; 1048 case XmlParser.ATTRIBUTE_ENTITIES: 1049 return "ENTITIES"; 1050 case XmlParser.ATTRIBUTE_ENUMERATED: 1051 case XmlParser.ATTRIBUTE_NMTOKEN: 1054 return "NMTOKEN"; 1055 case XmlParser.ATTRIBUTE_NMTOKENS: 1056 return "NMTOKENS"; 1057 case XmlParser.ATTRIBUTE_NOTATION: 1058 return "NOTATION"; 1061 1062 } 1063 1064 return null; 1065 } 1066 1067 1068 1072 public String getValue (int i) 1073 { 1074 return (String ) (attributeValues.get (i)); 1075 } 1076 1077 1078 1081 public int getIndex (String uri, String local) 1082 { 1083 int length = getLength (); 1084 1085 for (int i = 0; i < length; i++) { 1086 if (!getURI (i).equals (uri)) 1087 continue; 1088 if (getLocalName (i).equals (local)) 1089 return i; 1090 } 1091 return -1; 1092 } 1093 1094 1095 1098 public int getIndex (String xmlName) 1099 { 1100 int length = getLength (); 1101 1102 for (int i = 0; i < length; i++) { 1103 if (getQName (i).equals (xmlName)) 1104 return i; 1105 } 1106 return -1; 1107 } 1108 1109 1110 1113 public String getType (String uri, String local) 1114 { 1115 int index = getIndex (uri, local); 1116 1117 if (index < 0) 1118 return null; 1119 return getType (index); 1120 } 1121 1122 1123 1127 public String getType (String xmlName) 1128 { 1129 int index = getIndex (xmlName); 1130 1131 if (index < 0) 1132 return null; 1133 return getType (index); 1134 } 1135 1136 1137 1140 public String getValue (String uri, String local) 1141 { 1142 int index = getIndex (uri, local); 1143 1144 if (index < 0) 1145 return null; 1146 return getValue (index); 1147 } 1148 1149 1150 1154 public String getValue (String xmlName) 1155 { 1156 int index = getIndex (xmlName); 1157 1158 if (index < 0) 1159 return null; 1160 return getValue (index); 1161 } 1162 1163 1164 1168 1171 public String getPublicId () 1172 { 1173 return null; } 1175 1176 1179 public String getSystemId () 1180 { 1181 return (String ) entityStack.get ( entityStack.size() - 1 ); 1182 } 1183 1184 1187 public int getLineNumber () 1188 { 1189 return parser.getLineNumber (); 1190 } 1191 1192 1195 public int getColumnNumber () 1196 { 1197 return parser.getColumnNumber (); 1198 } 1199 1200 1202 private static class Adapter implements ContentHandler 1203 { 1204 private DocumentHandler docHandler; 1205 1206 Adapter (DocumentHandler dh) 1207 { docHandler = dh; } 1208 1209 1210 public void setDocumentLocator (Locator l) 1211 { docHandler.setDocumentLocator (l); } 1212 1213 public void startDocument () throws SAXException 1214 { docHandler.startDocument (); } 1215 1216 public void processingInstruction (String target, String data) 1217 throws SAXException 1218 { docHandler.processingInstruction (target, data); } 1219 1220 public void startPrefixMapping (String prefix, String uri) 1221 { } 1222 1223 public void startElement ( 1224 String namespace, 1225 String local, 1226 String name, 1227 Attributes attrs ) throws SAXException 1228 { 1229 docHandler.startElement (name, (AttributeList) attrs); 1230 } 1231 1232 public void characters (char buf [], int offset, int len) 1233 throws SAXException 1234 { 1235 docHandler.characters (buf, offset, len); 1236 } 1237 1238 public void ignorableWhitespace (char buf [], int offset, int len) 1239 throws SAXException 1240 { 1241 docHandler.ignorableWhitespace (buf, offset, len); 1242 } 1243 1244 public void skippedEntity (String name) 1245 { } 1246 1247 public void endElement (String u, String l, String name) 1248 throws SAXException 1249 { docHandler.endElement (name); } 1250 1251 public void endPrefixMapping (String prefix) 1252 { } 1253 1254 public void endDocument () throws SAXException 1255 { docHandler.endDocument (); } 1256 } 1257} 1258 1259 | Popular Tags |