Add null-safe variants of Files.isDirectory and Files.isRegularFile
Fixes
MODIFY
src/main/java/org/apache/commons/io/FileUtils.java
src/main/java/org/apache/commons/io/FileUtils.java
import java.nio.file.CopyOption;
import java.nio.file.Files;
import java.nio.file.LinkOption;
+import java.nio.file.NotDirectoryException;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
import java.time.Instant;
@@ -1490,12 +1491,32 @@ public static String getUserDirectoryPath() {
return System.getProperty("user.home");
}
+ /**
+ * Tests whether the specified {@code File} is a directory or not. Implemented as a
+ * null-safe delegate to {@code Files.isDirectory(Path path, LinkOption... options)}.
+ *
+ * @param file the path to the file.
+ * @param options options indicating how symbolic links are handled
+ * @return {@code true} if the file is a directory; {@code false} if
+ * the path is null, the file does not exist, is not a directory, or it cannot
+ * be determined if the file is a directory or not.
+ * @throws SecurityException In the case of the default provider, and a security manager is installed, the
+ * {@link SecurityManager#checkRead(String) checkRead} method is invoked to check read
+ * access to the directory.
+ * @since 2.9.0
+ */
+ public static boolean isDirectory(final File file, final LinkOption... options) {
+ return file != null ? Files.isDirectory(file.toPath(), options) : false;
+ }
+
/**
* Tests whether the directory is empty.
*
* @param directory the directory to query.
* @return whether the directory is empty.
* @throws IOException if an I/O error occurs.
+ * @throws NotDirectoryException if the file could not otherwise be opened because it is not a directory
+ * <i>(optional specific exception)</i>.
* @since 2.9.0
*/
public static boolean isEmptyDirectory(final File directory) throws IOException {
@@ -1823,6 +1844,24 @@ public static boolean isFileOlder(final File file, final long timeMillis) {
return file.exists() ? lastModifiedUnchecked(file) < timeMillis : false;
}
+ /**
+ * Tests whether the specified {@code File} is a regular file or not. Implemented as a
+ * null-safe delegate to {@code Files.isRegularFile(Path path, LinkOption... options)}.
+ *
+ * @param file the path to the file.
+ * @param options options indicating how symbolic links are handled
+ * @return {@code true} if the file is a regular file; {@code false} if
+ * the path is null, the file does not exist, is not a directory, or it cannot
+ * be determined if the file is a regular file or not.
+ * @throws SecurityException In the case of the default provider, and a security manager is installed, the
+ * {@link SecurityManager#checkRead(String) checkRead} method is invoked to check read
+ * access to the directory.
+ * @since 2.9.0
+ */
+ public static boolean isRegularFile(final File file, final LinkOption... options) {
+ return file != null ? Files.isRegularFile(file.toPath(), options) : false;
+ }
+
/**
* Tests whether the specified file is a symbolic link rather than an actual file.
* <p>

MODIFY
src/main/java/org/apache/commons/io/file/PathUtils.java
src/main/java/org/apache/commons/io/file/PathUtils.java
@@ -717,6 +717,24 @@ public static boolean fileContentEquals(final Path path1, final Path path2, fina
return fileAttributeView == null ? null : fileAttributeView.getAcl();
}
+ /**
+ * Tests whether the specified {@code Path} is a directory or not. Implemented as a
+ * null-safe delegate to {@code Files.isDirectory(Path path, LinkOption... options)}.
+ *
+ * @param path the path to the file.
+ * @param options options indicating how symbolic links are handled
+ * @return {@code true} if the file is a directory; {@code false} if
+ * the path is null, the file does not exist, is not a directory, or it cannot
+ * be determined if the file is a directory or not.
+ * @throws SecurityException In the case of the default provider, and a security manager is installed, the
+ * {@link SecurityManager#checkRead(String) checkRead} method is invoked to check read
+ * access to the directory.
+ * @since 2.9.0
+ */
+ public static boolean isDirectory(final Path path, final LinkOption... options) {
+ return path != null ? Files.isDirectory(path, options) : false;
+ }
+
/**
* Tests whether the given file or directory is empty.
*
@@ -781,6 +799,24 @@ public static boolean isNewer(final Path file, final long timeMillis, final Link
return Files.getLastModifiedTime(file, options).toMillis() > timeMillis;
}
+ /**
+ * Tests whether the specified {@code Path} is a regular file or not. Implemented as a
+ * null-safe delegate to {@code Files.isRegularFile(Path path, LinkOption... options)}.
+ *
+ * @param path the path to the file.
+ * @param options options indicating how symbolic links are handled
+ * @return {@code true} if the file is a regular file; {@code false} if
+ * the path is null, the file does not exist, is not a directory, or it cannot
+ * be determined if the file is a regular file or not.
+ * @throws SecurityException In the case of the default provider, and a security manager is installed, the
+ * {@link SecurityManager#checkRead(String) checkRead} method is invoked to check read
+ * access to the directory.
+ * @since 2.9.0
+ */
+ public static boolean isRegularFile(final Path path, final LinkOption... options) {
+ return path != null ? Files.isRegularFile(path, options) : false;
+ }
+
/**
* Creates a new DirectoryStream for Paths rooted at the given directory.
*

MODIFY
src/test/java/org/apache/commons/io/FileUtilsTestCase.java
src/test/java/org/apache/commons/io/FileUtilsTestCase.java
@@ -1779,6 +1779,30 @@ public void testIsFileNewerOlder() throws Exception {
assertThrows(IllegalArgumentException.class, () -> FileUtils.isFileOlder(oldFile, invalidFile));
}
+ @Test
+ public void testIsDirectory() throws IOException {
+ assertFalse(FileUtils.isDirectory(null));
+
+ assertTrue(FileUtils.isDirectory(temporaryFolder));
+ assertFalse(FileUtils.isDirectory(testFile1));
+
+ final Path tempDir = Files.createTempDirectory(getClass().getCanonicalName());
+ final File tempDirAsFile = tempDir.toFile();
+ Files.delete(tempDir);
+ assertFalse(FileUtils.isDirectory(tempDirAsFile));
+ }
+
+ @Test
+ public void testIsRegularFile() throws IOException {
+ assertFalse(FileUtils.isRegularFile(null));
+
+ assertFalse(FileUtils.isRegularFile(temporaryFolder));
+ assertTrue(FileUtils.isRegularFile(testFile1));
+
+ Files.delete(testFile1.toPath());
+ assertFalse(FileUtils.isRegularFile(testFile1));
+ }
+
@Test
public void testIterateFiles() throws Exception {
final File srcDir = temporaryFolder;

MODIFY
src/test/java/org/apache/commons/io/file/PathUtilsTest.java
src/test/java/org/apache/commons/io/file/PathUtilsTest.java
@@ -69,6 +69,31 @@ public void testCreateDirectoriesNew() throws IOException {
assertEquals(tempDir, PathUtils.createParentDirectories(tempDir.resolve("child")));
}
+ @Test
+ public void testIsDirectory() throws IOException {
+ assertFalse(PathUtils.isDirectory(null));
+
+ assertTrue(PathUtils.isDirectory(tempDir));
+ Path testFile1 = Files.createTempFile(tempDir, "prefix", null);
+ assertFalse(PathUtils.isDirectory(testFile1));
+
+ final Path tempDir = Files.createTempDirectory(getClass().getCanonicalName());
+ Files.delete(tempDir);
+ assertFalse(PathUtils.isDirectory(tempDir));
+ }
+
+ @Test
+ public void testIsRegularFile() throws IOException {
+ assertFalse(PathUtils.isRegularFile(null));
+
+ assertFalse(PathUtils.isRegularFile(tempDir));
+ Path testFile1 = Files.createTempFile(tempDir, "prefix", null);
+ assertTrue(PathUtils.isRegularFile(testFile1));
+
+ Files.delete(testFile1);
+ assertFalse(PathUtils.isRegularFile(testFile1));
+ }
+
@Test
public void testNewDirectoryStream() throws Exception {
final PathFilter pathFilter = new NameFileFilter(PATH_FIXTURE);

[IO-709] Add null-safe variants of Files.isDirectory and Files.isRegularFile (#194)

Fixes https://issues.apache.org/jira/browse/IO-709