1 package org.simantics.backup;
3 import java.io.IOException;
4 import java.nio.file.Files;
5 import java.nio.file.Path;
6 import java.nio.file.Paths;
7 import java.util.ArrayList;
8 import java.util.Collection;
10 import java.util.concurrent.ExecutionException;
11 import java.util.concurrent.Future;
12 import java.util.function.Consumer;
14 import org.eclipse.core.runtime.CoreException;
15 import org.eclipse.core.runtime.IStatus;
16 import org.eclipse.core.runtime.MultiStatus;
17 import org.eclipse.core.runtime.Status;
18 import org.osgi.framework.InvalidSyntaxException;
19 import org.osgi.framework.ServiceReference;
22 * @author Jani Simomaa
24 public class BackupProviderService {
26 private static volatile int threadCounter = 0;
28 public static void backup(String targetPath, int revision) throws BackupException {
29 backup(Paths.get(targetPath), revision, null);
36 * @throws BackupException
38 public static void backup(Path targetPath, int revision, Consumer<BackupException> callback) throws BackupException {
39 List<IBackupProvider> providers = getBackupProviders();
41 if (!Files.exists(targetPath))
42 Files.createDirectories(targetPath);
43 Backups.lock(providers);
45 boolean unlockedAlready = false;
46 BackupException problem = null;
48 List<Future<BackupException>> backups = Backups.syncBackup(providers, targetPath, revision);
49 // Unlock providers at this stage
50 Backups.unlock(providers);
51 unlockedAlready = true;
53 // Wait for all providers to complete their work.
54 List<Exception> exceptions = new ArrayList<>(backups.size());
55 for (Future<BackupException> f : backups) {
57 Exception e = f.get();
60 } catch (InterruptedException | ExecutionException e) {
65 // Throw BackupException if any of the backup operations failed.
66 if (!exceptions.isEmpty()) {
67 IStatus[] ss = exceptions.stream()
68 .map(e -> new Status(IStatus.ERROR, Activator.BUNDLE_ID, e.getMessage(), e))
69 .toArray(IStatus[]::new);
70 problem = new BackupException(new CoreException(new MultiStatus(Activator.BUNDLE_ID, 0, ss,
71 "Backup operation(s) failed to complete.", null)));
74 } catch (BackupException e) {
76 } catch (Throwable t) {
77 problem = new BackupException(t);
80 Backups.unlock(providers);
83 callback.accept(problem);
84 }, "Backup thread " + (++threadCounter)).start();
85 } catch (IOException e) {
86 throw new BackupException(e);
94 public static void restore(Path fromPath, int revision) throws BackupException {
95 restore(getBackupProviders(), fromPath, revision);
98 private static void restore(Collection<IBackupProvider> providers, Path fromPath, int revision) throws BackupException {
99 for (IBackupProvider provider : providers)
100 provider.restore(fromPath, revision);
103 private static List<IBackupProvider> getBackupProviders() throws BackupException {
105 List<IBackupProvider> results = new ArrayList<>();
106 Collection<ServiceReference<IBackupProvider>> backupProviders = Activator.getContext().getServiceReferences(IBackupProvider.class, null);
107 for (ServiceReference<IBackupProvider> reference : backupProviders) {
108 results.add(Activator.getContext().getService(reference));
111 } catch (InvalidSyntaxException e) {
112 throw new BackupException("Failed to enumerate backup providers.", e);