Skip to content

Instantly share code, notes, and snippets.

@mihaita-tinta
Created August 19, 2021 14:15
Show Gist options
  • Save mihaita-tinta/dd541d1c50ae366ddc7bf48a1e45e2fa to your computer and use it in GitHub Desktop.
Save mihaita-tinta/dd541d1c50ae366ddc7bf48a1e45e2fa to your computer and use it in GitHub Desktop.
MonitoringFileService scans for changes for a given file
package com.mih.webauthn.demo.file;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.FileSystemResource;
import org.springframework.stereotype.Service;
import java.io.IOException;
import java.nio.file.*;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Consumer;
import static java.nio.file.StandardWatchEventKinds.ENTRY_MODIFY;
@Service
public class MonitoringFileService {
private static final Logger log = LoggerFactory.getLogger(MonitoringFileService.class);
private final AtomicBoolean listen = new AtomicBoolean(false);
private final WatchKey key;
private final Path monitoringDirectory;
private final Path file;
private final List<Consumer<Path>> callbacks = new CopyOnWriteArrayList<>();
private final ExecutorService executorService = Executors.newSingleThreadExecutor();
public MonitoringFileService(@Value("${logging.file.path}") String directory, @Value("${logging.file.name:spring.log}") String fileName) throws IOException {
this.monitoringDirectory = new FileSystemResource(directory).getFile().toPath();
this.file = monitoringDirectory.resolve(fileName);
final WatchService ws = FileSystems.getDefault().newWatchService();
key = monitoringDirectory.register(ws, ENTRY_MODIFY);
executorService.submit(() -> monitor());
}
public void listen(Consumer<Path> consumer) {
callbacks.add(consumer);
}
void monitor() {
listen.set(true);
while (listen.get()) {
try {
Thread.sleep(50);
for (final WatchEvent<?> event : key.pollEvents()) {
final Path changed = monitoringDirectory.resolve((Path) event.context());
if (event.kind() == ENTRY_MODIFY && changed.equals(file)) {
log.trace("monitor - ENTRY_MODIFY: " + changed);
callbacks.forEach(c -> c.accept(changed));
}
}
boolean isKeyStillValid = key.reset();
if (!isKeyStillValid) {
log.trace("monitor - key is no longer valid: " + key);
listen.set(false);
}
} catch (InterruptedException ex) {
listen.set(false);
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment