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