From c80f07422f61b3da9034fc7a392e17f0a9144d84 Mon Sep 17 00:00:00 2001 From: Viraj Jasani Date: Wed, 12 May 2021 07:04:01 +0530 Subject: [PATCH] HADOOP-17686. Avoid potential NPE by using Path#getParentPath API in hadoop-huaweicloud (#2990) Signed-off-by: Takanobu Asanuma --- .../hadoop/fs/obs/OBSObjectBucketUtils.java | 9 +++++-- .../main/java/org/apache/hadoop/fs/Path.java | 26 ++++++++++++++++--- 2 files changed, 29 insertions(+), 6 deletions(-) diff --git a/hadoop-cloud-storage-project/hadoop-huaweicloud/src/main/java/org/apache/hadoop/fs/obs/OBSObjectBucketUtils.java b/hadoop-cloud-storage-project/hadoop-huaweicloud/src/main/java/org/apache/hadoop/fs/obs/OBSObjectBucketUtils.java index e632f61ca2d..ca29a965e99 100644 --- a/hadoop-cloud-storage-project/hadoop-huaweicloud/src/main/java/org/apache/hadoop/fs/obs/OBSObjectBucketUtils.java +++ b/hadoop-cloud-storage-project/hadoop-huaweicloud/src/main/java/org/apache/hadoop/fs/obs/OBSObjectBucketUtils.java @@ -55,6 +55,7 @@ import java.util.Collections; import java.util.Comparator; import java.util.LinkedList; import java.util.List; +import java.util.Optional; import java.util.Set; import java.util.TreeSet; import java.util.concurrent.ExecutionException; @@ -872,8 +873,12 @@ final class OBSObjectBucketUtils { directories.add(p.toString()); } while (p.compareTo(sourcePath) > 0) { - p = p.getParent(); - if (p.isRoot() || p.compareTo(sourcePath) == 0) { + Optional parent = p.getOptionalParentPath(); + if (!parent.isPresent()) { + break; + } + p = parent.get(); + if (p.compareTo(sourcePath) == 0) { break; } directories.add(p.toString()); diff --git a/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/Path.java b/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/Path.java index 2649d279aa1..f70ff01e4a0 100644 --- a/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/Path.java +++ b/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/Path.java @@ -24,6 +24,7 @@ import java.io.ObjectInputValidation; import java.io.Serializable; import java.net.URI; import java.net.URISyntaxException; +import java.util.Optional; import java.util.regex.Pattern; import org.apache.avro.reflect.Stringable; @@ -420,22 +421,39 @@ public class Path } /** - * Returns the parent of a path or null if at root. + * Returns the parent of a path or null if at root. Better alternative is + * {@link #getOptionalParentPath()} to handle nullable value for root path. + * * @return the parent of a path or null if at root */ public Path getParent() { + return getParentUtil(); + } + + /** + * Returns the parent of a path as {@link Optional} or + * {@link Optional#empty()} i.e an empty Optional if at root. + * + * @return Parent of path wrappen in {@link Optional}. + * {@link Optional#empty()} i.e an empty Optional if at root. + */ + public Optional getOptionalParentPath() { + return Optional.ofNullable(getParentUtil()); + } + + private Path getParentUtil() { String path = uri.getPath(); int lastSlash = path.lastIndexOf('/'); int start = startPositionWithoutWindowsDrive(path); if ((path.length() == start) || // empty path - (lastSlash == start && path.length() == start+1)) { // at root + (lastSlash == start && path.length() == start + 1)) { // at root return null; } String parent; - if (lastSlash==-1) { + if (lastSlash == -1) { parent = CUR_DIR; } else { - parent = path.substring(0, lastSlash==start?start+1:lastSlash); + parent = path.substring(0, lastSlash == start ? start + 1 : lastSlash); } return new Path(uri.getScheme(), uri.getAuthority(), parent); }