1 package org.simantics.backup;
\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
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
22 * @author Jani Simomaa
\r
24 public class BackupProviderService {
\r
26 private static volatile int threadCounter = 0;
\r
28 public static void backup(String targetPath, int revision) throws BackupException {
\r
29 backup(Paths.get(targetPath), revision, null);
\r
36 * @throws BackupException
\r
38 public static void backup(Path targetPath, int revision, Consumer<BackupException> callback) throws BackupException {
\r
39 List<IBackupProvider> providers = getBackupProviders();
\r
41 if (!Files.exists(targetPath))
\r
42 Files.createDirectories(targetPath);
\r
43 Backups.lock(providers);
\r
45 boolean unlockedAlready = false;
\r
46 BackupException problem = null;
\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
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
57 Exception e = f.get();
\r
60 } catch (InterruptedException | ExecutionException e) {
\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
74 } catch (BackupException e) {
\r
76 } catch (Throwable t) {
\r
77 problem = new BackupException(t);
\r
79 if (!unlockedAlready)
\r
80 Backups.unlock(providers);
\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
94 public static void restore(Path fromPath, int revision) throws BackupException {
\r
95 restore(getBackupProviders(), fromPath, revision);
\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
103 private static List<IBackupProvider> getBackupProviders() throws BackupException {
\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
111 } catch (InvalidSyntaxException e) {
\r
112 throw new BackupException("Failed to enumerate backup providers.", e);
\r