diff --git hcatalog/webhcat/svr/src/main/java/org/apache/hive/hcatalog/templeton/tool/TempletonUtils.java hcatalog/webhcat/svr/src/main/java/org/apache/hive/hcatalog/templeton/tool/TempletonUtils.java index e0ccc70d52..df94a475e6 100644 --- hcatalog/webhcat/svr/src/main/java/org/apache/hive/hcatalog/templeton/tool/TempletonUtils.java +++ hcatalog/webhcat/svr/src/main/java/org/apache/hive/hcatalog/templeton/tool/TempletonUtils.java @@ -36,6 +36,7 @@ import java.util.List; import java.util.Map; import java.util.Properties; +import java.util.Random; import java.util.StringTokenizer; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -320,16 +321,42 @@ public static boolean hadoopFsIsMissing(FileSystem fs, Path p) { public static String addUserHomeDirectoryIfApplicable(String origPathStr, String user) throws IOException, URISyntaxException { URI uri = new URI(origPathStr); + String plus = null; if (uri.getPath().isEmpty()) { String newPath = "/user/" + user; uri = UriBuilder.fromUri(uri).replacePath(newPath).build(); } else if (!new Path(uri.getPath()).isAbsolute()) { String newPath = "/user/" + user + "/" + uri.getPath(); + if(newPath.contains("+")) { + /** + * URLDecoder.decode() will change "+" to " ". + * May or may not be correct: https://stackoverflow.com/questions/1005676/urls-and-plus-signs + * Either way, "foo+bar" is a legal directory name in HDFS + * The following malarkey is to preserve the "+" to prevent this becoming a backwards + * compatibility issue + */ + Random r = new Random(); + plus = Integer.toString(r.nextInt(900000) + 100000);//6digit string + int limit = 1000; + while (newPath.contains(plus) && limit-- > 0) { + plus = Integer.toString(r.nextInt(900000) + 100000); + } + if(limit <= 0) { + throw new IllegalArgumentException("Cannot add home directory for '" + origPathStr + "\'"); + } + newPath = newPath.replace("+", plus); + } uri = UriBuilder.fromUri(uri).replacePath(newPath).build(); } // no work needed for absolute paths - return uri.toString(); + //Using UTF-8 per JavaDoc on decode(); + //need to decode() because UriBuilder UTF-8s multi-byte chars so directory names end up not + //like the user expects + if(plus != null) { + return URLDecoder.decode(uri.toString(), "UTF-8").replace(plus, "+"); + } + return URLDecoder.decode(uri.toString(), "UTF-8"); } public static Path hadoopFsPath(String fname, final Configuration conf, String user) diff --git hcatalog/webhcat/svr/src/test/java/org/apache/hive/hcatalog/templeton/tool/TestTempletonUtils.java hcatalog/webhcat/svr/src/test/java/org/apache/hive/hcatalog/templeton/tool/TestTempletonUtils.java index 3dcdd64844..43b26cd0cc 100644 --- hcatalog/webhcat/svr/src/test/java/org/apache/hive/hcatalog/templeton/tool/TestTempletonUtils.java +++ hcatalog/webhcat/svr/src/test/java/org/apache/hive/hcatalog/templeton/tool/TestTempletonUtils.java @@ -26,7 +26,6 @@ import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.fs.FileSystem; import org.apache.hadoop.hive.shims.HadoopShimsSecure; -import org.apache.hadoop.hive.shims.ShimLoader; import org.apache.hadoop.util.StringUtils; import org.junit.After; import org.junit.Assert; @@ -271,18 +270,19 @@ public void testConstructingUserHomeDirectory() throws Exception { String[] sources = new String[] { "output+", "/user/hadoop/output", "hdfs://container", "hdfs://container/", "hdfs://container/path", "output#link", "hdfs://cointaner/output#link", - "hdfs://container@acc/test" }; + "hdfs://container@acc/test", "/user/webhcat/düsseldorf", "düsseldorf", "䶴狝A﨩O" }; String[] expectedResults = new String[] { "/user/webhcat/output+", "/user/hadoop/output", "hdfs://container/user/webhcat", "hdfs://container/", "hdfs://container/path", "/user/webhcat/output#link", "hdfs://cointaner/output#link", - "hdfs://container@acc/test" }; + "hdfs://container@acc/test", "/user/webhcat/düsseldorf","/user/webhcat/düsseldorf", + "/user/webhcat/䶴狝A﨩O" }; for (int i = 0; i < sources.length; i++) { String source = sources[i]; String expectedResult = expectedResults[i]; String result = TempletonUtils.addUserHomeDirectoryIfApplicable(source, "webhcat"); - Assert.assertEquals(result, expectedResult); + Assert.assertEquals("i=" + i, expectedResult, result); } String badUri = "c:\\some\\path";