X-Git-Url: https://gerrit.simantics.org/r/gitweb?p=simantics%2Fplatform.git;a=blobdiff_plain;f=bundles%2Forg.simantics.fileimport%2Fsrc%2Forg%2Fsimantics%2Ffileimport%2Fdropins%2FFileImportDropins.java;h=fb01e42e5cf3f61ba5f5db97c70fefb550e3358a;hp=a32dd98775639f0f15b5224d011b72b54e7f17b2;hb=664f37a026967c90a9a8a4ef3c5336ee426f67aa;hpb=b35573372259ace60d8827766fe41443f4c57629 diff --git a/bundles/org.simantics.fileimport/src/org/simantics/fileimport/dropins/FileImportDropins.java b/bundles/org.simantics.fileimport/src/org/simantics/fileimport/dropins/FileImportDropins.java index a32dd9877..fb01e42e5 100644 --- a/bundles/org.simantics.fileimport/src/org/simantics/fileimport/dropins/FileImportDropins.java +++ b/bundles/org.simantics.fileimport/src/org/simantics/fileimport/dropins/FileImportDropins.java @@ -1,140 +1,200 @@ -package org.simantics.fileimport.dropins; - -import static java.nio.file.StandardWatchEventKinds.OVERFLOW; -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.IOException; -import java.nio.file.FileSystem; -import java.nio.file.FileVisitResult; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.SimpleFileVisitor; -import java.nio.file.WatchEvent; -import java.nio.file.WatchEvent.Kind; -import java.nio.file.attribute.BasicFileAttributes; -import java.util.HashMap; -import java.util.Map; -import java.util.Optional; -import java.util.concurrent.atomic.AtomicBoolean; -import java.nio.file.WatchKey; -import java.nio.file.WatchService; - -import org.simantics.fileimport.Activator; -import org.simantics.fileimport.FileImportService; - -public class FileImportDropins { - - private static Thread watcherThread = null; - private static DropinsFolderWatcher watcher = null; - - public static void watchDropinsFolder() { - if (watcher == null && watcherThread == null) { - try { - watcher = new DropinsFolderWatcher(Activator.getDropinsFolder()); - watcherThread = new Thread(watcher, "Simantics Dropins Folder watcher thread"); - watcherThread.setDaemon(true); - watcherThread.start(); - } catch (IOException e) { - e.printStackTrace(); - } - } - } - - public static void unwatchDropinsFolder() { - watcher.stop(); - try { - watcherThread.join(500); - if (watcherThread.isAlive()) - watcherThread.interrupt(); - } catch (InterruptedException e) { - e.printStackTrace(); - } - watcherThread = null; - watcher = null; - } - - private static class DropinsFolderWatcher implements Runnable { - - private final Path dropinsFolder; - private final WatchService ws; - private final AtomicBoolean stopped = new AtomicBoolean(true); - - private final Map keys = new HashMap<>(); - - public DropinsFolderWatcher(Path dropinsFolder) throws IOException { - this.dropinsFolder = dropinsFolder; - FileSystem fs = dropinsFolder.getFileSystem(); - this.ws = fs.newWatchService(); - registerAll(this.dropinsFolder); - } - - @Override - public void run() { - stopped.set(false); - - while (!stopped.get()) { - try { - WatchKey key = ws.take(); - for (WatchEvent watchEvent : key.pollEvents()) { - if (OVERFLOW == watchEvent.kind()) - continue; // loop - - @SuppressWarnings("unchecked") - WatchEvent pathEvent = (WatchEvent) watchEvent; - Kind kind = pathEvent.kind(); - - Path parent = keys.get(key); - Path newPath = parent.resolve(pathEvent.context()); - if (FileImportService.DB_FILE.equals(newPath.getFileName().toString())) - continue; - if (ENTRY_CREATE == kind) { - System.out.println("New path created: " + newPath); - FileImportService.performFileImport(newPath, Optional.empty()); - register(newPath); - } else if (ENTRY_MODIFY == kind) { - System.out.println("New path modified: " + newPath); - } else if (ENTRY_DELETE == kind) { - System.out.println("New path deleted: " + newPath); - FileImportService.removeResourceForFile(newPath.toAbsolutePath(), Optional.empty()); - } - } - if (!key.reset()) { - keys.remove(key); -// break; // loop - } - } catch (IOException e) { - e.printStackTrace(); - } catch (InterruptedException e) { - if (!stopped.get()) - e.printStackTrace(); - } catch (Throwable t) { - t.printStackTrace(); - } - } - } - - public void stop() { - stopped.set(true); - } - - private void registerAll(Path path) throws IOException { - Files.walkFileTree(path, new SimpleFileVisitor() { - - @Override - public FileVisitResult preVisitDirectory(Path file, BasicFileAttributes attrs) throws IOException { - register(file); - return FileVisitResult.CONTINUE; - } - }); - } - - private void register(Path path) throws IOException { - if (Files.isDirectory(path)) { - WatchKey key = path.toAbsolutePath().register(ws, ENTRY_CREATE, ENTRY_DELETE, ENTRY_MODIFY); - keys.put(key, path); - } - } - } -} +package org.simantics.fileimport.dropins; + +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 static java.nio.file.StandardWatchEventKinds.OVERFLOW; + +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.RandomAccessFile; +import java.nio.file.FileSystem; +import java.nio.file.FileSystemException; +import java.nio.file.FileVisitResult; +import java.nio.file.Files; +import java.nio.file.Path; +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.HashMap; +import java.util.Map; +import java.util.Optional; +import java.util.concurrent.atomic.AtomicBoolean; + +import org.simantics.fileimport.Activator; +import org.simantics.fileimport.FileImportService; + +/** + * Directory watcher based on {@link java.nio.file.WatchService} which will listen to file changes inside the dropins directory + * ~/workspace/.metadata/plugins/org.simantics.fileimport/dropins + * + * @author Jani Simomaa + * + */ +public class FileImportDropins { + + private static Thread watcherThread = null; + private static DropinsFolderWatcher watcher = null; + + /** + * Start watching the dropins folder which are located in + * ~/workspace/.metadata/plugins/org.simantics.fileimport/dropins + */ + public static void watchDropinsFolder() { + if (watcher == null && watcherThread == null) { + try { + watcher = new DropinsFolderWatcher(Activator.getDropinsFolder()); + watcherThread = new Thread(watcher, "Simantics Dropins Folder watcher thread"); + watcherThread.setDaemon(true); + watcherThread.start(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + + /** + * Stop watching the dropins folder + */ + public static void unwatchDropinsFolder() { + if (watcher == null) + return; + watcher.stop(); + try { + watcherThread.join(500); + if (watcherThread.isAlive()) + watcherThread.interrupt(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + watcherThread = null; + watcher = null; + } + + private static class DropinsFolderWatcher implements Runnable { + + private final Path dropinsFolder; + private final WatchService ws; + private final AtomicBoolean stopped = new AtomicBoolean(true); + + private final Map keys = new HashMap<>(); + + public DropinsFolderWatcher(Path dropinsFolder) throws IOException { + this.dropinsFolder = dropinsFolder; + FileSystem fs = dropinsFolder.getFileSystem(); + this.ws = fs.newWatchService(); + registerAll(this.dropinsFolder); + } + + private static void syncPath(Path f) throws IOException { + // Does not seem to need 's' according to unit test in Windows + boolean synced = false; + int count = 0; + while (!synced) { + try (RandomAccessFile raf = new RandomAccessFile(f.toFile(), "rw")) { + raf.getFD().sync(); + synced = true; + } catch (IOException e) { + if (count == 3) { + throw e; + } else { + try { + Thread.sleep(50); + } catch (InterruptedException e1) { + e1.printStackTrace(); + } + count++; + } + } + } + } + + @Override + public void run() { + stopped.set(false); + + while (!stopped.get()) { + try { + WatchKey key = ws.take(); + for (WatchEvent watchEvent : key.pollEvents()) { + if (OVERFLOW == watchEvent.kind()) + continue; // loop + + @SuppressWarnings("unchecked") + WatchEvent pathEvent = (WatchEvent) watchEvent; + Kind kind = pathEvent.kind(); + + Path parent = keys.get(key); + Path newPath = parent.resolve(pathEvent.context()); + if (FileImportService.DB_FILE.equals(newPath.getFileName().toString())) + continue; + if (ENTRY_CREATE == kind) { + System.out.println("New path created: " + newPath); + int current = 0; + + while (!Files.isWritable(newPath) && current <= 10) { + System.out.println("Sleeping for file import (current=" + current +")"); + Thread.sleep(200); + current++; + } + + FileImportService.performFileImport(newPath, Optional.empty(), Optional.of(t -> { + if ((t instanceof FileSystemException) || (t instanceof FileNotFoundException)) { + try { + syncPath(newPath); + } catch (IOException e) { + e.printStackTrace(); + } + FileImportService.performFileImport(newPath, Optional.empty(), Optional.empty()); + } else { + t.printStackTrace(); + } + })); + register(newPath); + + } else if (ENTRY_MODIFY == kind) { + System.out.println("New path modified: " + newPath); + } else if (ENTRY_DELETE == kind) { + System.out.println("New path deleted: " + newPath); + FileImportService.removeResourceForFile(newPath.toAbsolutePath(), Optional.empty()); + } + } + if (!key.reset()) { + keys.remove(key); +// break; // loop + } + } catch (InterruptedException e) { + if (!stopped.get()) + e.printStackTrace(); + } catch (Throwable t) { + t.printStackTrace(); + } + } + } + + public void stop() { + stopped.set(true); + } + + private void registerAll(Path path) throws IOException { + Files.walkFileTree(path, new SimpleFileVisitor() { + + @Override + public FileVisitResult preVisitDirectory(Path file, BasicFileAttributes attrs) throws IOException { + register(file); + return FileVisitResult.CONTINUE; + } + }); + } + + private void register(Path path) throws IOException { + if (Files.isDirectory(path)) { + WatchKey key = path.toAbsolutePath().register(ws, ENTRY_CREATE, ENTRY_DELETE, ENTRY_MODIFY); + keys.put(key, path); + } + } + } +}