Last active
February 17, 2018 17:46
-
-
Save dangnhdev/09117687ab95e266c7bf to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.activestudy.Utility.file.watchservice; | |
import java.io.IOException; | |
import java.nio.file.*; | |
import java.util.*; | |
import static java.nio.file.StandardWatchEventKinds.*; | |
import java.nio.file.WatchEvent.Kind; | |
import java.nio.file.attribute.BasicFileAttributes; | |
/** | |
* A class based on NIO's WatchService to watch entire folder. | |
* | |
* @author NguyenHaiDang@ActiveStudy | |
*/ | |
public class WatchDirService implements Runnable { | |
private final WatchService watchService; | |
private final Map<WatchKey, Path> keyPathMap = new HashMap<>(); | |
private final WatchEvent.Kind[] eventKinds; | |
private Path currentFilePath; | |
private WatchEventAction onCreatedAction; | |
private WatchEventAction onModifiedAction; | |
private WatchEventAction onDeletedAction; | |
private final boolean all; | |
public WatchDirService(boolean all, WatchEvent.Kind... eventKinds) { | |
try { | |
this.watchService = FileSystems.getDefault().newWatchService(); | |
} catch (IOException ex) { | |
throw new RuntimeException("Cannot create watch service. Reason: ", ex); | |
} | |
this.eventKinds = eventKinds; | |
this.all = all; | |
} | |
/** | |
* This blocking method continously watch given directories until an | |
* exception throw or it have no job to do anymore (ex: folder deleted, | |
* permission changed...) | |
* | |
* @throws IOException | |
* @throws InterruptedException | |
*/ | |
private void watch() throws IOException, InterruptedException { | |
MAIN_LOOP: | |
while (true) { | |
final WatchKey key = watchService.take(); | |
INNER_LOOP: | |
for (WatchEvent<?> watchEvent : key.pollEvents()) { | |
final Kind<?> kind = watchEvent.kind(); | |
WatchEvent<Path> watchEventPath = (WatchEvent<Path>) watchEvent; | |
Path fileName = watchEventPath.context(); | |
Path parentDir = keyPathMap.get(key); | |
Path child = parentDir.resolve(fileName); | |
setCurrentFilePath(child); | |
if (kind == ENTRY_CREATE) { | |
if (Files.isDirectory(child, LinkOption.NOFOLLOW_LINKS) && all) { | |
registerDir(child); | |
} | |
performAction(onCreatedAction); | |
continue; | |
} | |
if (kind == ENTRY_MODIFY) { | |
performAction(onModifiedAction); | |
continue; | |
} | |
if (kind == ENTRY_DELETE) { | |
performAction(onDeletedAction); | |
} | |
} | |
boolean validKey = key.reset(); | |
if (!validKey) { | |
keyPathMap.remove(key); | |
if (keyPathMap.isEmpty()) { | |
watchService.close(); | |
break MAIN_LOOP; | |
} | |
} | |
} | |
} | |
private void registerPath(Path path) throws IOException { | |
WatchKey key = path.register(watchService, eventKinds); | |
keyPathMap.put(key, path); | |
} | |
/** | |
* Register a directory to watch | |
* | |
* @param dir Path, the Path object represent the directory | |
* @throws IOException | |
*/ | |
public void registerDir(Path dir) throws IOException { | |
if (Files.isDirectory(dir, LinkOption.NOFOLLOW_LINKS)) { | |
if (all) { | |
Files.walkFileTree(dir, new SimpleFileVisitor<Path>() { | |
@Override | |
public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) | |
throws IOException { | |
registerPath(dir); | |
return FileVisitResult.CONTINUE; | |
} | |
public FileVisitResult visitFileFailed(Path file, IOException exc) | |
throws IOException { | |
return FileVisitResult.CONTINUE; | |
} | |
}); | |
} else registerPath(dir); | |
} | |
} | |
private void setCurrentFilePath(Path file) { | |
currentFilePath = file; | |
} | |
/** | |
* | |
* @return the Path object of the file which is making current event | |
*/ | |
public Path getCurrentFilePath() { | |
return currentFilePath; | |
} | |
public void setOnCreatedAction(WatchEventAction onCreatedAction) { | |
this.onCreatedAction = onCreatedAction; | |
} | |
public void setOnModifiedAction(WatchEventAction onModifiedAction) { | |
this.onModifiedAction = onModifiedAction; | |
} | |
public void setOnDeletedAction(WatchEventAction onDeletedAction) { | |
this.onDeletedAction = onDeletedAction; | |
} | |
private void performAction(WatchEventAction ea) { | |
ea.doAction(); | |
} | |
@Override | |
public void run() { | |
try { | |
watch(); | |
} catch (IOException | InterruptedException ex) { | |
throw new RuntimeException(ex); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment