diff --git a/src/main/java/org/carlspring/cloud/storage/s3fs/S3Path.java b/src/main/java/org/carlspring/cloud/storage/s3fs/S3Path.java index a1ad2485..41058667 100644 --- a/src/main/java/org/carlspring/cloud/storage/s3fs/S3Path.java +++ b/src/main/java/org/carlspring/cloud/storage/s3fs/S3Path.java @@ -32,6 +32,7 @@ public class S3Path public static final String PATH_SEPARATOR = "/"; public static final String PATH_OTHER_INSTANCE_MESSAGE = "other must be an instance of %s"; + public static final String PATH_OTHER_INSTANCE_OR_RELATIVE_MESSAGE = "other must be an instance of %s or a relative Path"; /** * S3FileStore which represents the Bucket this path resides in. @@ -444,16 +445,34 @@ public Path normalize() @Override public Path resolve(Path other) { + String otherUri = ""; if (other.isAbsolute()) { Preconditions.checkArgument(other instanceof S3Path, - PATH_OTHER_INSTANCE_MESSAGE, + PATH_OTHER_INSTANCE_OR_RELATIVE_MESSAGE, S3Path.class.getName()); return other; } + else if (other instanceof S3Path) + { + S3Path otherS3Path = (S3Path) other; + otherUri = otherS3Path.uri; + } + else + { + int nameCount = other.getNameCount(); + for (int i = 0; i < nameCount; i++) + { + if (i > 0) + { + otherUri += PATH_SEPARATOR; + } + + otherUri += other.getName(i); + } + } - S3Path otherS3Path = (S3Path) other; StringBuilder pathBuilder = new StringBuilder(); if (this.isAbsolute()) @@ -463,9 +482,9 @@ public Path resolve(Path other) pathBuilder.append(this.uri); - if (!otherS3Path.uri.isEmpty()) + if (!otherUri.isEmpty()) { - pathBuilder.append(PATH_SEPARATOR + otherS3Path.uri); + pathBuilder.append(PATH_SEPARATOR + otherUri); } return new S3Path(this.fileSystem, pathBuilder.toString()); diff --git a/src/test/java/org/carlspring/cloud/storage/s3fs/path/ResolveTest.java b/src/test/java/org/carlspring/cloud/storage/s3fs/path/ResolveTest.java index 64dc15f1..d06dc587 100644 --- a/src/test/java/org/carlspring/cloud/storage/s3fs/path/ResolveTest.java +++ b/src/test/java/org/carlspring/cloud/storage/s3fs/path/ResolveTest.java @@ -6,12 +6,14 @@ import org.carlspring.cloud.storage.s3fs.util.S3EndpointConstant; import java.io.IOException; +import java.nio.file.Paths; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import static org.carlspring.cloud.storage.s3fs.util.S3EndpointConstant.S3_GLOBAL_URI_TEST; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; class ResolveTest extends S3UnitTestBase @@ -64,4 +66,34 @@ void resolve() assertEquals(getPath("/bucket2/other/child"), getPath("/bucket/path/to/file").resolve("/bucket2/other/child")); } + + @Test + void nonS3Paths() + { + S3Path parent = getPath("/bucket"); + S3Path child = getPath("/bucket/rabbit"); + S3Path deepChild = getPath("/bucket/rabbit/in/space"); + S3Path resolved = (S3Path) parent.resolve(child); + + assertEquals(child, resolved); + + resolved = (S3Path) parent.resolve("rabbit"); + assertEquals(child, resolved); + + resolved = (S3Path) parent.resolve(Paths.get("rabbit")); //unixPath + assertEquals(child, resolved); + + resolved = (S3Path) parent.resolve(Paths.get("rabbit").resolve("in").resolve("space")); + assertEquals(deepChild, resolved); + + resolved = (S3Path) parent.resolve(Paths.get("./rabbit")); //unixPath + assertEquals("s3://s3.test.amazonaws.com/bucket/./rabbit", resolved.toString()); + + resolved = (S3Path) parent.resolve(Paths.get("./rabbit in space")); //unixPath + assertEquals("s3://s3.test.amazonaws.com/bucket/./rabbit%20in%20space", resolved.toString()); + + IllegalArgumentException e = assertThrows(IllegalArgumentException.class, () -> + parent.resolve(Paths.get("tempDirectory").toAbsolutePath())); + assertEquals("other must be an instance of org.carlspring.cloud.storage.s3fs.S3Path or a relative Path", e.getMessage()); + } }