1 18 package org.apache.beehive.netui.core.urls; 19 20 import org.apache.beehive.netui.util.internal.InternalStringBuilder; 21 22 import org.apache.beehive.netui.core.URLCodec; 23 24 import java.net.URI ; 25 import java.net.URISyntaxException ; 26 import java.net.URL ; 27 import java.util.ArrayList ; 28 import java.util.Collections ; 29 import java.util.Iterator ; 30 import java.util.LinkedHashMap ; 31 import java.util.List ; 32 import java.util.Map ; 33 import java.util.StringTokenizer ; 34 import java.util.HashMap ; 35 36 62 public class MutableURI 63 { 64 65 public static final int UNDEFINED_PORT = -1; 66 67 68 public static final String DEFAULT_ENCODING = "UTF-8"; 69 70 71 private String _encoding; 72 73 74 private String _scheme; 75 76 81 private String _userInfo; 82 83 84 private String _host; 85 86 87 private int _port = UNDEFINED_PORT; 88 89 90 private String _path; 91 92 93 private LinkedHashMap _params; 94 95 96 private String _fragment; 97 98 99 private static final String AMP_ENTITY = "&"; 100 private static final String AMP_CHAR = "&"; 101 102 private static final Map EMPTY_MAP = 103 Collections.unmodifiableMap( new HashMap () ); 104 105 108 public MutableURI() 109 { 110 } 111 112 119 public MutableURI( String uriString, boolean encoded ) throws URISyntaxException 120 { 121 assert uriString != null : "The uri cannot be null."; 122 123 if ( uriString == null ) 124 { 125 throw new IllegalArgumentException ( "The URI cannot be null." ); 126 } 127 128 URI uri = null; 129 130 if ( encoded ) 131 { 132 uri = new URI ( uriString ); 134 } 135 else 136 { 137 uri = encodeURI( uriString ); 139 } 140 141 setURI( uri ); 142 } 143 144 156 public MutableURI( String scheme, String userInfo, String host, int port, 157 String path, String query, String fragment ) 158 { 159 setScheme( scheme ); 160 setUserInfo( userInfo ); 161 setHost( host ); 162 setPort( port ); 163 setPath( path ); 164 setQuery( query ); 165 setFragment( fragment ); 166 } 167 168 173 public MutableURI( URI uri ) 174 { 175 assert uri != null : "The URI cannot be null."; 176 177 if ( uri == null ) 178 { 179 throw new IllegalArgumentException ( "The URI cannot be null." ); 180 } 181 182 setURI( uri ); 183 } 184 185 201 public MutableURI( URL url ) throws URISyntaxException 202 { 203 assert url != null : "The URL cannot be null."; 204 205 if ( url == null ) 206 { 207 throw new IllegalArgumentException ( "The URL cannot be null." ); 208 } 209 210 URI uri = url.toURI(); 211 setURI( uri ); 212 } 213 214 223 public void setURI( String uriString, boolean encoded ) throws URISyntaxException 224 { 225 if ( uriString == null ) 226 { 227 setScheme( null ); 228 setUserInfo( null ); 229 setHost( null ); 230 setPort( UNDEFINED_PORT ); 231 setPath( null ); 232 setQuery( null ); 233 setFragment( null ); 234 } 235 else 236 { 237 URI uri = null; 238 239 if ( encoded ) 240 { 241 uri = new URI ( uriString ); 243 } 244 else 245 { 246 uri = encodeURI( uriString ); 248 } 249 250 setURI( uri ); 251 } 252 } 253 254 261 public void setURI( URI uri ) 262 { 263 setScheme( uri.getScheme() ); 264 setUserInfo( uri.getRawUserInfo() ); 265 setHost( uri.getHost() ); 266 setPort( uri.getPort() ); 267 setPath( uri.getRawPath() ); 268 setQuery( uri.getRawQuery() ); 269 setFragment( uri.getRawFragment() ); 270 } 271 272 277 public void setEncoding( String encoding ) 278 { 279 _encoding = encoding; 280 } 281 282 287 public String getEncoding() 288 { 289 return _encoding; 290 } 291 292 297 public void setScheme( String scheme ) 298 { 299 _scheme = null; 300 if ( scheme != null && scheme.length() > 0 ) 301 { 302 _scheme = scheme; 303 } 304 } 305 306 312 public String getScheme() 313 { 314 return _scheme; 315 } 316 317 322 public void setUserInfo( String userInfo ) 323 { 324 _userInfo = null; 325 if ( userInfo != null && userInfo.length() > 0 ) 326 { 327 _userInfo = userInfo; 328 } 329 } 330 331 337 public String getUserInfo() 338 { 339 return _userInfo; 340 } 341 342 347 public void setHost( String host ) 348 { 349 _host = null; 350 if ( host != null && host.length() > 0 ) 351 { 352 boolean needBrackets = ( ( host.indexOf( ':' ) >= 0 ) 358 && !host.startsWith( "[" ) 359 && !host.endsWith( "]" ) ); 360 361 if ( needBrackets ) 362 { 363 _host = '[' + host + ']'; 364 } 365 else 366 { 367 _host = host; 368 } 369 } 370 371 if ( _host == null ) 372 { 373 setUserInfo( null ); 374 setPort( UNDEFINED_PORT ); 375 } 376 } 377 378 384 public String getHost() 385 { 386 return _host; 387 } 388 389 394 public void setPort( int port ) 395 { 396 assert ( port >= 0 && port <= 65535 ) || ( port == UNDEFINED_PORT ) 397 : "Invalid port" ; 398 399 if ( ( port > 65535 ) || ( port < 0 && port != UNDEFINED_PORT ) ) 400 { 401 throw new IllegalArgumentException ( "A port must be between 0 and 65535 or equal to " 402 + UNDEFINED_PORT + "."); 403 } 404 405 _port = port; 406 } 407 408 414 public int getPort() 415 { 416 return _port; 417 } 418 419 424 public void setPath( String path ) 425 { 426 if ( path == null ) 428 { 429 _path = null; 430 setQuery( null ); 431 setFragment( null ); 432 } 433 else 434 { 435 _path = path; 436 } 437 } 438 439 444 public String getPath() 445 { 446 return _path; 447 } 448 449 456 public void setQuery( String query ) 457 { 458 _params = null; 459 460 if ( query == null || query.length() == 0 ) { return; } 461 462 for ( StringTokenizer tok = new StringTokenizer ( query, "&" ); tok.hasMoreElements(); ) 463 { 464 String queryItem = tok.nextToken(); 465 466 if ( queryItem.startsWith( "amp;" ) ) 467 { 468 queryItem = queryItem.substring( 4 ); 469 } 470 471 int eq = queryItem.indexOf( '=' ); 472 if ( eq != -1 ) 473 { 474 addParameter( queryItem.substring( 0, eq ) , queryItem.substring( eq + 1 ), true ); 475 } 476 else 477 { 478 addParameter( queryItem, null, true ); 479 } 480 } 481 } 482 483 494 public String getQuery( URIContext uriContext ) 495 { 496 if ( _params == null || _params.isEmpty() ) { return null; } 497 498 String paramSeparator = AMP_ENTITY; 499 if ( uriContext == null ) 500 { 501 uriContext = getDefaultContext(); 502 } 503 504 if ( !uriContext.useAmpEntity() ) 505 { 506 paramSeparator = AMP_CHAR; 507 } 508 509 InternalStringBuilder query = new InternalStringBuilder( 64 ); 510 boolean firstParam = true; 511 for ( Iterator i = _params.keySet().iterator(); i.hasNext(); ) 512 { 513 String name = ( String ) i.next(); 514 515 for ( Iterator j = ( ( List ) _params.get( name ) ).iterator(); j.hasNext(); ) 516 { 517 String value = ( String ) j.next(); 518 519 if ( firstParam ) 520 { 521 firstParam = false; 522 } 523 else 524 { 525 query.append( paramSeparator ); 526 } 527 528 query.append( name ); 529 530 if ( value != null ) { query.append( '=' ).append( value ); } 531 } 532 } 533 534 return query.toString(); 535 } 536 537 553 public void addParameter( String name, String value, boolean encoded ) 554 { 555 if ( name == null ) throw new IllegalArgumentException ( "A parameter name may not be null." ); 556 557 if ( !encoded ) 558 { 559 name = encode( name ); 560 value = encode( value ); 561 } 562 563 if ( _params == null ) _params = new LinkedHashMap (); 564 List values = ( List ) _params.get( name ); 565 566 if ( values == null ) 567 { 568 values = new ArrayList (); 569 _params.put( name, values ); 570 } 571 572 values.add( value ); 573 } 574 575 588 public void addParameters( Map newParams, boolean encoded ) 589 { 590 if ( newParams == null ) 591 { 592 throw new IllegalArgumentException ( "Cannot add null map of parameters." ); 593 } 594 595 if ( newParams.size() == 0 ) 596 { 597 return; 598 } 599 600 if ( _params == null ) 601 { 602 _params = new LinkedHashMap (); 603 } 604 605 Iterator keys = newParams.keySet().iterator(); 606 while ( keys.hasNext() ) 607 { 608 String name = ( String ) keys.next(); 609 String encodedName = name; 610 611 if ( !encoded ) { encodedName = encode( name ); } 612 613 List values = ( List ) _params.get( encodedName ); 614 if ( values == null ) 615 { 616 values = new ArrayList (); 617 _params.put( encodedName, values ); 618 } 619 620 Object newValue = newParams.get( name ); 621 if ( newValue == null ) 622 { 623 values.add( null ); 624 } 625 else if ( newValue instanceof String ) 626 { 627 addValue( values, ( String ) newValue, encoded ); 628 } 629 else if ( newValue instanceof String [] ) 630 { 631 String newValues[] = ( String [] ) newValue; 632 for ( int i = 0; i < newValues.length; i++ ) 633 { 634 addValue( values, newValues[i], encoded ); 635 } 636 } 637 else if ( newValue instanceof List ) 638 { 639 Iterator newValues = ( ( List ) newValue ).iterator(); 640 while ( newValues.hasNext() ) 641 { 642 addValue( values, newValues.next().toString(), encoded ); 643 } 644 } 645 else 646 { 647 addValue( values, newValue.toString(), encoded ); 648 } 649 } 650 } 651 652 private void addValue( List list, String value, boolean encoded ) 653 { 654 if ( !encoded ) 655 { 656 value = encode( value ); 657 } 658 659 list.add( value ); 660 } 661 662 670 public String getParameter( String name ) 671 { 672 if ( _params == null ) { return null; } 673 674 List values = ( List ) _params.get( name ); 675 if ( values != null && values.size() > 0 ) 676 { 677 return ( String ) values.get( 0 ); 678 } 679 else 680 { 681 return null; 682 } 683 } 684 685 691 public List getParameters( String name ) 692 { 693 if ( _params == null ) 694 { 695 return Collections.EMPTY_LIST; 696 } 697 else 698 { 699 List values = ( List ) _params.get( name ); 700 701 if ( values == null ) 702 { 703 return Collections.EMPTY_LIST; 704 } 705 else 706 { 707 return Collections.unmodifiableList( values ); 708 } 709 } 710 } 711 712 717 public Map getParameters() 718 { 719 if ( _params == null ) 720 { 721 return EMPTY_MAP; 722 } 723 else 724 { 725 return Collections.unmodifiableMap( _params ); 726 } 727 } 728 729 734 public void removeParameter( String name ) 735 { 736 if ( _params == null ) { return; } 737 738 _params.remove( name ); 739 } 740 741 746 public void setFragment( String fragment ) 747 { 748 _fragment = null; 749 if ( fragment != null && fragment.length() > 0 ) 750 { 751 _fragment = fragment; 752 } 753 } 754 755 760 public String getFragment() 761 { 762 return _fragment; 763 } 764 765 772 public boolean isAbsolute() { 773 return getScheme() != null; 774 } 775 776 786 public String getURIString( URIContext uriContext ) 787 { 788 InternalStringBuilder buf = new InternalStringBuilder( 128 ); 789 790 if ( getScheme() != null ) 792 { 793 buf.append( getScheme() ).append( ':' ); 794 } 795 796 if ( getHost() != null) 798 { 799 buf.append( "//" ); 800 801 if ( getUserInfo() != null ) 802 { 803 buf.append( getUserInfo() ); 804 buf.append( '@' ); 805 } 806 807 buf.append( getHost() ); 808 809 if ( getPort() != UNDEFINED_PORT ) 810 { 811 buf.append( ':' ).append( getPort() ); 812 } 813 } 814 815 if ( getPath() != null ) 817 { 818 if ( isAbsolute() ) 819 { 820 appendEnsureSeparator( buf, getPath() ); 822 } 823 else 824 { 825 buf.append( getPath() ); 826 } 827 } 828 829 if ( _params != null && _params.size() > 0 ) 831 { 832 buf.append( '?' ); 833 buf.append( getQuery( uriContext ) ); 834 } 835 836 if ( getFragment() != null && getFragment().length() > 0 ) 838 { 839 buf.append( '#' ).append( getFragment() ); 840 } 841 842 String url = buf.toString(); 843 844 return url; 845 } 846 847 852 public static URIContext getDefaultContext() 853 { 854 URIContext uriContext = new URIContext(); 855 uriContext.setUseAmpEntity( true ); 856 857 return uriContext; 858 } 859 860 private static void appendEnsureSeparator( InternalStringBuilder buf, String token ) 861 { 862 if ( token != null && token.length() > 0 ) 863 { 864 if ( buf.charAt( buf.length() - 1 ) != '/' && token.charAt( 0 ) != '/' ) 865 { 866 buf.append( '/' ); 867 } 868 if ( buf.charAt( buf.length() - 1 ) == '/' && token.charAt( 0 ) == '/' ) 869 { 870 token = token.substring( 1 ); 871 } 872 buf.append( token ); 873 } 874 } 875 876 883 public static String encode( String url, String encoding ) 884 { 885 String encodedURL = null; 886 try 887 { 888 encodedURL = URLCodec.encode( url, encoding ); 889 } 890 catch ( java.io.UnsupportedEncodingException e ) 891 { 892 try 894 { 895 encodedURL = URLCodec.encode( url, DEFAULT_ENCODING ); 896 } 897 catch ( java.io.UnsupportedEncodingException ignore ) 898 { 899 } 900 } 901 return encodedURL; 902 } 903 904 912 public String encode( String url ) 913 { 914 return encode( url, _encoding ); 915 } 916 917 924 925 public boolean equals( Object object ) 926 { 927 if ( object == this ) { return true; } 928 929 if ( object == null || !object.getClass().equals( this.getClass() ) ) 930 { 931 return false; 932 } 933 934 MutableURI testURI = ( MutableURI ) object; 935 936 if ( ( _scheme == testURI.getScheme() || ( _scheme != null && _scheme.equalsIgnoreCase( testURI.getScheme() ) ) ) && 937 ( _userInfo == testURI.getUserInfo() || ( _userInfo != null && _userInfo.equals( testURI.getUserInfo() ) ) ) && 938 ( _host == testURI.getHost() || ( _host != null && _host.equalsIgnoreCase( testURI.getHost() ) ) ) && 939 _port == testURI.getPort() && 940 ( _path == testURI.getPath() || ( _path != null && _path.equals( testURI.getPath() ) ) ) && 941 ( _fragment == testURI.getFragment() || ( _fragment != null && _fragment.equals( testURI.getFragment() ) ) ) && 942 ( _encoding == testURI.getEncoding() || ( _encoding != null && _encoding.equals( testURI.getEncoding() ) ) ) ) 943 { 944 Map params = getParameters(); 945 Map testParams = testURI.getParameters(); 946 947 if ( params == testParams || ( params != null && params.equals( testParams ) ) ) { 948 return true; 949 } 950 } 951 952 return false; 953 } 954 955 971 972 public int hashCode() 973 { 974 return 0; 975 } 976 977 987 protected static URI encodeURI( String original ) throws URISyntaxException 988 { 989 if ( original == null ) 990 { 991 throw new IllegalArgumentException ( "URI-Reference required" ); 992 } 993 994 String scheme = null; 995 String authority = null; 996 String path = null; 997 String query = null; 998 String fragment = null; 999 String tmp = original.trim(); 1000 int length = tmp.length(); 1001 int from = 0; 1002 1003 boolean isStartedFromPath = false; 1005 int atColon = tmp.indexOf( ':' ); 1006 int atSlash = tmp.indexOf( '/' ); 1007 1008 if ( atColon < 0 || ( atSlash >= 0 && atSlash < atColon ) ) 1009 { 1010 isStartedFromPath = true; 1011 } 1012 1013 int at = indexFirstOf( tmp, isStartedFromPath ? "/?#" : ":/?#", from ); 1014 1015 if ( at == -1 ) 1016 { 1017 at = 0; 1018 } 1019 1020 if ( at < length && tmp.charAt( at ) == ':' ) 1022 { 1023 scheme = tmp.substring( 0, at ).toLowerCase(); 1024 from = ++at; 1025 } 1026 1027 if ( 0 <= at && at < length ) 1029 { 1030 if ( tmp.charAt( at ) == '/' ) 1031 { 1032 if ( at + 2 < length && tmp.charAt( at + 1 ) == '/' ) 1033 { 1034 int next = indexFirstOf( tmp, "/?#", at + 2 ); 1036 if ( next == -1 ) 1037 { 1038 next = ( tmp.substring( at + 2 ).length() == 0 ) ? at + 2 : tmp.length(); 1039 } 1040 authority = tmp.substring( at + 2, next ); 1041 from = at = next; 1042 } 1043 } 1044 else if ( scheme != null && tmp.indexOf( '/', at + 1 ) < 0 ) 1045 { 1046 int next = tmp.indexOf( '#', at ); 1047 if ( next == -1 ) 1048 { 1049 next = length; 1050 } 1051 String ssp = tmp.substring( at, next ); 1052 if ( next != length ) 1053 { 1054 fragment = tmp.substring( next + 1 ); 1055 } 1056 return new URI ( scheme, ssp, fragment ); 1057 } 1058 } 1059 1060 if ( from < length ) 1062 { 1063 int next = indexFirstOf( tmp, "?#", from ); 1064 if ( next == -1 ) 1065 { 1066 next = length; 1067 } 1068 path = tmp.substring( from, next ); 1069 at = next; 1070 } 1071 1072 if ( 0 <= at && at + 1 < length && tmp.charAt( at ) == '?' ) 1074 { 1075 int next = tmp.indexOf( '#', at + 1 ); 1076 if ( next == -1 ) 1077 { 1078 next = length; 1079 } 1080 query = tmp.substring( at + 1, next ); 1081 at = next; 1082 } 1083 1084 if ( 0 <= at && at + 1 <= length && tmp.charAt( at ) == '#' ) 1086 { 1087 if ( at + 1 == length ) 1088 { fragment = ""; 1090 } 1091 else 1092 { 1093 fragment = tmp.substring( at + 1 ); 1094 } 1095 } 1096 1097 return new URI ( scheme, authority, path, query, fragment ); 1099 } 1100 1101 1110 protected static int indexFirstOf( String s, String delims, int offset ) 1111 { 1112 if ( s == null || s.length() == 0 ) 1113 { 1114 return -1; 1115 } 1116 if ( delims == null || delims.length() == 0 ) 1117 { 1118 return -1; 1119 } 1120 1121 if ( offset < 0 ) 1123 { 1124 offset = 0; 1125 } 1126 else if ( offset > s.length() ) 1127 { 1128 return -1; 1129 } 1130 1131 int min = s.length(); 1133 char[] delim = delims.toCharArray(); 1134 for ( int i = 0; i < delim.length; i++ ) 1135 { 1136 int at = s.indexOf( delim[i], offset ); 1137 if ( at >= 0 && at < min ) 1138 { 1139 min = at; 1140 } 1141 } 1142 1143 return ( min == s.length() ) ? -1 : min; 1144 } 1145} 1146 | Popular Tags |