package husacct.control.task; import static java.nio.file.LinkOption.NOFOLLOW_LINKS; import static java.nio.file.StandardWatchEventKinds.ENTRY_CREATE; import static java.nio.file.StandardWatchEventKinds.ENTRY_DELETE; import static java.nio.file.StandardWatchEventKinds.ENTRY_MODIFY; 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.Paths; import java.nio.file.SimpleFileVisitor; import java.nio.file.WatchEvent; import java.nio.file.WatchEvent.Kind; import java.nio.file.WatchKey; import java.nio.file.WatchService; import java.nio.file.attribute.BasicFileAttributes; import java.util.ArrayList; import java.util.HashMap; public class FileController { private WatchService watcher; private HashMap<WatchKey,Path> keys; private ArrayList<IFileChangeListener> listeners; @SuppressWarnings("unchecked") static <T> WatchEvent<T> cast(WatchEvent<?> event) { return (WatchEvent<T>)event; } public FileController(MainController mainController) { try { watcher = FileSystems.getDefault().newWatchService(); keys = new HashMap<WatchKey,Path>(); listeners = new ArrayList<IFileChangeListener>(); } catch (IOException e) { e.printStackTrace(); } } public void addProject(String folder) throws IOException { Path project = Paths.get(folder); Files.walkFileTree(project, new SimpleFileVisitor<Path>() { @Override public FileVisitResult preVisitDirectory(Path directory, BasicFileAttributes attrs) throws IOException { addDirectory(directory); return FileVisitResult.CONTINUE; } }); } public void addFileChangeListener(IFileChangeListener listener) { listeners.add(listener); } public void processEvents() throws IOException { for (;;) { WatchKey key; try { key = watcher.take(); } catch (InterruptedException x) { return; } Path directory = keys.get(key); if (directory == null) { System.err.println("WatchKey not recognized!!"); continue; } for (WatchEvent<?> event: key.pollEvents()) { Kind<?> kind = event.kind(); WatchEvent<Path> castedEvent = cast(event); Path relativePath = castedEvent.context(); Path path = directory.resolve(relativePath); System.out.format("%s: %s\n", kind.name(), path); if ((kind == ENTRY_CREATE)) { if (Files.isDirectory(path, NOFOLLOW_LINKS)) { addDirectory(path); } else { for(IFileChangeListener listener : listeners) listener.onCreate(path); } } else if((kind == ENTRY_MODIFY)) { if (!Files.isDirectory(path, NOFOLLOW_LINKS)) { for(IFileChangeListener listener : listeners) listener.onUpdate(path); } } else if ((kind == ENTRY_DELETE)) { if (Files.isDirectory(path, NOFOLLOW_LINKS)) { File dir = path.toFile(); for(File f : dir.listFiles()) { for(IFileChangeListener listener : listeners) listener.onRemove(f.toPath()); } } else { for(IFileChangeListener listener : listeners) listener.onRemove(path); } } } boolean valid = key.reset(); if (!valid) { keys.remove(key); if (keys.isEmpty()) { break; } } } } private void addDirectory(Path directory) throws IOException { WatchKey key = directory.register(watcher, ENTRY_CREATE, ENTRY_DELETE, ENTRY_MODIFY); keys.put(key, directory); } }