public static String safeRelativize ( final URI baseURI , final URI toUri ) throws URISyntaxException { // For compatibility followed // http://msdn.microsoft.com/en-us/library/system.uri.makerelativeuri.aspx // if host and scheme are not identical return from uri if ( ! baseURI . getHost ( ) . equals ( toUri . getHost ( ) ) || ! baseURI . getScheme ( ) . equals ( toUri . getScheme ( ) ) ) { return toUri . toString ( ) ; } final String basePath = baseURI . getPath ( ) ; String toPath = toUri . getPath ( ) ; int truncatePtr = 1 ; // Seek to first Difference // int maxLength = Math.min(basePath.length(), toPath.length()); int m = 0 ; int ellipsesCount = 0 ; for ( ; m < basePath . length ( ) ; m ++ ) { if ( m >= toPath . length ( ) ) { if ( basePath . charAt ( m ) == ' ' ) { ellipsesCount ++ ; } } else { if ( basePath . charAt ( m ) != toPath . charAt ( m ) ) { break ; } else if ( basePath . charAt ( m ) == ' ' ) { truncatePtr = m + 1 ; } } } // ../containername and ../containername/{path} should increment the truncatePtr // otherwise toPath will incorrectly begin with /containername if ( m < toPath . length ( ) && toPath . charAt ( m ) == ' ' ) { // this is to handle the empty directory case with the '/' delimiter // for example, ../containername/ and ../containername// should not increment the truncatePtr if ( ! ( toPath . charAt ( m - 1 ) == ' ' && basePath . charAt ( m - 1 ) == ' ' ) ) { truncatePtr = m + 1 ; } } if ( m == toPath . length ( ) ) { // No path difference, return query + fragment return new URI ( null , null , null , toUri . getQuery ( ) , toUri . getFragment ( ) ) . toString ( ) ; } else { toPath = toPath . substring ( truncatePtr ) ; final StringBuilder sb = new StringBuilder ( ) ; while ( ellipsesCount > 0 ) { sb . append ( "../" ) ; ellipsesCount -- ; } if ( ! Utility . isNullOrEmpty ( toPath ) ) { sb . append ( toPath ) ; } if ( ! Utility . isNullOrEmpty ( toUri . getQuery ( ) ) ) { sb . append ( "?" ) ; sb . append ( toUri . getQuery ( ) ) ; } if ( ! Utility . isNullOrEmpty ( toUri . getFragment ( ) ) ) { sb . append ( "#" ) ; sb . append ( toUri . getRawFragment ( ) ) ; } return sb . toString ( ) ; } }
Determines the relative difference between the two specified URIs .