Skip to content

Commit

Permalink
Make the getParent(URI) helper more robust
Browse files Browse the repository at this point in the history
This fixes the behavior on Windows, avoiding InvalidPathExceptions.
  • Loading branch information
ctrueden committed Oct 9, 2024
1 parent 61911bf commit 8acdc6b
Showing 1 changed file with 40 additions and 2 deletions.
42 changes: 40 additions & 2 deletions src/main/java/mpicbg/spim/data/generic/XmlIoAbstractSpimData.java
Original file line number Diff line number Diff line change
Expand Up @@ -199,12 +199,50 @@ protected URI loadBasePathURI( final Element root, final URI xmlURI ) throws Spi
return XmlHelpers.loadPathURI( root, BASEPATH_TAG, ".", parent );
}

/**
* Gets a URI's parent, e.g. the containing directory of a file.
* <p>
* This function behaves differently than the invocation
* {@code uri.resolve("..")} when the URI ends in a trailing slash:
* </p>
* <pre>{@code
* jshell> var u = new URI("file:/foo/bar/")
* u ==> file:/foo/bar/
*
* jshell> u.resolve("..")
* $2 ==> file:/foo/
*
* jshell> u = new URI("file:/foo/bar")
* u ==> file:/foo/bar
*
* jshell> u.resolve("..")
* $4 ==> file:/
* }</pre>
* <p>
* Whereas this function returns "file:/C:/foo/" in both cases.
*/
private static URI getParent( final URI uri ) throws SpimDataIOException
{
try
{
final String parent = Paths.get( uri.getPath() ).getParent().toString() + "/";
return new URI( uri.getScheme(), uri.getAuthority(), parent, uri.getQuery(), uri.getFragment() );
final String uriPath = uri.getPath();
final int parentSlash = uriPath.lastIndexOf( "/", uriPath.length() - 2 );
if ( parentSlash < 0 )
{
throw new SpimDataIOException( "URI is already at the root" );
}
// NB: The "+ 1" below is *very important*, so that the resultant URI
// ends in a trailing slash. The behaviour of URI differs depending on
// whether this trailing slash is present; specifically:
//
// * new URI("file:/foo/bar/").resolve(".") -> "file:/foo/bar/"
// * new URI("file:/foo/bar").resolve(".") -> "file:/foo/"
//
// That is: /foo/bar/ is considered to be in the directory /foo/bar,
// whereas /foo/bar is considered to be in the directory /foo.
final String parentPath = uriPath.substring( 0, parentSlash + 1 );
return new URI( uri.getScheme(), uri.getUserInfo(), uri.getHost(),
uri.getPort(), parentPath, uri.getQuery(), uri.getFragment() );
}
catch ( URISyntaxException e )
{
Expand Down

0 comments on commit 8acdc6b

Please sign in to comment.