複数のイベントのセットは、ファイルの作成/変更に使用されるツールによって異なります。
1.Vimで新規ファイル作成
MODIFIED、CREATED イベントが発生する
2.Vimでファイルを修正
DELETED、MODIFIED、CREATED イベントが発生する
3.Linuxコマンド「mv」を使用して、ファイルを他のフォルダーから監視フォルダーに移動します
MODIFIED イベントが発生する
4.Linuxコマンド「cp」を使用して、ファイルを他のフォルダーから監視フォルダーにコピーします
同じファイル名のファイルが存在しない場合、MODIFIED、CREATED が実行されます。同じファイル名のファイルが存在する場合、CREATED が実行されます。
3 つのマップを使用して、WatchEvent を反復する for ループで CREATED/MODIFIED/DELETED エントリを収集しました。次に、これら 3 つのマップに対して 3 つの for ループを実行して、通知する必要がある正しいイベントを特定します (例: ファイル名が 3 つのマップすべてに表示される場合、それは MODIFIED イベントであると言えます)。
File f = new File(sourceDir);
if (!f.exists() || !f.isDirectory()) {
LOGGER.warn("File " + sourceDir + " does not exist OR is not a directory");
return;
}
WatchService watchService = FileSystems.getDefault().newWatchService();
Path watchedDir = f.toPath();
watchedDir.register(watchService, ENTRY_CREATE, ENTRY_DELETE, ENTRY_MODIFY);
while (true) {
try {
WatchKey watchKey = watchService.take();
Thread.sleep(checkInterval);
//Events fired by Java NIO file watcher depends on the tool used
//to create/update/delete file. We need those 3 maps to collect
//all entries fired by NIO watcher. Then, make 3 loops at the end
//to determine the correct unique event to notify
final Map<String, Boolean> createdEntries = new HashMap<>();
final Map<String, Boolean> modifiedEntries = new HashMap<>();
final Map<String, Boolean> deletedEntries = new HashMap<>();
List<WatchEvent<?>> events = watchKey.pollEvents();
for (WatchEvent<?> event : events) {
if (event.kind() == OVERFLOW) {
continue;
}
WatchEvent<Path> pathEvent = (WatchEvent<Path>) event;
WatchEvent.Kind<Path> kind = pathEvent.kind();
Path path = pathEvent.context();
String fileName = path.toString();
if (accept(fileName)) {
if (kind == ENTRY_CREATE) {
createdEntries.put(fileName, true);
} else if (kind == ENTRY_MODIFY) {
modifiedEntries.put(fileName, true);
} else if (kind == ENTRY_DELETE) {
deletedEntries.put(fileName, true);
}
}
}
long timeStamp = System.currentTimeMillis();
final Map<String, Boolean> handledEntries = new HashMap<>();
//3 for loops to determine correct event to notify
for (String key : createdEntries.keySet()) {
if (handledEntries.get(key) == null) {
Boolean modified = modifiedEntries.get(key);
Boolean deleted = deletedEntries.get(key);
if (modified != null && deleted != null) {
//A triplet of DELETED/MODIFIED/CREATED means a MODIFIED event
LOGGER.debug("File " + key + " was modified");
notifyFileModified(key, timeStamp);
} else if (modified != null) {
LOGGER.debug("New file " + key + " was created");
notifyFileCreated(key, timeStamp);
} else {
LOGGER.debug("New file " + key + " was created");
notifyFileCreated(key, timeStamp);
}
handledEntries.put(key, true);
}
}
for (String key : modifiedEntries.keySet()) {
if (handledEntries.get(key) == null) {
//Current entry survives from loop on CREATED entries. It is certain
//that we have MODIFIED event
LOGGER.debug("File " + key + " was modified");
notifyFileModified(key, timeStamp);
handledEntries.put(key, true);
}
}
for (String key : deletedEntries.keySet()) {
if (handledEntries.get(key) == null) {
//Current entry survives from two loops on CREATED/MODIFIED entries. It is certain
//that we have DELETE event
LOGGER.debug("File " + key + " was deleted");
notifyFileDeleted(key, timeStamp);
}
}
boolean valid = watchKey.reset();
if (!valid) {
break;
}
} catch (Exception ex) {
LOGGER.warn("Error while handling file events under: " + sourceDir, ex);
}
Thread.sleep(checkInterval);
}