Details
Description
FileUtils.isSymlink returns false for broken symlinks.
In contrast, java 7 java.nio.file.Files.isSymbolicLink() returns true for broken symlink.
One possible work around for java 6 and below is to use the fact that File.exists() returns false for a broken symlink and the fact that the file is found in its parents directory listing.
I don't have a compelling argument for fixing this, here is a candidate patch.
someguy@weeble:~/prog/java/commons-io/commons-io$ svn diff src/main/java/org/apache/commons/io/FileUtils.java Index: src/main/java/org/apache/commons/io/FileUtils.java =================================================================== --- src/main/java/org/apache/commons/io/FileUtils.java (revision 1609743) +++ src/main/java/org/apache/commons/io/FileUtils.java (working copy) @@ -3068,10 +3068,41 @@ } if (fileInCanonicalDir.getCanonicalFile().equals(fileInCanonicalDir.getAbsoluteFile())) { - return false; + return isBrokenSymlink(file); } else { return true; } } + /** + * Determines if the specified file is possibly a broken symbolic link. + * + * @param file the file to check + * @return true if the file is a Symbolic Link + * @throws IOException if an IO error occurs while checking the file + */ + private static boolean isBrokenSymlink(final File file) throws IOException { + // if file exists then if it is a symlink it's not broken + if ( file.exists() ) { + return false; + } + // a broken symlink will show up in the list of files of its parent directory + final File canon = file.getCanonicalFile(); + File parentDir = canon.getParentFile(); + if ( parentDir == null || ! parentDir.exists() ) { + return false; + } + + // is it worthwhile to create a FileFilterUtil method for this? + // is it worthwhile to create an "identity" IOFileFilter for this? + File[] fileInDir = parentDir.listFiles( + new FileFilter() { + public boolean accept( File aFile ) { + return aFile.equals(canon); + } + } + ); + return fileInDir.length > 0; + } + }
someguy@weeble:~/prog/java/commons-io/commons-io$ svn diff src/test/java/org/apache/commons/io/FileUtilsCleanSymlinksTestCase.java Index: src/test/java/org/apache/commons/io/FileUtilsCleanSymlinksTestCase.java =================================================================== --- src/test/java/org/apache/commons/io/FileUtilsCleanSymlinksTestCase.java (revision 1609743) +++ src/test/java/org/apache/commons/io/FileUtilsCleanSymlinksTestCase.java (working copy) @@ -203,6 +203,25 @@ assertFalse(FileUtils.isSymlink(randomFile)); } + public void testIdentifiesBrokenSymlinkFile() throws Exception { + if (System.getProperty("os.name").startsWith("Win")) { + // cant create symlinks in windows. + return; + } + + final File noexistFile = new File(top, "noexist"); + final File symlinkFile = new File(top, "fakeinner"); + final File badSymlinkInPathFile = new File(symlinkFile, "fakeinner"); + final File noexistParentFile = new File("noexist", "file"); + + setupSymlink(noexistFile, symlinkFile); + + assertTrue(FileUtils.isSymlink(symlinkFile)); + assertFalse(FileUtils.isSymlink(noexistFile)); + assertFalse(FileUtils.isSymlink(noexistParentFile)); + assertFalse(FileUtils.isSymlink(badSymlinkInPathFile)); + } + public void testCorrectlyIdentifySymlinkWithParentSymLink() throws Exception { if (System.getProperty("os.name").startsWith("Win")) { // cant create symlinks in windows.