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 watchServices = new HashMap<>(); private final Map 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 ev = (WatchEvent) 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(); } }