Forked from fabriziofortino/RecursiveWatcherService.java
Created
July 17, 2019 06:34
-
-
Save cgyy/82042685ed8e8a5c40ba68069b25d0fc to your computer and use it in GitHub Desktop.
Java 8 Recursive WatchService
This file contains 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.keepithttps; | |
import com.sun.nio.file.SensitivityWatchEventModifier; | |
import org.slf4j.Logger; | |
import org.slf4j.LoggerFactory; | |
import org.springframework.beans.factory.annotation.Value; | |
import org.springframework.stereotype.Service; | |
import java.io.File; | |
import java.io.IOException; | |
import java.nio.file.FileSystems; | |
import java.nio.file.FileVisitResult; | |
import java.nio.file.Files; | |
import java.nio.file.Path; | |
import java.nio.file.SimpleFileVisitor; | |
import java.nio.file.WatchEvent; | |
import java.nio.file.WatchKey; | |
import java.nio.file.WatchService; | |
import java.nio.file.attribute.BasicFileAttributes; | |
import java.util.HashMap; | |
import java.util.Map; | |
import java.util.concurrent.ExecutorService; | |
import java.util.concurrent.Executors; | |
import java.util.function.Consumer; | |
import javax.annotation.PostConstruct; | |
import javax.annotation.PreDestroy; | |
import static java.nio.file.StandardWatchEventKinds.ENTRY_CREATE; | |
import static java.nio.file.StandardWatchEventKinds.OVERFLOW; | |
@Service | |
public class RecursiWatcherService { | |
private static final Logger LOG = LoggerFactory.getLogger(RecursiWatcherService.class); | |
@Value("${root.folder}") | |
private File rootFolder; | |
private WatchService watcher; | |
private ExecutorService executor; | |
@PostConstruct | |
public void init() throws IOException { | |
watcher = FileSystems.getDefault().newWatchService(); | |
executor = Executors.newSingleThreadExecutor(); | |
startRecursiveWatcher(); | |
} | |
@PreDestroy | |
public void cleanup() { | |
try { | |
watcher.close(); | |
} catch (IOException e) { | |
LOG.error("Error closing watcher service", e); | |
} | |
executor.shutdown(); | |
} | |
private void startRecursiveWatcher() throws IOException { | |
LOG.info("Starting Recursive Watcher"); | |
final Map<WatchKey, Path> keys = new HashMap<>(); | |
Consumer<Path> register = p -> { | |
if (!p.toFile().exists() || !p.toFile().isDirectory()) { | |
throw new RuntimeException("folder " + p + " does not exist or is not a directory"); | |
} | |
try { | |
Files.walkFileTree(p, new SimpleFileVisitor<Path>() { | |
@Override | |
public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException { | |
LOG.info("registering " + dir + " in watcher service"); | |
WatchKey watchKey = dir.register(watcher, new WatchEvent.Kind[]{ENTRY_CREATE}, SensitivityWatchEventModifier.HIGH); | |
keys.put(watchKey, dir); | |
return FileVisitResult.CONTINUE; | |
} | |
}); | |
} catch (IOException e) { | |
throw new RuntimeException("Error registering path " + p); | |
} | |
}; | |
register.accept(rootFolder.toPath()); | |
executor.submit(() -> { | |
while (true) { | |
final WatchKey key; | |
try { | |
key = watcher.take(); // wait for a key to be available | |
} catch (InterruptedException ex) { | |
return; | |
} | |
final Path dir = keys.get(key); | |
if (dir == null) { | |
System.err.println("WatchKey " + key + " not recognized!"); | |
continue; | |
} | |
key.pollEvents().stream() | |
.filter(e -> (e.kind() != OVERFLOW)) | |
.map(e -> ((WatchEvent<Path>) e).context()) | |
.forEach(p -> { | |
final Path absPath = dir.resolve(p); | |
if (absPath.toFile().isDirectory()) { | |
register.accept(absPath); | |
} else { | |
final File f = absPath.toFile(); | |
LOG.info("Detected new file " + f.getAbsolutePath()); | |
} | |
}); | |
boolean valid = key.reset(); // IMPORTANT: The key must be reset after processed | |
if (!valid) { | |
break; | |
} | |
} | |
}); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment