Merge "Small SCL changes"
[simantics/platform.git] / bundles / org.simantics.fileimport / src / org / simantics / fileimport / dropins / FileImportDropins.java
1 package org.simantics.fileimport.dropins;\r
2 \r
3 import static java.nio.file.StandardWatchEventKinds.OVERFLOW;\r
4 import static java.nio.file.StandardWatchEventKinds.ENTRY_CREATE;\r
5 import static java.nio.file.StandardWatchEventKinds.ENTRY_DELETE;\r
6 import static java.nio.file.StandardWatchEventKinds.ENTRY_MODIFY;\r
7 \r
8 import java.io.IOException;\r
9 import java.nio.file.FileSystem;\r
10 import java.nio.file.FileVisitResult;\r
11 import java.nio.file.Files;\r
12 import java.nio.file.Path;\r
13 import java.nio.file.SimpleFileVisitor;\r
14 import java.nio.file.WatchEvent;\r
15 import java.nio.file.WatchEvent.Kind;\r
16 import java.nio.file.attribute.BasicFileAttributes;\r
17 import java.util.HashMap;\r
18 import java.util.Map;\r
19 import java.util.Optional;\r
20 import java.util.concurrent.atomic.AtomicBoolean;\r
21 import java.nio.file.WatchKey;\r
22 import java.nio.file.WatchService;\r
23 \r
24 import org.simantics.fileimport.Activator;\r
25 import org.simantics.fileimport.FileImportService;\r
26 \r
27 public class FileImportDropins {\r
28     \r
29     private static Thread watcherThread = null;\r
30     private static DropinsFolderWatcher watcher = null;\r
31 \r
32     public static void watchDropinsFolder() {\r
33         if (watcher == null && watcherThread == null) {\r
34             try {\r
35                 watcher = new DropinsFolderWatcher(Activator.getDropinsFolder());\r
36                 watcherThread = new Thread(watcher, "Simantics Dropins Folder watcher thread");\r
37                 watcherThread.setDaemon(true);\r
38                 watcherThread.start();\r
39             } catch (IOException e) {\r
40                 e.printStackTrace();\r
41             }\r
42         }\r
43     }\r
44     \r
45     public static void unwatchDropinsFolder() {\r
46         watcher.stop();\r
47         try {\r
48             watcherThread.join(500);\r
49             if (watcherThread.isAlive())\r
50                 watcherThread.interrupt();\r
51         } catch (InterruptedException e) {\r
52             e.printStackTrace();\r
53         }\r
54         watcherThread = null;\r
55         watcher = null;\r
56     }\r
57     \r
58     private static class DropinsFolderWatcher implements Runnable {\r
59 \r
60         private final Path dropinsFolder;\r
61         private final WatchService ws;\r
62         private final AtomicBoolean stopped = new AtomicBoolean(true);\r
63         \r
64         private final Map<WatchKey, Path> keys = new HashMap<>();\r
65         \r
66         public DropinsFolderWatcher(Path dropinsFolder) throws IOException {\r
67             this.dropinsFolder = dropinsFolder;\r
68             FileSystem fs = dropinsFolder.getFileSystem();\r
69             this.ws = fs.newWatchService();\r
70             registerAll(this.dropinsFolder);\r
71         }\r
72         \r
73         @Override\r
74         public void run() {\r
75             stopped.set(false);\r
76 \r
77             while (!stopped.get()) {\r
78                 try {\r
79                     WatchKey key = ws.take();\r
80                     for (WatchEvent<?> watchEvent : key.pollEvents()) {\r
81                         if (OVERFLOW == watchEvent.kind())\r
82                             continue; // loop\r
83                         \r
84                         @SuppressWarnings("unchecked")\r
85                         WatchEvent<Path> pathEvent = (WatchEvent<Path>) watchEvent;\r
86                         Kind<Path> kind = pathEvent.kind();\r
87                         \r
88                         Path parent = keys.get(key);\r
89                         Path newPath = parent.resolve(pathEvent.context());\r
90                         if (FileImportService.DB_FILE.equals(newPath.getFileName().toString()))\r
91                             continue;\r
92                         if (ENTRY_CREATE == kind) {\r
93                             System.out.println("New path created: " + newPath);\r
94                             FileImportService.performFileImport(newPath, Optional.empty());\r
95                             register(newPath);\r
96                         } else if (ENTRY_MODIFY == kind) {\r
97                             System.out.println("New path modified: " + newPath);\r
98                         } else if (ENTRY_DELETE == kind) {\r
99                             System.out.println("New path deleted: " + newPath);\r
100                             FileImportService.removeResourceForFile(newPath.toAbsolutePath(), Optional.empty());\r
101                         }\r
102                     }\r
103                     if (!key.reset()) {\r
104                         keys.remove(key);\r
105 //                        break; // loop\r
106                     }\r
107                 } catch (IOException e) {\r
108                     e.printStackTrace();\r
109                 } catch (InterruptedException e) {\r
110                     if (!stopped.get())\r
111                         e.printStackTrace();\r
112                 } catch (Throwable t) {\r
113                     t.printStackTrace();\r
114                 }\r
115             }\r
116         }\r
117         \r
118         public void stop() {\r
119             stopped.set(true);\r
120         }\r
121         \r
122         private void registerAll(Path path) throws IOException {\r
123             Files.walkFileTree(path, new SimpleFileVisitor<Path>() {\r
124                 \r
125                 @Override\r
126                 public FileVisitResult preVisitDirectory(Path file, BasicFileAttributes attrs) throws IOException {\r
127                     register(file);\r
128                     return FileVisitResult.CONTINUE;\r
129                 }\r
130             });\r
131         }\r
132 \r
133         private void register(Path path) throws IOException {\r
134             if (Files.isDirectory(path)) {\r
135                 WatchKey key = path.toAbsolutePath().register(ws, ENTRY_CREATE, ENTRY_DELETE, ENTRY_MODIFY);\r
136                 keys.put(key, path);\r
137             }\r
138         }\r
139     }\r
140 }\r