1 16 17 package org.apache.xerces.impl; 18 19 import java.io.IOException ; 20 import java.io.InputStream ; 21 import java.io.InputStreamReader ; 22 import java.io.Reader ; 23 import java.io.StringReader ; 24 import java.lang.reflect.Method ; 25 import java.net.HttpURLConnection ; 26 import java.net.URL ; 27 import java.net.URLConnection ; 28 import java.util.Hashtable ; 29 import java.util.Iterator ; 30 import java.util.Locale ; 31 import java.util.Map ; 32 import java.util.Stack ; 33 34 import org.apache.xerces.impl.io.ASCIIReader; 35 import org.apache.xerces.impl.io.UCSReader; 36 import org.apache.xerces.impl.io.UTF8Reader; 37 import org.apache.xerces.impl.msg.XMLMessageFormatter; 38 import org.apache.xerces.impl.validation.ValidationManager; 39 import org.apache.xerces.util.AugmentationsImpl; 40 import org.apache.xerces.util.EncodingMap; 41 import org.apache.xerces.util.HTTPInputSource; 42 import org.apache.xerces.util.SecurityManager; 43 import org.apache.xerces.util.SymbolTable; 44 import org.apache.xerces.util.URI; 45 import org.apache.xerces.util.XMLChar; 46 import org.apache.xerces.util.XMLEntityDescriptionImpl; 47 import org.apache.xerces.util.XMLResourceIdentifierImpl; 48 import org.apache.xerces.xni.Augmentations; 49 import org.apache.xerces.xni.XMLResourceIdentifier; 50 import org.apache.xerces.xni.XNIException; 51 import org.apache.xerces.xni.parser.XMLComponent; 52 import org.apache.xerces.xni.parser.XMLComponentManager; 53 import org.apache.xerces.xni.parser.XMLConfigurationException; 54 import org.apache.xerces.xni.parser.XMLEntityResolver; 55 import org.apache.xerces.xni.parser.XMLInputSource; 56 57 83 public class XMLEntityManager 84 implements XMLComponent, XMLEntityResolver { 85 86 90 91 public static final int DEFAULT_BUFFER_SIZE = 2048; 92 93 94 public static final int DEFAULT_XMLDECL_BUFFER_SIZE = 64; 95 96 97 public static final int DEFAULT_INTERNAL_BUFFER_SIZE = 512; 98 99 101 102 protected static final String VALIDATION = 103 Constants.SAX_FEATURE_PREFIX + Constants.VALIDATION_FEATURE; 104 105 106 protected static final String EXTERNAL_GENERAL_ENTITIES = 107 Constants.SAX_FEATURE_PREFIX + Constants.EXTERNAL_GENERAL_ENTITIES_FEATURE; 108 109 110 protected static final String EXTERNAL_PARAMETER_ENTITIES = 111 Constants.SAX_FEATURE_PREFIX + Constants.EXTERNAL_PARAMETER_ENTITIES_FEATURE; 112 113 114 protected static final String ALLOW_JAVA_ENCODINGS = 115 Constants.XERCES_FEATURE_PREFIX + Constants.ALLOW_JAVA_ENCODINGS_FEATURE; 116 117 118 protected static final String WARN_ON_DUPLICATE_ENTITYDEF = 119 Constants.XERCES_FEATURE_PREFIX +Constants.WARN_ON_DUPLICATE_ENTITYDEF_FEATURE; 120 121 122 protected static final String STANDARD_URI_CONFORMANT = 123 Constants.XERCES_FEATURE_PREFIX +Constants.STANDARD_URI_CONFORMANT_FEATURE; 124 125 protected static final String PARSER_SETTINGS = 126 Constants.XERCES_FEATURE_PREFIX + Constants.PARSER_SETTINGS; 127 128 130 131 protected static final String SYMBOL_TABLE = 132 Constants.XERCES_PROPERTY_PREFIX + Constants.SYMBOL_TABLE_PROPERTY; 133 134 135 protected static final String ERROR_REPORTER = 136 Constants.XERCES_PROPERTY_PREFIX + Constants.ERROR_REPORTER_PROPERTY; 137 138 139 protected static final String ENTITY_RESOLVER = 140 Constants.XERCES_PROPERTY_PREFIX + Constants.ENTITY_RESOLVER_PROPERTY; 141 142 protected static final String VALIDATION_MANAGER = 144 Constants.XERCES_PROPERTY_PREFIX + Constants.VALIDATION_MANAGER_PROPERTY; 145 146 147 protected static final String BUFFER_SIZE = 148 Constants.XERCES_PROPERTY_PREFIX + Constants.BUFFER_SIZE_PROPERTY; 149 150 151 protected static final String SECURITY_MANAGER = 152 Constants.XERCES_PROPERTY_PREFIX + Constants.SECURITY_MANAGER_PROPERTY; 153 154 156 157 private static final String [] RECOGNIZED_FEATURES = { 158 VALIDATION, 159 EXTERNAL_GENERAL_ENTITIES, 160 EXTERNAL_PARAMETER_ENTITIES, 161 ALLOW_JAVA_ENCODINGS, 162 WARN_ON_DUPLICATE_ENTITYDEF, 163 STANDARD_URI_CONFORMANT 164 }; 165 166 167 private static final Boolean [] FEATURE_DEFAULTS = { 168 null, 169 Boolean.TRUE, 170 Boolean.TRUE, 171 Boolean.FALSE, 172 Boolean.FALSE, 173 Boolean.FALSE 174 }; 175 176 177 private static final String [] RECOGNIZED_PROPERTIES = { 178 SYMBOL_TABLE, 179 ERROR_REPORTER, 180 ENTITY_RESOLVER, 181 VALIDATION_MANAGER, 182 BUFFER_SIZE, 183 SECURITY_MANAGER, 184 }; 185 186 187 private static final Object [] PROPERTY_DEFAULTS = { 188 null, 189 null, 190 null, 191 null, 192 new Integer (DEFAULT_BUFFER_SIZE), 193 null, 194 }; 195 196 private static final String XMLEntity = "[xml]".intern(); 197 private static final String DTDEntity = "[dtd]".intern(); 198 199 201 206 private static final boolean DEBUG_BUFFER = false; 207 208 209 private static final boolean DEBUG_ENTITIES = false; 210 211 212 private static final boolean DEBUG_ENCODINGS = false; 213 214 private static final boolean DEBUG_RESOLVER = false; 216 217 221 223 227 protected boolean fValidation; 228 229 233 protected boolean fExternalGeneralEntities = true; 234 235 239 protected boolean fExternalParameterEntities = true; 240 241 245 protected boolean fAllowJavaEncodings; 246 247 250 protected boolean fWarnDuplicateEntityDef; 251 252 256 protected boolean fStrictURI; 257 258 260 264 protected SymbolTable fSymbolTable; 265 266 270 protected XMLErrorReporter fErrorReporter; 271 272 276 protected XMLEntityResolver fEntityResolver; 277 278 282 protected ValidationManager fValidationManager; 283 284 286 291 protected int fBufferSize = DEFAULT_BUFFER_SIZE; 292 293 protected SecurityManager fSecurityManager = null; 296 297 301 protected boolean fStandalone; 302 303 protected boolean fInExternalSubset = false; 306 307 309 310 protected XMLEntityHandler fEntityHandler; 311 312 314 315 protected XMLEntityScanner fEntityScanner; 316 317 318 protected XMLEntityScanner fXML10EntityScanner; 319 320 321 protected XMLEntityScanner fXML11EntityScanner; 322 323 protected int fEntityExpansionLimit = 0; 326 protected int fEntityExpansionCount = 0; 328 329 331 332 protected Hashtable fEntities = new Hashtable (); 333 334 335 protected Stack fEntityStack = new Stack (); 336 337 338 protected ScannedEntity fCurrentEntity; 339 340 342 343 protected Hashtable fDeclaredEntities; 344 345 347 348 private final XMLResourceIdentifierImpl fResourceIdentifier = new XMLResourceIdentifierImpl(); 349 350 351 private final Augmentations fEntityAugs = new AugmentationsImpl(); 352 353 354 private CharacterBufferPool fBufferPool = new CharacterBufferPool(fBufferSize, DEFAULT_INTERNAL_BUFFER_SIZE); 355 356 360 361 public XMLEntityManager() { 362 this(null); 363 } 365 373 public XMLEntityManager(XMLEntityManager entityManager) { 374 375 376 fDeclaredEntities = entityManager != null 378 ? entityManager.getDeclaredEntities() : null; 379 380 setScannerVersion(Constants.XML_VERSION_1_0); 381 } 383 387 392 public void setStandalone(boolean standalone) { 393 fStandalone = standalone; 394 } 396 397 public boolean isStandalone() { 398 return fStandalone; 399 } 401 407 public void setEntityHandler(XMLEntityHandler entityHandler) { 408 fEntityHandler = entityHandler; 409 } 411 public XMLResourceIdentifier getCurrentResourceIdentifier() { 417 return fResourceIdentifier; 418 } 419 420 public ScannedEntity getCurrentEntity() { 426 return fCurrentEntity; 427 } 428 429 443 public void addInternalEntity(String name, String text) { 444 if (!fEntities.containsKey(name)) { 445 Entity entity = new InternalEntity(name, text, fInExternalSubset); 446 fEntities.put(name, entity); 447 } 448 else{ 449 if(fWarnDuplicateEntityDef){ 450 fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN, 451 "MSG_DUPLICATE_ENTITY_DEFINITION", 452 new Object []{ name }, 453 XMLErrorReporter.SEVERITY_WARNING ); 454 } 455 } 456 457 } 459 481 public void addExternalEntity(String name, 482 String publicId, String literalSystemId, 483 String baseSystemId) throws IOException { 484 if (!fEntities.containsKey(name)) { 485 if (baseSystemId == null) { 486 int size = fEntityStack.size(); 488 if (size == 0 && fCurrentEntity != null && fCurrentEntity.entityLocation != null) { 489 baseSystemId = fCurrentEntity.entityLocation.getExpandedSystemId(); 490 } 491 for (int i = size - 1; i >= 0 ; i--) { 492 ScannedEntity externalEntity = 493 (ScannedEntity)fEntityStack.elementAt(i); 494 if (externalEntity.entityLocation != null && externalEntity.entityLocation.getExpandedSystemId() != null) { 495 baseSystemId = externalEntity.entityLocation.getExpandedSystemId(); 496 break; 497 } 498 } 499 } 500 Entity entity = new ExternalEntity(name, 501 new XMLEntityDescriptionImpl(name, publicId, literalSystemId, baseSystemId, 502 expandSystemId(literalSystemId, baseSystemId, false)), null, fInExternalSubset); 503 fEntities.put(name, entity); 504 } 505 else{ 506 if(fWarnDuplicateEntityDef){ 507 fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN, 508 "MSG_DUPLICATE_ENTITY_DEFINITION", 509 new Object []{ name }, 510 XMLErrorReporter.SEVERITY_WARNING ); 511 } 512 } 513 514 } 516 523 public boolean isExternalEntity(String entityName) { 524 525 Entity entity = (Entity)fEntities.get(entityName); 526 if (entity == null) { 527 return false; 528 } 529 return entity.isExternal(); 530 } 531 532 540 public boolean isEntityDeclInExternalSubset(String entityName) { 541 542 Entity entity = (Entity)fEntities.get(entityName); 543 if (entity == null) { 544 return false; 545 } 546 return entity.isEntityDeclInExternalSubset(); 547 } 548 549 565 public void addUnparsedEntity(String name, 566 String publicId, String systemId, 567 String baseSystemId, String notation) { 568 if (!fEntities.containsKey(name)) { 569 Entity entity = new ExternalEntity(name, 570 new XMLEntityDescriptionImpl(name, publicId, systemId, baseSystemId, null), 571 notation, fInExternalSubset); 572 fEntities.put(name, entity); 573 } 574 else{ 575 if(fWarnDuplicateEntityDef){ 576 fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN, 577 "MSG_DUPLICATE_ENTITY_DEFINITION", 578 new Object []{ name }, 579 XMLErrorReporter.SEVERITY_WARNING ); 580 } 581 } 582 } 584 591 public boolean isUnparsedEntity(String entityName) { 592 593 Entity entity = (Entity)fEntities.get(entityName); 594 if (entity == null) { 595 return false; 596 } 597 return entity.isUnparsed(); 598 } 599 600 606 public boolean isDeclaredEntity(String entityName) { 607 608 Entity entity = (Entity)fEntities.get(entityName); 609 return entity != null; 610 } 611 612 634 public XMLInputSource resolveEntity(XMLResourceIdentifier resourceIdentifier) 635 throws IOException , XNIException { 636 if(resourceIdentifier == null ) return null; 637 String publicId = resourceIdentifier.getPublicId(); 638 String literalSystemId = resourceIdentifier.getLiteralSystemId(); 639 String baseSystemId = resourceIdentifier.getBaseSystemId(); 640 String expandedSystemId = resourceIdentifier.getExpandedSystemId(); 641 boolean needExpand = (expandedSystemId == null); 648 if (baseSystemId == null && fCurrentEntity != null && fCurrentEntity.entityLocation != null) { 652 baseSystemId = fCurrentEntity.entityLocation.getExpandedSystemId(); 653 if (baseSystemId != null) 654 needExpand = true; 655 } 656 if (needExpand) 657 expandedSystemId = expandSystemId(literalSystemId, baseSystemId, false); 658 659 XMLInputSource xmlInputSource = null; 661 if (fEntityResolver != null) { 662 resourceIdentifier.setBaseSystemId(baseSystemId); 663 resourceIdentifier.setExpandedSystemId(expandedSystemId); 664 xmlInputSource = fEntityResolver.resolveEntity(resourceIdentifier); 665 } 666 667 if (xmlInputSource == null) { 673 xmlInputSource = new XMLInputSource(publicId, literalSystemId, baseSystemId); 677 } 678 679 if (DEBUG_RESOLVER) { 680 System.err.println("XMLEntityManager.resolveEntity(" + publicId + ")"); 681 System.err.println(" = " + xmlInputSource); 682 } 683 684 return xmlInputSource; 685 686 } 688 698 public void startEntity(String entityName, boolean literal) 699 throws IOException , XNIException { 700 701 Entity entity = (Entity)fEntities.get(entityName); 703 if (entity == null) { 704 if (fEntityHandler != null) { 705 String encoding = null; 706 fResourceIdentifier.clear(); 707 fEntityAugs.removeAllItems(); 708 fEntityAugs.putItem(Constants.ENTITY_SKIPPED, Boolean.TRUE); 709 fEntityHandler.startEntity(entityName, fResourceIdentifier, encoding, fEntityAugs); 710 fEntityAugs.removeAllItems(); 711 fEntityAugs.putItem(Constants.ENTITY_SKIPPED, Boolean.TRUE); 712 fEntityHandler.endEntity(entityName, fEntityAugs); 713 } 714 return; 715 } 716 717 boolean external = entity.isExternal(); 719 if (external && (fValidationManager == null || !fValidationManager.isCachedDTD())) { 720 boolean unparsed = entity.isUnparsed(); 721 boolean parameter = entityName.startsWith("%"); 722 boolean general = !parameter; 723 if (unparsed || (general && !fExternalGeneralEntities) || 724 (parameter && !fExternalParameterEntities)) { 725 if (fEntityHandler != null) { 726 fResourceIdentifier.clear(); 727 final String encoding = null; 728 ExternalEntity externalEntity = (ExternalEntity)entity; 729 String extLitSysId = (externalEntity.entityLocation != null ? externalEntity.entityLocation.getLiteralSystemId() : null); 733 String extBaseSysId = (externalEntity.entityLocation != null ? externalEntity.entityLocation.getBaseSystemId() : null); 734 String expandedSystemId = expandSystemId(extLitSysId, extBaseSysId, false); 735 fResourceIdentifier.setValues( 736 (externalEntity.entityLocation != null ? externalEntity.entityLocation.getPublicId() : null), 737 extLitSysId, extBaseSysId, expandedSystemId); 738 fEntityAugs.removeAllItems(); 739 fEntityAugs.putItem(Constants.ENTITY_SKIPPED, Boolean.TRUE); 740 fEntityHandler.startEntity(entityName, fResourceIdentifier, encoding, fEntityAugs); 741 fEntityAugs.removeAllItems(); 742 fEntityAugs.putItem(Constants.ENTITY_SKIPPED, Boolean.TRUE); 743 fEntityHandler.endEntity(entityName, fEntityAugs); 744 } 745 return; 746 } 747 } 748 749 int size = fEntityStack.size(); 751 for (int i = size; i >= 0; i--) { 752 Entity activeEntity = i == size 753 ? fCurrentEntity 754 : (Entity)fEntityStack.elementAt(i); 755 if (activeEntity.name == entityName) { 756 StringBuffer path = new StringBuffer (entityName); 757 for (int j = i + 1; j < size; j++) { 758 activeEntity = (Entity)fEntityStack.elementAt(j); 759 path.append(" -> "); 760 path.append(activeEntity.name); 761 } 762 path.append(" -> "); 763 path.append(fCurrentEntity.name); 764 path.append(" -> "); 765 path.append(entityName); 766 fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN, 767 "RecursiveReference", 768 new Object [] { entityName, path.toString() }, 769 XMLErrorReporter.SEVERITY_FATAL_ERROR); 770 if (fEntityHandler != null) { 771 fResourceIdentifier.clear(); 772 final String encoding = null; 773 if (external) { 774 ExternalEntity externalEntity = (ExternalEntity)entity; 775 String extLitSysId = (externalEntity.entityLocation != null ? externalEntity.entityLocation.getLiteralSystemId() : null); 777 String extBaseSysId = (externalEntity.entityLocation != null ? externalEntity.entityLocation.getBaseSystemId() : null); 778 String expandedSystemId = expandSystemId(extLitSysId, extBaseSysId, false); 779 fResourceIdentifier.setValues( 780 (externalEntity.entityLocation != null ? externalEntity.entityLocation.getPublicId() : null), 781 extLitSysId, extBaseSysId, expandedSystemId); 782 } 783 fEntityAugs.removeAllItems(); 784 fEntityAugs.putItem(Constants.ENTITY_SKIPPED, Boolean.TRUE); 785 fEntityHandler.startEntity(entityName, fResourceIdentifier, encoding, fEntityAugs); 786 fEntityAugs.removeAllItems(); 787 fEntityAugs.putItem(Constants.ENTITY_SKIPPED, Boolean.TRUE); 788 fEntityHandler.endEntity(entityName, fEntityAugs); 789 } 790 return; 791 } 792 } 793 794 XMLInputSource xmlInputSource = null; 796 if (external) { 797 ExternalEntity externalEntity = (ExternalEntity)entity; 798 xmlInputSource = resolveEntity(externalEntity.entityLocation); 799 } 800 801 else { 803 InternalEntity internalEntity = (InternalEntity)entity; 804 Reader reader = new StringReader (internalEntity.text); 805 xmlInputSource = new XMLInputSource(null, null, null, reader, null); 806 } 807 808 startEntity(entityName, xmlInputSource, literal, external); 810 811 } 813 822 public void startDocumentEntity(XMLInputSource xmlInputSource) 823 throws IOException , XNIException { 824 startEntity(XMLEntity, xmlInputSource, false, true); 825 } 827 836 public void startDTDEntity(XMLInputSource xmlInputSource) 837 throws IOException , XNIException { 838 startEntity(DTDEntity, xmlInputSource, false, true); 839 } 841 public void startExternalSubset() { 844 fInExternalSubset = true; 845 } 846 847 public void endExternalSubset() { 848 fInExternalSubset = false; 849 } 850 851 866 public void startEntity(String name, 867 XMLInputSource xmlInputSource, 868 boolean literal, boolean isExternal) 869 throws IOException , XNIException { 870 871 String encoding = setupCurrentEntity(name, xmlInputSource, literal, isExternal); 872 873 if( fSecurityManager != null && fEntityExpansionCount++ > fEntityExpansionLimit ){ 879 fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN, 880 "EntityExpansionLimitExceeded", 881 new Object []{new Integer (fEntityExpansionLimit) }, 882 XMLErrorReporter.SEVERITY_FATAL_ERROR ); 883 fEntityExpansionCount = 0; 887 } 888 889 if (fEntityHandler != null) { 891 fEntityHandler.startEntity(name, fResourceIdentifier, encoding, null); 892 } 893 894 } 896 909 public String setupCurrentEntity(String name, XMLInputSource xmlInputSource, 910 boolean literal, boolean isExternal) 911 throws IOException , XNIException { 912 914 final String publicId = xmlInputSource.getPublicId(); 915 String literalSystemId = xmlInputSource.getSystemId(); 916 String baseSystemId = xmlInputSource.getBaseSystemId(); 917 String encoding = xmlInputSource.getEncoding(); 918 final boolean encodingExternallySpecified = (encoding != null); 919 Boolean isBigEndian = null; 920 921 InputStream stream = null; 923 Reader reader = xmlInputSource.getCharacterStream(); 924 String expandedSystemId = expandSystemId(literalSystemId, baseSystemId, fStrictURI); 926 if (baseSystemId == null) { 927 baseSystemId = expandedSystemId; 928 } 929 if (reader == null) { 930 stream = xmlInputSource.getByteStream(); 931 if (stream == null) { 932 URL location = new URL (expandedSystemId); 933 URLConnection connect = location.openConnection(); 934 if (!(connect instanceof HttpURLConnection )) { 935 stream = connect.getInputStream(); 936 } 937 else { 938 boolean followRedirects = true; 939 940 if (xmlInputSource instanceof HTTPInputSource) { 942 final HttpURLConnection urlConnection = (HttpURLConnection ) connect; 943 final HTTPInputSource httpInputSource = (HTTPInputSource) xmlInputSource; 944 945 Iterator propIter = httpInputSource.getHTTPRequestProperties(); 947 while (propIter.hasNext()) { 948 Map.Entry entry = (Map.Entry ) propIter.next(); 949 urlConnection.setRequestProperty((String ) entry.getKey(), (String ) entry.getValue()); 950 } 951 952 followRedirects = httpInputSource.getFollowHTTPRedirects(); 954 if (!followRedirects) { 955 setInstanceFollowRedirects(urlConnection, followRedirects); 956 } 957 } 958 959 stream = connect.getInputStream(); 960 961 965 if (followRedirects) { 966 String redirect = connect.getURL().toString(); 967 if (!redirect.equals(expandedSystemId)) { 970 literalSystemId = redirect; 971 expandedSystemId = redirect; 972 } 973 } 974 } 975 } 976 stream = new RewindableInputStream(stream); 978 979 if (encoding == null) { 981 final byte[] b4 = new byte[4]; 983 int count = 0; 984 for (; count<4; count++ ) { 985 b4[count] = (byte)stream.read(); 986 } 987 if (count == 4) { 988 Object [] encodingDesc = getEncodingName(b4, count); 989 encoding = (String )(encodingDesc[0]); 990 isBigEndian = (Boolean )(encodingDesc[1]); 991 992 stream.reset(); 993 int offset = 0; 994 if (count > 2 && encoding.equals("UTF-8")) { 998 int b0 = b4[0] & 0xFF; 999 int b1 = b4[1] & 0xFF; 1000 int b2 = b4[2] & 0xFF; 1001 if (b0 == 0xEF && b1 == 0xBB && b2 == 0xBF) { 1002 stream.skip(3); 1004 } 1005 } 1006 reader = createReader(stream, encoding, isBigEndian); 1007 } 1008 else { 1009 reader = createReader(stream, encoding, isBigEndian); 1010 } 1011 } 1012 1013 else { 1015 encoding = encoding.toUpperCase(Locale.ENGLISH); 1016 1017 if (encoding.equals("UTF-8")) { 1019 final int[] b3 = new int[3]; 1020 int count = 0; 1021 for (; count < 3; ++count) { 1022 b3[count] = stream.read(); 1023 if (b3[count] == -1) 1024 break; 1025 } 1026 if (count == 3) { 1027 if (b3[0] != 0xEF || b3[1] != 0xBB || b3[2] != 0xBF) { 1028 stream.reset(); 1030 } 1031 } 1032 else { 1033 stream.reset(); 1034 } 1035 reader = createReader(stream, encoding, isBigEndian); 1036 } 1037 else if (encoding.equals("UTF-16")) { 1040 final int[] b4 = new int[4]; 1041 int count = 0; 1042 for (; count < 4; ++count) { 1043 b4[count] = stream.read(); 1044 if (b4[count] == -1) 1045 break; 1046 } 1047 stream.reset(); 1048 1049 String utf16Encoding = "UTF-16"; 1050 if (count >= 2) { 1051 final int b0 = b4[0]; 1052 final int b1 = b4[1]; 1053 if (b0 == 0xFE && b1 == 0xFF) { 1054 utf16Encoding = "UTF-16BE"; 1056 isBigEndian = Boolean.TRUE; 1057 } 1058 else if (b0 == 0xFF && b1 == 0xFE) { 1059 utf16Encoding = "UTF-16LE"; 1061 isBigEndian = Boolean.FALSE; 1062 } 1063 else if (count == 4) { 1064 final int b2 = b4[2]; 1065 final int b3 = b4[3]; 1066 if (b0 == 0x00 && b1 == 0x3C && b2 == 0x00 && b3 == 0x3F) { 1067 utf16Encoding = "UTF-16BE"; 1069 isBigEndian = Boolean.TRUE; 1070 } 1071 if (b0 == 0x3C && b1 == 0x00 && b2 == 0x3F && b3 == 0x00) { 1072 utf16Encoding = "UTF-16LE"; 1074 isBigEndian = Boolean.FALSE; 1075 } 1076 } 1077 } 1078 reader = createReader(stream, utf16Encoding, isBigEndian); 1079 } 1080 else if (encoding.equals("ISO-10646-UCS-4")) { 1083 final int[] b4 = new int[4]; 1084 int count = 0; 1085 for (; count < 4; ++count) { 1086 b4[count] = stream.read(); 1087 if (b4[count] == -1) 1088 break; 1089 } 1090 stream.reset(); 1091 1092 if (count == 4) { 1094 if (b4[0] == 0x00 && b4[1] == 0x00 && b4[2] == 0x00 && b4[3] == 0x3C) { 1096 isBigEndian = Boolean.TRUE; 1097 } 1098 else if (b4[0] == 0x3C && b4[1] == 0x00 && b4[2] == 0x00 && b4[3] == 0x00) { 1100 isBigEndian = Boolean.FALSE; 1101 } 1102 } 1103 reader = createReader(stream, encoding, isBigEndian); 1104 } 1105 else if (encoding.equals("ISO-10646-UCS-2")) { 1108 final int[] b4 = new int[4]; 1109 int count = 0; 1110 for (; count < 4; ++count) { 1111 b4[count] = stream.read(); 1112 if (b4[count] == -1) 1113 break; 1114 } 1115 stream.reset(); 1116 1117 if (count == 4) { 1118 if (b4[0] == 0x00 && b4[1] == 0x3C && b4[2] == 0x00 && b4[3] == 0x3F) { 1120 isBigEndian = Boolean.TRUE; 1121 } 1122 else if (b4[0] == 0x3C && b4[1] == 0x00 && b4[2] == 0x3F && b4[3] == 0x00) { 1124 isBigEndian = Boolean.FALSE; 1125 } 1126 } 1127 reader = createReader(stream, encoding, isBigEndian); 1128 } 1129 else { 1130 reader = createReader(stream, encoding, isBigEndian); 1131 } 1132 } 1133 1134 if (DEBUG_ENCODINGS) { 1138 System.out.println("$$$ no longer wrapping reader in OneCharReader"); 1139 } 1140 } 1142 1143 fReaderStack.push(reader); 1146 1147 if (fCurrentEntity != null) { 1149 fEntityStack.push(fCurrentEntity); 1150 } 1151 1152 fCurrentEntity = new ScannedEntity(name, 1154 new XMLResourceIdentifierImpl(publicId, literalSystemId, baseSystemId, expandedSystemId), 1155 stream, reader, encoding, literal, false, isExternal); 1156 fCurrentEntity.setEncodingExternallySpecified(encodingExternallySpecified); 1157 fEntityScanner.setCurrentEntity(fCurrentEntity); 1158 fResourceIdentifier.setValues(publicId, literalSystemId, baseSystemId, expandedSystemId); 1159 return encoding; 1160 } 1162 public void setScannerVersion(short version) { 1164 if(version == Constants.XML_VERSION_1_0) { 1165 if(fXML10EntityScanner == null) { 1166 fXML10EntityScanner = new XMLEntityScanner(); 1167 } 1168 fXML10EntityScanner.reset(fSymbolTable, this, fErrorReporter); 1169 fEntityScanner = fXML10EntityScanner; 1170 fEntityScanner.setCurrentEntity(fCurrentEntity); 1171 } else { 1172 if(fXML11EntityScanner == null) { 1173 fXML11EntityScanner = new XML11EntityScanner(); 1174 } 1175 fXML11EntityScanner.reset(fSymbolTable, this, fErrorReporter); 1176 fEntityScanner = fXML11EntityScanner; 1177 fEntityScanner.setCurrentEntity(fCurrentEntity); 1178 } 1179 } 1181 1182 public XMLEntityScanner getEntityScanner() { 1183 if(fEntityScanner == null) { 1184 if(fXML10EntityScanner == null) { 1186 fXML10EntityScanner = new XMLEntityScanner(); 1187 } 1188 fXML10EntityScanner.reset(fSymbolTable, this, fErrorReporter); 1189 fEntityScanner = fXML10EntityScanner; 1190 } 1191 return fEntityScanner; 1192 } 1194 protected Stack fReaderStack = new Stack (); 1196 1197 1200 public void closeReaders() { 1201 for (int i = fReaderStack.size()-1; i >= 0; i--) { 1203 try { 1204 ((Reader )fReaderStack.pop()).close(); 1205 } catch (IOException e) { 1206 } 1208 } 1209 } 1210 1211 1215 1229 public void reset(XMLComponentManager componentManager) 1230 throws XMLConfigurationException { 1231 1232 boolean parser_settings; 1233 try { 1234 parser_settings = componentManager.getFeature(PARSER_SETTINGS); 1235 } catch (XMLConfigurationException e) { 1236 parser_settings = true; 1237 } 1238 1239 if (!parser_settings) { 1240 reset(); 1242 return; 1243 } 1244 1245 try { 1247 fValidation = componentManager.getFeature(VALIDATION); 1248 } 1249 catch (XMLConfigurationException e) { 1250 fValidation = false; 1251 } 1252 try { 1253 fExternalGeneralEntities = componentManager.getFeature(EXTERNAL_GENERAL_ENTITIES); 1254 } 1255 catch (XMLConfigurationException e) { 1256 fExternalGeneralEntities = true; 1257 } 1258 try { 1259 fExternalParameterEntities = componentManager.getFeature(EXTERNAL_PARAMETER_ENTITIES); 1260 } 1261 catch (XMLConfigurationException e) { 1262 fExternalParameterEntities = true; 1263 } 1264 1265 try { 1267 fAllowJavaEncodings = componentManager.getFeature(ALLOW_JAVA_ENCODINGS); 1268 } 1269 catch (XMLConfigurationException e) { 1270 fAllowJavaEncodings = false; 1271 } 1272 1273 try { 1274 fWarnDuplicateEntityDef = componentManager.getFeature(WARN_ON_DUPLICATE_ENTITYDEF); 1275 } 1276 catch (XMLConfigurationException e) { 1277 fWarnDuplicateEntityDef = false; 1278 } 1279 1280 try { 1281 fStrictURI = componentManager.getFeature(STANDARD_URI_CONFORMANT); 1282 } 1283 catch (XMLConfigurationException e) { 1284 fStrictURI = false; 1285 } 1286 1287 fSymbolTable = (SymbolTable)componentManager.getProperty(SYMBOL_TABLE); 1289 fErrorReporter = (XMLErrorReporter)componentManager.getProperty(ERROR_REPORTER); 1290 try { 1291 fEntityResolver = (XMLEntityResolver)componentManager.getProperty(ENTITY_RESOLVER); 1292 } 1293 catch (XMLConfigurationException e) { 1294 fEntityResolver = null; 1295 } 1296 try { 1297 fValidationManager = (ValidationManager)componentManager.getProperty(VALIDATION_MANAGER); 1298 } 1299 catch (XMLConfigurationException e) { 1300 fValidationManager = null; 1301 } 1302 try { 1303 fSecurityManager = (SecurityManager )componentManager.getProperty(SECURITY_MANAGER); 1304 } 1305 catch (XMLConfigurationException e) { 1306 fSecurityManager = null; 1307 } 1308 1309 reset(); 1311 1312 } 1314 public void reset() { 1318 fEntityExpansionLimit = (fSecurityManager != null)?fSecurityManager.getEntityExpansionLimit():0; 1319 1320 fStandalone = false; 1322 fEntities.clear(); 1323 fEntityStack.removeAllElements(); 1324 fEntityExpansionCount = 0; 1325 1326 fCurrentEntity = null; 1327 if(fXML10EntityScanner != null){ 1329 fXML10EntityScanner.reset(fSymbolTable, this, fErrorReporter); 1330 } 1331 if(fXML11EntityScanner != null) { 1332 fXML11EntityScanner.reset(fSymbolTable, this, fErrorReporter); 1333 } 1334 1335 if (DEBUG_ENTITIES) { 1337 addInternalEntity("text", "Hello, World."); 1338 addInternalEntity("empty-element", "<foo/>"); 1339 addInternalEntity("balanced-element", "<foo></foo>"); 1340 addInternalEntity("balanced-element-with-text", "<foo>Hello, World</foo>"); 1341 addInternalEntity("balanced-element-with-entity", "<foo>&text;</foo>"); 1342 addInternalEntity("unbalanced-entity", "<foo>"); 1343 addInternalEntity("recursive-entity", "<foo>&recursive-entity2;</foo>"); 1344 addInternalEntity("recursive-entity2", "<bar>&recursive-entity3;</bar>"); 1345 addInternalEntity("recursive-entity3", "<baz>&recursive-entity;</baz>"); 1346 try { 1347 addExternalEntity("external-text", null, "external-text.ent", "test/external-text.xml"); 1348 addExternalEntity("external-balanced-element", null, "external-balanced-element.ent", "test/external-balanced-element.xml"); 1349 addExternalEntity("one", null, "ent/one.ent", "test/external-entity.xml"); 1350 addExternalEntity("two", null, "ent/two.ent", "test/ent/one.xml"); 1351 } 1352 catch (IOException ex) { 1353 } 1355 } 1356 1357 if (fDeclaredEntities != null) { 1359 java.util.Enumeration keys = fDeclaredEntities.keys(); 1360 while (keys.hasMoreElements()) { 1361 Object key = keys.nextElement(); 1362 Object value = fDeclaredEntities.get(key); 1363 fEntities.put(key, value); 1364 } 1365 } 1366 fEntityHandler = null; 1367 1368 } 1370 1375 public String [] getRecognizedFeatures() { 1376 return (String [])(RECOGNIZED_FEATURES.clone()); 1377 } 1379 1394 public void setFeature(String featureId, boolean state) 1395 throws XMLConfigurationException { 1396 1397 if (featureId.startsWith(Constants.XERCES_FEATURE_PREFIX)) { 1399 final int suffixLength = featureId.length() - Constants.XERCES_FEATURE_PREFIX.length(); 1400 if (suffixLength == Constants.ALLOW_JAVA_ENCODINGS_FEATURE.length() && 1401 featureId.endsWith(Constants.ALLOW_JAVA_ENCODINGS_FEATURE)) { 1402 fAllowJavaEncodings = state; 1403 } 1404 } 1405 1406 } 1408 1413 public String [] getRecognizedProperties() { 1414 return (String [])(RECOGNIZED_PROPERTIES.clone()); 1415 } 1417 1432 public void setProperty(String propertyId, Object value) 1433 throws XMLConfigurationException { 1434 1435 if (propertyId.startsWith(Constants.XERCES_PROPERTY_PREFIX)) { 1437 final int suffixLength = propertyId.length() - Constants.XERCES_PROPERTY_PREFIX.length(); 1438 1439 if (suffixLength == Constants.SYMBOL_TABLE_PROPERTY.length() && 1440 propertyId.endsWith(Constants.SYMBOL_TABLE_PROPERTY)) { 1441 fSymbolTable = (SymbolTable)value; 1442 return; 1443 } 1444 if (suffixLength == Constants.ERROR_REPORTER_PROPERTY.length() && 1445 propertyId.endsWith(Constants.ERROR_REPORTER_PROPERTY)) { 1446 fErrorReporter = (XMLErrorReporter)value; 1447 return; 1448 } 1449 if (suffixLength == Constants.ENTITY_RESOLVER_PROPERTY.length() && 1450 propertyId.endsWith(Constants.ENTITY_RESOLVER_PROPERTY)) { 1451 fEntityResolver = (XMLEntityResolver)value; 1452 return; 1453 } 1454 if (suffixLength == Constants.BUFFER_SIZE_PROPERTY.length() && 1455 propertyId.endsWith(Constants.BUFFER_SIZE_PROPERTY)) { 1456 Integer bufferSize = (Integer )value; 1457 if (bufferSize != null && 1458 bufferSize.intValue() > DEFAULT_XMLDECL_BUFFER_SIZE) { 1459 fBufferSize = bufferSize.intValue(); 1460 fEntityScanner.setBufferSize(fBufferSize); 1461 fBufferPool.setExternalBufferSize(fBufferSize); 1462 } 1463 } 1464 if (suffixLength == Constants.SECURITY_MANAGER_PROPERTY.length() && 1465 propertyId.endsWith(Constants.SECURITY_MANAGER_PROPERTY)) { 1466 fSecurityManager = (SecurityManager )value; 1467 fEntityExpansionLimit = (fSecurityManager != null)?fSecurityManager.getEntityExpansionLimit():0; 1468 } 1469 } 1470 1471 } 1473 1482 public Boolean getFeatureDefault(String featureId) { 1483 for (int i = 0; i < RECOGNIZED_FEATURES.length; i++) { 1484 if (RECOGNIZED_FEATURES[i].equals(featureId)) { 1485 return FEATURE_DEFAULTS[i]; 1486 } 1487 } 1488 return null; 1489 } 1491 1500 public Object getPropertyDefault(String propertyId) { 1501 for (int i = 0; i < RECOGNIZED_PROPERTIES.length; i++) { 1502 if (RECOGNIZED_PROPERTIES[i].equals(propertyId)) { 1503 return PROPERTY_DEFAULTS[i]; 1504 } 1505 } 1506 return null; 1507 } 1509 1513 private static String gUserDir; 1515 private static URI gUserDirURI; 1517 private static boolean gNeedEscaping[] = new boolean[128]; 1519 private static char gAfterEscaping1[] = new char[128]; 1521 private static char gAfterEscaping2[] = new char[128]; 1523 private static char[] gHexChs = {'0', '1', '2', '3', '4', '5', '6', '7', 1524 '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}; 1525 static { 1527 for (int i = 0; i <= 0x1f; i++) { 1528 gNeedEscaping[i] = true; 1529 gAfterEscaping1[i] = gHexChs[i >> 4]; 1530 gAfterEscaping2[i] = gHexChs[i & 0xf]; 1531 } 1532 gNeedEscaping[0x7f] = true; 1533 gAfterEscaping1[0x7f] = '7'; 1534 gAfterEscaping2[0x7f] = 'F'; 1535 char[] escChs = {' ', '<', '>', '#', '%', '"', '{', '}', 1536 '|', '\\', '^', '~', '[', ']', '`'}; 1537 int len = escChs.length; 1538 char ch; 1539 for (int i = 0; i < len; i++) { 1540 ch = escChs[i]; 1541 gNeedEscaping[ch] = true; 1542 gAfterEscaping1[ch] = gHexChs[ch >> 4]; 1543 gAfterEscaping2[ch] = gHexChs[ch & 0xf]; 1544 } 1545 } 1546 private static synchronized URI getUserDir() throws URI.MalformedURIException { 1557 String userDir = ""; 1559 try { 1560 userDir = System.getProperty("user.dir"); 1561 } 1562 catch (SecurityException se) { 1563 } 1564 1565 if (userDir.length() == 0) 1567 return new URI("file", "", "", null, null); 1568 1569 if (gUserDirURI != null && userDir.equals(gUserDir)) { 1572 return gUserDirURI; 1573 } 1574 1575 gUserDir = userDir; 1577 1578 char separator = java.io.File.separatorChar; 1579 userDir = userDir.replace(separator, '/'); 1580 1581 int len = userDir.length(), ch; 1582 StringBuffer buffer = new StringBuffer (len*3); 1583 if (len >= 2 && userDir.charAt(1) == ':') { 1585 ch = Character.toUpperCase(userDir.charAt(0)); 1586 if (ch >= 'A' && ch <= 'Z') { 1587 buffer.append('/'); 1588 } 1589 } 1590 1591 int i = 0; 1593 for (; i < len; i++) { 1594 ch = userDir.charAt(i); 1595 if (ch >= 128) 1597 break; 1598 if (gNeedEscaping[ch]) { 1599 buffer.append('%'); 1600 buffer.append(gAfterEscaping1[ch]); 1601 buffer.append(gAfterEscaping2[ch]); 1602 } 1604 else { 1605 buffer.append((char)ch); 1606 } 1607 } 1608 1609 if (i < len) { 1611 byte[] bytes = null; 1613 byte b; 1614 try { 1615 bytes = userDir.substring(i).getBytes("UTF-8"); 1616 } catch (java.io.UnsupportedEncodingException e) { 1617 return new URI("file", "", userDir, null, null); 1619 } 1620 len = bytes.length; 1621 1622 for (i = 0; i < len; i++) { 1624 b = bytes[i]; 1625 if (b < 0) { 1627 ch = b + 256; 1628 buffer.append('%'); 1629 buffer.append(gHexChs[ch >> 4]); 1630 buffer.append(gHexChs[ch & 0xf]); 1631 } 1632 else if (gNeedEscaping[b]) { 1633 buffer.append('%'); 1634 buffer.append(gAfterEscaping1[b]); 1635 buffer.append(gAfterEscaping2[b]); 1636 } 1637 else { 1638 buffer.append((char)b); 1639 } 1640 } 1641 } 1642 1643 if (!userDir.endsWith("/")) 1645 buffer.append('/'); 1646 1647 gUserDirURI = new URI("file", "", buffer.toString(), null, null); 1648 1649 return gUserDirURI; 1650 } 1651 1652 1659 public static void absolutizeAgainstUserDir(URI uri) 1660 throws URI.MalformedURIException { 1661 uri.absolutize(getUserDir()); 1662 } 1663 1664 1677 public static String expandSystemId(String systemId, String baseSystemId, 1678 boolean strict) 1679 throws URI.MalformedURIException { 1680 1681 if (systemId == null) { 1684 return null; 1685 } 1686 1687 if (strict) { 1689 return expandSystemIdStrictOn(systemId, baseSystemId); 1690 } 1691 1692 try { 1694 return expandSystemIdStrictOff(systemId, baseSystemId); 1695 } 1696 catch (URI.MalformedURIException e) { 1697 } 1699 1700 if (systemId.length() == 0) { 1702 return systemId; 1703 } 1704 1705 String id = fixURI(systemId); 1707 1708 URI base = null; 1710 URI uri = null; 1711 try { 1712 if (baseSystemId == null || baseSystemId.length() == 0 || 1713 baseSystemId.equals(systemId)) { 1714 base = getUserDir(); 1715 } 1716 else { 1717 try { 1718 base = new URI(fixURI(baseSystemId).trim()); 1719 } 1720 catch (URI.MalformedURIException e) { 1721 if (baseSystemId.indexOf(':') != -1) { 1722 base = new URI("file", "", fixURI(baseSystemId).trim(), null, null); 1725 } 1726 else { 1727 base = new URI(getUserDir(), fixURI(baseSystemId)); 1728 } 1729 } 1730 } 1731 uri = new URI(base, id.trim()); 1733 } 1734 catch (Exception e) { 1735 1737 } 1738 1739 if (uri == null) { 1740 return systemId; 1741 } 1742 return uri.toString(); 1743 1744 } 1746 1749 private static String expandSystemIdStrictOn(String systemId, String baseSystemId) 1750 throws URI.MalformedURIException { 1751 1752 URI systemURI = new URI(systemId, true); 1753 if (systemURI.isAbsoluteURI()) { 1755 return systemId; 1756 } 1757 1758 URI baseURI = null; 1760 if (baseSystemId == null || baseSystemId.length() == 0) { 1761 baseURI = getUserDir(); 1762 } 1763 else { 1764 baseURI = new URI(baseSystemId, true); 1765 if (!baseURI.isAbsoluteURI()) { 1766 baseURI.absolutize(getUserDir()); 1768 } 1769 } 1770 1771 systemURI.absolutize(baseURI); 1773 1774 return systemURI.toString(); 1776 1777 1779 } 1781 1784 private static String expandSystemIdStrictOff(String systemId, String baseSystemId) 1785 throws URI.MalformedURIException { 1786 1787 URI systemURI = new URI(systemId, true); 1788 if (systemURI.isAbsoluteURI()) { 1790 if (systemURI.getScheme().length() > 1) { 1791 return systemId; 1792 } 1793 1799 throw new URI.MalformedURIException(); 1800 } 1801 1802 URI baseURI = null; 1804 if (baseSystemId == null || baseSystemId.length() == 0) { 1805 baseURI = getUserDir(); 1806 } 1807 else { 1808 baseURI = new URI(baseSystemId, true); 1809 if (!baseURI.isAbsoluteURI()) { 1810 baseURI.absolutize(getUserDir()); 1812 } 1813 } 1814 1815 systemURI.absolutize(baseURI); 1817 1818 return systemURI.toString(); 1820 1821 1823 } 1825 1829 public static void setInstanceFollowRedirects(HttpURLConnection urlCon, boolean followRedirects) { 1830 try { 1831 Method method = HttpURLConnection .class.getMethod("setInstanceFollowRedirects", new Class [] {Boolean.TYPE}); 1832 method.invoke(urlCon, new Object [] {followRedirects ? Boolean.TRUE : Boolean.FALSE}); 1833 } 1834 catch (Exception exc) {} 1836 } 1837 1838 1842 1847 void endEntity() throws XNIException { 1848 1849 if (DEBUG_BUFFER) { 1851 System.out.print("(endEntity: "); 1852 print(fCurrentEntity); 1853 System.out.println(); 1854 } 1855 if (fEntityHandler != null) { 1856 fEntityHandler.endEntity(fCurrentEntity.name, null); 1857 } 1858 1859 try { 1864 fCurrentEntity.reader.close(); 1865 } 1866 catch (IOException e) { 1867 } 1869 if(!fReaderStack.isEmpty()) { 1873 fReaderStack.pop(); 1874 } 1875 1876 fBufferPool.returnToPool(fCurrentEntity.fBuffer); 1878 1879 fCurrentEntity = fEntityStack.size() > 0 1881 ? (ScannedEntity)fEntityStack.pop() : null; 1882 fEntityScanner.setCurrentEntity(fCurrentEntity); 1883 if (DEBUG_BUFFER) { 1884 System.out.print(")endEntity: "); 1885 print(fCurrentEntity); 1886 System.out.println(); 1887 } 1888 1889 } 1891 1901 protected Object [] getEncodingName(byte[] b4, int count) { 1902 1903 if (count < 2) { 1904 return new Object []{"UTF-8", null}; 1905 } 1906 1907 int b0 = b4[0] & 0xFF; 1909 int b1 = b4[1] & 0xFF; 1910 if (b0 == 0xFE && b1 == 0xFF) { 1911 return new Object [] {"UTF-16BE", Boolean.TRUE}; 1913 } 1914 if (b0 == 0xFF && b1 == 0xFE) { 1915 return new Object [] {"UTF-16LE", Boolean.FALSE}; 1917 } 1918 1919 if (count < 3) { 1922 return new Object [] {"UTF-8", null}; 1923 } 1924 1925 int b2 = b4[2] & 0xFF; 1927 if (b0 == 0xEF && b1 == 0xBB && b2 == 0xBF) { 1928 return new Object [] {"UTF-8", null}; 1929 } 1930 1931 if (count < 4) { 1934 return new Object [] {"UTF-8", null}; 1935 } 1936 1937 int b3 = b4[3] & 0xFF; 1939 if (b0 == 0x00 && b1 == 0x00 && b2 == 0x00 && b3 == 0x3C) { 1940 return new Object [] {"ISO-10646-UCS-4", Boolean.TRUE}; 1942 } 1943 if (b0 == 0x3C && b1 == 0x00 && b2 == 0x00 && b3 == 0x00) { 1944 return new Object [] {"ISO-10646-UCS-4", Boolean.FALSE}; 1946 } 1947 if (b0 == 0x00 && b1 == 0x00 && b2 == 0x3C && b3 == 0x00) { 1948 return new Object [] {"ISO-10646-UCS-4", null}; 1951 } 1952 if (b0 == 0x00 && b1 == 0x3C && b2 == 0x00 && b3 == 0x00) { 1953 return new Object [] {"ISO-10646-UCS-4", null}; 1956 } 1957 if (b0 == 0x00 && b1 == 0x3C && b2 == 0x00 && b3 == 0x3F) { 1958 return new Object [] {"UTF-16BE", Boolean.TRUE}; 1962 } 1963 if (b0 == 0x3C && b1 == 0x00 && b2 == 0x3F && b3 == 0x00) { 1964 return new Object [] {"UTF-16LE", Boolean.FALSE}; 1967 } 1968 if (b0 == 0x4C && b1 == 0x6F && b2 == 0xA7 && b3 == 0x94) { 1969 return new Object [] {"CP037", null}; 1972 } 1973 1974 return new Object [] {"UTF-8", null}; 1976 1977 } 1979 1995 protected Reader createReader(InputStream inputStream, String encoding, Boolean isBigEndian) 1996 throws IOException { 1997 1998 if (encoding == null) { 2000 encoding = "UTF-8"; 2001 } 2002 2003 String ENCODING = encoding.toUpperCase(Locale.ENGLISH); 2005 if (ENCODING.equals("UTF-8")) { 2006 if (DEBUG_ENCODINGS) { 2007 System.out.println("$$$ creating UTF8Reader"); 2008 } 2009 return new UTF8Reader(inputStream, fBufferSize, fErrorReporter.getMessageFormatter(XMLMessageFormatter.XML_DOMAIN), fErrorReporter.getLocale() ); 2010 } 2011 if(ENCODING.equals("ISO-10646-UCS-4")) { 2012 if(isBigEndian != null) { 2013 boolean isBE = isBigEndian.booleanValue(); 2014 if(isBE) { 2015 return new UCSReader(inputStream, UCSReader.UCS4BE); 2016 } else { 2017 return new UCSReader(inputStream, UCSReader.UCS4LE); 2018 } 2019 } else { 2020 fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN, 2021 "EncodingByteOrderUnsupported", 2022 new Object [] { encoding }, 2023 XMLErrorReporter.SEVERITY_FATAL_ERROR); 2024 } 2025 } 2026 if(ENCODING.equals("ISO-10646-UCS-2")) { 2027 if(isBigEndian != null) { boolean isBE = isBigEndian.booleanValue(); 2029 if(isBE) { 2030 return new UCSReader(inputStream, UCSReader.UCS2BE); 2031 } else { 2032 return new UCSReader(inputStream, UCSReader.UCS2LE); 2033 } 2034 } else { 2035 fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN, 2036 "EncodingByteOrderUnsupported", 2037 new Object [] { encoding }, 2038 XMLErrorReporter.SEVERITY_FATAL_ERROR); 2039 } 2040 } 2041 2042 boolean validIANA = XMLChar.isValidIANAEncoding(encoding); 2044 boolean validJava = XMLChar.isValidJavaEncoding(encoding); 2045 if (!validIANA || (fAllowJavaEncodings && !validJava)) { 2046 fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN, 2047 "EncodingDeclInvalid", 2048 new Object [] { encoding }, 2049 XMLErrorReporter.SEVERITY_FATAL_ERROR); 2050 encoding = "ISO-8859-1"; 2059 } 2060 2061 String javaEncoding = EncodingMap.getIANA2JavaMapping(ENCODING); 2063 if (javaEncoding == null) { 2064 if(fAllowJavaEncodings) { 2065 javaEncoding = encoding; 2066 } else { 2067 fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN, 2068 "EncodingDeclInvalid", 2069 new Object [] { encoding }, 2070 XMLErrorReporter.SEVERITY_FATAL_ERROR); 2071 javaEncoding = "ISO8859_1"; 2073 } 2074 } 2075 else if (javaEncoding.equals("ASCII")) { 2076 if (DEBUG_ENCODINGS) { 2077 System.out.println("$$$ creating ASCIIReader"); 2078 } 2079 return new ASCIIReader(inputStream, fBufferSize, fErrorReporter.getMessageFormatter(XMLMessageFormatter.XML_DOMAIN), fErrorReporter.getLocale()); 2080 } 2081 2082 2083 if (DEBUG_ENCODINGS) { 2084 System.out.print("$$$ creating Java InputStreamReader: encoding="+javaEncoding); 2085 if (javaEncoding == encoding) { 2086 System.out.print(" (IANA encoding)"); 2087 } 2088 System.out.println(); 2089 } 2090 return new InputStreamReader (inputStream, javaEncoding); 2091 2092 } 2094 2098 2105 protected static String fixURI(String str) { 2106 2107 str = str.replace(java.io.File.separatorChar, '/'); 2109 2110 StringBuffer sb = null; 2111 2112 if (str.length() >= 2) { 2114 char ch1 = str.charAt(1); 2115 if (ch1 == ':') { 2117 char ch0 = Character.toUpperCase(str.charAt(0)); 2118 if (ch0 >= 'A' && ch0 <= 'Z') { 2119 sb = new StringBuffer (str.length() + 8); 2120 sb.append("file:///"); 2121 } 2122 } 2123 else if (ch1 == '/' && str.charAt(0) == '/') { 2125 sb = new StringBuffer (str.length() + 5); 2126 sb.append("file:"); 2127 } 2128 } 2129 2130 int pos = str.indexOf(' '); 2131 if (pos < 0) { 2134 if (sb != null) { 2135 sb.append(str); 2136 str = sb.toString(); 2137 } 2138 } 2139 else { 2143 if (sb == null) 2144 sb = new StringBuffer (str.length()); 2145 for (int i = 0; i < pos; i++) 2147 sb.append(str.charAt(i)); 2148 sb.append("%20"); 2150 for (int i = pos+1; i < str.length(); i++) { 2152 if (str.charAt(i) == ' ') 2153 sb.append("%20"); 2154 else 2155 sb.append(str.charAt(i)); 2156 } 2157 str = sb.toString(); 2158 } 2159 2160 return str; 2162 2163 } 2165 2169 2177 Hashtable getDeclaredEntities() { 2178 return fEntities; 2179 } 2181 2182 static final void print(ScannedEntity currentEntity) { 2183 if (DEBUG_BUFFER) { 2184 if (currentEntity != null) { 2185 System.out.print('['); 2186 System.out.print(currentEntity.count); 2187 System.out.print(' '); 2188 System.out.print(currentEntity.position); 2189 if (currentEntity.count > 0) { 2190 System.out.print(" \""); 2191 for (int i = 0; i < currentEntity.count; i++) { 2192 if (i == currentEntity.position) { 2193 System.out.print('^'); 2194 } 2195 char c = currentEntity.ch[i]; 2196 switch (c) { 2197 case '\n': { 2198 System.out.print("\\n"); 2199 break; 2200 } 2201 case '\r': { 2202 System.out.print("\\r"); 2203 break; 2204 } 2205 case '\t': { 2206 System.out.print("\\t"); 2207 break; 2208 } 2209 case '\\': { 2210 System.out.print("\\\\"); 2211 break; 2212 } 2213 default: { 2214 System.out.print(c); 2215 } 2216 } 2217 } 2218 if (currentEntity.position == currentEntity.count) { 2219 System.out.print('^'); 2220 } 2221 System.out.print('"'); 2222 } 2223 System.out.print(']'); 2224 System.out.print(" @ "); 2225 System.out.print(currentEntity.lineNumber); 2226 System.out.print(','); 2227 System.out.print(currentEntity.columnNumber); 2228 } 2229 else { 2230 System.out.print("*NO CURRENT ENTITY*"); 2231 } 2232 } 2233 } 2235 2239 2246 public static abstract class Entity { 2247 2248 2252 2253 public String name; 2254 2255 public boolean inExternalSubset; 2258 2259 2263 2264 public Entity() { 2265 clear(); 2266 } 2268 2269 public Entity(String name, boolean inExternalSubset) { 2270 this.name = name; 2271 this.inExternalSubset = inExternalSubset; 2272 } 2274 2278 2279 public boolean isEntityDeclInExternalSubset () { 2280 return inExternalSubset; 2281 } 2282 2283 2284 public abstract boolean isExternal(); 2285 2286 2287 public abstract boolean isUnparsed(); 2288 2289 2290 public void clear() { 2291 name = null; 2292 inExternalSubset = false; 2293 } 2295 2296 public void setValues(Entity entity) { 2297 name = entity.name; 2298 inExternalSubset = entity.inExternalSubset; 2299 } 2301 } 2303 2310 protected static class InternalEntity 2311 extends Entity { 2312 2313 2317 2318 public String text; 2319 2320 2324 2325 public InternalEntity() { 2326 clear(); 2327 } 2329 2330 public InternalEntity(String name, String text, boolean inExternalSubset) { 2331 super(name,inExternalSubset); 2332 this.text = text; 2333 } 2335 2339 2340 public final boolean isExternal() { 2341 return false; 2342 } 2344 2345 public final boolean isUnparsed() { 2346 return false; 2347 } 2349 2350 public void clear() { 2351 super.clear(); 2352 text = null; 2353 } 2355 2356 public void setValues(Entity entity) { 2357 super.setValues(entity); 2358 text = null; 2359 } 2361 2362 public void setValues(InternalEntity entity) { 2363 super.setValues(entity); 2364 text = entity.text; 2365 } 2367 } 2369 2376 protected static class ExternalEntity 2377 extends Entity { 2378 2379 2383 2384 public XMLResourceIdentifier entityLocation; 2385 2386 2387 public String notation; 2388 2389 2393 2394 public ExternalEntity() { 2395 clear(); 2396 } 2398 2399 public ExternalEntity(String name, XMLResourceIdentifier entityLocation, 2400 String notation, boolean inExternalSubset) { 2401 super(name,inExternalSubset); 2402 this.entityLocation = entityLocation; 2403 this.notation = notation; 2404 } 2406 2410 2411 public final boolean isExternal() { 2412 return true; 2413 } 2415 2416 public final boolean isUnparsed() { 2417 return notation != null; 2418 } 2420 2421 public void clear() { 2422 super.clear(); 2423 entityLocation = null; 2424 notation = null; 2425 } 2427 2428 public void setValues(Entity entity) { 2429 super.setValues(entity); 2430 entityLocation = null; 2431 notation = null; 2432 } 2434 2435 public void setValues(ExternalEntity entity) { 2436 super.setValues(entity); 2437 entityLocation = entity.entityLocation; 2438 notation = entity.notation; 2439 } 2441 } 2443 2450 public class ScannedEntity 2451 extends Entity { 2452 2453 2457 2459 2460 public InputStream stream; 2461 2462 2463 public Reader reader; 2464 2465 2467 2468 public XMLResourceIdentifier entityLocation; 2469 2470 2471 public int lineNumber = 1; 2472 2473 2474 public int columnNumber = 1; 2475 2476 2478 2479 public String encoding; 2480 2481 2485 boolean externallySpecifiedEncoding = false; 2486 2487 2489 2490 public String xmlVersion = "1.0"; 2491 2492 2494 2495 public boolean literal; 2496 2497 public boolean isExternal; 2499 2500 2502 2503 public char[] ch = null; 2504 2505 2506 public int position; 2507 2508 2509 public int baseCharOffset; 2510 2511 2512 public int startPosition; 2513 2514 2515 public int count; 2516 2517 public boolean mayReadChunks; 2519 2520 2521 private CharacterBuffer fBuffer; 2522 2523 2524 2528 2529 public ScannedEntity(String name, 2530 XMLResourceIdentifier entityLocation, 2531 InputStream stream, Reader reader, 2532 String encoding, boolean literal, boolean mayReadChunks, boolean isExternal) { 2533 super(name,XMLEntityManager.this.fInExternalSubset); 2534 this.entityLocation = entityLocation; 2535 this.stream = stream; 2536 this.reader = reader; 2537 this.encoding = encoding; 2538 this.literal = literal; 2539 this.mayReadChunks = mayReadChunks; 2540 this.isExternal = isExternal; 2541 this.fBuffer = fBufferPool.getBuffer(isExternal); 2542 this.ch = fBuffer.ch; 2543 } 2545 2549 2550 public final boolean isExternal() { 2551 return isExternal; 2552 } 2554 2555 public final boolean isUnparsed() { 2556 return false; 2557 } 2559 public void setReader(InputStream stream, String encoding, Boolean isBigEndian) throws IOException { 2560 reader = createReader(stream, encoding, isBigEndian); 2561 } 2562 2563 public String getExpandedSystemId() { 2567 2568 int size = fEntityStack.size(); 2570 for (int i = size - 1; i >= 0 ; i--) { 2571 ScannedEntity externalEntity = 2572 (ScannedEntity)fEntityStack.elementAt(i); 2573 2574 if (externalEntity.entityLocation != null && 2575 externalEntity.entityLocation.getExpandedSystemId() != null) { 2576 return externalEntity.entityLocation.getExpandedSystemId(); 2577 } 2578 } 2579 return null; 2580 } 2581 2582 public String getLiteralSystemId() { 2585 int size = fEntityStack.size(); 2587 for (int i = size - 1; i >= 0 ; i--) { 2588 ScannedEntity externalEntity = 2589 (ScannedEntity)fEntityStack.elementAt(i); 2590 2591 if (externalEntity.entityLocation != null && 2592 externalEntity.entityLocation.getLiteralSystemId() != null) { 2593 return externalEntity.entityLocation.getLiteralSystemId(); 2594 } 2595 } 2596 return null; 2597 } 2598 2599 public int getLineNumber() { 2602 int size = fEntityStack.size(); 2604 for (int i=size-1; i>0 ; i--) { 2605 ScannedEntity firstExternalEntity = (ScannedEntity)fEntityStack.elementAt(i); 2606 if (firstExternalEntity.isExternal()) { 2607 return firstExternalEntity.lineNumber; 2608 } 2609 } 2610 return -1; 2611 } 2612 2613 public int getColumnNumber() { 2616 int size = fEntityStack.size(); 2618 for (int i=size-1; i>0 ; i--) { 2619 ScannedEntity firstExternalEntity = (ScannedEntity)fEntityStack.elementAt(i); 2620 if (firstExternalEntity.isExternal()) { 2621 return firstExternalEntity.columnNumber; 2622 } 2623 } 2624 return -1; 2625 } 2626 2627 public int getCharacterOffset() { 2630 int size = fEntityStack.size(); 2632 for (int i=size-1; i>0 ; i--) { 2633 ScannedEntity firstExternalEntity = (ScannedEntity)fEntityStack.elementAt(i); 2634 if (firstExternalEntity.isExternal()) { 2635 return firstExternalEntity.baseCharOffset + (firstExternalEntity.position - firstExternalEntity.startPosition); 2636 } 2637 } 2638 return -1; 2639 } 2640 2641 public String getEncoding() { 2643 int size = fEntityStack.size(); 2645 for (int i=size-1; i>0 ; i--) { 2646 ScannedEntity firstExternalEntity = (ScannedEntity)fEntityStack.elementAt(i); 2647 if (firstExternalEntity.isExternal()) { 2648 return firstExternalEntity.encoding; 2649 } 2650 } 2651 return null; 2652 } 2653 2654 public String getXMLVersion() { 2656 int size = fEntityStack.size(); 2658 for (int i=size-1; i>0 ; i--) { 2659 ScannedEntity firstExternalEntity = (ScannedEntity)fEntityStack.elementAt(i); 2660 if (firstExternalEntity.isExternal()) { 2661 return firstExternalEntity.xmlVersion; 2662 } 2663 } 2664 return null; 2665 } 2666 2667 2668 public boolean isEncodingExternallySpecified() { 2669 return externallySpecifiedEncoding; 2670 } 2671 2672 2673 public void setEncodingExternallySpecified(boolean value) { 2674 externallySpecifiedEncoding = value; 2675 } 2676 2677 2681 2682 public String toString() { 2683 2684 StringBuffer str = new StringBuffer (); 2685 str.append("name=\""+name+'"'); 2686 str.append(",ch="); 2687 str.append(ch); 2688 str.append(",position=" + position); 2689 str.append(",count=" + count); 2690 str.append(",baseCharOffset=" + baseCharOffset); 2691 str.append(",startPosition=" + startPosition); 2692 return str.toString(); 2693 2694 } 2696 } 2698 2706 private static class CharacterBuffer { 2707 2708 2709 private char[] ch; 2710 2711 2712 private boolean isExternal; 2713 2714 public CharacterBuffer(boolean isExternal, int size) { 2715 this.isExternal = isExternal; 2716 ch = new char[size]; 2717 } 2718 } 2719 2720 2728 private static class CharacterBufferPool { 2729 2730 private static final int DEFAULT_POOL_SIZE = 3; 2731 2732 private CharacterBuffer[] fInternalBufferPool; 2733 private CharacterBuffer[] fExternalBufferPool; 2734 2735 private int fExternalBufferSize; 2736 private int fInternalBufferSize; 2737 private int poolSize; 2738 2739 private int fInternalTop; 2740 private int fExternalTop; 2741 2742 public CharacterBufferPool(int externalBufferSize, int internalBufferSize) { 2743 this(DEFAULT_POOL_SIZE, externalBufferSize, internalBufferSize); 2744 } 2745 2746 public CharacterBufferPool(int poolSize, int externalBufferSize, int internalBufferSize) { 2747 fExternalBufferSize = externalBufferSize; 2748 fInternalBufferSize = internalBufferSize; 2749 this.poolSize = poolSize; 2750 init(); 2751 } 2752 2753 2754 private void init() { 2755 fInternalBufferPool = new CharacterBuffer[poolSize]; 2756 fExternalBufferPool = new CharacterBuffer[poolSize]; 2757 fInternalTop = -1; 2758 fExternalTop = -1; 2759 } 2760 2761 2762 public CharacterBuffer getBuffer(boolean external) { 2763 if (external) { 2764 if (fExternalTop > -1) { 2765 return (CharacterBuffer)fExternalBufferPool[fExternalTop--]; 2766 } 2767 else { 2768 return new CharacterBuffer(true, fExternalBufferSize); 2769 } 2770 } 2771 else { 2772 if (fInternalTop > -1) { 2773 return (CharacterBuffer)fInternalBufferPool[fInternalTop--]; 2774 } 2775 else { 2776 return new CharacterBuffer(false, fInternalBufferSize); 2777 } 2778 } 2779 } 2780 2781 2782 public void returnToPool(CharacterBuffer buffer) { 2783 if (buffer.isExternal) { 2784 if (fExternalTop < fExternalBufferPool.length - 1) { 2785 fExternalBufferPool[++fExternalTop] = buffer; 2786 } 2787 } 2788 else if (fInternalTop < fInternalBufferPool.length - 1) { 2789 fInternalBufferPool[++fInternalTop] = buffer; 2790 } 2791 } 2792 2793 2794 public void setExternalBufferSize(int bufferSize) { 2795 fExternalBufferSize = bufferSize; 2796 fExternalBufferPool = new CharacterBuffer[poolSize]; 2797 fExternalTop = -1; 2798 } 2799 } 2800 2801 2823 protected final class RewindableInputStream extends InputStream { 2824 2825 private InputStream fInputStream; 2826 private byte[] fData; 2827 private int fStartOffset; 2828 private int fEndOffset; 2829 private int fOffset; 2830 private int fLength; 2831 private int fMark; 2832 2833 public RewindableInputStream(InputStream is) { 2834 fData = new byte[DEFAULT_XMLDECL_BUFFER_SIZE]; 2835 fInputStream = is; 2836 fStartOffset = 0; 2837 fEndOffset = -1; 2838 fOffset = 0; 2839 fLength = 0; 2840 fMark = 0; 2841 } 2842 2843 public void setStartOffset(int offset) { 2844 fStartOffset = offset; 2845 } 2846 2847 public void rewind() { 2848 fOffset = fStartOffset; 2849 } 2850 2851 public int read() throws IOException { 2852 int b = 0; 2853 if (fOffset < fLength) { 2854 return fData[fOffset++] & 0xff; 2855 } 2856 if (fOffset == fEndOffset) { 2857 return -1; 2858 } 2859 if (fOffset == fData.length) { 2860 byte[] newData = new byte[fOffset << 1]; 2861 System.arraycopy(fData, 0, newData, 0, fOffset); 2862 fData = newData; 2863 } 2864 b = fInputStream.read(); 2865 if (b == -1) { 2866 fEndOffset = fOffset; 2867 return -1; 2868 } 2869 fData[fLength++] = (byte)b; 2870 fOffset++; 2871 return b & 0xff; 2872 } 2873 2874 public int read(byte[] b, int off, int len) throws IOException { 2875 int bytesLeft = fLength - fOffset; 2876 if (bytesLeft == 0) { 2877 if (fOffset == fEndOffset) { 2878 return -1; 2879 } 2880 if(fCurrentEntity.mayReadChunks) { 2882 return fInputStream.read(b, off, len); 2883 } 2884 int returnedVal = read(); 2885 if(returnedVal == -1) { 2886 fEndOffset = fOffset; 2887 return -1; 2888 } 2889 b[off] = (byte)returnedVal; 2890 return 1; 2891 } 2892 if (len < bytesLeft) { 2893 if (len <= 0) { 2894 return 0; 2895 } 2896 } 2897 else { 2898 len = bytesLeft; 2899 } 2900 if (b != null) { 2901 System.arraycopy(fData, fOffset, b, off, len); 2902 } 2903 fOffset += len; 2904 return len; 2905 } 2906 2907 public long skip(long n) 2908 throws IOException 2909 { 2910 int bytesLeft; 2911 if (n <= 0) { 2912 return 0; 2913 } 2914 bytesLeft = fLength - fOffset; 2915 if (bytesLeft == 0) { 2916 if (fOffset == fEndOffset) { 2917 return 0; 2918 } 2919 return fInputStream.skip(n); 2920 } 2921 if (n <= bytesLeft) { 2922 fOffset += n; 2923 return n; 2924 } 2925 fOffset += bytesLeft; 2926 if (fOffset == fEndOffset) { 2927 return bytesLeft; 2928 } 2929 n -= bytesLeft; 2930 2938 return fInputStream.skip(n) + bytesLeft; 2939 } 2940 2941 public int available() throws IOException { 2942 int bytesLeft = fLength - fOffset; 2943 if (bytesLeft == 0) { 2944 if (fOffset == fEndOffset) { 2945 return -1; 2946 } 2947 return fCurrentEntity.mayReadChunks ? fInputStream.available() 2948 : 0; 2949 } 2950 return bytesLeft; 2951 } 2952 2953 public void mark(int howMuch) { 2954 fMark = fOffset; 2955 } 2956 2957 public void reset() { 2958 fOffset = fMark; 2959 } 2960 2961 public boolean markSupported() { 2962 return true; 2963 } 2964 2965 public void close() throws IOException { 2966 if (fInputStream != null) { 2967 fInputStream.close(); 2968 fInputStream = null; 2969 } 2970 } 2971 } 2973} | Popular Tags |