1 31 32 package org.apache.commons.httpclient; 33 34 import java.io.IOException ; 35 import java.io.ObjectInputStream ; 36 import java.io.ObjectOutputStream ; 37 import java.io.Serializable ; 38 import java.io.UnsupportedEncodingException ; 39 import java.util.Locale ; 40 import java.util.BitSet ; 41 import java.util.Hashtable ; 42 import java.net.URL ; 43 44 117 public class URI implements Cloneable , Comparable , Serializable { 118 119 120 122 123 protected URI() { 124 } 125 126 127 137 public URI(char[] escaped, String charset) 138 throws URIException, NullPointerException { 139 protocolCharset = charset; 140 parseUriReference(new String (escaped), true); 141 } 142 143 144 154 public URI(char[] escaped) 155 throws URIException, NullPointerException { 156 parseUriReference(new String (escaped), true); 157 } 158 159 160 169 public URI(String original, String charset) throws URIException { 170 protocolCharset = charset; 171 parseUriReference(original, false); 172 } 173 174 175 188 public URI(String original) throws URIException { 189 parseUriReference(original, false); 190 } 191 192 193 201 public URI(URL url) throws URIException { 202 this(url.toString()); 203 } 204 205 206 222 public URI(String scheme, String schemeSpecificPart, String fragment) 223 throws URIException { 224 225 if (scheme == null) { 227 throw new URIException(URIException.PARSING, "scheme required"); 228 } 229 char[] s = scheme.toLowerCase().toCharArray(); 230 if (validate(s, URI.scheme)) { 231 _scheme = s; } else { 233 throw new URIException(URIException.PARSING, "incorrect scheme"); 234 } 235 _opaque = encode(schemeSpecificPart, allowed_opaque_part, 236 getProtocolCharset()); 237 _is_opaque_part = true; 239 _fragment = fragment.toCharArray(); 240 241 setURI(); 242 } 243 244 245 265 public URI(String scheme, String authority, String path, String query, 266 String fragment) throws URIException { 267 268 StringBuffer buff = new StringBuffer (); 270 if (scheme != null) { 271 buff.append(scheme); 272 buff.append(':'); 273 } 274 if (authority != null) { 275 buff.append("//"); 276 buff.append(authority); 277 } 278 if (path != null) { if ((scheme != null || authority != null) 280 && !path.startsWith("/")) { 281 throw new URIException(URIException.PARSING, 282 "abs_path requested"); 283 } 284 buff.append(path); 285 } 286 if (query != null) { 287 buff.append('?'); 288 buff.append(query); 289 } 290 if (fragment != null) { 291 buff.append('#'); 292 buff.append(fragment); 293 } 294 parseUriReference(buff.toString(), false); 295 } 296 297 298 308 public URI(String scheme, String userinfo, String host, int port) 309 throws URIException { 310 311 this(scheme, userinfo, host, port, null, null, null); 312 } 313 314 315 326 public URI(String scheme, String userinfo, String host, int port, 327 String path) throws URIException { 328 329 this(scheme, userinfo, host, port, path, null, null); 330 } 331 332 333 345 public URI(String scheme, String userinfo, String host, int port, 346 String path, String query) throws URIException { 347 348 this(scheme, userinfo, host, port, path, query, null); 349 } 350 351 352 365 public URI(String scheme, String userinfo, String host, int port, 366 String path, String query, String fragment) throws URIException { 367 368 this(scheme, (host == null) ? null 369 : ((userinfo != null) ? userinfo + '@' : "") + host 370 + ((port != -1) ? ":" + port : ""), path, query, fragment); 371 } 372 373 374 384 public URI(String scheme, String host, String path, String fragment) 385 throws URIException { 386 387 this(scheme, host, path, null, fragment); 388 } 389 390 391 398 public URI(URI base, String relative) throws URIException { 399 this(base, new URI(relative)); 400 } 401 402 403 453 public URI(URI base, URI relative) throws URIException { 454 455 if (base._scheme == null) { 456 throw new URIException(URIException.PARSING, "base URI required"); 457 } 458 if (base._scheme != null) { 459 this._scheme = base._scheme; 460 this._authority = base._authority; 461 } 462 if (base._is_opaque_part || relative._is_opaque_part) { 463 this._scheme = base._scheme; 464 this._is_opaque_part = base._is_opaque_part 465 || relative._is_opaque_part; 466 this._opaque = relative._opaque; 467 this._fragment = relative._fragment; 468 this.setURI(); 469 return; 470 } 471 if (relative._scheme != null) { 472 this._scheme = relative._scheme; 473 this._is_net_path = relative._is_net_path; 474 this._authority = relative._authority; 475 if (relative._is_server) { 476 this._is_server = relative._is_server; 477 this._userinfo = relative._userinfo; 478 this._host = relative._host; 479 this._port = relative._port; 480 } else if (relative._is_reg_name) { 481 this._is_reg_name = relative._is_reg_name; 482 } 483 this._is_abs_path = relative._is_abs_path; 484 this._is_rel_path = relative._is_rel_path; 485 this._path = relative._path; 486 } else if (base._authority != null && relative._scheme == null) { 487 this._is_net_path = base._is_net_path; 488 this._authority = base._authority; 489 if (base._is_server) { 490 this._is_server = base._is_server; 491 this._userinfo = base._userinfo; 492 this._host = base._host; 493 this._port = base._port; 494 } else if (base._is_reg_name) { 495 this._is_reg_name = base._is_reg_name; 496 } 497 } 498 if (relative._authority != null) { 499 this._is_net_path = relative._is_net_path; 500 this._authority = relative._authority; 501 if (relative._is_server) { 502 this._is_server = relative._is_server; 503 this._userinfo = relative._userinfo; 504 this._host = relative._host; 505 this._port = relative._port; 506 } else if (relative._is_reg_name) { 507 this._is_reg_name = relative._is_reg_name; 508 } 509 this._is_abs_path = relative._is_abs_path; 510 this._is_rel_path = relative._is_rel_path; 511 this._path = relative._path; 512 } 513 if (relative._scheme == null && relative._authority == null) { 515 if ((relative._path == null || relative._path.length == 0) 516 && relative._query == null) { 517 this._path = base._path; 520 this._query = base._query; 521 } else { 522 this._path = resolvePath(base._path, relative._path); 523 } 524 } 525 if (relative._query != null) { 527 this._query = relative._query; 528 } 529 if (relative._fragment != null) { 531 this._fragment = relative._fragment; 532 } 533 this.setURI(); 534 parseUriReference(new String (_uri), true); 537 } 538 539 541 542 static final long serialVersionUID = 604752400577948726L; 543 544 545 548 protected int hash = 0; 549 550 551 556 protected char[] _uri = null; 557 558 559 562 protected String protocolCharset = null; 563 564 565 568 protected static String defaultProtocolCharset = "UTF-8"; 569 570 571 575 protected static String defaultDocumentCharset = null; 576 protected static String defaultDocumentCharsetByLocale = null; 577 protected static String defaultDocumentCharsetByPlatform = null; 578 static { 580 Locale locale = Locale.getDefault(); 581 if (locale != null) { 583 defaultDocumentCharsetByLocale = 584 LocaleToCharsetMap.getCharset(locale); 585 defaultDocumentCharset = defaultDocumentCharsetByLocale; 587 } 588 try { 590 defaultDocumentCharsetByPlatform = System.getProperty("file.encoding"); 591 } catch(SecurityException ignore) { 592 } 593 if (defaultDocumentCharset == null) { 594 defaultDocumentCharset = defaultDocumentCharsetByPlatform; 596 } 597 } 598 599 600 603 protected char[] _scheme = null; 604 605 606 609 protected char[] _opaque = null; 610 611 612 615 protected char[] _authority = null; 616 617 618 621 protected char[] _userinfo = null; 622 623 624 627 protected char[] _host = null; 628 629 630 633 protected int _port = -1; 634 635 636 639 protected char[] _path = null; 640 641 642 645 protected char[] _query = null; 646 647 648 651 protected char[] _fragment = null; 652 653 654 657 protected static char[] rootPath = { '/' }; 658 659 661 666 protected static final BitSet percent = new BitSet (256); 667 static { 669 percent.set('%'); 670 } 671 672 673 680 protected static final BitSet digit = new BitSet (256); 681 static { 683 for (int i = '0'; i <= '9'; i++) { 684 digit.set(i); 685 } 686 } 687 688 689 695 protected static final BitSet alpha = new BitSet (256); 696 static { 698 for (int i = 'a'; i <= 'z'; i++) { 699 alpha.set(i); 700 } 701 for (int i = 'A'; i <= 'Z'; i++) { 702 alpha.set(i); 703 } 704 } 705 706 707 713 protected static final BitSet alphanum = new BitSet (256); 714 static { 716 alphanum.or(alpha); 717 alphanum.or(digit); 718 } 719 720 721 728 protected static final BitSet hex = new BitSet (256); 729 static { 731 hex.or(digit); 732 for (int i = 'a'; i <= 'f'; i++) { 733 hex.set(i); 734 } 735 for (int i = 'A'; i <= 'F'; i++) { 736 hex.set(i); 737 } 738 } 739 740 741 747 protected static final BitSet escaped = new BitSet (256); 748 static { 750 escaped.or(percent); 751 escaped.or(hex); 752 } 753 754 755 762 protected static final BitSet mark = new BitSet (256); 763 static { 765 mark.set('-'); 766 mark.set('_'); 767 mark.set('.'); 768 mark.set('!'); 769 mark.set('~'); 770 mark.set('*'); 771 mark.set('\''); 772 mark.set('('); 773 mark.set(')'); 774 } 775 776 777 784 protected static final BitSet unreserved = new BitSet (256); 785 static { 787 unreserved.or(alphanum); 788 unreserved.or(mark); 789 } 790 791 792 799 protected static final BitSet reserved = new BitSet (256); 800 static { 802 reserved.set(';'); 803 reserved.set('/'); 804 reserved.set('?'); 805 reserved.set(':'); 806 reserved.set('@'); 807 reserved.set('&'); 808 reserved.set('='); 809 reserved.set('+'); 810 reserved.set('$'); 811 reserved.set(','); 812 } 813 814 815 821 protected static final BitSet uric = new BitSet (256); 822 static { 824 uric.or(reserved); 825 uric.or(unreserved); 826 uric.or(escaped); 827 } 828 829 830 836 protected static final BitSet fragment = uric; 837 838 839 845 protected static final BitSet query = uric; 846 847 848 855 protected static final BitSet pchar = new BitSet (256); 856 static { 858 pchar.or(unreserved); 859 pchar.or(escaped); 860 pchar.set(':'); 861 pchar.set('@'); 862 pchar.set('&'); 863 pchar.set('='); 864 pchar.set('+'); 865 pchar.set('$'); 866 pchar.set(','); 867 } 868 869 870 876 protected static final BitSet param = pchar; 877 878 879 885 protected static final BitSet segment = new BitSet (256); 886 static { 888 segment.or(pchar); 889 segment.set(';'); 890 segment.or(param); 891 } 892 893 894 900 protected static final BitSet path_segments = new BitSet (256); 901 static { 903 path_segments.set('/'); 904 path_segments.or(segment); 905 } 906 907 908 914 protected static final BitSet abs_path = new BitSet (256); 915 static { 917 abs_path.set('/'); 918 abs_path.or(path_segments); 919 } 920 921 922 929 protected static final BitSet uric_no_slash = new BitSet (256); 930 static { 932 uric_no_slash.or(unreserved); 933 uric_no_slash.or(escaped); 934 uric_no_slash.set(';'); 935 uric_no_slash.set('?'); 936 uric_no_slash.set(';'); 937 uric_no_slash.set('@'); 938 uric_no_slash.set('&'); 939 uric_no_slash.set('='); 940 uric_no_slash.set('+'); 941 uric_no_slash.set('$'); 942 uric_no_slash.set(','); 943 } 944 945 946 952 protected static final BitSet opaque_part = new BitSet (256); 953 static { 955 opaque_part.or(uric_no_slash); 957 opaque_part.or(uric); 958 } 959 960 961 967 protected static final BitSet path = new BitSet (256); 968 static { 970 path.or(abs_path); 971 path.or(opaque_part); 972 } 973 974 975 978 protected static final BitSet port = digit; 979 980 981 987 protected static final BitSet IPv4address = new BitSet (256); 988 static { 990 IPv4address.or(digit); 991 IPv4address.set('.'); 992 } 993 994 995 1001 protected static final BitSet IPv6address = new BitSet (256); 1002 static { 1004 IPv6address.or(hex); IPv6address.set(':'); 1006 IPv6address.or(IPv4address); 1007 } 1008 1009 1010 1016 protected static final BitSet IPv6reference = new BitSet (256); 1017 static { 1019 IPv6reference.set('['); 1020 IPv6reference.or(IPv6address); 1021 IPv6reference.set(']'); 1022 } 1023 1024 1025 1031 protected static final BitSet toplabel = new BitSet (256); 1032 static { 1034 toplabel.or(alphanum); 1035 toplabel.set('-'); 1036 } 1037 1038 1039 1045 protected static final BitSet domainlabel = toplabel; 1046 1047 1048 1054 protected static final BitSet hostname = new BitSet (256); 1055 static { 1057 hostname.or(toplabel); 1058 hostname.set('.'); 1060 } 1061 1062 1063 1069 protected static final BitSet host = new BitSet (256); 1070 static { 1072 host.or(hostname); 1073 host.or(IPv6reference); } 1076 1077 1078 1084 protected static final BitSet hostport = new BitSet (256); 1085 static { 1087 hostport.or(host); 1088 hostport.set(':'); 1089 hostport.or(port); 1090 } 1091 1092 1093 1100 protected static final BitSet userinfo = new BitSet (256); 1101 static { 1103 userinfo.or(unreserved); 1104 userinfo.or(escaped); 1105 userinfo.set(';'); 1106 userinfo.set(':'); 1107 userinfo.set('&'); 1108 userinfo.set('='); 1109 userinfo.set('+'); 1110 userinfo.set('$'); 1111 userinfo.set(','); 1112 } 1113 1114 1115 1118 public static final BitSet within_userinfo = new BitSet (256); 1119 static { 1121 within_userinfo.or(userinfo); 1122 within_userinfo.clear(';'); within_userinfo.clear(':'); 1124 within_userinfo.clear('@'); 1125 within_userinfo.clear('?'); 1126 within_userinfo.clear('/'); 1127 } 1128 1129 1130 1136 protected static final BitSet server = new BitSet (256); 1137 static { 1139 server.or(userinfo); 1140 server.set('@'); 1141 server.or(hostport); 1142 } 1143 1144 1145 1152 protected static final BitSet reg_name = new BitSet (256); 1153 static { 1155 reg_name.or(unreserved); 1156 reg_name.or(escaped); 1157 reg_name.set('$'); 1158 reg_name.set(','); 1159 reg_name.set(';'); 1160 reg_name.set(':'); 1161 reg_name.set('@'); 1162 reg_name.set('&'); 1163 reg_name.set('='); 1164 reg_name.set('+'); 1165 } 1166 1167 1168 1174 protected static final BitSet authority = new BitSet (256); 1175 static { 1177 authority.or(server); 1178 authority.or(reg_name); 1179 } 1180 1181 1182 1188 protected static final BitSet scheme = new BitSet (256); 1189 static { 1191 scheme.or(alpha); 1192 scheme.or(digit); 1193 scheme.set('+'); 1194 scheme.set('-'); 1195 scheme.set('.'); 1196 } 1197 1198 1199 1206 protected static final BitSet rel_segment = new BitSet (256); 1207 static { 1209 rel_segment.or(unreserved); 1210 rel_segment.or(escaped); 1211 rel_segment.set(';'); 1212 rel_segment.set('@'); 1213 rel_segment.set('&'); 1214 rel_segment.set('='); 1215 rel_segment.set('+'); 1216 rel_segment.set('$'); 1217 rel_segment.set(','); 1218 } 1219 1220 1221 1227 protected static final BitSet rel_path = new BitSet (256); 1228 static { 1230 rel_path.or(rel_segment); 1231 rel_path.or(abs_path); 1232 } 1233 1234 1235 1241 protected static final BitSet net_path = new BitSet (256); 1242 static { 1244 net_path.set('/'); 1245 net_path.or(authority); 1246 net_path.or(abs_path); 1247 } 1248 1249 1250 1256 protected static final BitSet hier_part = new BitSet (256); 1257 static { 1259 hier_part.or(net_path); 1260 hier_part.or(abs_path); 1261 hier_part.or(query); 1263 } 1264 1265 1266 1272 protected static final BitSet relativeURI = new BitSet (256); 1273 static { 1275 relativeURI.or(net_path); 1276 relativeURI.or(abs_path); 1277 relativeURI.or(rel_path); 1278 relativeURI.or(query); 1280 } 1281 1282 1283 1289 protected static final BitSet absoluteURI = new BitSet (256); 1290 static { 1292 absoluteURI.or(scheme); 1293 absoluteURI.set(':'); 1294 absoluteURI.or(hier_part); 1295 absoluteURI.or(opaque_part); 1296 } 1297 1298 1299 1305 protected static final BitSet URI_reference = new BitSet (256); 1306 static { 1308 URI_reference.or(absoluteURI); 1309 URI_reference.or(relativeURI); 1310 URI_reference.set('#'); 1311 URI_reference.or(fragment); 1312 } 1313 1314 1317 1320 public static final BitSet control = new BitSet (256); 1321 static { 1323 for (int i = 0; i <= 0x1F; i++) { 1324 control.set(i); 1325 } 1326 control.set(0x7F); 1327 } 1328 1329 1332 public static final BitSet space = new BitSet (256); 1333 static { 1335 space.set(0x20); 1336 } 1337 1338 1339 1342 public static final BitSet delims = new BitSet (256); 1343 static { 1345 delims.set('<'); 1346 delims.set('>'); 1347 delims.set('#'); 1348 delims.set('%'); 1349 delims.set('"'); 1350 } 1351 1352 1353 1356 public static final BitSet unwise = new BitSet (256); 1357 static { 1359 unwise.set('{'); 1360 unwise.set('}'); 1361 unwise.set('|'); 1362 unwise.set('\\'); 1363 unwise.set('^'); 1364 unwise.set('['); 1365 unwise.set(']'); 1366 unwise.set('`'); 1367 } 1368 1369 1370 1373 public static final BitSet disallowed_rel_path = new BitSet (256); 1374 static { 1376 disallowed_rel_path.or(uric); 1377 disallowed_rel_path.andNot(rel_path); 1378 } 1379 1380 1381 1384 public static final BitSet disallowed_opaque_part = new BitSet (256); 1385 static { 1387 disallowed_opaque_part.or(uric); 1388 disallowed_opaque_part.andNot(opaque_part); 1389 } 1390 1391 1393 1396 public static final BitSet allowed_authority = new BitSet (256); 1397 static { 1399 allowed_authority.or(authority); 1400 allowed_authority.clear('%'); 1401 } 1402 1403 1404 1407 public static final BitSet allowed_opaque_part = new BitSet (256); 1408 static { 1410 allowed_opaque_part.or(opaque_part); 1411 allowed_opaque_part.clear('%'); 1412 } 1413 1414 1415 1418 public static final BitSet allowed_reg_name = new BitSet (256); 1419 static { 1421 allowed_reg_name.or(reg_name); 1422 allowed_reg_name.clear('%'); 1424 } 1425 1426 1427 1430 public static final BitSet allowed_userinfo = new BitSet (256); 1431 static { 1433 allowed_userinfo.or(userinfo); 1434 allowed_userinfo.clear('%'); 1436 } 1437 1438 1439 1442 public static final BitSet allowed_within_userinfo = new BitSet (256); 1443 static { 1445 allowed_within_userinfo.or(within_userinfo); 1446 allowed_within_userinfo.clear('%'); 1447 } 1448 1449 1450 1454 public static final BitSet allowed_IPv6reference = new BitSet (256); 1455 static { 1457 allowed_IPv6reference.or(IPv6reference); 1458 allowed_IPv6reference.clear('['); 1460 allowed_IPv6reference.clear(']'); 1461 } 1462 1463 1464 1468 public static final BitSet allowed_host = new BitSet (256); 1469 static { 1471 allowed_host.or(hostname); 1472 allowed_host.or(allowed_IPv6reference); 1473 } 1474 1475 1476 1479 public static final BitSet allowed_within_authority = new BitSet (256); 1480 static { 1482 allowed_within_authority.or(server); 1483 allowed_within_authority.or(reg_name); 1484 allowed_within_authority.clear(';'); 1485 allowed_within_authority.clear(':'); 1486 allowed_within_authority.clear('@'); 1487 allowed_within_authority.clear('?'); 1488 allowed_within_authority.clear('/'); 1489 } 1490 1491 1492 1495 public static final BitSet allowed_abs_path = new BitSet (256); 1496 static { 1498 allowed_abs_path.or(abs_path); 1499 allowed_abs_path.andNot(percent); 1501 } 1502 1503 1504 1507 public static final BitSet allowed_rel_path = new BitSet (256); 1508 static { 1510 allowed_rel_path.or(rel_path); 1511 allowed_rel_path.clear('%'); 1512 } 1513 1514 1515 1518 public static final BitSet allowed_within_path = new BitSet (256); 1519 static { 1521 allowed_within_path.or(abs_path); 1522 allowed_within_path.clear('/'); 1523 allowed_within_path.clear(';'); 1524 allowed_within_path.clear('='); 1525 allowed_within_path.clear('?'); 1526 } 1527 1528 1529 1532 public static final BitSet allowed_query = new BitSet (256); 1533 static { 1535 allowed_query.or(uric); 1536 allowed_query.clear('%'); 1537 } 1538 1539 1540 1543 public static final BitSet allowed_within_query = new BitSet (256); 1544 static { 1546 allowed_within_query.or(allowed_query); 1547 allowed_within_query.andNot(reserved); } 1549 1550 1551 1554 public static final BitSet allowed_fragment = new BitSet (256); 1555 static { 1557 allowed_fragment.or(uric); 1558 allowed_fragment.clear('%'); 1559 } 1560 1561 1563 1565 protected boolean _is_hier_part; 1568 protected boolean _is_opaque_part; 1569 protected boolean _is_net_path; 1572 protected boolean _is_abs_path; 1573 protected boolean _is_rel_path; 1574 protected boolean _is_reg_name; 1577 protected boolean _is_server; protected boolean _is_hostname; 1581 protected boolean _is_IPv4address; 1582 protected boolean _is_IPv6reference; 1583 1584 1586 1621 protected static char[] encode(String original, BitSet allowed, 1622 String charset) throws URIException { 1623 1624 if (original == null) { 1626 throw new URIException(URIException.PARSING, "null"); 1627 } 1628 if (allowed == null) { 1630 throw new URIException(URIException.PARSING, 1631 "null allowed characters"); 1632 } 1633 byte[] octets; 1634 try { 1635 octets = original.getBytes(charset); 1636 } catch (UnsupportedEncodingException error) { 1637 throw new URIException(URIException.UNSUPPORTED_ENCODING, charset); 1638 } 1639 StringBuffer buf = new StringBuffer (octets.length); 1640 for (int i = 0; i < octets.length; i++) { 1641 char c = (char) octets[i]; 1642 if (allowed.get(c)) { 1643 buf.append(c); 1644 } else { 1645 buf.append('%'); 1646 byte b = octets[i]; char hexadecimal = Character.forDigit((b >> 4) & 0xF, 16); 1648 buf.append(Character.toUpperCase(hexadecimal)); hexadecimal = Character.forDigit(b & 0xF, 16); 1650 buf.append(Character.toUpperCase(hexadecimal)); } 1652 } 1653 1654 return buf.toString().toCharArray(); 1655 } 1656 1657 1658 1688 protected static String decode(char[] component, String charset) 1689 throws URIException { 1690 1691 if (component == null) { 1693 return null; 1694 } 1695 1696 byte[] octets; 1697 try { 1698 octets = new String (component).getBytes(charset); 1699 } catch (UnsupportedEncodingException error) { 1700 throw new URIException(URIException.UNSUPPORTED_ENCODING, 1701 "not supported " + charset + " encoding"); 1702 } 1703 int length = octets.length; 1704 int oi = 0; for (int ii = 0; ii < length; oi++) { 1706 byte aByte = (byte) octets[ii++]; 1707 if (aByte == '%' && ii + 2 <= length) { 1708 byte high = (byte) Character.digit((char) octets[ii++], 16); 1709 byte low = (byte) Character.digit((char) octets[ii++], 16); 1710 if (high == -1 || low == -1) { 1711 throw new URIException(URIException.ESCAPING, 1712 "incomplete trailing escape pattern"); 1713 1714 } 1715 aByte = (byte) ((high << 4) + low); 1716 } 1717 octets[oi] = (byte) aByte; 1718 } 1719 1720 String result; 1721 try { 1722 result = new String (octets, 0, oi, charset); 1723 } catch (UnsupportedEncodingException error) { 1724 throw new URIException(URIException.UNSUPPORTED_ENCODING, 1725 "not supported " + charset + " encoding"); 1726 } 1727 1728 return result; 1729 } 1730 1731 1732 1740 protected boolean prevalidate(String component, BitSet disallowed) { 1741 if (component == null) { 1743 return false; } 1745 char[] target = component.toCharArray(); 1746 for (int i = 0; i < target.length; i++) { 1747 if (disallowed.get(target[i])) { 1748 return false; 1749 } 1750 } 1751 return true; 1752 } 1753 1754 1755 1764 protected boolean validate(char[] component, BitSet generous) { 1765 return validate(component, 0, -1, generous); 1767 } 1768 1769 1770 1785 protected boolean validate(char[] component, int soffset, int eoffset, 1786 BitSet generous) { 1787 if (eoffset == -1) { 1789 eoffset = component.length - 1; 1790 } 1791 for (int i = soffset; i <= eoffset; i++) { 1792 if (!generous.get(component[i])) { 1793 return false; 1794 } 1795 } 1796 return true; 1797 } 1798 1799 1800 1830 protected void parseUriReference(String original, boolean escaped) 1831 throws URIException { 1832 1833 if (original == null) { 1835 throw new URIException("URI-Reference required"); 1836 } 1837 1838 1841 String tmp = original.trim(); 1842 1843 1847 int length = tmp.length(); 1848 1849 1852 if (length > 0) { 1853 char[] firstDelimiter = { tmp.charAt(0) }; 1854 if (validate(firstDelimiter, delims)) { 1855 if (length >= 2) { 1856 char[] lastDelimiter = { tmp.charAt(length - 1) }; 1857 if (validate(lastDelimiter, delims)) { 1858 tmp = tmp.substring(1, length - 1); 1859 length = length - 2; 1860 } 1861 } 1862 } 1863 } 1864 1865 1868 int from = 0; 1869 1870 1873 boolean isStartedFromPath = false; 1874 int atColon = tmp.indexOf(':'); 1875 int atSlash = tmp.indexOf('/'); 1876 if (atColon < 0 || (atSlash >= 0 && atSlash < atColon)) { 1877 isStartedFromPath = true; 1878 } 1879 1880 1886 int at = indexFirstOf(tmp, isStartedFromPath ? "/?#" : ":/?#", from); 1887 if (at == -1) { 1888 at = 0; 1889 } 1890 1891 1899 if (at < length && tmp.charAt(at) == ':') { 1900 char[] target = tmp.substring(0, at).toLowerCase().toCharArray(); 1901 if (validate(target, scheme)) { 1902 _scheme = target; 1903 } else { 1904 throw new URIException("incorrect scheme"); 1905 } 1906 from = ++at; 1907 } 1908 1909 1917 _is_net_path = _is_abs_path = _is_rel_path = _is_hier_part = false; 1919 if (0 <= at && at < length && tmp.charAt(at) == '/') { 1920 _is_hier_part = true; 1922 if (at + 2 < length && tmp.charAt(at + 1) == '/') { 1923 int next = indexFirstOf(tmp, "/?#", at + 2); 1925 if (next == -1) { 1926 next = (tmp.substring(at + 2).length() == 0) ? at + 2 1927 : tmp.length(); 1928 } 1929 parseAuthority(tmp.substring(at + 2, next), escaped); 1930 from = at = next; 1931 _is_net_path = true; 1933 } 1934 if (from == at) { 1935 _is_abs_path = true; 1937 } 1938 } 1939 1940 1948 if (from < length) { 1949 int next = indexFirstOf(tmp, "?#", from); 1951 if (next == -1) { 1952 next = tmp.length(); 1953 } 1954 if (!_is_abs_path) { 1955 if (!escaped 1956 && prevalidate(tmp.substring(from, next), disallowed_rel_path) 1957 || escaped 1958 && validate(tmp.substring(from, next).toCharArray(), rel_path)) { 1959 _is_rel_path = true; 1961 } else if (!escaped 1962 && prevalidate(tmp.substring(from, next), disallowed_opaque_part) 1963 || escaped 1964 && validate(tmp.substring(from, next).toCharArray(), opaque_part)) { 1965 _is_opaque_part = true; 1967 } else { 1968 _path = null; 1970 } 1971 } 1972 if (escaped) { 1973 setRawPath(tmp.substring(from, next).toCharArray()); 1974 } else { 1975 setPath(tmp.substring(from, next)); 1976 } 1977 at = next; 1978 } 1979 1980 String charset = getProtocolCharset(); 1982 1983 1991 if (0 <= at && at + 1 < length && tmp.charAt(at) == '?') { 1992 int next = tmp.indexOf('#', at + 1); 1993 if (next == -1) { 1994 next = tmp.length(); 1995 } 1996 _query = (escaped) ? tmp.substring(at + 1, next).toCharArray() 1997 : encode(tmp.substring(at + 1, next), allowed_query, charset); 1998 at = next; 1999 } 2000 2001 2009 if (0 <= at && at + 1 <= length && tmp.charAt(at) == '#') { 2010 if (at + 1 == length) { _fragment = "".toCharArray(); 2012 } else { 2013 _fragment = (escaped) ? tmp.substring(at + 1).toCharArray() 2014 : encode(tmp.substring(at + 1), allowed_fragment, charset); 2015 } 2016 } 2017 2018 setURI(); 2020 } 2021 2022 2023 2031 protected int indexFirstOf(String s, String delims) { 2032 return indexFirstOf(s, delims, -1); 2033 } 2034 2035 2036 2045 protected int indexFirstOf(String s, String delims, int offset) { 2046 if (s == null || s.length() == 0) { 2047 return -1; 2048 } 2049 if (delims == null || delims.length() == 0) { 2050 return -1; 2051 } 2052 if (offset < 0) { 2054 offset = 0; 2055 } else if (offset > s.length()) { 2056 return -1; 2057 } 2058 int min = s.length(); 2060 char[] delim = delims.toCharArray(); 2061 for (int i = 0; i < delim.length; i++) { 2062 int at = s.indexOf(delim[i], offset); 2063 if (at >= 0 && at < min) { 2064 min = at; 2065 } 2066 } 2067 return (min == s.length()) ? -1 : min; 2068 } 2069 2070 2071 2079 protected int indexFirstOf(char[] s, char delim) { 2080 return indexFirstOf(s, delim, 0); 2081 } 2082 2083 2084 2093 protected int indexFirstOf(char[] s, char delim, int offset) { 2094 if (s == null || s.length == 0) { 2095 return -1; 2096 } 2097 if (offset < 0) { 2099 offset = 0; 2100 } else if (offset > s.length) { 2101 return -1; 2102 } 2103 for (int i = offset; i < s.length; i++) { 2104 if (s[i] == delim) { 2105 return i; 2106 } 2107 } 2108 return -1; 2109 } 2110 2111 2112 2119 protected void parseAuthority(String original, boolean escaped) 2120 throws URIException { 2121 2122 _is_reg_name = _is_server = 2124 _is_hostname = _is_IPv4address = _is_IPv6reference = false; 2125 2126 String charset = getProtocolCharset(); 2128 2129 boolean hasPort = true; 2130 int from = 0; 2131 int next = original.indexOf('@'); 2132 if (next != -1) { _userinfo = (escaped) ? original.substring(0, next).toCharArray() 2135 : encode(original.substring(0, next), allowed_userinfo, 2136 charset); 2137 from = next + 1; 2138 } 2139 next = original.indexOf('[', from); 2140 if (next >= from) { 2141 next = original.indexOf(']', from); 2142 if (next == -1) { 2143 throw new URIException(URIException.PARSING, "IPv6reference"); 2144 } else { 2145 next++; 2146 } 2147 _host = (escaped) ? original.substring(from, next).toCharArray() 2149 : encode(original.substring(from, next), allowed_IPv6reference, 2150 charset); 2151 _is_IPv6reference = true; 2153 } else { next = original.indexOf(':', from); 2155 if (next == -1) { 2156 next = original.length(); 2157 hasPort = false; 2158 } 2159 _host = original.substring(from, next).toCharArray(); 2161 if (validate(_host, IPv4address)) { 2162 _is_IPv4address = true; 2164 } else if (validate(_host, hostname)) { 2165 _is_hostname = true; 2167 } else { 2168 _is_reg_name = true; 2170 } 2171 } 2172 if (_is_reg_name) { 2173 _is_server = _is_hostname = _is_IPv4address = 2175 _is_IPv6reference = false; 2176 _authority = (escaped) ? original.toString().toCharArray() 2178 : encode(original.toString(), allowed_reg_name, charset); 2179 } else { 2180 if (original.length() - 1 > next && hasPort 2181 && original.charAt(next) == ':') { from = next + 1; 2183 try { 2184 _port = Integer.parseInt(original.substring(from)); 2185 } catch (NumberFormatException error) { 2186 throw new URIException(URIException.PARSING, 2187 "invalid port number"); 2188 } 2189 } 2190 StringBuffer buf = new StringBuffer (); 2192 if (_userinfo != null) { buf.append(_userinfo); 2194 buf.append('@'); 2195 } 2196 if (_host != null) { 2197 buf.append(_host); 2198 if (_port != -1) { 2199 buf.append(':'); 2200 buf.append(_port); 2201 } 2202 } 2203 _authority = buf.toString().toCharArray(); 2204 _is_server = true; 2206 } 2207 } 2208 2209 2210 2215 protected void setURI() { 2216 StringBuffer buf = new StringBuffer (); 2218 if (_scheme != null) { 2220 buf.append(_scheme); 2221 buf.append(':'); 2222 } 2223 if (_is_net_path) { 2224 buf.append("//"); 2225 if (_authority != null) { if (_userinfo != null) { if (_host != null) { 2228 buf.append(_host); 2229 if (_port != -1) { 2230 buf.append(':'); 2231 buf.append(_port); 2232 } 2233 } 2234 } else { 2235 buf.append(_authority); 2236 } 2237 } 2238 } 2239 if (_opaque != null && _is_opaque_part) { 2240 buf.append(_opaque); 2241 } else if (_path != null) { 2242 if (_path.length != 0) { 2244 buf.append(_path); 2245 } 2246 } 2247 if (_query != null) { buf.append('?'); 2249 buf.append(_query); 2250 } 2251 _uri = buf.toString().toCharArray(); 2253 hash = 0; 2254 } 2255 2256 2258 2259 2264 public boolean isAbsoluteURI() { 2265 return (_scheme != null); 2266 } 2267 2268 2269 2274 public boolean isRelativeURI() { 2275 return (_scheme == null); 2276 } 2277 2278 2279 2284 public boolean isHierPart() { 2285 return _is_hier_part; 2286 } 2287 2288 2289 2294 public boolean isOpaquePart() { 2295 return _is_opaque_part; 2296 } 2297 2298 2299 2306 public boolean isNetPath() { 2307 return _is_net_path || (_authority != null); 2308 } 2309 2310 2311 2316 public boolean isAbsPath() { 2317 return _is_abs_path; 2318 } 2319 2320 2321 2326 public boolean isRelPath() { 2327 return _is_rel_path; 2328 } 2329 2330 2331 2338 public boolean hasAuthority() { 2339 return (_authority != null) || _is_net_path; 2340 } 2341 2342 2347 public boolean isRegName() { 2348 return _is_reg_name; 2349 } 2350 2351 2352 2357 public boolean isServer() { 2358 return _is_server; 2359 } 2360 2361 2362 2367 public boolean hasUserinfo() { 2368 return (_userinfo != null); 2369 } 2370 2371 2372 2377 public boolean isHostname() { 2378 return _is_hostname; 2379 } 2380 2381 2382 2387 public boolean isIPv4address() { 2388 return _is_IPv4address; 2389 } 2390 2391 2392 2397 public boolean isIPv6reference() { 2398 return _is_IPv6reference; 2399 } 2400 2401 2402 2407 public boolean hasQuery() { 2408 return (_query != null); 2409 } 2410 2411 2412 2417 public boolean hasFragment() { 2418 return (_fragment != null); 2419 } 2420 2421 2422 2424 2425 2467 public static void setDefaultProtocolCharset(String charset) 2468 throws DefaultCharsetChanged { 2469 2470 defaultProtocolCharset = charset; 2471 throw new DefaultCharsetChanged(DefaultCharsetChanged.PROTOCOL_CHARSET, 2472 "the default protocol charset changed"); 2473 } 2474 2475 2476 2490 public static String getDefaultProtocolCharset() { 2491 return defaultProtocolCharset; 2492 } 2493 2494 2495 2503 public String getProtocolCharset() { 2504 return (protocolCharset != null) 2505 ? protocolCharset 2506 : defaultProtocolCharset; 2507 } 2508 2509 2510 2547 public static void setDefaultDocumentCharset(String charset) 2548 throws DefaultCharsetChanged { 2549 2550 defaultDocumentCharset = charset; 2551 throw new DefaultCharsetChanged(DefaultCharsetChanged.DOCUMENT_CHARSET, 2552 "the default document charset changed"); 2553 } 2554 2555 2556 2561 public static String getDefaultDocumentCharset() { 2562 return defaultDocumentCharset; 2563 } 2564 2565 2566 2571 public static String getDefaultDocumentCharsetByLocale() { 2572 return defaultDocumentCharsetByLocale; 2573 } 2574 2575 2576 2581 public static String getDefaultDocumentCharsetByPlatform() { 2582 return defaultDocumentCharsetByPlatform; 2583 } 2584 2585 2587 2592 public char[] getRawScheme() { 2593 return _scheme; 2594 } 2595 2596 2597 2603 public String getScheme() { 2604 return (_scheme == null) ? null : new String (_scheme); 2605 } 2606 2607 2609 2621 public void setRawAuthority(char[] escapedAuthority) 2622 throws URIException, NullPointerException { 2623 2624 parseAuthority(new String (escapedAuthority), true); 2625 setURI(); 2626 } 2627 2628 2629 2638 public void setEscapedAuthority(String escapedAuthority) 2639 throws URIException { 2640 2641 parseAuthority(escapedAuthority, true); 2642 setURI(); 2643 } 2644 2645 2646 2651 public char[] getRawAuthority() { 2652 return _authority; 2653 } 2654 2655 2656 2661 public String getEscapedAuthority() { 2662 return (_authority == null) ? null : new String (_authority); 2663 } 2664 2665 2666 2672 public String getAuthority() throws URIException { 2673 return (_authority == null) ? null : decode(_authority, 2674 getProtocolCharset()); 2675 } 2676 2677 2679 2685 public char[] getRawUserinfo() { 2686 return _userinfo; 2687 } 2688 2689 2690 2696 public String getEscapedUserinfo() { 2697 return (_userinfo == null) ? null : new String (_userinfo); 2698 } 2699 2700 2701 2708 public String getUserinfo() throws URIException { 2709 return (_userinfo == null) ? null : decode(_userinfo, 2710 getProtocolCharset()); 2711 } 2712 2713 2715 2724 public char[] getRawHost() { 2725 return _host; 2726 } 2727 2728 2729 2739 public String getHost() throws URIException { 2740 return decode(_host, getProtocolCharset()); 2741 } 2742 2743 2745 2754 public int getPort() { 2755 return _port; 2756 } 2757 2758 2760 2767 public void setRawPath(char[] escapedPath) throws URIException { 2768 if (escapedPath == null || escapedPath.length == 0) { 2769 _path = _opaque = escapedPath; 2770 setURI(); 2771 return; 2772 } 2773 escapedPath = removeFragmentIdentifier(escapedPath); 2775 if (_is_net_path || _is_abs_path) { 2776 if (escapedPath[0] != '/') { 2777 throw new URIException(URIException.PARSING, 2778 "not absolute path"); 2779 } 2780 if (!validate(escapedPath, abs_path)) { 2781 throw new URIException(URIException.ESCAPING, 2782 "escaped absolute path not valid"); 2783 } 2784 _path = escapedPath; 2785 } else if (_is_rel_path) { 2786 int at = indexFirstOf(escapedPath, '/'); 2787 if (at == 0) { 2788 throw new URIException(URIException.PARSING, "incorrect path"); 2789 } 2790 if (at > 0 && !validate(escapedPath, 0, at - 1, rel_segment) 2791 && !validate(escapedPath, at, -1, abs_path) 2792 || at < 0 && !validate(escapedPath, 0, -1, rel_segment)) { 2793 2794 throw new URIException(URIException.ESCAPING, 2795 "escaped relative path not valid"); 2796 } 2797 _path = escapedPath; 2798 } else if (_is_opaque_part) { 2799 if (!uric_no_slash.get(escapedPath[0]) 2800 && !validate(escapedPath, 1, -1, uric)) { 2801 throw new URIException(URIException.ESCAPING, 2802 "escaped opaque part not valid"); 2803 } 2804 _opaque = escapedPath; 2805 } else { 2806 throw new URIException(URIException.PARSING, "incorrect path"); 2807 } 2808 setURI(); 2809 } 2810 2811 2812 2819 public void setEscapedPath(String escapedPath) throws URIException { 2820 if (escapedPath == null) { 2821 _path = _opaque = null; 2822 setURI(); 2823 return; 2824 } 2825 setRawPath(escapedPath.toCharArray()); 2826 } 2827 2828 2829 2836 public void setPath(String path) throws URIException { 2837 2838 if (path == null || path.length() == 0) { 2839 _path = _opaque = (path == null) ? null : path.toCharArray(); 2840 setURI(); 2841 return; 2842 } 2843 String charset = getProtocolCharset(); 2845 2846 if (_is_net_path || _is_abs_path) { 2847 _path = encode(path, allowed_abs_path, charset); 2848 } else if (_is_rel_path) { 2849 StringBuffer buff = new StringBuffer (path.length()); 2850 int at = path.indexOf('/'); 2851 if (at == 0) { throw new URIException(URIException.PARSING, 2853 "incorrect relative path"); 2854 } 2855 if (at > 0) { 2856 buff.append(encode(path.substring(0, at), allowed_rel_path, 2857 charset)); 2858 buff.append(encode(path.substring(at), allowed_abs_path, 2859 charset)); 2860 } else { 2861 buff.append(encode(path, allowed_rel_path, charset)); 2862 } 2863 _path = buff.toString().toCharArray(); 2864 } else if (_is_opaque_part) { 2865 StringBuffer buf = new StringBuffer (); 2866 buf.insert(0, encode(path.substring(0, 1), uric_no_slash, charset)); 2867 buf.insert(1, encode(path.substring(1), uric, charset)); 2868 _opaque = buf.toString().toCharArray(); 2869 } else { 2870 throw new URIException(URIException.PARSING, "incorrect path"); 2871 } 2872 setURI(); 2873 } 2874 2875 2876 2884 protected char[] resolvePath(char[] basePath, char[] relPath) 2885 throws URIException { 2886 2887 String base = (basePath == null) ? "" : new String (basePath); 2889 int at = base.lastIndexOf('/'); 2890 if (at != -1) { 2891 basePath = base.substring(0, at + 1).toCharArray(); 2892 } 2893 if (relPath == null || relPath.length == 0) { 2895 return normalize(basePath); 2896 } else if (relPath[0] == '/') { 2897 return normalize(relPath); 2898 } else { 2899 StringBuffer buff = new StringBuffer (base.length() 2900 + relPath.length); 2901 buff.append((at != -1) ? base.substring(0, at + 1) : "/"); 2902 buff.append(relPath); 2903 return normalize(buff.toString().toCharArray()); 2904 } 2905 } 2906 2907 2908 2917 protected char[] getRawCurrentHierPath(char[] path) throws URIException { 2918 2919 if (_is_opaque_part) { 2920 throw new URIException(URIException.PARSING, "no hierarchy level"); 2921 } 2922 if (path == null) { 2923 throw new URIException(URIException.PARSING, "empty path"); 2924 } 2925 String buff = new String (path); 2926 int first = buff.indexOf('/'); 2927 int last = buff.lastIndexOf('/'); 2928 if (last == 0) { 2929 return rootPath; 2930 } else if (first != last && last != -1) { 2931 return buff.substring(0, last).toCharArray(); 2932 } 2933 return path; 2935 } 2936 2937 2938 2944 public char[] getRawCurrentHierPath() throws URIException { 2945 return (_path == null) ? null : getRawCurrentHierPath(_path); 2946 } 2947 2948 2949 2955 public String getEscapedCurrentHierPath() throws URIException { 2956 char[] path = getRawCurrentHierPath(); 2957 return (path == null) ? null : new String (path); 2958 } 2959 2960 2961 2968 public String getCurrentHierPath() throws URIException { 2969 char[] path = getRawCurrentHierPath(); 2970 return (path == null) ? null : decode(path, getProtocolCharset()); 2971 } 2972 2973 2974 2980 public char[] getRawAboveHierPath() throws URIException { 2981 char[] path = getRawCurrentHierPath(); 2982 return (path == null) ? null : getRawCurrentHierPath(path); 2983 } 2984 2985 2986 2992 public String getEscapedAboveHierPath() throws URIException { 2993 char[] path = getRawAboveHierPath(); 2994 return (path == null) ? null : new String (path); 2995 } 2996 2997 2998 3005 public String getAboveHierPath() throws URIException { 3006 char[] path = getRawAboveHierPath(); 3007 return (path == null) ? null : decode(path, getProtocolCharset()); 3008 } 3009 3010 3011 3019 public char[] getRawPath() { 3020 return _is_opaque_part ? _opaque : _path; 3021 } 3022 3023 3024 3034 public String getEscapedPath() { 3035 char[] path = getRawPath(); 3036 return (path == null) ? null : new String (path); 3037 } 3038 3039 3040 3049 public String getPath() throws URIException { 3050 char[] path = getRawPath(); 3051 return (path == null) ? null : decode(path, getProtocolCharset()); 3052 } 3053 3054 3055 3060 public char[] getRawName() { 3061 if (_path == null) { 3062 return null; 3063 } 3064 3065 int at = 0; 3066 for (int i = _path.length - 1; i >= 0; i--) { 3067 if (_path[i] == '/') { 3068 at = i + 1; 3069 break; 3070 } 3071 } 3072 int len = _path.length - at; 3073 char[] basename = new char[len]; 3074 System.arraycopy(_path, at, basename, 0, len); 3075 return basename; 3076 } 3077 3078 3079 3084 public String getEscapedName() { 3085 char[] basename = getRawName(); 3086 return (basename == null) ? null : new String (basename); 3087 } 3088 3089 3090 3098 public String getName() throws URIException { 3099 char[] basename = getRawName(); 3100 return (basename == null) ? null : decode(getRawName(), 3101 getProtocolCharset()); 3102 } 3103 3104 3106 3111 public char[] getRawPathQuery() { 3112 3113 if (_path == null && _query == null) { 3114 return null; 3115 } 3116 StringBuffer buff = new StringBuffer (); 3117 if (_path != null) { 3118 buff.append(_path); 3119 } 3120 if (_query != null) { 3121 buff.append('?'); 3122 buff.append(_query); 3123 } 3124 return buff.toString().toCharArray(); 3125 } 3126 3127 3128 3133 public String getEscapedPathQuery() { 3134 char[] rawPathQuery = getRawPathQuery(); 3135 return (rawPathQuery == null) ? null : new String (rawPathQuery); 3136 } 3137 3138 3139 3147 public String getPathQuery() throws URIException { 3148 char[] rawPathQuery = getRawPathQuery(); 3149 return (rawPathQuery == null) ? null : decode(rawPathQuery, 3150 getProtocolCharset()); 3151 } 3152 3153 3155 3161 public void setRawQuery(char[] escapedQuery) throws URIException { 3162 if (escapedQuery == null || escapedQuery.length == 0) { 3163 _query = escapedQuery; 3164 setURI(); 3165 return; 3166 } 3167 escapedQuery = removeFragmentIdentifier(escapedQuery); 3169 if (!validate(escapedQuery, query)) { 3170 throw new URIException(URIException.ESCAPING, 3171 "escaped query not valid"); 3172 } 3173 _query = escapedQuery; 3174 setURI(); 3175 } 3176 3177 3178 3184 public void setEscapedQuery(String escapedQuery) throws URIException { 3185 if (escapedQuery == null) { 3186 _query = null; 3187 setURI(); 3188 return; 3189 } 3190 setRawQuery(escapedQuery.toCharArray()); 3191 } 3192 3193 3194 3211 public void setQuery(String query) throws URIException { 3212 if (query == null || query.length() == 0) { 3213 _query = (query == null) ? null : query.toCharArray(); 3214 setURI(); 3215 return; 3216 } 3217 setRawQuery(encode(query, allowed_query, getProtocolCharset())); 3218 } 3219 3220 3221 3226 public char[] getRawQuery() { 3227 return _query; 3228 } 3229 3230 3231 3236 public String getEscapedQuery() { 3237 return (_query == null) ? null : new String (_query); 3238 } 3239 3240 3241 3249 public String getQuery() throws URIException { 3250 return (_query == null) ? null : decode(_query, getProtocolCharset()); 3251 } 3252 3253 3255 3261 public void setRawFragment(char[] escapedFragment) throws URIException { 3262 if (escapedFragment == null || escapedFragment.length == 0) { 3263 _fragment = escapedFragment; 3264 hash = 0; 3265 return; 3266 } 3267 if (!validate(escapedFragment, fragment)) { 3268 throw new URIException(URIException.ESCAPING, 3269 "escaped fragment not valid"); 3270 } 3271 _fragment = escapedFragment; 3272 hash = 0; 3273 } 3274 3275 3276 3282 public void setEscapedFragment(String escapedFragment) throws URIException { 3283 if (escapedFragment == null) { 3284 _fragment = null; 3285 hash = 0; 3286 return; 3287 } 3288 setRawFragment(escapedFragment.toCharArray()); 3289 } 3290 3291 3292 3298 public void setFragment(String fragment) throws URIException { 3299 if (fragment == null || fragment.length() == 0) { 3300 _fragment = (fragment == null) ? null : fragment.toCharArray(); 3301 hash = 0; 3302 return; 3303 } 3304 _fragment = encode(fragment, allowed_fragment, getProtocolCharset()); 3305 hash = 0; 3306 } 3307 3308 3309 3324 public char[] getRawFragment() { 3325 return _fragment; 3326 } 3327 3328 3329 3334 public String getEscapedFragment() { 3335 return (_fragment == null) ? null : new String (_fragment); 3336 } 3337 3338 3339 3347 public String getFragment() throws URIException { 3348 return (_fragment == null) ? null : decode(_fragment, 3349 getProtocolCharset()); 3350 } 3351 3352 3354 3360 protected char[] removeFragmentIdentifier(char[] component) { 3361 if (component == null) { 3362 return null; 3363 } 3364 int lastIndex = new String (component).indexOf('#'); 3365 if (lastIndex != -1) { 3366 component = new String (component).substring(0, 3367 lastIndex).toCharArray(); 3368 } 3369 return component; 3370 } 3371 3372 3373 3383 protected char[] normalize(char[] path) throws URIException { 3384 3385 if (path == null) { 3386 return null; 3387 } 3388 3389 String normalized = new String (path); 3390 3391 if (normalized.startsWith("./")) { 3393 normalized = normalized.substring(1); 3394 } else if (normalized.startsWith("../")) { 3395 normalized = normalized.substring(2); 3396 } else if (normalized.startsWith("..")) { 3397 normalized = normalized.substring(2); 3398 } 3399 3400 int index = -1; 3402 while ((index = normalized.indexOf("/./")) != -1) { 3403 normalized = normalized.substring(0, index) + normalized.substring(index + 2); 3404 } 3405 3406 if (normalized.endsWith("/.")) { 3408 normalized = normalized.substring(0, normalized.length() - 1); 3409 } 3410 3411 int startIndex = 0; 3412 3413 while ((index = normalized.indexOf("/../", startIndex)) != -1) { 3419 int slashIndex = normalized.lastIndexOf('/', index - 1); 3420 if (slashIndex >= 0) { 3421 normalized = normalized.substring(0, slashIndex) + normalized.substring(index + 3); 3422 } else { 3423 startIndex = index + 3; 3424 } 3425 } 3426 if (normalized.endsWith("/..")) { 3427 int slashIndex = normalized.lastIndexOf('/', normalized.length() - 4); 3428 if (slashIndex >= 0) { 3429 normalized = normalized.substring(0, slashIndex + 1); 3430 } 3431 } 3432 3433 while ((index = normalized.indexOf("/../")) != -1) { 3439 int slashIndex = normalized.lastIndexOf('/', index - 1); 3440 if (slashIndex >= 0) { 3441 break; 3442 } else { 3443 normalized = normalized.substring(index + 3); 3444 } 3445 } 3446 if (normalized.endsWith("/..")) { 3447 int slashIndex = normalized.lastIndexOf('/', normalized.length() - 4); 3448 if (slashIndex < 0) { 3449 normalized = "/"; 3450 } 3451 } 3452 3453 return normalized.toCharArray(); 3454 } 3455 3456 3457 3466 public void normalize() throws URIException { 3467 if (isAbsPath()) { 3468 _path = normalize(_path); 3469 setURI(); 3470 } 3471 } 3472 3473 3474 3481 protected boolean equals(char[] first, char[] second) { 3482 3483 if (first == null && second == null) { 3484 return true; 3485 } 3486 if (first == null || second == null) { 3487 return false; 3488 } 3489 if (first.length != second.length) { 3490 return false; 3491 } 3492 for (int i = 0; i < first.length; i++) { 3493 if (first[i] != second[i]) { 3494 return false; 3495 } 3496 } 3497 return true; 3498 } 3499 3500 3501 3507 public boolean equals(Object obj) { 3508 3509 if (obj == this) { 3511 return true; 3512 } 3513 if (!(obj instanceof URI)) { 3514 return false; 3515 } 3516 URI another = (URI) obj; 3517 if (!equals(_scheme, another._scheme)) { 3519 return false; 3520 } 3521 if (!equals(_opaque, another._opaque)) { 3523 return false; 3524 } 3525 if (!equals(_authority, another._authority)) { 3528 return false; 3529 } 3530 if (!equals(_path, another._path)) { 3532 return false; 3533 } 3534 if (!equals(_query, another._query)) { 3536 return false; 3537 } 3538 if (!equals(_fragment, another._fragment)) { 3540 return false; 3541 } 3542 return true; 3543 } 3544 3545 3547 3553 protected void writeObject(ObjectOutputStream oos) 3554 throws IOException { 3555 3556 oos.defaultWriteObject(); 3557 } 3558 3559 3560 3568 protected void readObject(ObjectInputStream ois) 3569 throws ClassNotFoundException , IOException { 3570 3571 ois.defaultReadObject(); 3572 } 3573 3574 3576 3581 public int hashCode() { 3582 if (hash == 0) { 3583 char[] c = _uri; 3584 if (c != null) { 3585 for (int i = 0, len = c.length; i < len; i++) { 3586 hash = 31 * hash + c[i]; 3587 } 3588 } 3589 c = _fragment; 3590 if (c != null) { 3591 for (int i = 0, len = c.length; i < len; i++) { 3592 hash = 31 * hash + c[i]; 3593 } 3594 } 3595 } 3596 return hash; 3597 } 3598 3599 3601 3609 public int compareTo(Object obj) throws ClassCastException { 3610 3611 URI another = (URI) obj; 3612 if (!equals(_authority, another.getRawAuthority())) { 3613 return -1; 3614 } 3615 return toString().compareTo(another.toString()); 3616 } 3617 3618 3620 3630 public synchronized Object clone() { 3631 3632 URI instance = new URI(); 3633 3634 instance._uri = _uri; 3635 instance._scheme = _scheme; 3636 instance._opaque = _opaque; 3637 instance._authority = _authority; 3638 instance._userinfo = _userinfo; 3639 instance._host = _host; 3640 instance._port = _port; 3641 instance._path = _path; 3642 instance._query = _query; 3643 instance._fragment = _fragment; 3644 instance.protocolCharset = protocolCharset; 3646 instance._is_hier_part = _is_hier_part; 3648 instance._is_opaque_part = _is_opaque_part; 3649 instance._is_net_path = _is_net_path; 3650 instance._is_abs_path = _is_abs_path; 3651 instance._is_rel_path = _is_rel_path; 3652 instance._is_reg_name = _is_reg_name; 3653 instance._is_server = _is_server; 3654 instance._is_hostname = _is_hostname; 3655 instance._is_IPv4address = _is_IPv4address; 3656 instance._is_IPv6reference = _is_IPv6reference; 3657 3658 return instance; 3659 } 3660 3661 3663 3678 public char[] getRawURI() { 3679 return _uri; 3680 } 3681 3682 3683 3689 public String getEscapedURI() { 3690 return (_uri == null) ? null : new String (_uri); 3691 } 3692 3693 3694 3702 public String getURI() throws URIException { 3703 return (_uri == null) ? null : decode(_uri, getProtocolCharset()); 3704 } 3705 3706 3707 3712 public char[] getRawURIReference() { 3713 if (_fragment == null) { 3714 return _uri; 3715 } 3716 if (_uri == null) { 3717 return _fragment; 3718 } 3719 String uriReference = new String (_uri) + "#" + new String (_fragment); 3721 return uriReference.toCharArray(); 3722 } 3723 3724 3725 3730 public String getEscapedURIReference() { 3731 char[] uriReference = getRawURIReference(); 3732 return (uriReference == null) ? null : new String (uriReference); 3733 } 3734 3735 3736 3742 public String getURIReference() throws URIException { 3743 char[] uriReference = getRawURIReference(); 3744 return (uriReference == null) ? null : decode(uriReference, 3745 getProtocolCharset()); 3746 } 3747 3748 3749 3766 public String toString() { 3767 return getEscapedURI(); 3768 } 3769 3770 3771 3773 3777 public static class DefaultCharsetChanged extends RuntimeException { 3778 3779 3781 3787 public DefaultCharsetChanged(int reasonCode, String reason) { 3788 super(reason); 3789 this.reason = reason; 3790 this.reasonCode = reasonCode; 3791 } 3792 3793 3795 3796 public static final int UNKNOWN = 0; 3797 3798 3799 public static final int PROTOCOL_CHARSET = 1; 3800 3801 3802 public static final int DOCUMENT_CHARSET = 2; 3803 3804 3806 3807 private int reasonCode; 3808 3809 3810 private String reason; 3811 3812 3814 3819 public int getReasonCode() { 3820 return reasonCode; 3821 } 3822 3823 3828 public String getReason() { 3829 return reason; 3830 } 3831 3832 } 3833 3834 3835 3842 public static class LocaleToCharsetMap { 3843 3844 3845 private static final Hashtable LOCALE_TO_CHARSET_MAP; 3846 static { 3847 LOCALE_TO_CHARSET_MAP = new Hashtable (); 3848 LOCALE_TO_CHARSET_MAP.put("ar", "ISO-8859-6"); 3849 LOCALE_TO_CHARSET_MAP.put("be", "ISO-8859-5"); 3850 LOCALE_TO_CHARSET_MAP.put("bg", "ISO-8859-5"); 3851 LOCALE_TO_CHARSET_MAP.put("ca", "ISO-8859-1"); 3852 LOCALE_TO_CHARSET_MAP.put("cs", "ISO-8859-2"); 3853 LOCALE_TO_CHARSET_MAP.put("da", "ISO-8859-1"); 3854 LOCALE_TO_CHARSET_MAP.put("de", "ISO-8859-1"); 3855 LOCALE_TO_CHARSET_MAP.put("el", "ISO-8859-7"); 3856 LOCALE_TO_CHARSET_MAP.put("en", "ISO-8859-1"); 3857 LOCALE_TO_CHARSET_MAP.put("es", "ISO-8859-1"); 3858 LOCALE_TO_CHARSET_MAP.put("et", "ISO-8859-1"); 3859 LOCALE_TO_CHARSET_MAP.put("fi", "ISO-8859-1"); 3860 LOCALE_TO_CHARSET_MAP.put("fr", "ISO-8859-1"); 3861 LOCALE_TO_CHARSET_MAP.put("hr", "ISO-8859-2"); 3862 LOCALE_TO_CHARSET_MAP.put("hu", "ISO-8859-2"); 3863 LOCALE_TO_CHARSET_MAP.put("is", "ISO-8859-1"); 3864 LOCALE_TO_CHARSET_MAP.put("it", "ISO-8859-1"); 3865 LOCALE_TO_CHARSET_MAP.put("iw", "ISO-8859-8"); 3866 LOCALE_TO_CHARSET_MAP.put("ja", "Shift_JIS"); 3867 LOCALE_TO_CHARSET_MAP.put("ko", "EUC-KR"); 3868 LOCALE_TO_CHARSET_MAP.put("lt", "ISO-8859-2"); 3869 LOCALE_TO_CHARSET_MAP.put("lv", "ISO-8859-2"); 3870 LOCALE_TO_CHARSET_MAP.put("mk", "ISO-8859-5"); 3871 LOCALE_TO_CHARSET_MAP.put("nl", "ISO-8859-1"); 3872 LOCALE_TO_CHARSET_MAP.put("no", "ISO-8859-1"); 3873 LOCALE_TO_CHARSET_MAP.put("pl", "ISO-8859-2"); 3874 LOCALE_TO_CHARSET_MAP.put("pt", "ISO-8859-1"); 3875 LOCALE_TO_CHARSET_MAP.put("ro", "ISO-8859-2"); 3876 LOCALE_TO_CHARSET_MAP.put("ru", "ISO-8859-5"); 3877 LOCALE_TO_CHARSET_MAP.put("sh", "ISO-8859-5"); 3878 LOCALE_TO_CHARSET_MAP.put("sk", "ISO-8859-2"); 3879 LOCALE_TO_CHARSET_MAP.put("sl", "ISO-8859-2"); 3880 LOCALE_TO_CHARSET_MAP.put("sq", "ISO-8859-2"); 3881 LOCALE_TO_CHARSET_MAP.put("sr", "ISO-8859-5"); 3882 LOCALE_TO_CHARSET_MAP.put("sv", "ISO-8859-1"); 3883 LOCALE_TO_CHARSET_MAP.put("tr", "ISO-8859-9"); 3884 LOCALE_TO_CHARSET_MAP.put("uk", "ISO-8859-5"); 3885 LOCALE_TO_CHARSET_MAP.put("zh", "GB2312"); 3886 LOCALE_TO_CHARSET_MAP.put("zh_TW", "Big5"); 3887 } 3888 3889 3896 public static String getCharset(Locale locale) { 3897 String charset = 3899 (String ) LOCALE_TO_CHARSET_MAP.get(locale.toString()); 3900 if (charset != null) { 3901 return charset; 3902 } 3903 3904 charset = (String ) LOCALE_TO_CHARSET_MAP.get(locale.getLanguage()); 3906 return charset; } 3908 3909 } 3910 3911} 3912 3913 | Popular Tags |