]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.backup/src/org/simantics/backup/BackupProviderService.java
added org.simantics.backup
[simantics/platform.git] / bundles / org.simantics.backup / src / org / simantics / backup / BackupProviderService.java
diff --git a/bundles/org.simantics.backup/src/org/simantics/backup/BackupProviderService.java b/bundles/org.simantics.backup/src/org/simantics/backup/BackupProviderService.java
new file mode 100644 (file)
index 0000000..3223041
--- /dev/null
@@ -0,0 +1,116 @@
+package org.simantics.backup;\r
+\r
+import java.io.IOException;\r
+import java.nio.file.Files;\r
+import java.nio.file.Path;\r
+import java.nio.file.Paths;\r
+import java.util.ArrayList;\r
+import java.util.Collection;\r
+import java.util.List;\r
+import java.util.concurrent.ExecutionException;\r
+import java.util.concurrent.Future;\r
+import java.util.function.Consumer;\r
+\r
+import org.eclipse.core.runtime.CoreException;\r
+import org.eclipse.core.runtime.IStatus;\r
+import org.eclipse.core.runtime.MultiStatus;\r
+import org.eclipse.core.runtime.Status;\r
+import org.osgi.framework.InvalidSyntaxException;\r
+import org.osgi.framework.ServiceReference;\r
+\r
+/**\r
+ * @author Jani Simomaa\r
+ */\r
+public class BackupProviderService {\r
+\r
+    private static volatile int threadCounter = 0;\r
+\r
+    public static void backup(String targetPath, int revision) throws BackupException {\r
+       backup(Paths.get(targetPath), revision, null);\r
+    }\r
+    \r
+    /**\r
+     * @param targetPath\r
+     * @param revision\r
+     * @param callback \r
+     * @throws BackupException \r
+     */\r
+    public static void backup(Path targetPath, int revision, Consumer<BackupException> callback) throws BackupException {\r
+        List<IBackupProvider> providers = getBackupProviders();\r
+        try {\r
+            if (!Files.exists(targetPath))\r
+                Files.createDirectories(targetPath);\r
+            Backups.lock(providers);\r
+            new Thread(() -> {\r
+                boolean unlockedAlready = false;\r
+                BackupException problem = null;\r
+                try {\r
+                    List<Future<BackupException>> backups = Backups.syncBackup(providers, targetPath, revision);\r
+                    // Unlock providers at this stage\r
+                    Backups.unlock(providers);\r
+                    unlockedAlready = true;\r
+                    \r
+                    // Wait for all providers to complete their work.\r
+                    List<Exception> exceptions = new ArrayList<>(backups.size());\r
+                    for (Future<BackupException> f : backups) {\r
+                        try {\r
+                            Exception e = f.get();\r
+                            if (e != null)\r
+                                exceptions.add(e);\r
+                        } catch (InterruptedException | ExecutionException e) {\r
+                            exceptions.add(e);\r
+                        }\r
+                    }\r
+\r
+                    // Throw BackupException if any of the backup operations failed.\r
+                    if (!exceptions.isEmpty()) {\r
+                        IStatus[] ss = exceptions.stream()\r
+                                .map(e -> new Status(IStatus.ERROR, Activator.BUNDLE_ID, e.getMessage(), e))\r
+                                .toArray(IStatus[]::new);\r
+                        problem = new BackupException(new CoreException(new MultiStatus(Activator.BUNDLE_ID, 0, ss,\r
+                                "Backup operation(s) failed to complete.", null)));\r
+                    }\r
+\r
+                } catch (BackupException e) {\r
+                    problem = e;\r
+                } catch (Throwable t) {\r
+                    problem = new BackupException(t);\r
+                } finally {\r
+                    if (!unlockedAlready)\r
+                        Backups.unlock(providers);\r
+                }\r
+                if (callback != null)\r
+                    callback.accept(problem);\r
+            }, "Backup thread " + (++threadCounter)).start();\r
+        } catch (IOException e) {\r
+            throw new BackupException(e);\r
+        }\r
+    }\r
+\r
+    /**\r
+     * @param fromPath\r
+     * @param revision\r
+     */\r
+    public static void restore(Path fromPath, int revision) throws BackupException {\r
+        restore(getBackupProviders(), fromPath, revision);\r
+    }\r
+\r
+    private static void restore(Collection<IBackupProvider> providers, Path fromPath, int revision) throws BackupException {\r
+        for (IBackupProvider provider : providers)\r
+            provider.restore(fromPath, revision);\r
+    }\r
+\r
+    private static List<IBackupProvider> getBackupProviders() throws BackupException {\r
+        try {\r
+            List<IBackupProvider> results = new ArrayList<>();\r
+            Collection<ServiceReference<IBackupProvider>> backupProviders = Activator.getContext().getServiceReferences(IBackupProvider.class, null);\r
+            for (ServiceReference<IBackupProvider> reference : backupProviders) {\r
+                results.add(Activator.getContext().getService(reference));\r
+            }\r
+            return results;\r
+        } catch (InvalidSyntaxException e) {\r
+            throw new BackupException("Failed to enumerate backup providers.", e);\r
+        }\r
+    }\r
+\r
+}\r