package org.springblade.mdm.machineback.filewatch;
|
|
import org.springframework.stereotype.Service;
|
|
import java.io.IOException;
|
import java.nio.file.*;
|
import java.util.HashMap;
|
import java.util.Map;
|
import java.util.concurrent.ExecutorService;
|
import java.util.concurrent.Executors;
|
|
import static java.nio.file.StandardWatchEventKinds.*;
|
@Service
|
public class FileWatcherService {
|
|
private final ExecutorService executor = Executors.newCachedThreadPool();
|
private final Map<Path, WatchService> watchServices = new HashMap<>();
|
private final Map<Path, FileChangeListener> listeners = new HashMap<>();
|
|
public interface FileChangeListener {
|
void onFileCreated(Path filePath);
|
void onFileModified(Path filePath);
|
void onFileDeleted(Path filePath);
|
}
|
|
public void watchDirectory(Path directory, FileChangeListener listener) throws IOException {
|
if (!Files.isDirectory(directory)) {
|
throw new IllegalArgumentException("Path must be a directory: " + directory);
|
}
|
|
if (watchServices.containsKey(directory)) {
|
throw new IllegalStateException("Directory is already being watched: " + directory);
|
}
|
|
WatchService watchService = FileSystems.getDefault().newWatchService();
|
directory.register(watchService, ENTRY_CREATE, ENTRY_MODIFY, ENTRY_DELETE);
|
|
watchServices.put(directory, watchService);
|
listeners.put(directory, listener);
|
|
executor.submit(() -> {
|
try {
|
while (true) {
|
WatchKey key = watchService.take();
|
for (WatchEvent<?> event : key.pollEvents()) {
|
WatchEvent.Kind<?> kind = event.kind();
|
|
@SuppressWarnings("unchecked")
|
WatchEvent<Path> ev = (WatchEvent<Path>) event;
|
Path fileName = ev.context();
|
Path fullPath = directory.resolve(fileName);
|
|
FileChangeListener currentListener = listeners.get(directory);
|
if (currentListener == null) break;
|
|
if (kind == ENTRY_CREATE) {
|
currentListener.onFileCreated(fullPath);
|
} else if (kind == ENTRY_MODIFY) {
|
currentListener.onFileModified(fullPath);
|
} else if (kind == ENTRY_DELETE) {
|
currentListener.onFileDeleted(fullPath);
|
}
|
}
|
boolean valid = key.reset();
|
if (!valid) {
|
break;
|
}
|
}
|
} catch (InterruptedException e) {
|
Thread.currentThread().interrupt();
|
} catch (ClosedWatchServiceException e) {
|
// Service was closed, exit normally
|
}
|
});
|
}
|
|
public void stopWatching(Path directory) throws IOException {
|
WatchService watchService = watchServices.remove(directory);
|
listeners.remove(directory);
|
if (watchService != null) {
|
watchService.close();
|
}
|
}
|
|
public void shutdown() {
|
executor.shutdownNow();
|
watchServices.values().forEach(watchService -> {
|
try {
|
watchService.close();
|
} catch (IOException e) {
|
// Ignore on shutdown
|
}
|
});
|
watchServices.clear();
|
listeners.clear();
|
}
|
}
|