diff --git a/hadoop-tools/hadoop-aws/src/main/java/org/apache/hadoop/fs/s3a/S3AFileSystem.java b/hadoop-tools/hadoop-aws/src/main/java/org/apache/hadoop/fs/s3a/S3AFileSystem.java index fa7de69140fcf..e4b46e8c4ab5d 100644 --- a/hadoop-tools/hadoop-aws/src/main/java/org/apache/hadoop/fs/s3a/S3AFileSystem.java +++ b/hadoop-tools/hadoop-aws/src/main/java/org/apache/hadoop/fs/s3a/S3AFileSystem.java @@ -25,6 +25,7 @@ import java.io.InterruptedIOException; import java.io.UncheckedIOException; import java.net.URI; +import java.net.URISyntaxException; import java.nio.file.AccessDeniedException; import java.text.DateFormat; import java.text.SimpleDateFormat; @@ -1652,7 +1653,12 @@ public Path makeQualified(final Path path) { LOG.debug("Stripping trailing '/' from {}", q); // deal with an empty "/" at the end by mapping to the parent and // creating a new path from it - q = new Path(urlString.substring(0, urlString.length() - 1)); + try { + q = new Path(new URI(urlString.substring(0, urlString.length() - 1))); + } catch (URISyntaxException e) { + LOG.error(String.format("Error removing trailing / from path %s", path.toString())); + return q; + } } } if (!q.isRoot() && q.getName().isEmpty()) { diff --git a/hadoop-tools/hadoop-aws/src/test/java/org/apache/hadoop/fs/s3a/ITestS3AMiscOperations.java b/hadoop-tools/hadoop-aws/src/test/java/org/apache/hadoop/fs/s3a/ITestS3AMiscOperations.java index 4aa9c6a52eaa2..59170cd3460bb 100644 --- a/hadoop-tools/hadoop-aws/src/test/java/org/apache/hadoop/fs/s3a/ITestS3AMiscOperations.java +++ b/hadoop-tools/hadoop-aws/src/test/java/org/apache/hadoop/fs/s3a/ITestS3AMiscOperations.java @@ -313,6 +313,15 @@ public void testPathFixup() throws Throwable { fs.makeQualified(pathFromTrailingURI)); } + @Test + public void testQualifyPathWithWhitespace() { + final S3AFileSystem fs = getFileSystem(); + Path pathWithSpace = fs.makeQualified(new Path("path with space")); + Path pathWithSpaceTrailingSlash = fs.makeQualified(new Path("path with space/")); + // removing trailing / should not recreate the Path object in a URL encoded way + assertEquals(pathWithSpace, pathWithSpaceTrailingSlash); + } + /** * Verify that paths with a trailing "//" are fixed up. */