diff --git a/src/main/java/com/upplication/s3fs/S3Path.java b/src/main/java/com/upplication/s3fs/S3Path.java index e67660e..7a460c6 100644 --- a/src/main/java/com/upplication/s3fs/S3Path.java +++ b/src/main/java/com/upplication/s3fs/S3Path.java @@ -1,9 +1,7 @@ package com.upplication.s3fs; -import com.google.common.base.*; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.Lists; -import com.upplication.s3fs.attribute.S3BasicFileAttributes; +import static com.google.common.collect.Iterables.concat; +import static java.lang.String.format; import java.io.File; import java.io.IOException; @@ -11,12 +9,20 @@ import java.net.URI; import java.net.URL; import java.net.URLDecoder; -import java.nio.file.*; +import java.net.URLEncoder; +import java.nio.file.LinkOption; +import java.nio.file.Path; +import java.nio.file.WatchEvent; +import java.nio.file.WatchKey; +import java.nio.file.WatchService; import java.util.Iterator; import java.util.List; -import static com.google.common.collect.Iterables.*; -import static java.lang.String.format; +import com.google.common.base.Preconditions; +import com.google.common.base.Splitter; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.Lists; +import com.upplication.s3fs.attribute.S3BasicFileAttributes; public class S3Path implements Path { @@ -583,10 +589,17 @@ public int hashCode() { * @return String */ private String encode(String uri) { - // remove special case URI starting with // - uri = uri.replace("//", "/"); - uri = uri.replaceAll(" ", "%20"); - return uri; + try { + // URL encode all characters, but then convert known allowed characters back + return URLEncoder.encode(uri, "UTF-8") + .replace("%3A", ":") + .replace("%2F", "/") + .replace("+", "%20"); + } catch (UnsupportedEncodingException e) { + // This should never happen unless there is something + // fundamentally broken with the running JVM. + throw new RuntimeException(e); + } } /** diff --git a/src/test/java/com/upplication/s3fs/Path/ToUriTest.java b/src/test/java/com/upplication/s3fs/Path/ToUriTest.java index 422c79c..fd302cd 100644 --- a/src/test/java/com/upplication/s3fs/Path/ToUriTest.java +++ b/src/test/java/com/upplication/s3fs/Path/ToUriTest.java @@ -1,13 +1,9 @@ package com.upplication.s3fs.Path; -import com.google.common.collect.ImmutableMap; -import com.upplication.s3fs.S3FileSystem; -import com.upplication.s3fs.S3FileSystemProvider; -import com.upplication.s3fs.S3Path; -import com.upplication.s3fs.S3UnitTestBase; -import com.upplication.s3fs.util.S3EndpointConstant; -import org.junit.Before; -import org.junit.Test; +import static com.upplication.s3fs.AmazonS3Factory.ACCESS_KEY; +import static com.upplication.s3fs.AmazonS3Factory.SECRET_KEY; +import static com.upplication.s3fs.util.S3EndpointConstant.S3_GLOBAL_URI_TEST; +import static org.junit.Assert.assertEquals; import java.io.IOException; import java.net.URI; @@ -15,11 +11,15 @@ import java.nio.file.Path; import java.util.Map; -import static com.upplication.s3fs.AmazonS3Factory.ACCESS_KEY; -import static com.upplication.s3fs.AmazonS3Factory.SECRET_KEY; -import static com.upplication.s3fs.util.S3EndpointConstant.*; +import org.junit.Before; +import org.junit.Test; -import static org.junit.Assert.assertEquals; +import com.google.common.collect.ImmutableMap; +import com.upplication.s3fs.S3FileSystem; +import com.upplication.s3fs.S3FileSystemProvider; +import com.upplication.s3fs.S3Path; +import com.upplication.s3fs.S3UnitTestBase; +import com.upplication.s3fs.util.S3EndpointConstant; public class ToUriTest extends S3UnitTestBase { @@ -50,6 +50,25 @@ public void toUri() { assertEquals(path, pathActual); } + @Test + public void toUriSpecialChars() { + Path path = getPath("/bucket/([fol! @#$%der])"); + URI uri = path.toUri(); + + // the scheme is s3 + assertEquals("s3", uri.getScheme()); + + // could get the correct fileSystem + S3FileSystem fs = s3fsProvider.getFileSystem(uri); + // the host is the endpoint specified in fileSystem + assertEquals(fs.getEndpoint(), uri.getHost()); + + // bucket name as first path + Path pathActual = fs.provider().getPath(uri); + + assertEquals(path, pathActual); + } + @Test public void toUriWithEndSlash() { S3Path s3Path = getPath("/bucket/folder/");