From 90951f79898fe8d7eec94329a99d94b409b8d7f0 Mon Sep 17 00:00:00 2001 From: Reinhard Pointner Date: Mon, 28 Jul 2014 10:00:27 +0000 Subject: [PATCH] * avoid potentially NULL-listFiles() calls --- source/net/filebot/Main.java | 2 +- source/net/filebot/cli/CmdlineOperations.java | 13 ++-- .../net/filebot/cli/FolderWatchService.java | 7 +-- .../net/filebot/format/MediaBindingBean.java | 10 +-- .../filebot/hash/VerificationUtilities.java | 62 ++++++++----------- source/net/filebot/media/MediaDetection.java | 4 +- source/net/filebot/media/ReleaseInfo.java | 14 ++--- .../filebot/ui/rename/MovieHashMatcher.java | 4 +- .../sfv/ChecksumTableTransferablePolicy.java | 2 +- .../TransferablePolicyFileFilter.java | 21 ++++--- source/net/filebot/util/FileUtilities.java | 28 ++++++++- 11 files changed, 85 insertions(+), 82 deletions(-) diff --git a/source/net/filebot/Main.java b/source/net/filebot/Main.java index c80291e9..14cefab3 100644 --- a/source/net/filebot/Main.java +++ b/source/net/filebot/Main.java @@ -92,7 +92,7 @@ public class Main { if (args.clearCache()) { // clear preferences and cache System.out.println("Clear cache and temporary files"); - for (File folder : getApplicationFolder().getAbsoluteFile().listFiles(FOLDERS)) { + for (File folder : getChildren(getApplicationFolder().getAbsoluteFile(), FOLDERS)) { if (matches("cache|temp|grape|reports|logs", folder.getName())) { if (delete(folder)) { System.out.println("* Delete " + folder); diff --git a/source/net/filebot/cli/CmdlineOperations.java b/source/net/filebot/cli/CmdlineOperations.java index f7f1e438..a6376498 100644 --- a/source/net/filebot/cli/CmdlineOperations.java +++ b/source/net/filebot/cli/CmdlineOperations.java @@ -150,7 +150,8 @@ public class CmdlineOperations implements CmdlineInterface { return renameAll(renameMap, renameAction, ConflictAction.forName(conflict), null); } - public List renameSeries(Collection files, RenameAction renameAction, ConflictAction conflictAction, File outputDir, ExpressionFormat format, EpisodeListProvider db, String query, SortOrder sortOrder, ExpressionFilter filter, Locale locale, boolean strict) throws Exception { + public List renameSeries(Collection files, RenameAction renameAction, ConflictAction conflictAction, File outputDir, ExpressionFormat format, EpisodeListProvider db, String query, SortOrder sortOrder, ExpressionFilter filter, Locale locale, boolean strict) + throws Exception { CLILogger.config(format("Rename episodes using [%s]", db.getName())); // ignore sample files @@ -344,10 +345,10 @@ public class CmdlineOperations implements CmdlineInterface { // collect useful nfo files even if they are not part of the selected fileset Set effectiveNfoFileSet = new TreeSet(nfoFiles); for (File dir : mapByFolder(movieFiles).keySet()) { - addAll(effectiveNfoFileSet, dir.listFiles(NFO_FILES)); + effectiveNfoFileSet.addAll(getChildren(dir, NFO_FILES)); } for (File dir : filter(fileset, FOLDERS)) { - addAll(effectiveNfoFileSet, dir.listFiles(NFO_FILES)); + effectiveNfoFileSet.addAll(getChildren(dir, NFO_FILES)); } for (File nfo : effectiveNfoFileSet) { @@ -758,7 +759,7 @@ public class CmdlineOperations implements CmdlineInterface { List videoFiles = filter(filter(files, VIDEO_FILES), new FileFilter() { // save time on repeating filesystem calls - private final Map cache = new HashMap(); + private final Map> cache = new HashMap>(); private final SubtitleNaming naming = getSubtitleNaming(format); @@ -776,9 +777,9 @@ public class CmdlineOperations implements CmdlineInterface { @Override public boolean accept(File video) { - File[] subtitlesByFolder = cache.get(video.getParentFile()); + List subtitlesByFolder = cache.get(video.getParentFile()); if (subtitlesByFolder == null) { - subtitlesByFolder = video.getParentFile().listFiles(SUBTITLE_FILES); + subtitlesByFolder = getChildren(video.getParentFile(), SUBTITLE_FILES); cache.put(video.getParentFile(), subtitlesByFolder); } diff --git a/source/net/filebot/cli/FolderWatchService.java b/source/net/filebot/cli/FolderWatchService.java index 6fc2d99d..f80040e2 100644 --- a/source/net/filebot/cli/FolderWatchService.java +++ b/source/net/filebot/cli/FolderWatchService.java @@ -112,11 +112,8 @@ public abstract class FolderWatchService implements Closeable { } private void watchFolderTree(File root) throws IOException { - File[] folders = root.listFiles(FOLDERS); - if (folders != null) { - for (File it : folders) { - watchFolderTree(it); - } + for (File it : getChildren(root, FOLDERS)) { + watchFolderTree(it); } startWatch(root); diff --git a/source/net/filebot/format/MediaBindingBean.java b/source/net/filebot/format/MediaBindingBean.java index cfa57f98..ab8b537d 100644 --- a/source/net/filebot/format/MediaBindingBean.java +++ b/source/net/filebot/format/MediaBindingBean.java @@ -501,7 +501,7 @@ public class MediaBindingBean { if (hasExtension(mediaFile, "idx")) { return Language.getLanguage(grepLanguageFromSUBIDX(mediaFile)); } else if (hasExtension(mediaFile, "sub")) { - for (File idx : mediaFile.getParentFile().listFiles(new ExtensionFileFilter("idx"))) { + for (File idx : getChildren(mediaFile.getParentFile(), new ExtensionFileFilter("idx"))) { if (isDerived(idx, mediaFile)) { return Language.getLanguage(grepLanguageFromSUBIDX(idx)); } @@ -807,7 +807,7 @@ public class MediaBindingBean { // file is a subtitle, or nfo, etc String baseName = stripReleaseInfo(FileUtilities.getName(mediaFile)).toLowerCase(); - File[] videos = mediaFile.getParentFile().listFiles(VIDEO_FILES); + List videos = getChildren(mediaFile.getParentFile(), VIDEO_FILES); // find corresponding movie file for (File movieFile : videos) { @@ -817,15 +817,15 @@ public class MediaBindingBean { } // still no good match found -> just take the most probable video from the same folder - if (videos.length > 0) { - sort(videos, new SimilarityComparator(FileUtilities.getName(mediaFile)) { + if (videos.size() > 0) { + videos.sort(new SimilarityComparator(FileUtilities.getName(mediaFile)) { @Override public int compare(Object o1, Object o2) { return super.compare(FileUtilities.getName((File) o1), FileUtilities.getName((File) o2)); } }); - return videos[0]; + return videos.get(0); } } diff --git a/source/net/filebot/hash/VerificationUtilities.java b/source/net/filebot/hash/VerificationUtilities.java index b5e1dc94..a9452151 100644 --- a/source/net/filebot/hash/VerificationUtilities.java +++ b/source/net/filebot/hash/VerificationUtilities.java @@ -1,7 +1,5 @@ - package net.filebot.hash; - import static net.filebot.util.FileUtilities.*; import java.io.File; @@ -12,51 +10,45 @@ import java.util.Map.Entry; import java.util.regex.Matcher; import java.util.regex.Pattern; - public final class VerificationUtilities { - + /** - * A {@link Pattern} that will match checksums enclosed in brackets ("[]" or "()"). A - * checksum string is a hex number with at least 8 digits. Capturing group 0 will contain - * the matched checksum string. + * A {@link Pattern} that will match checksums enclosed in brackets ("[]" or "()"). A checksum string is a hex number with at least 8 digits. Capturing group 0 will contain the matched checksum string. */ public static final Pattern EMBEDDED_CHECKSUM = Pattern.compile("(?<=\\[|\\()(\\p{XDigit}{8})(?=\\]|\\))"); - - + public static String getEmbeddedChecksum(CharSequence string) { Matcher matcher = EMBEDDED_CHECKSUM.matcher(string); String embeddedChecksum = null; - + // get last match while (matcher.find()) { embeddedChecksum = matcher.group(); } - + return embeddedChecksum; } - - + public static String getHashFromVerificationFile(File file, HashType type, int maxDepth) throws IOException { return getHashFromVerificationFile(file.getParentFile(), file, type, 0, maxDepth); } - - + private static String getHashFromVerificationFile(File folder, File target, HashType type, int depth, int maxDepth) throws IOException { // stop if we reached max depth or the file system root if (folder == null || depth > maxDepth) return null; - + // scan all sfv files in this folder - for (File verificationFile : folder.listFiles(type.getFilter())) { + for (File verificationFile : getChildren(folder, type.getFilter())) { VerificationFileReader parser = new VerificationFileReader(createTextReader(verificationFile), type.getFormat()); - + try { while (parser.hasNext()) { Entry entry = parser.next(); - + // resolve relative file path File file = new File(folder, entry.getKey().getPath()); - + if (target.equals(file)) { return entry.getValue(); } @@ -65,44 +57,41 @@ public final class VerificationUtilities { parser.close(); } } - + return getHashFromVerificationFile(folder.getParentFile(), target, type, depth + 1, maxDepth); } - - + public static HashType getHashType(File verificationFile) { for (HashType hashType : HashType.values()) { if (hashType.getFilter().accept(verificationFile)) return hashType; } - + return null; } - - + public static HashType getHashTypeByExtension(String extension) { for (HashType hashType : HashType.values()) { if (hashType.getFilter().acceptExtension(extension)) return hashType; } - + return null; } - - + public static String computeHash(File file, HashType type) throws IOException, InterruptedException { Hash hash = type.newHash(); - + // calculate checksum InputStream in = new FileInputStream(file); - + try { byte[] buffer = new byte[32 * 1024]; int len = 0; - + while ((len = in.read(buffer)) >= 0) { hash.update(buffer, 0, len); - + // make this long-running operation interruptible if (Thread.interrupted()) throw new InterruptedException(); @@ -110,16 +99,15 @@ public final class VerificationUtilities { } finally { in.close(); } - + return hash.digest(); } - - + /** * Dummy constructor to prevent instantiation. */ private VerificationUtilities() { throw new UnsupportedOperationException(); } - + } diff --git a/source/net/filebot/media/MediaDetection.java b/source/net/filebot/media/MediaDetection.java index b828d5a6..511bac6d 100644 --- a/source/net/filebot/media/MediaDetection.java +++ b/source/net/filebot/media/MediaDetection.java @@ -1103,7 +1103,7 @@ public class MediaDetection { if (file.isDirectory()) { nfoFiles.addAll(filter(listFiles(file), NFO_FILES)); } else if (file.getParentFile().isDirectory()) { - addAll(nfoFiles, file.getParentFile().listFiles(NFO_FILES)); + nfoFiles.addAll(getChildren(file.getParentFile(), NFO_FILES)); } // parse ids from nfo files @@ -1135,7 +1135,7 @@ public class MediaDetection { if (!folder.exists()) continue; - for (File nfo : folder.listFiles(NFO_FILES)) { + for (File nfo : getChildren(folder, NFO_FILES)) { String text = new String(readFile(nfo), "UTF-8"); for (int imdbid : grepImdbId(text)) { diff --git a/source/net/filebot/media/ReleaseInfo.java b/source/net/filebot/media/ReleaseInfo.java index b4eb1bc2..cd2f4f4c 100644 --- a/source/net/filebot/media/ReleaseInfo.java +++ b/source/net/filebot/media/ReleaseInfo.java @@ -194,24 +194,18 @@ public class ReleaseInfo { volumes.add(new File(System.getProperty("user.home"))); // Windows / Linux / Mac system roots - addAll(volumes, File.listRoots()); + volumes.addAll(getFileSystemRoots()); if (File.separator.equals("/")) { // Linux and Mac system root folders - for (File root : File.listRoots()) { - File[] f = root.listFiles(FOLDERS); - if (f != null) { - addAll(volumes, f); - } + for (File root : getFileSystemRoots()) { + volumes.addAll(getChildren(root, FOLDERS)); } // user-specific media roots for (File root : getMediaRoots()) { if (root.isDirectory()) { - File[] f = root.listFiles(FOLDERS); - if (f != null) { - addAll(volumes, f); - } + volumes.addAll(getChildren(root, FOLDERS)); } } } diff --git a/source/net/filebot/ui/rename/MovieHashMatcher.java b/source/net/filebot/ui/rename/MovieHashMatcher.java index 03df73c9..f2b08978 100644 --- a/source/net/filebot/ui/rename/MovieHashMatcher.java +++ b/source/net/filebot/ui/rename/MovieHashMatcher.java @@ -112,10 +112,10 @@ class MovieHashMatcher implements AutoCompleteMatcher { // collect useful nfo files even if they are not part of the selected fileset Set effectiveNfoFileSet = new TreeSet(nfoFiles); for (File dir : mapByFolder(movieFiles).keySet()) { - addAll(effectiveNfoFileSet, dir.listFiles(NFO_FILES)); + effectiveNfoFileSet.addAll(getChildren(dir, NFO_FILES)); } for (File dir : filter(fileset, FOLDERS)) { - addAll(effectiveNfoFileSet, dir.listFiles(NFO_FILES)); + effectiveNfoFileSet.addAll(getChildren(dir, NFO_FILES)); } for (File nfo : effectiveNfoFileSet) { diff --git a/source/net/filebot/ui/sfv/ChecksumTableTransferablePolicy.java b/source/net/filebot/ui/sfv/ChecksumTableTransferablePolicy.java index c4c20dcb..d50bad73 100644 --- a/source/net/filebot/ui/sfv/ChecksumTableTransferablePolicy.java +++ b/source/net/filebot/ui/sfv/ChecksumTableTransferablePolicy.java @@ -198,7 +198,7 @@ class ChecksumTableTransferablePolicy extends BackgroundFileTransferablePolicy getChildren(File file) { - File[] files = file.listFiles(); + public static List getFileSystemRoots() { + File[] roots = File.listRoots(); + + // roots array may be null if folder permissions do not allow listing of files + if (roots == null) { + roots = new File[0]; + } + + return asList(roots); + } + + public static List getChildren(File folder) { + File[] files = folder.listFiles(); // children array may be null if folder permissions do not allow listing of files if (files == null) { - return asList(new File[0]); + files = new File[0]; + } + + return asList(files); + } + + public static List getChildren(File folder, FileFilter filter) { + File[] files = folder.listFiles(filter); + + // children array may be null if folder permissions do not allow listing of files + if (files == null) { + files = new File[0]; } return asList(files);