Skip to content

Commit 02dd9aa

Browse files
committed
Make the getParent(URI) helper more robust
This fixes the behavior on Windows, avoiding InvalidPathExceptions.
1 parent 61911bf commit 02dd9aa

File tree

1 file changed

+34
-2
lines changed

1 file changed

+34
-2
lines changed

src/main/java/mpicbg/spim/data/generic/XmlIoAbstractSpimData.java

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -199,12 +199,44 @@ protected URI loadBasePathURI( final Element root, final URI xmlURI ) throws Spi
199199
return XmlHelpers.loadPathURI( root, BASEPATH_TAG, ".", parent );
200200
}
201201

202+
/**
203+
* Gets a URI's parent, e.g. the containing directory of a file.
204+
* <p>
205+
* This function behaves differently than the invocation
206+
* {@code uri.resolve("..")} when the URI ends in a trailing slash:
207+
* </p>
208+
* <pre>{@code
209+
* jshell> new URI("file:/foo/bar/").resolve("..")
210+
* $1 ==> file:/foo/
211+
*
212+
* jshell> new URI("file:/foo/bar").resolve("..")
213+
* $2 ==> file:/
214+
* }</pre>
215+
* <p>
216+
* Whereas this function returns "file:/foo/" in both cases.
217+
*/
202218
private static URI getParent( final URI uri ) throws SpimDataIOException
203219
{
204220
try
205221
{
206-
final String parent = Paths.get( uri.getPath() ).getParent().toString() + "/";
207-
return new URI( uri.getScheme(), uri.getAuthority(), parent, uri.getQuery(), uri.getFragment() );
222+
final String uriPath = uri.getPath();
223+
final int parentSlash = uriPath.lastIndexOf( "/", uriPath.length() - 2 );
224+
if ( parentSlash < 0 )
225+
{
226+
throw new SpimDataIOException( "URI is already at the root" );
227+
}
228+
// NB: The "+ 1" below is *very important*, so that the resultant URI
229+
// ends in a trailing slash. The behaviour of URI differs depending on
230+
// whether this trailing slash is present; specifically:
231+
//
232+
// * new URI("file:/foo/bar/").resolve(".") -> "file:/foo/bar/"
233+
// * new URI("file:/foo/bar").resolve(".") -> "file:/foo/"
234+
//
235+
// That is: /foo/bar/ is considered to be in the directory /foo/bar,
236+
// whereas /foo/bar is considered to be in the directory /foo.
237+
final String parentPath = uriPath.substring( 0, parentSlash + 1 );
238+
return new URI( uri.getScheme(), uri.getUserInfo(), uri.getHost(),
239+
uri.getPort(), parentPath, uri.getQuery(), uri.getFragment() );
208240
}
209241
catch ( URISyntaxException e )
210242
{

0 commit comments

Comments
 (0)