diff --git a/src/main/java/mpicbg/spim/data/generic/XmlIoAbstractSpimData.java b/src/main/java/mpicbg/spim/data/generic/XmlIoAbstractSpimData.java index 07a1de7..5c8504e 100644 --- a/src/main/java/mpicbg/spim/data/generic/XmlIoAbstractSpimData.java +++ b/src/main/java/mpicbg/spim/data/generic/XmlIoAbstractSpimData.java @@ -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. + *

+ * This function behaves differently than the invocation + * {@code uri.resolve("..")} when the URI ends in a trailing slash: + *

+ *
{@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:/
+	 * }
+ *

+ * 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 ) {