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