8262742: (fs) Add Path::resolve with varargs string
Reviewed-by: alanb
This commit is contained in:
parent
8008e27c55
commit
2bdfa836ad
src/java.base
test/jdk/java/nio/file/Path
@ -516,6 +516,90 @@ public interface Path
|
|||||||
return resolve(getFileSystem().getPath(other));
|
return resolve(getFileSystem().getPath(other));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resolves a path against this path, and then iteratively resolves any
|
||||||
|
* additional paths.
|
||||||
|
*
|
||||||
|
* <p> This method resolves {@code first} against this {@code Path} as if
|
||||||
|
* by calling {@link #resolve(Path)}. If {@code more} has one or more
|
||||||
|
* elements then it resolves the first element against the result, then
|
||||||
|
* iteratively resolves all subsequent elements. This method returns the
|
||||||
|
* result from the final resolve.
|
||||||
|
*
|
||||||
|
* @implSpec
|
||||||
|
* The default implementation is equivalent to the result obtained with:
|
||||||
|
* {@snippet lang=java :
|
||||||
|
* Path result = resolve(first);
|
||||||
|
* for (Path p : more) {
|
||||||
|
* result = result.resolve(p);
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* @param first
|
||||||
|
* the first path to resolve against this path
|
||||||
|
* @param more
|
||||||
|
* additional paths to iteratively resolve
|
||||||
|
*
|
||||||
|
* @return the resulting path
|
||||||
|
*
|
||||||
|
* @see #resolve(Path)
|
||||||
|
* @since 22
|
||||||
|
*/
|
||||||
|
default Path resolve(Path first, Path... more) {
|
||||||
|
Path result = resolve(first);
|
||||||
|
for (Path p : more) {
|
||||||
|
result = result.resolve(p);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts a path string to a path, resolves that path against this path,
|
||||||
|
* and then iteratively performs the same procedure for any additional
|
||||||
|
* path strings.
|
||||||
|
*
|
||||||
|
* <p> This method converts {@code first} to a {@code Path} and resolves
|
||||||
|
* that {@code Path} against this {@code Path} as if by calling
|
||||||
|
* {@link #resolve(String)}. If {@code more} has one or more elements
|
||||||
|
* then it converts the first element to a path, resolves that path against
|
||||||
|
* the result, then iteratively converts and resolves all subsequent
|
||||||
|
* elements. This method returns the result from the final resolve.
|
||||||
|
*
|
||||||
|
* @implSpec
|
||||||
|
* The default implementation is equivalent to the result obtained with:
|
||||||
|
* {@snippet lang=java :
|
||||||
|
* Path result = resolve(first);
|
||||||
|
* for (String s : more) {
|
||||||
|
* result = result.resolve(s);
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* @param first
|
||||||
|
* the first path string to convert to a path and
|
||||||
|
* resolve against this path
|
||||||
|
*
|
||||||
|
* @param more
|
||||||
|
* additional path strings to be iteratively converted to
|
||||||
|
* paths and resolved
|
||||||
|
*
|
||||||
|
* @return the resulting path
|
||||||
|
*
|
||||||
|
* @throws InvalidPathException
|
||||||
|
* if a path string cannot be converted to a Path.
|
||||||
|
*
|
||||||
|
* @see #resolve(Path,Path...)
|
||||||
|
* @see #resolve(String)
|
||||||
|
*
|
||||||
|
* @since 22
|
||||||
|
*/
|
||||||
|
default Path resolve(String first, String... more) {
|
||||||
|
Path result = resolve(first);
|
||||||
|
for (String s : more) {
|
||||||
|
result = result.resolve(s);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resolves the given path against this path's {@link #getParent parent}
|
* Resolves the given path against this path's {@link #getParent parent}
|
||||||
* path. This is useful where a file name needs to be <i>replaced</i> with
|
* path. This is useful where a file name needs to be <i>replaced</i> with
|
||||||
|
@ -397,6 +397,83 @@ class UnixPath implements Path {
|
|||||||
return resolve(new UnixPath(getFileSystem(), other));
|
return resolve(new UnixPath(getFileSystem(), other));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static final byte[] resolve(byte[] base, byte[]... children) {
|
||||||
|
// 'start' is either zero, indicating the base, or indicates which
|
||||||
|
// child is that last one which is an absolute path
|
||||||
|
int start = 0;
|
||||||
|
int resultLength = base.length;
|
||||||
|
|
||||||
|
// Locate the last child which is an absolute path and calculate
|
||||||
|
// the total number of bytes in the resolved path
|
||||||
|
final int count = children.length;
|
||||||
|
if (count > 0) {
|
||||||
|
for (int i = 0; i < count; i++) {
|
||||||
|
byte[] b = children[i];
|
||||||
|
if (b.length > 0) {
|
||||||
|
if (b[0] == '/') {
|
||||||
|
start = i + 1;
|
||||||
|
resultLength = b.length;
|
||||||
|
} else {
|
||||||
|
if (resultLength > 0)
|
||||||
|
resultLength++;
|
||||||
|
resultLength += b.length;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the base is not being superseded by a child which is an
|
||||||
|
// absolute path, then if at least one child is non-empty and
|
||||||
|
// the base consists only of a '/', then decrement resultLength to
|
||||||
|
// account for an extra '/' added in the resultLength computation.
|
||||||
|
if (start == 0 && resultLength > base.length && base.length == 1 && base[0] == '/')
|
||||||
|
resultLength--;
|
||||||
|
|
||||||
|
// Allocate the result array and return if empty.
|
||||||
|
byte[] result = new byte[resultLength];
|
||||||
|
if (result.length == 0)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
// Prepend the base if it is non-empty and would not later be
|
||||||
|
// overwritten by an absolute child
|
||||||
|
int offset = 0;
|
||||||
|
if (start == 0 && base.length > 0) {
|
||||||
|
System.arraycopy(base, 0, result, 0, base.length);
|
||||||
|
offset += base.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Append children starting with the last one which is an
|
||||||
|
// absolute path
|
||||||
|
if (count > 0) {
|
||||||
|
int idx = Math.max(0, start - 1);
|
||||||
|
for (int i = idx; i < count; i++) {
|
||||||
|
byte[] b = children[i];
|
||||||
|
if (b.length > 0) {
|
||||||
|
if (offset > 0 && result[offset - 1] != '/')
|
||||||
|
result[offset++] = '/';
|
||||||
|
System.arraycopy(b, 0, result, offset, b.length);
|
||||||
|
offset += b.length;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public UnixPath resolve(Path first, Path... more) {
|
||||||
|
if (more.length == 0)
|
||||||
|
return resolve(first);
|
||||||
|
|
||||||
|
byte[][] children = new byte[1 + more.length][];
|
||||||
|
children[0] = toUnixPath(first).path;
|
||||||
|
for (int i = 0; i < more.length; i++)
|
||||||
|
children[i + 1] = toUnixPath(more[i]).path;
|
||||||
|
|
||||||
|
byte[] result = resolve(path, children);
|
||||||
|
return new UnixPath(getFileSystem(), result);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public UnixPath relativize(Path obj) {
|
public UnixPath relativize(Path obj) {
|
||||||
UnixPath child = toUnixPath(obj);
|
UnixPath child = toUnixPath(obj);
|
||||||
|
@ -22,7 +22,8 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/* @test
|
/* @test
|
||||||
* @bug 4313887 6838333 6925932 7006126 8037945 8072495 8140449 8254876 8298478
|
* @bug 4313887 6838333 6925932 7006126 8037945 8072495 8140449 8254876 8262742
|
||||||
|
* 8298478
|
||||||
* @summary Unit test for java.nio.file.Path path operations
|
* @summary Unit test for java.nio.file.Path path operations
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -182,6 +183,27 @@ public class PathOps {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Note: "expected" is first parameter here
|
||||||
|
PathOps resolve(String expected, String first, String... more) {
|
||||||
|
out.format("test resolve %s varargs (String)\n", path());
|
||||||
|
checkPath();
|
||||||
|
check(path.resolve(first, more), expected);
|
||||||
|
Path[] others = new Path[more.length];
|
||||||
|
int i = 0;
|
||||||
|
for (String s : more) {
|
||||||
|
others[i++] = Path.of(s);
|
||||||
|
}
|
||||||
|
return resolve(expected, Path.of(first), others);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Note: "expected" is first parameter here
|
||||||
|
PathOps resolve(String expected, Path first, Path... more) {
|
||||||
|
out.format("test resolve %s varargs (Path)\n", path());
|
||||||
|
checkPath();
|
||||||
|
check(path.resolve(first, more), expected);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
PathOps resolveSibling(String other, String expected) {
|
PathOps resolveSibling(String other, String expected) {
|
||||||
out.format("test resolveSibling %s\n", other);
|
out.format("test resolveSibling %s\n", other);
|
||||||
checkPath();
|
checkPath();
|
||||||
@ -543,6 +565,35 @@ public class PathOps {
|
|||||||
.resolve("C:foo", "C:foo")
|
.resolve("C:foo", "C:foo")
|
||||||
.resolve("\\\\server\\share\\bar", "\\\\server\\share\\bar");
|
.resolve("\\\\server\\share\\bar", "\\\\server\\share\\bar");
|
||||||
|
|
||||||
|
// resolve - varargs
|
||||||
|
test("C:\\tmp")
|
||||||
|
.resolve("C:\\tmp\\foo\\bar\\gus", "foo", "bar", "gus")
|
||||||
|
.resolve("C:\\gus", "\\foo", "bar", "\\gus")
|
||||||
|
.resolve("C:\\tmp\\baz", "", "", "baz");
|
||||||
|
test("C:\\tmp\\foo")
|
||||||
|
.resolve("C:\\tmp\\foo\\bar\\gus", "", "bar\\gus", "")
|
||||||
|
.resolve("C:\\tmp\\foo\\bar\\gus\\foo\\baz",
|
||||||
|
"", "bar\\gus", "foo\\baz")
|
||||||
|
.resolve("C:\\bar\\gus\\baz", "", "C:\\bar\\gus", "baz")
|
||||||
|
.resolve("C:\\tmp\\bar", "C:\\bar\\gus", "baz", "C:\\tmp\\bar");
|
||||||
|
test("tmp")
|
||||||
|
.resolve("tmp\\foo\\bar\\gus", "foo", "bar", "gus")
|
||||||
|
.resolve("\\gus", "\\foo", "bar", "\\gus")
|
||||||
|
.resolve("tmp\\baz", "", "", "baz");
|
||||||
|
test("")
|
||||||
|
.resolve("", "", "")
|
||||||
|
.resolve("\\bar", "foo", "\\bar", "")
|
||||||
|
.resolve("foo\\bar\\gus", "foo", "bar", "gus")
|
||||||
|
.resolve("baz", "", "", "baz");
|
||||||
|
test("\\")
|
||||||
|
.resolve("\\foo", "foo", "")
|
||||||
|
.resolve("\\foo", "", "foo")
|
||||||
|
.resolve("\\bar", "foo", "", "\\bar");
|
||||||
|
test("C:")
|
||||||
|
.resolve("C:foo\\bar\\gus", "foo", "bar", "gus")
|
||||||
|
.resolve("C:baz", "", "baz")
|
||||||
|
.resolve("C:", "", "");
|
||||||
|
|
||||||
// resolveSibling
|
// resolveSibling
|
||||||
test("foo")
|
test("foo")
|
||||||
.resolveSibling("bar", "bar")
|
.resolveSibling("bar", "bar")
|
||||||
@ -1669,6 +1720,31 @@ public class PathOps {
|
|||||||
.resolve("foo", "foo")
|
.resolve("foo", "foo")
|
||||||
.resolve("/foo", "/foo");
|
.resolve("/foo", "/foo");
|
||||||
|
|
||||||
|
// resolve - varargs
|
||||||
|
test("/tmp")
|
||||||
|
.resolve("/tmp/foo/bar/gus", "foo", "bar", "gus")
|
||||||
|
.resolve("/gus", "/foo", "bar", "/gus")
|
||||||
|
.resolve("/tmp/baz", "", "", "baz");
|
||||||
|
test("/tmp/foo")
|
||||||
|
.resolve("/tmp/foo/bar/gus", "", "bar/gus", "")
|
||||||
|
.resolve("/tmp/foo/bar/gus/foo/baz", "", "bar/gus", "foo/baz")
|
||||||
|
.resolve("/bar/gus/baz", "", "/bar/gus", "baz")
|
||||||
|
.resolve("/tmp/bar", "/bar/gus", "baz", "/tmp/bar");
|
||||||
|
test("tmp")
|
||||||
|
.resolve("tmp/foo/bar/gus", "foo", "bar", "gus")
|
||||||
|
.resolve("/gus", "/foo", "bar", "/gus")
|
||||||
|
.resolve("tmp/baz", "", "", "baz");
|
||||||
|
test("")
|
||||||
|
.resolve("", "", "")
|
||||||
|
.resolve("/bar", "foo", "/bar", "")
|
||||||
|
.resolve("foo/bar/gus", "foo", "bar", "gus")
|
||||||
|
.resolve("baz", "", "", "baz");
|
||||||
|
test("/")
|
||||||
|
.resolve("/foo", "", "", "foo", "")
|
||||||
|
.resolve("/foo", "foo", "")
|
||||||
|
.resolve("/foo", "", "foo")
|
||||||
|
.resolve("/bar", "foo", "", "/bar");
|
||||||
|
|
||||||
// resolveSibling
|
// resolveSibling
|
||||||
test("foo")
|
test("foo")
|
||||||
.resolveSibling("bar", "bar")
|
.resolveSibling("bar", "bar")
|
||||||
@ -2077,7 +2153,7 @@ public class PathOps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Path.of("foo", null);
|
Path.of("foo", (String[])null);
|
||||||
throw new RuntimeException("NullPointerException not thrown");
|
throw new RuntimeException("NullPointerException not thrown");
|
||||||
} catch (NullPointerException npe) {
|
} catch (NullPointerException npe) {
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user