1 package org.simantics.fileimport.dropins;
3 import static java.nio.file.StandardWatchEventKinds.ENTRY_CREATE;
4 import static java.nio.file.StandardWatchEventKinds.ENTRY_DELETE;
5 import static java.nio.file.StandardWatchEventKinds.ENTRY_MODIFY;
6 import static java.nio.file.StandardWatchEventKinds.OVERFLOW;
8 import java.io.FileNotFoundException;
9 import java.io.IOException;
10 import java.io.RandomAccessFile;
11 import java.nio.file.FileSystem;
12 import java.nio.file.FileSystemException;
13 import java.nio.file.FileVisitResult;
14 import java.nio.file.Files;
15 import java.nio.file.Path;
16 import java.nio.file.SimpleFileVisitor;
17 import java.nio.file.WatchEvent;
18 import java.nio.file.WatchEvent.Kind;
19 import java.nio.file.WatchKey;
20 import java.nio.file.WatchService;
21 import java.nio.file.attribute.BasicFileAttributes;
22 import java.util.HashMap;
24 import java.util.Optional;
25 import java.util.concurrent.atomic.AtomicBoolean;
27 import org.simantics.fileimport.Activator;
28 import org.simantics.fileimport.FileImportService;
31 * Directory watcher based on {@link java.nio.file.WatchService} which will listen to file changes inside the dropins directory
32 * ~/workspace/.metadata/plugins/org.simantics.fileimport/dropins
34 * @author Jani Simomaa
37 public class FileImportDropins {
39 private static Thread watcherThread = null;
40 private static DropinsFolderWatcher watcher = null;
43 * Start watching the dropins folder which are located in
44 * ~/workspace/.metadata/plugins/org.simantics.fileimport/dropins
46 public static void watchDropinsFolder() {
47 if (watcher == null && watcherThread == null) {
49 watcher = new DropinsFolderWatcher(Activator.getDropinsFolder());
50 watcherThread = new Thread(watcher, "Simantics Dropins Folder watcher thread");
51 watcherThread.setDaemon(true);
52 watcherThread.start();
53 } catch (IOException e) {
60 * Stop watching the dropins folder
62 public static void unwatchDropinsFolder() {
67 watcherThread.join(500);
68 if (watcherThread.isAlive())
69 watcherThread.interrupt();
70 } catch (InterruptedException e) {
77 private static class DropinsFolderWatcher implements Runnable {
79 private final Path dropinsFolder;
80 private final WatchService ws;
81 private final AtomicBoolean stopped = new AtomicBoolean(true);
83 private final Map<WatchKey, Path> keys = new HashMap<>();
85 public DropinsFolderWatcher(Path dropinsFolder) throws IOException {
86 this.dropinsFolder = dropinsFolder;
87 FileSystem fs = dropinsFolder.getFileSystem();
88 this.ws = fs.newWatchService();
89 registerAll(this.dropinsFolder);
92 private static void syncPath(Path f) throws IOException {
93 // Does not seem to need 's' according to unit test in Windows
94 boolean synced = false;
97 try (RandomAccessFile raf = new RandomAccessFile(f.toFile(), "rw")) {
100 } catch (IOException e) {
106 } catch (InterruptedException e1) {
107 e1.printStackTrace();
119 while (!stopped.get()) {
121 WatchKey key = ws.take();
122 for (WatchEvent<?> watchEvent : key.pollEvents()) {
123 if (OVERFLOW == watchEvent.kind())
126 @SuppressWarnings("unchecked")
127 WatchEvent<Path> pathEvent = (WatchEvent<Path>) watchEvent;
128 Kind<Path> kind = pathEvent.kind();
130 Path parent = keys.get(key);
131 Path newPath = parent.resolve(pathEvent.context());
132 if (FileImportService.DB_FILE.equals(newPath.getFileName().toString()))
134 if (ENTRY_CREATE == kind) {
135 System.out.println("New path created: " + newPath);
138 while (!Files.isWritable(newPath) && current <= 10) {
139 System.out.println("Sleeping for file import (current=" + current +")");
144 FileImportService.performFileImport(newPath, Optional.of(t -> {
145 if ((t instanceof FileSystemException) || (t instanceof FileNotFoundException)) {
148 } catch (IOException e) {
151 FileImportService.performFileImport(newPath, Optional.empty());
158 } else if (ENTRY_MODIFY == kind) {
159 System.out.println("New path modified: " + newPath);
160 } else if (ENTRY_DELETE == kind) {
161 System.out.println("New path deleted: " + newPath);
162 FileImportService.removeResourceForFile(newPath.toAbsolutePath(), Optional.empty());
169 } catch (InterruptedException e) {
172 } catch (Throwable t) {
182 private void registerAll(Path path) throws IOException {
183 Files.walkFileTree(path, new SimpleFileVisitor<Path>() {
186 public FileVisitResult preVisitDirectory(Path file, BasicFileAttributes attrs) throws IOException {
188 return FileVisitResult.CONTINUE;
193 private void register(Path path) throws IOException {
194 if (Files.isDirectory(path)) {
195 WatchKey key = path.toAbsolutePath().register(ws, ENTRY_CREATE, ENTRY_DELETE, ENTRY_MODIFY);