1 16 17 package org.apache.xerces.util; 18 19 import java.io.IOException ; 20 import java.io.Serializable ; 21 22 57 public class URI implements Serializable { 58 59 65 public static class MalformedURIException extends IOException { 66 67 68 static final long serialVersionUID = -6695054834342951930L; 69 70 74 public MalformedURIException() { 75 super(); 76 } 77 78 84 public MalformedURIException(String p_msg) { 85 super(p_msg); 86 } 87 } 88 89 90 static final long serialVersionUID = 1601921774685357214L; 91 92 private static final byte [] fgLookupTable = new byte[128]; 93 94 97 98 99 private static final int RESERVED_CHARACTERS = 0x01; 101 102 104 private static final int MARK_CHARACTERS = 0x02; 105 106 107 private static final int SCHEME_CHARACTERS = 0x04; 108 109 111 private static final int USERINFO_CHARACTERS = 0x08; 112 113 114 private static final int ASCII_ALPHA_CHARACTERS = 0x10; 115 116 117 private static final int ASCII_DIGIT_CHARACTERS = 0x20; 118 119 120 private static final int ASCII_HEX_CHARACTERS = 0x40; 121 122 123 private static final int PATH_CHARACTERS = 0x80; 124 125 126 private static final int MASK_ALPHA_NUMERIC = ASCII_ALPHA_CHARACTERS | ASCII_DIGIT_CHARACTERS; 127 128 129 private static final int MASK_UNRESERVED_MASK = MASK_ALPHA_NUMERIC | MARK_CHARACTERS; 130 131 132 private static final int MASK_URI_CHARACTER = MASK_UNRESERVED_MASK | RESERVED_CHARACTERS; 133 134 135 private static final int MASK_SCHEME_CHARACTER = MASK_ALPHA_NUMERIC | SCHEME_CHARACTERS; 136 137 138 private static final int MASK_USERINFO_CHARACTER = MASK_UNRESERVED_MASK | USERINFO_CHARACTERS; 139 140 141 private static final int MASK_PATH_CHARACTER = MASK_UNRESERVED_MASK | PATH_CHARACTERS; 142 143 static { 144 for (int i = '0'; i <= '9'; ++i) { 146 fgLookupTable[i] |= ASCII_DIGIT_CHARACTERS | ASCII_HEX_CHARACTERS; 147 } 148 149 for (int i = 'A'; i <= 'F'; ++i) { 151 fgLookupTable[i] |= ASCII_ALPHA_CHARACTERS | ASCII_HEX_CHARACTERS; 152 fgLookupTable[i+0x00000020] |= ASCII_ALPHA_CHARACTERS | ASCII_HEX_CHARACTERS; 153 } 154 155 for (int i = 'G'; i <= 'Z'; ++i) { 157 fgLookupTable[i] |= ASCII_ALPHA_CHARACTERS; 158 fgLookupTable[i+0x00000020] |= ASCII_ALPHA_CHARACTERS; 159 } 160 161 fgLookupTable[';'] |= RESERVED_CHARACTERS; 163 fgLookupTable['/'] |= RESERVED_CHARACTERS; 164 fgLookupTable['?'] |= RESERVED_CHARACTERS; 165 fgLookupTable[':'] |= RESERVED_CHARACTERS; 166 fgLookupTable['@'] |= RESERVED_CHARACTERS; 167 fgLookupTable['&'] |= RESERVED_CHARACTERS; 168 fgLookupTable['='] |= RESERVED_CHARACTERS; 169 fgLookupTable['+'] |= RESERVED_CHARACTERS; 170 fgLookupTable['$'] |= RESERVED_CHARACTERS; 171 fgLookupTable[','] |= RESERVED_CHARACTERS; 172 fgLookupTable['['] |= RESERVED_CHARACTERS; 173 fgLookupTable[']'] |= RESERVED_CHARACTERS; 174 175 fgLookupTable['-'] |= MARK_CHARACTERS; 177 fgLookupTable['_'] |= MARK_CHARACTERS; 178 fgLookupTable['.'] |= MARK_CHARACTERS; 179 fgLookupTable['!'] |= MARK_CHARACTERS; 180 fgLookupTable['~'] |= MARK_CHARACTERS; 181 fgLookupTable['*'] |= MARK_CHARACTERS; 182 fgLookupTable['\''] |= MARK_CHARACTERS; 183 fgLookupTable['('] |= MARK_CHARACTERS; 184 fgLookupTable[')'] |= MARK_CHARACTERS; 185 186 fgLookupTable['+'] |= SCHEME_CHARACTERS; 188 fgLookupTable['-'] |= SCHEME_CHARACTERS; 189 fgLookupTable['.'] |= SCHEME_CHARACTERS; 190 191 fgLookupTable[';'] |= USERINFO_CHARACTERS; 193 fgLookupTable[':'] |= USERINFO_CHARACTERS; 194 fgLookupTable['&'] |= USERINFO_CHARACTERS; 195 fgLookupTable['='] |= USERINFO_CHARACTERS; 196 fgLookupTable['+'] |= USERINFO_CHARACTERS; 197 fgLookupTable['$'] |= USERINFO_CHARACTERS; 198 fgLookupTable[','] |= USERINFO_CHARACTERS; 199 200 fgLookupTable[';'] |= PATH_CHARACTERS; 202 fgLookupTable['/'] |= PATH_CHARACTERS; 203 fgLookupTable[':'] |= PATH_CHARACTERS; 204 fgLookupTable['@'] |= PATH_CHARACTERS; 205 fgLookupTable['&'] |= PATH_CHARACTERS; 206 fgLookupTable['='] |= PATH_CHARACTERS; 207 fgLookupTable['+'] |= PATH_CHARACTERS; 208 fgLookupTable['$'] |= PATH_CHARACTERS; 209 fgLookupTable[','] |= PATH_CHARACTERS; 210 } 211 212 213 private String m_scheme = null; 214 215 216 private String m_userinfo = null; 217 218 219 private String m_host = null; 220 221 222 private int m_port = -1; 223 224 225 private String m_regAuthority = null; 226 227 228 private String m_path = null; 229 230 232 private String m_queryString = null; 233 234 235 private String m_fragment = null; 236 237 private static boolean DEBUG = false; 238 239 242 public URI() { 243 } 244 245 251 public URI(URI p_other) { 252 initialize(p_other); 253 } 254 255 270 public URI(String p_uriSpec) throws MalformedURIException { 271 this((URI)null, p_uriSpec); 272 } 273 274 293 public URI(String p_uriSpec, boolean allowNonAbsoluteURI) throws MalformedURIException { 294 this((URI)null, p_uriSpec, allowNonAbsoluteURI); 295 } 296 297 309 public URI(URI p_base, String p_uriSpec) throws MalformedURIException { 310 initialize(p_base, p_uriSpec); 311 } 312 313 330 public URI(URI p_base, String p_uriSpec, boolean allowNonAbsoluteURI) throws MalformedURIException { 331 initialize(p_base, p_uriSpec, allowNonAbsoluteURI); 332 } 333 334 346 public URI(String p_scheme, String p_schemeSpecificPart) 347 throws MalformedURIException { 348 if (p_scheme == null || p_scheme.trim().length() == 0) { 349 throw new MalformedURIException( 350 "Cannot construct URI with null/empty scheme!"); 351 } 352 if (p_schemeSpecificPart == null || 353 p_schemeSpecificPart.trim().length() == 0) { 354 throw new MalformedURIException( 355 "Cannot construct URI with null/empty scheme-specific part!"); 356 } 357 setScheme(p_scheme); 358 setPath(p_schemeSpecificPart); 359 } 360 361 382 public URI(String p_scheme, String p_host, String p_path, 383 String p_queryString, String p_fragment) 384 throws MalformedURIException { 385 this(p_scheme, null, p_host, -1, p_path, p_queryString, p_fragment); 386 } 387 388 413 public URI(String p_scheme, String p_userinfo, 414 String p_host, int p_port, String p_path, 415 String p_queryString, String p_fragment) 416 throws MalformedURIException { 417 if (p_scheme == null || p_scheme.trim().length() == 0) { 418 throw new MalformedURIException("Scheme is required!"); 419 } 420 421 if (p_host == null) { 422 if (p_userinfo != null) { 423 throw new MalformedURIException( 424 "Userinfo may not be specified if host is not specified!"); 425 } 426 if (p_port != -1) { 427 throw new MalformedURIException( 428 "Port may not be specified if host is not specified!"); 429 } 430 } 431 432 if (p_path != null) { 433 if (p_path.indexOf('?') != -1 && p_queryString != null) { 434 throw new MalformedURIException( 435 "Query string cannot be specified in path and query string!"); 436 } 437 438 if (p_path.indexOf('#') != -1 && p_fragment != null) { 439 throw new MalformedURIException( 440 "Fragment cannot be specified in both the path and fragment!"); 441 } 442 } 443 444 setScheme(p_scheme); 445 setHost(p_host); 446 setPort(p_port); 447 setUserinfo(p_userinfo); 448 setPath(p_path); 449 setQueryString(p_queryString); 450 setFragment(p_fragment); 451 } 452 453 458 private void initialize(URI p_other) { 459 m_scheme = p_other.getScheme(); 460 m_userinfo = p_other.getUserinfo(); 461 m_host = p_other.getHost(); 462 m_port = p_other.getPort(); 463 m_regAuthority = p_other.getRegBasedAuthority(); 464 m_path = p_other.getPath(); 465 m_queryString = p_other.getQueryString(); 466 m_fragment = p_other.getFragment(); 467 } 468 469 487 private void initialize(URI p_base, String p_uriSpec, boolean allowNonAbsoluteURI) 488 throws MalformedURIException { 489 490 String uriSpec = p_uriSpec; 491 int uriSpecLen = (uriSpec != null) ? uriSpec.length() : 0; 492 493 if (p_base == null && uriSpecLen == 0) { 494 if (allowNonAbsoluteURI) { 495 m_path = ""; 496 return; 497 } 498 throw new MalformedURIException("Cannot initialize URI with empty parameters."); 499 } 500 501 if (uriSpecLen == 0) { 503 initialize(p_base); 504 return; 505 } 506 507 int index = 0; 508 509 int colonIdx = uriSpec.indexOf(':'); 511 if (colonIdx != -1) { 512 final int searchFrom = colonIdx - 1; 513 int slashIdx = uriSpec.lastIndexOf('/', searchFrom); 515 int queryIdx = uriSpec.lastIndexOf('?', searchFrom); 516 int fragmentIdx = uriSpec.lastIndexOf('#', searchFrom); 517 518 if (colonIdx == 0 || slashIdx != -1 || 519 queryIdx != -1 || fragmentIdx != -1) { 520 if (colonIdx == 0 || (p_base == null && fragmentIdx != 0 && !allowNonAbsoluteURI)) { 522 throw new MalformedURIException("No scheme found in URI."); 523 } 524 } 525 else { 526 initializeScheme(uriSpec); 527 index = m_scheme.length()+1; 528 529 if (colonIdx == uriSpecLen - 1 || uriSpec.charAt(colonIdx+1) == '#') { 531 throw new MalformedURIException("Scheme specific part cannot be empty."); 532 } 533 } 534 } 535 else if (p_base == null && uriSpec.indexOf('#') != 0 && !allowNonAbsoluteURI) { 536 throw new MalformedURIException("No scheme found in URI."); 537 } 538 539 if (((index+1) < uriSpecLen) && 549 (uriSpec.charAt(index) == '/' && uriSpec.charAt(index+1) == '/')) { 550 index += 2; 551 int startPos = index; 552 553 char testChar = '\0'; 555 while (index < uriSpecLen) { 556 testChar = uriSpec.charAt(index); 557 if (testChar == '/' || testChar == '?' || testChar == '#') { 558 break; 559 } 560 index++; 561 } 562 563 if (index > startPos) { 567 if (!initializeAuthority(uriSpec.substring(startPos, index))) { 570 index = startPos - 2; 571 } 572 } 573 else { 574 m_host = ""; 575 } 576 } 577 578 initializePath(uriSpec, index); 579 580 if (p_base != null) { 586 absolutize(p_base); 587 } 588 } 589 590 606 private void initialize(URI p_base, String p_uriSpec) 607 throws MalformedURIException { 608 609 String uriSpec = p_uriSpec; 610 int uriSpecLen = (uriSpec != null) ? uriSpec.length() : 0; 611 612 if (p_base == null && uriSpecLen == 0) { 613 throw new MalformedURIException( 614 "Cannot initialize URI with empty parameters."); 615 } 616 617 if (uriSpecLen == 0) { 619 initialize(p_base); 620 return; 621 } 622 623 int index = 0; 624 625 int colonIdx = uriSpec.indexOf(':'); 627 if (colonIdx != -1) { 628 final int searchFrom = colonIdx - 1; 629 int slashIdx = uriSpec.lastIndexOf('/', searchFrom); 631 int queryIdx = uriSpec.lastIndexOf('?', searchFrom); 632 int fragmentIdx = uriSpec.lastIndexOf('#', searchFrom); 633 634 if (colonIdx == 0 || slashIdx != -1 || 635 queryIdx != -1 || fragmentIdx != -1) { 636 if (colonIdx == 0 || (p_base == null && fragmentIdx != 0)) { 638 throw new MalformedURIException("No scheme found in URI."); 639 } 640 } 641 else { 642 initializeScheme(uriSpec); 643 index = m_scheme.length()+1; 644 645 if (colonIdx == uriSpecLen - 1 || uriSpec.charAt(colonIdx+1) == '#') { 647 throw new MalformedURIException("Scheme specific part cannot be empty."); 648 } 649 } 650 } 651 else if (p_base == null && uriSpec.indexOf('#') != 0) { 652 throw new MalformedURIException("No scheme found in URI."); 653 } 654 655 if (((index+1) < uriSpecLen) && 665 (uriSpec.charAt(index) == '/' && uriSpec.charAt(index+1) == '/')) { 666 index += 2; 667 int startPos = index; 668 669 char testChar = '\0'; 671 while (index < uriSpecLen) { 672 testChar = uriSpec.charAt(index); 673 if (testChar == '/' || testChar == '?' || testChar == '#') { 674 break; 675 } 676 index++; 677 } 678 679 if (index > startPos) { 683 if (!initializeAuthority(uriSpec.substring(startPos, index))) { 686 index = startPos - 2; 687 } 688 } 689 else { 690 m_host = ""; 691 } 692 } 693 694 initializePath(uriSpec, index); 695 696 if (p_base != null) { 702 absolutize(p_base); 703 } 704 } 705 706 711 public void absolutize(URI p_base) { 712 713 if (m_path.length() == 0 && m_scheme == null && 721 m_host == null && m_regAuthority == null) { 722 m_scheme = p_base.getScheme(); 723 m_userinfo = p_base.getUserinfo(); 724 m_host = p_base.getHost(); 725 m_port = p_base.getPort(); 726 m_regAuthority = p_base.getRegBasedAuthority(); 727 m_path = p_base.getPath(); 728 729 if (m_queryString == null) { 730 m_queryString = p_base.getQueryString(); 731 732 if (m_fragment == null) { 733 m_fragment = p_base.getFragment(); 734 } 735 } 736 return; 737 } 738 739 if (m_scheme == null) { 742 m_scheme = p_base.getScheme(); 743 } 744 else { 745 return; 746 } 747 748 if (m_host == null && m_regAuthority == null) { 751 m_userinfo = p_base.getUserinfo(); 752 m_host = p_base.getHost(); 753 m_port = p_base.getPort(); 754 m_regAuthority = p_base.getRegBasedAuthority(); 755 } 756 else { 757 return; 758 } 759 760 if (m_path.length() > 0 && 762 m_path.startsWith("/")) { 763 return; 764 } 765 766 String path = ""; 769 String basePath = p_base.getPath(); 770 771 if (basePath != null && basePath.length() > 0) { 773 int lastSlash = basePath.lastIndexOf('/'); 774 if (lastSlash != -1) { 775 path = basePath.substring(0, lastSlash+1); 776 } 777 } 778 else if (m_path.length() > 0) { 779 path = "/"; 780 } 781 782 path = path.concat(m_path); 784 785 int index = -1; 787 while ((index = path.indexOf("/./")) != -1) { 788 path = path.substring(0, index+1).concat(path.substring(index+3)); 789 } 790 791 if (path.endsWith("/.")) { 793 path = path.substring(0, path.length()-1); 794 } 795 796 index = 1; 799 int segIndex = -1; 800 String tempString = null; 801 802 while ((index = path.indexOf("/../", index)) > 0) { 803 tempString = path.substring(0, path.indexOf("/../")); 804 segIndex = tempString.lastIndexOf('/'); 805 if (segIndex != -1) { 806 if (!tempString.substring(segIndex).equals("..")) { 807 path = path.substring(0, segIndex+1).concat(path.substring(index+4)); 808 index = segIndex; 809 } 810 else { 811 index += 4; 812 } 813 } 814 else { 815 index += 4; 816 } 817 } 818 819 if (path.endsWith("/..")) { 822 tempString = path.substring(0, path.length()-3); 823 segIndex = tempString.lastIndexOf('/'); 824 if (segIndex != -1) { 825 path = path.substring(0, segIndex+1); 826 } 827 } 828 m_path = path; 829 } 830 831 839 private void initializeScheme(String p_uriSpec) 840 throws MalformedURIException { 841 int uriSpecLen = p_uriSpec.length(); 842 int index = 0; 843 String scheme = null; 844 char testChar = '\0'; 845 846 while (index < uriSpecLen) { 847 testChar = p_uriSpec.charAt(index); 848 if (testChar == ':' || testChar == '/' || 849 testChar == '?' || testChar == '#') { 850 break; 851 } 852 index++; 853 } 854 scheme = p_uriSpec.substring(0, index); 855 856 if (scheme.length() == 0) { 857 throw new MalformedURIException("No scheme found in URI."); 858 } 859 else { 860 setScheme(scheme); 861 } 862 } 863 864 873 private boolean initializeAuthority(String p_uriSpec) { 874 875 int index = 0; 876 int start = 0; 877 int end = p_uriSpec.length(); 878 879 char testChar = '\0'; 880 String userinfo = null; 881 882 if (p_uriSpec.indexOf('@', start) != -1) { 884 while (index < end) { 885 testChar = p_uriSpec.charAt(index); 886 if (testChar == '@') { 887 break; 888 } 889 index++; 890 } 891 userinfo = p_uriSpec.substring(start, index); 892 index++; 893 } 894 895 String host = null; 898 start = index; 899 boolean hasPort = false; 900 if (index < end) { 901 if (p_uriSpec.charAt(start) == '[') { 902 int bracketIndex = p_uriSpec.indexOf(']', start); 903 index = (bracketIndex != -1) ? bracketIndex : end; 904 if (index+1 < end && p_uriSpec.charAt(index+1) == ':') { 905 ++index; 906 hasPort = true; 907 } 908 else { 909 index = end; 910 } 911 } 912 else { 913 int colonIndex = p_uriSpec.lastIndexOf(':', end); 914 index = (colonIndex > start) ? colonIndex : end; 915 hasPort = (index != end); 916 } 917 } 918 host = p_uriSpec.substring(start, index); 919 int port = -1; 920 if (host.length() > 0) { 921 if (hasPort) { 923 index++; 924 start = index; 925 while (index < end) { 926 index++; 927 } 928 String portStr = p_uriSpec.substring(start, index); 929 if (portStr.length() > 0) { 930 938 try { 941 port = Integer.parseInt(portStr); 942 if (port == -1) --port; 943 } 944 catch (NumberFormatException nfe) { 945 port = -2; 946 } 947 } 948 } 949 } 950 951 if (isValidServerBasedAuthority(host, port, userinfo)) { 952 m_host = host; 953 m_port = port; 954 m_userinfo = userinfo; 955 return true; 956 } 957 else if (isValidRegistryBasedAuthority(p_uriSpec)) { 962 m_regAuthority = p_uriSpec; 963 return true; 964 } 965 return false; 966 } 967 968 979 private boolean isValidServerBasedAuthority(String host, int port, String userinfo) { 980 981 if (!isWellFormedAddress(host)) { 983 return false; 984 } 985 986 if (port < -1 || port > 65535) { 991 return false; 992 } 993 994 if (userinfo != null) { 996 int index = 0; 999 int end = userinfo.length(); 1000 char testChar = '\0'; 1001 while (index < end) { 1002 testChar = userinfo.charAt(index); 1003 if (testChar == '%') { 1004 if (index+2 >= end || 1005 !isHex(userinfo.charAt(index+1)) || 1006 !isHex(userinfo.charAt(index+2))) { 1007 return false; 1008 } 1009 index += 2; 1010 } 1011 else if (!isUserinfoCharacter(testChar)) { 1012 return false; 1013 } 1014 ++index; 1015 } 1016 } 1017 return true; 1018 } 1019 1020 1027 private boolean isValidRegistryBasedAuthority(String authority) { 1028 int index = 0; 1029 int end = authority.length(); 1030 char testChar; 1031 1032 while (index < end) { 1033 testChar = authority.charAt(index); 1034 1035 if (testChar == '%') { 1037 if (index+2 >= end || 1038 !isHex(authority.charAt(index+1)) || 1039 !isHex(authority.charAt(index+2))) { 1040 return false; 1041 } 1042 index += 2; 1043 } 1044 else if (!isPathCharacter(testChar)) { 1047 return false; 1048 } 1049 ++index; 1050 } 1051 return true; 1052 } 1053 1054 1062 private void initializePath(String p_uriSpec, int p_nStartIndex) 1063 throws MalformedURIException { 1064 if (p_uriSpec == null) { 1065 throw new MalformedURIException( 1066 "Cannot initialize path from null string!"); 1067 } 1068 1069 int index = p_nStartIndex; 1070 int start = p_nStartIndex; 1071 int end = p_uriSpec.length(); 1072 char testChar = '\0'; 1073 1074 if (start < end) { 1076 if (getScheme() == null || p_uriSpec.charAt(start) == '/') { 1078 1079 while (index < end) { 1083 testChar = p_uriSpec.charAt(index); 1084 1085 if (testChar == '%') { 1087 if (index+2 >= end || 1088 !isHex(p_uriSpec.charAt(index+1)) || 1089 !isHex(p_uriSpec.charAt(index+2))) { 1090 throw new MalformedURIException( 1091 "Path contains invalid escape sequence!"); 1092 } 1093 index += 2; 1094 } 1095 else if (!isPathCharacter(testChar)) { 1098 if (testChar == '?' || testChar == '#') { 1099 break; 1100 } 1101 throw new MalformedURIException( 1102 "Path contains invalid character: " + testChar); 1103 } 1104 ++index; 1105 } 1106 } 1107 else { 1108 1109 while (index < end) { 1112 testChar = p_uriSpec.charAt(index); 1113 1114 if (testChar == '?' || testChar == '#') { 1115 break; 1116 } 1117 1118 if (testChar == '%') { 1120 if (index+2 >= end || 1121 !isHex(p_uriSpec.charAt(index+1)) || 1122 !isHex(p_uriSpec.charAt(index+2))) { 1123 throw new MalformedURIException( 1124 "Opaque part contains invalid escape sequence!"); 1125 } 1126 index += 2; 1127 } 1128 else if (!isURICharacter(testChar)) { 1134 throw new MalformedURIException( 1135 "Opaque part contains invalid character: " + testChar); 1136 } 1137 ++index; 1138 } 1139 } 1140 } 1141 m_path = p_uriSpec.substring(start, index); 1142 1143 if (testChar == '?') { 1145 index++; 1146 start = index; 1147 while (index < end) { 1148 testChar = p_uriSpec.charAt(index); 1149 if (testChar == '#') { 1150 break; 1151 } 1152 if (testChar == '%') { 1153 if (index+2 >= end || 1154 !isHex(p_uriSpec.charAt(index+1)) || 1155 !isHex(p_uriSpec.charAt(index+2))) { 1156 throw new MalformedURIException( 1157 "Query string contains invalid escape sequence!"); 1158 } 1159 index += 2; 1160 } 1161 else if (!isURICharacter(testChar)) { 1162 throw new MalformedURIException( 1163 "Query string contains invalid character: " + testChar); 1164 } 1165 index++; 1166 } 1167 m_queryString = p_uriSpec.substring(start, index); 1168 } 1169 1170 if (testChar == '#') { 1172 index++; 1173 start = index; 1174 while (index < end) { 1175 testChar = p_uriSpec.charAt(index); 1176 1177 if (testChar == '%') { 1178 if (index+2 >= end || 1179 !isHex(p_uriSpec.charAt(index+1)) || 1180 !isHex(p_uriSpec.charAt(index+2))) { 1181 throw new MalformedURIException( 1182 "Fragment contains invalid escape sequence!"); 1183 } 1184 index += 2; 1185 } 1186 else if (!isURICharacter(testChar)) { 1187 throw new MalformedURIException( 1188 "Fragment contains invalid character: "+testChar); 1189 } 1190 index++; 1191 } 1192 m_fragment = p_uriSpec.substring(start, index); 1193 } 1194 } 1195 1196 1201 public String getScheme() { 1202 return m_scheme; 1203 } 1204 1205 1211 public String getSchemeSpecificPart() { 1212 StringBuffer schemespec = new StringBuffer (); 1213 1214 if (m_host != null || m_regAuthority != null) { 1215 schemespec.append("//"); 1216 1217 if (m_host != null) { 1219 1220 if (m_userinfo != null) { 1221 schemespec.append(m_userinfo); 1222 schemespec.append('@'); 1223 } 1224 1225 schemespec.append(m_host); 1226 1227 if (m_port != -1) { 1228 schemespec.append(':'); 1229 schemespec.append(m_port); 1230 } 1231 } 1232 else { 1234 schemespec.append(m_regAuthority); 1235 } 1236 } 1237 1238 if (m_path != null) { 1239 schemespec.append((m_path)); 1240 } 1241 1242 if (m_queryString != null) { 1243 schemespec.append('?'); 1244 schemespec.append(m_queryString); 1245 } 1246 1247 if (m_fragment != null) { 1248 schemespec.append('#'); 1249 schemespec.append(m_fragment); 1250 } 1251 1252 return schemespec.toString(); 1253 } 1254 1255 1260 public String getUserinfo() { 1261 return m_userinfo; 1262 } 1263 1264 1269 public String getHost() { 1270 return m_host; 1271 } 1272 1273 1278 public int getPort() { 1279 return m_port; 1280 } 1281 1282 1287 public String getRegBasedAuthority() { 1288 return m_regAuthority; 1289 } 1290 1291 1296 public String getAuthority() { 1297 StringBuffer authority = new StringBuffer (); 1298 if (m_host != null || m_regAuthority != null) { 1299 authority.append("//"); 1300 1301 if (m_host != null) { 1303 1304 if (m_userinfo != null) { 1305 authority.append(m_userinfo); 1306 authority.append('@'); 1307 } 1308 1309 authority.append(m_host); 1310 1311 if (m_port != -1) { 1312 authority.append(':'); 1313 authority.append(m_port); 1314 } 1315 } 1316 else { 1318 authority.append(m_regAuthority); 1319 } 1320 } 1321 return authority.toString(); 1322 } 1323 1324 1338 public String getPath(boolean p_includeQueryString, 1339 boolean p_includeFragment) { 1340 StringBuffer pathString = new StringBuffer (m_path); 1341 1342 if (p_includeQueryString && m_queryString != null) { 1343 pathString.append('?'); 1344 pathString.append(m_queryString); 1345 } 1346 1347 if (p_includeFragment && m_fragment != null) { 1348 pathString.append('#'); 1349 pathString.append(m_fragment); 1350 } 1351 return pathString.toString(); 1352 } 1353 1354 1360 public String getPath() { 1361 return m_path; 1362 } 1363 1364 1371 public String getQueryString() { 1372 return m_queryString; 1373 } 1374 1375 1382 public String getFragment() { 1383 return m_fragment; 1384 } 1385 1386 1395 public void setScheme(String p_scheme) throws MalformedURIException { 1396 if (p_scheme == null) { 1397 throw new MalformedURIException( 1398 "Cannot set scheme from null string!"); 1399 } 1400 if (!isConformantSchemeName(p_scheme)) { 1401 throw new MalformedURIException("The scheme is not conformant."); 1402 } 1403 1404 m_scheme = p_scheme.toLowerCase(); 1405 } 1406 1407 1416 public void setUserinfo(String p_userinfo) throws MalformedURIException { 1417 if (p_userinfo == null) { 1418 m_userinfo = null; 1419 return; 1420 } 1421 else { 1422 if (m_host == null) { 1423 throw new MalformedURIException( 1424 "Userinfo cannot be set when host is null!"); 1425 } 1426 1427 int index = 0; 1430 int end = p_userinfo.length(); 1431 char testChar = '\0'; 1432 while (index < end) { 1433 testChar = p_userinfo.charAt(index); 1434 if (testChar == '%') { 1435 if (index+2 >= end || 1436 !isHex(p_userinfo.charAt(index+1)) || 1437 !isHex(p_userinfo.charAt(index+2))) { 1438 throw new MalformedURIException( 1439 "Userinfo contains invalid escape sequence!"); 1440 } 1441 } 1442 else if (!isUserinfoCharacter(testChar)) { 1443 throw new MalformedURIException( 1444 "Userinfo contains invalid character:"+testChar); 1445 } 1446 index++; 1447 } 1448 } 1449 m_userinfo = p_userinfo; 1450 } 1451 1452 1464 public void setHost(String p_host) throws MalformedURIException { 1465 if (p_host == null || p_host.length() == 0) { 1466 if (p_host != null) { 1467 m_regAuthority = null; 1468 } 1469 m_host = p_host; 1470 m_userinfo = null; 1471 m_port = -1; 1472 return; 1473 } 1474 else if (!isWellFormedAddress(p_host)) { 1475 throw new MalformedURIException("Host is not a well formed address!"); 1476 } 1477 m_host = p_host; 1478 m_regAuthority = null; 1479 } 1480 1481 1492 public void setPort(int p_port) throws MalformedURIException { 1493 if (p_port >= 0 && p_port <= 65535) { 1494 if (m_host == null) { 1495 throw new MalformedURIException( 1496 "Port cannot be set when host is null!"); 1497 } 1498 } 1499 else if (p_port != -1) { 1500 throw new MalformedURIException("Invalid port number!"); 1501 } 1502 m_port = p_port; 1503 } 1504 1505 1516 public void setRegBasedAuthority(String authority) 1517 throws MalformedURIException { 1518 1519 if (authority == null) { 1520 m_regAuthority = null; 1521 return; 1522 } 1523 else if (authority.length() < 1 || 1526 !isValidRegistryBasedAuthority(authority) || 1527 authority.indexOf('/') != -1) { 1528 throw new MalformedURIException("Registry based authority is not well formed."); 1529 } 1530 m_regAuthority = authority; 1531 m_host = null; 1532 m_userinfo = null; 1533 m_port = -1; 1534 } 1535 1536 1550 public void setPath(String p_path) throws MalformedURIException { 1551 if (p_path == null) { 1552 m_path = null; 1553 m_queryString = null; 1554 m_fragment = null; 1555 } 1556 else { 1557 initializePath(p_path, 0); 1558 } 1559 } 1560 1561 1574 public void appendPath(String p_addToPath) 1575 throws MalformedURIException { 1576 if (p_addToPath == null || p_addToPath.trim().length() == 0) { 1577 return; 1578 } 1579 1580 if (!isURIString(p_addToPath)) { 1581 throw new MalformedURIException( 1582 "Path contains invalid character!"); 1583 } 1584 1585 if (m_path == null || m_path.trim().length() == 0) { 1586 if (p_addToPath.startsWith("/")) { 1587 m_path = p_addToPath; 1588 } 1589 else { 1590 m_path = "/" + p_addToPath; 1591 } 1592 } 1593 else if (m_path.endsWith("/")) { 1594 if (p_addToPath.startsWith("/")) { 1595 m_path = m_path.concat(p_addToPath.substring(1)); 1596 } 1597 else { 1598 m_path = m_path.concat(p_addToPath); 1599 } 1600 } 1601 else { 1602 if (p_addToPath.startsWith("/")) { 1603 m_path = m_path.concat(p_addToPath); 1604 } 1605 else { 1606 m_path = m_path.concat("/" + p_addToPath); 1607 } 1608 } 1609 } 1610 1611 1622 public void setQueryString(String p_queryString) throws MalformedURIException { 1623 if (p_queryString == null) { 1624 m_queryString = null; 1625 } 1626 else if (!isGenericURI()) { 1627 throw new MalformedURIException( 1628 "Query string can only be set for a generic URI!"); 1629 } 1630 else if (getPath() == null) { 1631 throw new MalformedURIException( 1632 "Query string cannot be set when path is null!"); 1633 } 1634 else if (!isURIString(p_queryString)) { 1635 throw new MalformedURIException( 1636 "Query string contains invalid character!"); 1637 } 1638 else { 1639 m_queryString = p_queryString; 1640 } 1641 } 1642 1643 1654 public void setFragment(String p_fragment) throws MalformedURIException { 1655 if (p_fragment == null) { 1656 m_fragment = null; 1657 } 1658 else if (!isGenericURI()) { 1659 throw new MalformedURIException( 1660 "Fragment can only be set for a generic URI!"); 1661 } 1662 else if (getPath() == null) { 1663 throw new MalformedURIException( 1664 "Fragment cannot be set when path is null!"); 1665 } 1666 else if (!isURIString(p_fragment)) { 1667 throw new MalformedURIException( 1668 "Fragment contains invalid character!"); 1669 } 1670 else { 1671 m_fragment = p_fragment; 1672 } 1673 } 1674 1675 1683 public boolean equals(Object p_test) { 1684 if (p_test instanceof URI) { 1685 URI testURI = (URI) p_test; 1686 if (((m_scheme == null && testURI.m_scheme == null) || 1687 (m_scheme != null && testURI.m_scheme != null && 1688 m_scheme.equals(testURI.m_scheme))) && 1689 ((m_userinfo == null && testURI.m_userinfo == null) || 1690 (m_userinfo != null && testURI.m_userinfo != null && 1691 m_userinfo.equals(testURI.m_userinfo))) && 1692 ((m_host == null && testURI.m_host == null) || 1693 (m_host != null && testURI.m_host != null && 1694 m_host.equals(testURI.m_host))) && 1695 m_port == testURI.m_port && 1696 ((m_path == null && testURI.m_path == null) || 1697 (m_path != null && testURI.m_path != null && 1698 m_path.equals(testURI.m_path))) && 1699 ((m_queryString == null && testURI.m_queryString == null) || 1700 (m_queryString != null && testURI.m_queryString != null && 1701 m_queryString.equals(testURI.m_queryString))) && 1702 ((m_fragment == null && testURI.m_fragment == null) || 1703 (m_fragment != null && testURI.m_fragment != null && 1704 m_fragment.equals(testURI.m_fragment)))) { 1705 return true; 1706 } 1707 } 1708 return false; 1709 } 1710 1711 1716 public String toString() { 1717 StringBuffer uriSpecString = new StringBuffer (); 1718 1719 if (m_scheme != null) { 1720 uriSpecString.append(m_scheme); 1721 uriSpecString.append(':'); 1722 } 1723 uriSpecString.append(getSchemeSpecificPart()); 1724 return uriSpecString.toString(); 1725 } 1726 1727 1734 public boolean isGenericURI() { 1735 return (m_host != null); 1738 } 1739 1740 1746 public boolean isAbsoluteURI() { 1747 return (m_scheme != null); 1749 } 1750 1751 1758 public static boolean isConformantSchemeName(String p_scheme) { 1759 if (p_scheme == null || p_scheme.trim().length() == 0) { 1760 return false; 1761 } 1762 1763 if (!isAlpha(p_scheme.charAt(0))) { 1764 return false; 1765 } 1766 1767 char testChar; 1768 int schemeLength = p_scheme.length(); 1769 for (int i = 1; i < schemeLength; ++i) { 1770 testChar = p_scheme.charAt(i); 1771 if (!isSchemeCharacter(testChar)) { 1772 return false; 1773 } 1774 } 1775 1776 return true; 1777 } 1778 1779 1791 public static boolean isWellFormedAddress(String address) { 1792 if (address == null) { 1793 return false; 1794 } 1795 1796 int addrLength = address.length(); 1797 if (addrLength == 0) { 1798 return false; 1799 } 1800 1801 if (address.startsWith("[")) { 1803 return isWellFormedIPv6Reference(address); 1804 } 1805 1806 if (address.startsWith(".") || 1808 address.startsWith("-") || 1809 address.endsWith("-")) { 1810 return false; 1811 } 1812 1813 int index = address.lastIndexOf('.'); 1817 if (address.endsWith(".")) { 1818 index = address.substring(0, index).lastIndexOf('.'); 1819 } 1820 1821 if (index+1 < addrLength && isDigit(address.charAt(index+1))) { 1822 return isWellFormedIPv4Address(address); 1823 } 1824 else { 1825 1829 if (addrLength > 255) { 1833 return false; 1834 } 1835 1836 char testChar; 1839 int labelCharCount = 0; 1840 1841 for (int i = 0; i < addrLength; i++) { 1842 testChar = address.charAt(i); 1843 if (testChar == '.') { 1844 if (!isAlphanum(address.charAt(i-1))) { 1845 return false; 1846 } 1847 if (i+1 < addrLength && !isAlphanum(address.charAt(i+1))) { 1848 return false; 1849 } 1850 labelCharCount = 0; 1851 } 1852 else if (!isAlphanum(testChar) && testChar != '-') { 1853 return false; 1854 } 1855 else if (++labelCharCount > 63) { 1857 return false; 1858 } 1859 } 1860 } 1861 return true; 1862 } 1863 1864 1875 public static boolean isWellFormedIPv4Address(String address) { 1876 1877 int addrLength = address.length(); 1878 char testChar; 1879 int numDots = 0; 1880 int numDigits = 0; 1881 1882 for (int i = 0; i < addrLength; i++) { 1893 testChar = address.charAt(i); 1894 if (testChar == '.') { 1895 if ((i > 0 && !isDigit(address.charAt(i-1))) || 1896 (i+1 < addrLength && !isDigit(address.charAt(i+1)))) { 1897 return false; 1898 } 1899 numDigits = 0; 1900 if (++numDots > 3) { 1901 return false; 1902 } 1903 } 1904 else if (!isDigit(testChar)) { 1905 return false; 1906 } 1907 else if (++numDigits > 3) { 1910 return false; 1911 } 1912 else if (numDigits == 3) { 1914 char first = address.charAt(i-2); 1915 char second = address.charAt(i-1); 1916 if (!(first < '2' || 1917 (first == '2' && 1918 (second < '5' || 1919 (second == '5' && testChar <= '5'))))) { 1920 return false; 1921 } 1922 } 1923 } 1924 return (numDots == 3); 1925 } 1926 1927 1942 public static boolean isWellFormedIPv6Reference(String address) { 1943 1944 int addrLength = address.length(); 1945 int index = 1; 1946 int end = addrLength-1; 1947 1948 if (!(addrLength > 2 && address.charAt(0) == '[' 1950 && address.charAt(end) == ']')) { 1951 return false; 1952 } 1953 1954 int [] counter = new int[1]; 1956 1957 index = scanHexSequence(address, index, end, counter); 1959 if (index == -1) { 1960 return false; 1961 } 1962 else if (index == end) { 1964 return (counter[0] == 8); 1965 } 1966 1967 if (index+1 < end && address.charAt(index) == ':') { 1968 if (address.charAt(index+1) == ':') { 1969 if (++counter[0] > 8) { 1971 return false; 1972 } 1973 index += 2; 1974 if (index == end) { 1976 return true; 1977 } 1978 } 1979 else { 1983 return (counter[0] == 6) && 1984 isWellFormedIPv4Address(address.substring(index+1, end)); 1985 } 1986 } 1987 else { 1988 return false; 1989 } 1990 1991 int prevCount = counter[0]; 1993 index = scanHexSequence(address, index, end, counter); 1994 1995 return (index == end) || 1999 (index != -1 && isWellFormedIPv4Address( 2000 address.substring((counter[0] > prevCount) ? index+1 : index, end))); 2001 } 2002 2003 2018 private static int scanHexSequence (String address, int index, int end, int [] counter) { 2019 2020 char testChar; 2021 int numDigits = 0; 2022 int start = index; 2023 2024 for (; index < end; ++index) { 2028 testChar = address.charAt(index); 2029 if (testChar == ':') { 2030 if (numDigits > 0 && ++counter[0] > 8) { 2032 return -1; 2033 } 2034 if (numDigits == 0 || ((index+1 < end) && address.charAt(index+1) == ':')) { 2036 return index; 2037 } 2038 numDigits = 0; 2039 } 2040 else if (!isHex(testChar)) { 2043 if (testChar == '.' && numDigits < 4 && numDigits > 0 && counter[0] <= 6) { 2044 int back = index - numDigits - 1; 2045 return (back >= start) ? back : (back+1); 2046 } 2047 return -1; 2048 } 2049 else if (++numDigits > 4) { 2051 return -1; 2052 } 2053 } 2054 return (numDigits > 0 && ++counter[0] <= 8) ? end : -1; 2055 } 2056 2057 2058 2063 private static boolean isDigit(char p_char) { 2064 return p_char >= '0' && p_char <= '9'; 2065 } 2066 2067 2073 private static boolean isHex(char p_char) { 2074 return (p_char <= 'f' && (fgLookupTable[p_char] & ASCII_HEX_CHARACTERS) != 0); 2075 } 2076 2077 2082 private static boolean isAlpha(char p_char) { 2083 return ((p_char >= 'a' && p_char <= 'z') || (p_char >= 'A' && p_char <= 'Z' )); 2084 } 2085 2086 2091 private static boolean isAlphanum(char p_char) { 2092 return (p_char <= 'z' && (fgLookupTable[p_char] & MASK_ALPHA_NUMERIC) != 0); 2093 } 2094 2095 2101 private static boolean isReservedCharacter(char p_char) { 2102 return (p_char <= ']' && (fgLookupTable[p_char] & RESERVED_CHARACTERS) != 0); 2103 } 2104 2105 2110 private static boolean isUnreservedCharacter(char p_char) { 2111 return (p_char <= '~' && (fgLookupTable[p_char] & MASK_UNRESERVED_MASK) != 0); 2112 } 2113 2114 2120 private static boolean isURICharacter (char p_char) { 2121 return (p_char <= '~' && (fgLookupTable[p_char] & MASK_URI_CHARACTER) != 0); 2122 } 2123 2124 2129 private static boolean isSchemeCharacter (char p_char) { 2130 return (p_char <= 'z' && (fgLookupTable[p_char] & MASK_SCHEME_CHARACTER) != 0); 2131 } 2132 2133 2138 private static boolean isUserinfoCharacter (char p_char) { 2139 return (p_char <= 'z' && (fgLookupTable[p_char] & MASK_USERINFO_CHARACTER) != 0); 2140 } 2141 2142 2147 private static boolean isPathCharacter (char p_char) { 2148 return (p_char <= '~' && (fgLookupTable[p_char] & MASK_PATH_CHARACTER) != 0); 2149 } 2150 2151 2152 2159 private static boolean isURIString(String p_uric) { 2160 if (p_uric == null) { 2161 return false; 2162 } 2163 int end = p_uric.length(); 2164 char testChar = '\0'; 2165 for (int i = 0; i < end; i++) { 2166 testChar = p_uric.charAt(i); 2167 if (testChar == '%') { 2168 if (i+2 >= end || 2169 !isHex(p_uric.charAt(i+1)) || 2170 !isHex(p_uric.charAt(i+2))) { 2171 return false; 2172 } 2173 else { 2174 i += 2; 2175 continue; 2176 } 2177 } 2178 if (isURICharacter(testChar)) { 2179 continue; 2180 } 2181 else { 2182 return false; 2183 } 2184 } 2185 return true; 2186 } 2187} 2188 | Popular Tags |