* fix NPE

This commit is contained in:
Reinhard Pointner 2014-03-29 02:24:37 +00:00
parent 6b2659f2a4
commit 92a433a77f
1 changed files with 46 additions and 69 deletions

View File

@ -1,7 +1,5 @@
package net.sourceforge.filebot.cli; package net.sourceforge.filebot.cli;
import static java.nio.file.StandardWatchEventKinds.*; import static java.nio.file.StandardWatchEventKinds.*;
import static java.util.Collections.*; import static java.util.Collections.*;
import static net.sourceforge.tuned.FileUtilities.*; import static net.sourceforge.tuned.FileUtilities.*;
@ -29,18 +27,17 @@ import java.util.logging.Logger;
import net.sourceforge.tuned.DefaultThreadFactory; import net.sourceforge.tuned.DefaultThreadFactory;
import net.sourceforge.tuned.Timer; import net.sourceforge.tuned.Timer;
public abstract class FolderWatchService implements Closeable { public abstract class FolderWatchService implements Closeable {
private final Collection<File> commitSet = new HashSet<File>(); private final Collection<File> commitSet = new HashSet<File>();
private final ExecutorService processor = Executors.newSingleThreadExecutor(); private final ExecutorService processor = Executors.newSingleThreadExecutor();
private final ExecutorService watchers = Executors.newCachedThreadPool(new DefaultThreadFactory("FolderWatchService")); private final ExecutorService watchers = Executors.newCachedThreadPool(new DefaultThreadFactory("FolderWatchService"));
private long commitDelay = 500; // 0.5 s private long commitDelay = 500; // 0.5 s
private boolean commitPerFolder = true; private boolean commitPerFolder = true;
private final Timer commitTimer = new Timer() { private final Timer commitTimer = new Timer() {
@Override @Override
public void run() { public void run() {
synchronized (processor) { synchronized (processor) {
@ -48,37 +45,32 @@ public abstract class FolderWatchService implements Closeable {
} }
} }
}; };
private final boolean watchTree; private final boolean watchTree;
public FolderWatchService(boolean watchTree) { public FolderWatchService(boolean watchTree) {
this.watchTree = watchTree; this.watchTree = watchTree;
} }
public synchronized void setCommitPerFolder(boolean enabled) { public synchronized void setCommitPerFolder(boolean enabled) {
this.commitPerFolder = enabled; this.commitPerFolder = enabled;
} }
public synchronized void setCommitDelay(long commitDelay) { public synchronized void setCommitDelay(long commitDelay) {
if (commitDelay < 0) if (commitDelay < 0)
throw new IllegalArgumentException("Delay must not be negativ"); throw new IllegalArgumentException("Delay must not be negativ");
this.commitDelay = commitDelay; this.commitDelay = commitDelay;
resetCommitTimer(); resetCommitTimer();
} }
public synchronized void resetCommitTimer() { public synchronized void resetCommitTimer() {
commitTimer.set(commitDelay, TimeUnit.MILLISECONDS, false); commitTimer.set(commitDelay, TimeUnit.MILLISECONDS, false);
} }
public synchronized void commit() { public synchronized void commit() {
final SortedSet<File> files = new TreeSet<File>(); final SortedSet<File> files = new TreeSet<File>();
synchronized (commitSet) { synchronized (commitSet) {
for (File it : commitSet) { for (File it : commitSet) {
if (it.isFile()) { if (it.isFile()) {
@ -87,16 +79,16 @@ public abstract class FolderWatchService implements Closeable {
} }
commitSet.clear(); commitSet.clear();
} }
if (files.isEmpty()) { if (files.isEmpty()) {
return; return;
} }
// divide into commit batches per folder if required // divide into commit batches per folder if required
final Map<File, ? extends Collection<File>> commitBatches = commitPerFolder ? mapByFolder(files) : singletonMap((File) null, files); final Map<File, ? extends Collection<File>> commitBatches = commitPerFolder ? mapByFolder(files) : singletonMap((File) null, files);
processor.submit(new Runnable() { processor.submit(new Runnable() {
@Override @Override
public void run() { public void run() {
synchronized (processor) { synchronized (processor) {
@ -107,37 +99,36 @@ public abstract class FolderWatchService implements Closeable {
} }
}); });
} }
public abstract void processCommitSet(File[] files, File dir); public abstract void processCommitSet(File[] files, File dir);
public synchronized void watchFolder(File folder) throws IOException { public synchronized void watchFolder(File folder) throws IOException {
if (!watchTree) { if (!watchTree) {
startWatch(folder); startWatch(folder);
return; return;
} }
watchFolderTree(folder); watchFolderTree(folder);
} }
private void watchFolderTree(File root) throws IOException { private void watchFolderTree(File root) throws IOException {
for (File it : root.listFiles(FOLDERS)) { File[] folders = root.listFiles(FOLDERS);
watchFolderTree(it); if (folders != null) {
for (File it : folders) {
watchFolderTree(it);
}
} }
startWatch(root); startWatch(root);
} }
private synchronized void startWatch(File node) throws IOException { private synchronized void startWatch(File node) throws IOException {
if (!node.isDirectory()) { if (!node.isDirectory()) {
throw new IllegalArgumentException("Must be a folder: " + node); throw new IllegalArgumentException("Must be a folder: " + node);
} }
watchers.submit(new FolderWatcher(node) { watchers.submit(new FolderWatcher(node) {
@Override @Override
protected void processEvents(List<WatchEvent<?>> events) { protected void processEvents(List<WatchEvent<?>> events) {
synchronized (commitSet) { synchronized (commitSet) {
@ -145,8 +136,7 @@ public abstract class FolderWatchService implements Closeable {
super.processEvents(events); super.processEvents(events);
} }
} }
@Override @Override
protected void created(File file) { protected void created(File file) {
synchronized (commitSet) { synchronized (commitSet) {
@ -154,7 +144,7 @@ public abstract class FolderWatchService implements Closeable {
commitSet.add(file); commitSet.add(file);
return; return;
} }
// start watching newly created folder // start watching newly created folder
if (watchTree) { if (watchTree) {
try { try {
@ -166,8 +156,7 @@ public abstract class FolderWatchService implements Closeable {
} }
} }
} }
@Override @Override
protected void modified(File file) { protected void modified(File file) {
synchronized (commitSet) { synchronized (commitSet) {
@ -176,8 +165,7 @@ public abstract class FolderWatchService implements Closeable {
} }
} }
} }
@Override @Override
protected void deleted(File file) { protected void deleted(File file) {
synchronized (commitSet) { synchronized (commitSet) {
@ -186,29 +174,25 @@ public abstract class FolderWatchService implements Closeable {
} }
}); });
} }
@Override @Override
public synchronized void close() throws IOException { public synchronized void close() throws IOException {
commitTimer.cancel(); commitTimer.cancel();
processor.shutdownNow(); processor.shutdownNow();
watchers.shutdownNow(); watchers.shutdownNow();
} }
private abstract static class FolderWatcher implements Runnable, Closeable { private abstract static class FolderWatcher implements Runnable, Closeable {
private final Path node; private final Path node;
private final WatchService watchService; private final WatchService watchService;
public FolderWatcher(File node) throws IOException { public FolderWatcher(File node) throws IOException {
this.node = node.toPath(); this.node = node.toPath();
this.watchService = this.node.getFileSystem().newWatchService(); this.watchService = this.node.getFileSystem().newWatchService();
this.node.register(watchService, ENTRY_CREATE, ENTRY_MODIFY, ENTRY_DELETE); this.node.register(watchService, ENTRY_CREATE, ENTRY_MODIFY, ENTRY_DELETE);
} }
@Override @Override
public void run() { public void run() {
try { try {
@ -219,8 +203,7 @@ public abstract class FolderWatchService implements Closeable {
Logger.getLogger(getClass().getName()).log(Level.WARNING, e.getMessage(), e); Logger.getLogger(getClass().getName()).log(Level.WARNING, e.getMessage(), e);
} }
} }
public void watch() throws IOException, InterruptedException { public void watch() throws IOException, InterruptedException {
try { try {
boolean valid = true; boolean valid = true;
@ -233,13 +216,11 @@ public abstract class FolderWatchService implements Closeable {
this.close(); this.close();
} }
} }
public File getAbsoluteFile(WatchEvent event) { public File getAbsoluteFile(WatchEvent event) {
return node.resolve(event.context().toString()).toFile(); return node.resolve(event.context().toString()).toFile();
} }
protected void processEvents(List<WatchEvent<?>> list) { protected void processEvents(List<WatchEvent<?>> list) {
for (WatchEvent event : list) { for (WatchEvent event : list) {
if (event.kind() == ENTRY_CREATE) { if (event.kind() == ENTRY_CREATE) {
@ -251,21 +232,17 @@ public abstract class FolderWatchService implements Closeable {
} }
} }
} }
protected abstract void created(File file); protected abstract void created(File file);
protected abstract void modified(File file); protected abstract void modified(File file);
protected abstract void deleted(File file); protected abstract void deleted(File file);
@Override @Override
public void close() throws IOException { public void close() throws IOException {
watchService.close(); watchService.close();
} }
} }
} }