]> gerrit.simantics Code Review - simantics/platform.git/blob - 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
1 package org.simantics.backup;\r
2 \r
3 import java.io.IOException;\r
4 import java.nio.file.Files;\r
5 import java.nio.file.Path;\r
6 import java.nio.file.Paths;\r
7 import java.util.ArrayList;\r
8 import java.util.Collection;\r
9 import java.util.List;\r
10 import java.util.concurrent.ExecutionException;\r
11 import java.util.concurrent.Future;\r
12 import java.util.function.Consumer;\r
13 \r
14 import org.eclipse.core.runtime.CoreException;\r
15 import org.eclipse.core.runtime.IStatus;\r
16 import org.eclipse.core.runtime.MultiStatus;\r
17 import org.eclipse.core.runtime.Status;\r
18 import org.osgi.framework.InvalidSyntaxException;\r
19 import org.osgi.framework.ServiceReference;\r
20 \r
21 /**\r
22  * @author Jani Simomaa\r
23  */\r
24 public class BackupProviderService {\r
25 \r
26     private static volatile int threadCounter = 0;\r
27 \r
28     public static void backup(String targetPath, int revision) throws BackupException {\r
29         backup(Paths.get(targetPath), revision, null);\r
30     }\r
31     \r
32     /**\r
33      * @param targetPath\r
34      * @param revision\r
35      * @param callback \r
36      * @throws BackupException \r
37      */\r
38     public static void backup(Path targetPath, int revision, Consumer<BackupException> callback) throws BackupException {\r
39         List<IBackupProvider> providers = getBackupProviders();\r
40         try {\r
41             if (!Files.exists(targetPath))\r
42                 Files.createDirectories(targetPath);\r
43             Backups.lock(providers);\r
44             new Thread(() -> {\r
45                 boolean unlockedAlready = false;\r
46                 BackupException problem = null;\r
47                 try {\r
48                     List<Future<BackupException>> backups = Backups.syncBackup(providers, targetPath, revision);\r
49                     // Unlock providers at this stage\r
50                     Backups.unlock(providers);\r
51                     unlockedAlready = true;\r
52                     \r
53                     // Wait for all providers to complete their work.\r
54                     List<Exception> exceptions = new ArrayList<>(backups.size());\r
55                     for (Future<BackupException> f : backups) {\r
56                         try {\r
57                             Exception e = f.get();\r
58                             if (e != null)\r
59                                 exceptions.add(e);\r
60                         } catch (InterruptedException | ExecutionException e) {\r
61                             exceptions.add(e);\r
62                         }\r
63                     }\r
64 \r
65                     // Throw BackupException if any of the backup operations failed.\r
66                     if (!exceptions.isEmpty()) {\r
67                         IStatus[] ss = exceptions.stream()\r
68                                 .map(e -> new Status(IStatus.ERROR, Activator.BUNDLE_ID, e.getMessage(), e))\r
69                                 .toArray(IStatus[]::new);\r
70                         problem = new BackupException(new CoreException(new MultiStatus(Activator.BUNDLE_ID, 0, ss,\r
71                                 "Backup operation(s) failed to complete.", null)));\r
72                     }\r
73 \r
74                 } catch (BackupException e) {\r
75                     problem = e;\r
76                 } catch (Throwable t) {\r
77                     problem = new BackupException(t);\r
78                 } finally {\r
79                     if (!unlockedAlready)\r
80                         Backups.unlock(providers);\r
81                 }\r
82                 if (callback != null)\r
83                     callback.accept(problem);\r
84             }, "Backup thread " + (++threadCounter)).start();\r
85         } catch (IOException e) {\r
86             throw new BackupException(e);\r
87         }\r
88     }\r
89 \r
90     /**\r
91      * @param fromPath\r
92      * @param revision\r
93      */\r
94     public static void restore(Path fromPath, int revision) throws BackupException {\r
95         restore(getBackupProviders(), fromPath, revision);\r
96     }\r
97 \r
98     private static void restore(Collection<IBackupProvider> providers, Path fromPath, int revision) throws BackupException {\r
99         for (IBackupProvider provider : providers)\r
100             provider.restore(fromPath, revision);\r
101     }\r
102 \r
103     private static List<IBackupProvider> getBackupProviders() throws BackupException {\r
104         try {\r
105             List<IBackupProvider> results = new ArrayList<>();\r
106             Collection<ServiceReference<IBackupProvider>> backupProviders = Activator.getContext().getServiceReferences(IBackupProvider.class, null);\r
107             for (ServiceReference<IBackupProvider> reference : backupProviders) {\r
108                 results.add(Activator.getContext().getService(reference));\r
109             }\r
110             return results;\r
111         } catch (InvalidSyntaxException e) {\r
112             throw new BackupException("Failed to enumerate backup providers.", e);\r
113         }\r
114     }\r
115 \r
116 }\r