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 Files.createDirectories(targetPath);
42 Backups.lock(providers);
44 boolean unlockedAlready = false;
45 BackupException problem = null;
47 List<Future<BackupException>> backups = Backups.syncBackup(providers, targetPath, revision);
48 // Unlock providers at this stage
49 Backups.unlock(providers);
50 unlockedAlready = true;
52 // Wait for all providers to complete their work.
53 List<Exception> exceptions = new ArrayList<>(backups.size());
54 for (Future<BackupException> f : backups) {
56 Exception e = f.get();
59 } catch (InterruptedException | ExecutionException e) {
64 // Throw BackupException if any of the backup operations failed.
65 if (!exceptions.isEmpty()) {
66 IStatus[] ss = exceptions.stream()
67 .map(e -> new Status(IStatus.ERROR, Activator.BUNDLE_ID, e.getMessage(), e))
68 .toArray(IStatus[]::new);
69 problem = new BackupException(new CoreException(new MultiStatus(Activator.BUNDLE_ID, 0, ss,
70 "Backup operation(s) failed to complete.", null)));
73 } catch (BackupException e) {
75 } catch (Throwable t) {
76 problem = new BackupException(t);
79 Backups.unlock(providers);
82 callback.accept(problem);
83 }, "Backup thread " + (++threadCounter)).start();
84 } catch (IOException e) {
85 throw new BackupException(e);
93 public static void restore(Path fromPath, int revision) throws BackupException {
94 restore(getBackupProviders(), fromPath, revision);
97 private static void restore(Collection<IBackupProvider> providers, Path fromPath, int revision) throws BackupException {
98 for (IBackupProvider provider : providers)
99 provider.restore(fromPath, revision);
102 private static List<IBackupProvider> getBackupProviders() throws BackupException {
104 List<IBackupProvider> results = new ArrayList<>();
105 Collection<ServiceReference<IBackupProvider>> backupProviders = Activator.getContext().getServiceReferences(IBackupProvider.class, null);
106 for (ServiceReference<IBackupProvider> reference : backupProviders) {
107 results.add(Activator.getContext().getService(reference));
110 } catch (InvalidSyntaxException e) {
111 throw new BackupException("Failed to enumerate backup providers.", e);