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();
        }
    }
public static String safeRelativize(final URI baseURI, final URI toUri) throws URISyntaxException {
        
        

        
        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;

        
        
        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;
                }
            }
        }

        
        
        if (m < toPath.length() && toPath.charAt(m) == '/') {
            
            
            if (!(toPath.charAt(m - 1) == '/' && basePath.charAt(m - 1) == '/')) {
                truncatePtr = m + 1;
            }
        }

        if (m == toPath.length()) {
            
            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();
        }
    }
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.

@param baseURI
A <code>java.net.URI</code> object that represents the base URI for which <code>toUri</code> will be
made relative.
@param toUri
A <code>java.net.URI</code> object that represents the URI to make relative to <code>baseURI</code>.

@return A <code>String</code> that either represents the relative URI of <code>toUri</code> to
<code>baseURI</code>, or the URI of <code>toUri</code> itself, depending on whether the hostname and
scheme are identical for <code>toUri</code> and <code>baseURI</code>. If the hostname and scheme of
<code>baseURI</code> and <code>toUri</code> are identical, this method returns an unencoded relative URI
such that if appended to <code>baseURI</code>, it will yield <code>toUri</code>. If the hostname or
scheme of <code>baseURI</code> and <code>toUri</code> are not identical, this method returns an unencoded
full URI specified by <code>toUri</code>.

@throws URISyntaxException
If <code>baseURI</code> or <code>toUri</code> is invalid.
Determines the relative difference between the two specified URIs .