HADOOP-15536. Adding support in FileUtil for the creation of directories. Contributed by Giovanni Matteo Fumarola.
Project: http://git-wip-us.apache.org/repos/asf/hadoop/repo Commit: http://git-wip-us.apache.org/repos/asf/hadoop/commit/bac459b3 Tree: http://git-wip-us.apache.org/repos/asf/hadoop/tree/bac459b3 Diff: http://git-wip-us.apache.org/repos/asf/hadoop/diff/bac459b3 Branch: refs/heads/HADOOP-15461 Commit: bac459b3fffb62e04ecf39ebf0c3ff54b2dc49c0 Parents: 866646e Author: Inigo Goiri <inigo...@apache.org> Authored: Fri Jun 29 13:38:24 2018 -0700 Committer: Inigo Goiri <inigo...@apache.org> Committed: Tue Jul 24 18:30:49 2018 -0700 ---------------------------------------------------------------------- .../java/org/apache/hadoop/fs/FileUtil.java | 50 +++++ .../apache/hadoop/fs/TestFileUtilsMkDir.java | 205 +++++++++++++++++++ 2 files changed, 255 insertions(+) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/hadoop/blob/bac459b3/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/FileUtil.java ---------------------------------------------------------------------- diff --git a/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/FileUtil.java b/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/FileUtil.java index f3b5d58..bf3feb5 100644 --- a/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/FileUtil.java +++ b/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/FileUtil.java @@ -57,6 +57,7 @@ import java.util.zip.ZipInputStream; import org.apache.commons.collections.map.CaseInsensitiveMap; import org.apache.commons.compress.archivers.tar.TarArchiveEntry; import org.apache.commons.compress.archivers.tar.TarArchiveInputStream; +import org.apache.commons.io.FileExistsException; import org.apache.hadoop.classification.InterfaceAudience; import org.apache.hadoop.classification.InterfaceStability; import org.apache.hadoop.conf.Configuration; @@ -1638,4 +1639,53 @@ public class FileUtil { // check for ports return srcUri.getPort()==dstUri.getPort(); } + + /** + * Creates the directory named by the destination pathname, including any + * necessary but nonexistent parent directories. Note that if this operation + * fails it may have succeeded in creating some of the necessary parent + * directories. + * + * @param dst the directory which creation should be performed. + * @return 0 on success or if the directory was already present, 1 otherwise. + * @throws FileExistsException if the dst is an existing file + */ + public static int mkDirs(String dst) throws FileAlreadyExistsException { + // Null pointer input check + if (dst == null) { + LOG.warn("Can not create a directory with null path"); + return 1; + } + File directory = new File(dst); + + // Create the directory(ies) + boolean result = false; + try { + result = directory.mkdirs(); + } catch (SecurityException e) { + LOG.warn("Unable to create the directory {}. Exception = {}", dst, + e.getMessage()); + return 1; + } + + // Check if mkdir created successfully the directory(ies) + if (result) { + LOG.debug("Directory created successfully: {}", dst); + return 0; + } else { + // File already present check + if (directory.exists()) { + if (directory.isFile()) { + throw new FileAlreadyExistsException( + "Can not create a directory since a file is already present" + + " at the destination " + dst); + } + LOG.debug("Directory already present {}", dst); + return 0; + } + LOG.warn("Unable to create the directory {}", dst); + return 1; + } + } + } http://git-wip-us.apache.org/repos/asf/hadoop/blob/bac459b3/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/fs/TestFileUtilsMkDir.java ---------------------------------------------------------------------- diff --git a/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/fs/TestFileUtilsMkDir.java b/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/fs/TestFileUtilsMkDir.java new file mode 100644 index 0000000..0e6bfdb --- /dev/null +++ b/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/fs/TestFileUtilsMkDir.java @@ -0,0 +1,205 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.hadoop.fs; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.nio.file.FileAlreadyExistsException; + +import org.apache.hadoop.test.GenericTestUtils; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +public class TestFileUtilsMkDir { + + private static final File TEST_DIR = GenericTestUtils.getTestDir("nm"); + private final File del = new File(TEST_DIR, "del"); + + @Before + public void before() { + cleanupImpl(); + } + + @After + public void tearDown() { + cleanupImpl(); + } + + private void cleanupImpl() { + FileUtil.fullyDelete(del, true); + Assert.assertTrue(!del.exists()); + } + + /** + * This test validates the correctness of {@link FileUtil#mkDirs(String)} in + * case of null pointer inputs. + * + * @throws IOException + */ + @Test + public void testMkDirsWithNullInput() throws IOException { + int result = FileUtil.mkDirs(null); + Assert.assertEquals(1, result); + } + + /** + * This test validates the correctness of {@link FileUtil#mkDirs(String)}. + * + * @throws IOException + */ + @Test + public void testMkDirs() throws IOException { + Assert.assertFalse(del.exists()); + del.mkdirs(); + + File directory = new File(del, "newDirectory"); + Assert.assertFalse(directory.exists()); + + // Create the directory + int result = FileUtil.mkDirs(directory.getAbsolutePath()); + Assert.assertEquals(0, result); + + Assert.assertTrue(directory.exists()); + Assert.assertTrue(directory.isDirectory()); + + directory.delete(); + } + + /** + * This test validates the correctness of {@link FileUtil#mkDirs(String)} in + * case of multiple parents. + * + * @throws IOException + */ + @Test + public void testMkDirsMultipleParents() throws IOException { + Assert.assertFalse(del.exists()); + del.mkdirs(); + + File directory = new File(del, "newParent1/newParent2/newDirectory"); + Assert.assertFalse(directory.exists()); + + // Create the directory + int result = FileUtil.mkDirs(directory.getAbsolutePath()); + Assert.assertEquals(0, result); + + Assert.assertTrue(directory.exists()); + Assert.assertTrue(directory.isDirectory()); + + Assert.assertTrue(directory.getParentFile().exists()); + Assert.assertTrue(directory.getParentFile().isDirectory()); + + Assert.assertTrue(directory.getParentFile().getParentFile().exists()); + Assert.assertTrue(directory.getParentFile().getParentFile().isDirectory()); + + directory.getParentFile().getParentFile().delete(); + directory.getParentFile().delete(); + directory.delete(); + } + + /** + * This test validates the correctness of {@link FileUtil#mkDirs(String)} in + * case of multiple same executions of MkDir. + * + * @throws IOException + */ + @Test + public void testMkDirsMultipleTimes() throws IOException { + Assert.assertFalse(del.exists()); + del.mkdirs(); + + File directory = new File(del, "newDirectory"); + Assert.assertFalse(directory.exists()); + + // Create the directory + int result = FileUtil.mkDirs(directory.getAbsolutePath()); + Assert.assertEquals(0, result); + + Assert.assertTrue(directory.exists()); + Assert.assertTrue(directory.isDirectory()); + + result = FileUtil.mkDirs(directory.getAbsolutePath()); + Assert.assertEquals(0, result); + + directory.delete(); + } + + /** + * This test validates the correctness of {@link FileUtil#mkDirs(String)} in + * case of a creation over a file. + * + * @throws IOException + */ + @Test + public void testMkDirsOverAFile() throws IOException { + Assert.assertFalse(del.exists()); + del.mkdirs(); + + File falseDirectory = new File(del, "newDirectory"); + Assert.assertFalse(falseDirectory.exists()); + + byte[] data = "some data".getBytes(); + + // write some data to the file + FileOutputStream os = new FileOutputStream(falseDirectory); + os.write(data); + os.close(); + + // Create the directory + try { + FileUtil.mkDirs(falseDirectory.getAbsolutePath()); + Assert.fail("The test should fail with FileAlreadyExistsException"); + } catch (FileAlreadyExistsException e) { + Assert.assertTrue(e.getMessage().startsWith( + "Can not create a directory since a file is already present")); + } + } + + /** + * This test validates the correctness of {@link FileUtil#mkDirs(String)} in + * case of a creation underneath a file. + * + * @throws IOException + */ + @Test + public void testMkDirsUnderNeathAFile() throws IOException { + Assert.assertFalse(del.exists()); + del.mkdirs(); + + File newFile = new File(del, "newFile"); + Assert.assertFalse(newFile.exists()); + + byte[] data = "some data".getBytes(); + + // write some data to the file + FileOutputStream os = new FileOutputStream(newFile); + os.write(data); + os.close(); + + File falseDirectory = new File(del, "newFile/newDirectory"); + + // Create the directory + int result = FileUtil.mkDirs(falseDirectory.getAbsolutePath()); + Assert.assertEquals(1, result); + + Assert.assertFalse(falseDirectory.exists()); + } +} --------------------------------------------------------------------- To unsubscribe, e-mail: common-commits-unsubscr...@hadoop.apache.org For additional commands, e-mail: common-commits-h...@hadoop.apache.org