+ @Override
+ public Path perform(ReadGraph graph) throws DatabaseException {
+ StringBuilder sb = new StringBuilder();
+ String uri = graph.getPossibleURI(input);
+ if (uri != null) {
+ sb.append(generateSHA1(uri)).append("_");
+ }
+ sb.append(graph.getRelatedValue(input, Layer0.getInstance(graph).HasName).toString());
+ Path filePath = Activator.getInstanceLocation().resolve(sb.toString());
+ tempFiles.computeIfAbsent(filePath, t -> {
+ try {
+ GraphFileUtil.writeDataToFile(graph, input, filePath.toFile());
+ } catch (IOException | DatabaseException e) {
+ LOGGER.error("Could not write data to file ", e);
+ }
+ return input;
+ });
+ LOGGER.info("Adding tempFile {} with resource {}", filePath, input);
+ return filePath;
+ }
+ });
+ }
+ try {
+ Editors.openExternalEditor(path.toFile());
+ } catch (PartInitException e) {
+ ExceptionUtils.logAndShowError(e);
+ }
+ }
+
+ public static String generateSHA1(String message) {
+ return hashString(message, "SHA-1");
+ }
+
+ private static String hashString(String message, String algorithm) {
+ try {
+ MessageDigest digest = MessageDigest.getInstance(algorithm);
+ byte[] hashedBytes = digest.digest(message.getBytes("UTF-8"));
+
+ return convertByteArrayToHexString(hashedBytes);
+ } catch (NoSuchAlgorithmException | UnsupportedEncodingException ex) {
+ // Should not happen
+ LOGGER.error("Could not generate hash", ex);
+ }
+ return "";
+ }
+
+ private static String convertByteArrayToHexString(byte[] arrayBytes) {
+ StringBuffer stringBuffer = new StringBuffer();
+ for (int i = 0; i < arrayBytes.length; i++) {
+ stringBuffer.append(Integer.toString((arrayBytes[i] & 0xff) + 0x100, 16)
+ .substring(1));
+ }
+ return stringBuffer.toString();
+ }
+
+ private static void watch() throws IOException {
+ if (fileWatcher == null) {
+ synchronized (ExternalEditorAdapter.class) {
+ if (fileWatcher == null) {
+ fileWatcher = new ExternalFileWatcher();
+ }
+ }
+ }
+ }
+
+ static class ExternalFileWatcher{
+
+ private ExecutorService service = Executors.newFixedThreadPool(1, r -> {
+ Thread t = new Thread(r);
+ t.setDaemon(true);
+ return t;
+ });
+
+ private final WatchService ws;
+ private final AtomicBoolean stopped = new AtomicBoolean(true);
+ private ConcurrentHashMap<WatchKey, Path> keys = new ConcurrentHashMap<>();
+
+ public ExternalFileWatcher() throws IOException {
+ ws = FileSystems.getDefault().newWatchService();
+
+ register(Activator.getInstanceLocation());
+
+ service.submit(() -> {
+ 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<Path> pathEvent = (WatchEvent<Path>) watchEvent;
+ Kind<Path> kind = pathEvent.kind();
+ Path parent = keys.get(key);
+ Path newPath = parent.resolve(pathEvent.context());
+ if (ENTRY_MODIFY == kind) {
+ LOGGER.info("New path modified: " + newPath);
+ Resource resource = tempFiles.get(newPath);
+ if (resource != null) {
+ GraphFileUtil.writeDataToGraph(newPath.toFile(), resource);
+ } else {
+ LOGGER.warn("No resource found for {}", newPath.toAbsolutePath());
+ }
+ } else if (ENTRY_DELETE == kind) {
+ System.out.println("New path deleted: " + newPath);
+ }
+ }
+ if (!key.reset()) {
+ keys.remove(key);
+// break; // loop
+ }
+ } catch (InterruptedException e) {
+ if (!stopped.get())
+ LOGGER.error("Could not stop", e);
+ } catch (Throwable t) {
+ LOGGER.error("An error occured", t);
+ }
+ }
+ });
+ }
+
+ public void stop() {
+ stopped.set(true);
+ }
+
+ private void register(Path path) throws IOException {
+ if (Files.isDirectory(path)) {
+ LOGGER.info("Registering path {}", path);
+ WatchKey key = path.toAbsolutePath().register(ws, ENTRY_DELETE, ENTRY_MODIFY);
+ keys.put(key, path);
+ }
+ }
+ }