blob: 995207592cf3c26ce789b60e01c24b22e4a54c98 [file] [log] [blame]
/*
* Copyright (c) 2015 Eike Stepper (Loehne, Germany) and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v2.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v20.html
*
* Contributors:
* Eike Stepper - initial API and implementation
*/
package org.eclipse.oomph.setup.internal.sync;
import org.eclipse.oomph.setup.SetupTask;
import org.eclipse.oomph.setup.internal.sync.DataProvider.Location;
import org.eclipse.oomph.setup.internal.sync.Snapshot.WorkingCopy;
import org.eclipse.oomph.setup.sync.SyncAction;
import org.eclipse.oomph.util.LockFile;
import org.eclipse.osgi.util.NLS;
import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CopyOnWriteArrayList;
/**
* @author Eike Stepper
*/
public class Synchronizer
{
private final List<SynchronizerListener> listeners = new CopyOnWriteArrayList<SynchronizerListener>();
private final Snapshot localSnapshot;
private final Snapshot remoteSnapshot;
private LockFile lockFile;
private Synchronization synchronization;
public Synchronizer(Snapshot localSnapshot, Snapshot remoteSnapshot)
{
this.localSnapshot = localSnapshot;
this.remoteSnapshot = remoteSnapshot;
}
public Synchronizer(DataProvider localDataProvider, DataProvider remoteDataProvider, File syncFolder)
{
this(localDataProvider, remoteDataProvider, syncFolder, Snapshot.DEFAULT_INCREMENTAL);
}
public Synchronizer(DataProvider localDataProvider, DataProvider remoteDataProvider, File syncFolder, boolean incremental)
{
this(new Snapshot(localDataProvider, syncFolder, incremental), new Snapshot(remoteDataProvider, syncFolder, incremental));
}
public Snapshot getLocalSnapshot()
{
return localSnapshot;
}
public Snapshot getRemoteSnapshot()
{
return remoteSnapshot;
}
public LockFile getLockFile()
{
return lockFile;
}
public void setLockFile(LockFile lockFile)
{
this.lockFile = lockFile;
}
public Synchronization synchronize() throws IOException, SynchronizerException
{
return synchronize(false);
}
public synchronized Synchronization synchronize(boolean deferLocal) throws IOException, SynchronizerException
{
if (synchronization != null)
{
synchronization.dispose();
synchronization = null;
}
if (lockFile != null)
{
try
{
lockFile.lock();
}
catch (Exception ex)
{
throw new LockException(lockFile.getFile());
}
}
try
{
synchronization = createSynchronization(deferLocal);
}
catch (IOException ex)
{
doReleaseLock();
throw ex;
}
catch (RuntimeException ex)
{
doReleaseLock();
throw ex;
}
catch (Error ex)
{
doReleaseLock();
throw ex;
}
return synchronization;
}
protected Synchronization createSynchronization(boolean deferLocal) throws IOException
{
return new Synchronization(this, deferLocal);
}
public void copyFilesTo(File target)
{
if (localSnapshot != null)
{
localSnapshot.copyFilesTo(target);
}
if (remoteSnapshot != null)
{
remoteSnapshot.copyFilesTo(target);
}
}
public void copyFilesFrom(File source)
{
if (localSnapshot != null)
{
localSnapshot.copyFilesFrom(source);
}
if (remoteSnapshot != null)
{
remoteSnapshot.copyFilesFrom(source);
}
}
public SynchronizerListener[] getListeners()
{
return listeners.toArray(new SynchronizerListener[listeners.size()]);
}
public void addListener(SynchronizerListener listener)
{
listeners.add(listener);
}
public void removeListener(SynchronizerListener listener)
{
listeners.remove(listener);
}
@Override
public String toString()
{
return getClass().getSimpleName() + "[" + localSnapshot + " <--> " + remoteSnapshot + "]"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
protected void syncStarted()
{
for (SynchronizerListener listener : listeners)
{
try
{
listener.syncStarted(synchronization);
}
catch (Throwable ex)
{
SetupSyncPlugin.INSTANCE.log(ex);
}
}
}
protected void workingCopyCreated(WorkingCopy workingCopy)
{
for (SynchronizerListener listener : listeners)
{
try
{
listener.workingCopyCreated(synchronization, workingCopy);
}
catch (Throwable ex)
{
SetupSyncPlugin.INSTANCE.log(ex);
}
}
}
protected void tasksCollected(Synchronization synchronization, Location location, Map<String, SetupTask> oldTasks, Map<String, SetupTask> newTasks)
{
for (SynchronizerListener listener : listeners)
{
try
{
listener.tasksCollected(synchronization, location, oldTasks, newTasks);
}
catch (Throwable ex)
{
SetupSyncPlugin.INSTANCE.log(ex);
}
}
}
protected void actionsComputed(Map<String, SyncAction> actions)
{
for (SynchronizerListener listener : listeners)
{
try
{
listener.actionsComputed(synchronization, actions);
}
catch (Throwable ex)
{
SetupSyncPlugin.INSTANCE.log(ex);
}
}
}
protected void actionResolved(SyncAction action, String id)
{
for (SynchronizerListener listener : listeners)
{
try
{
listener.actionResolved(synchronization, action, id);
}
catch (Throwable ex)
{
SetupSyncPlugin.INSTANCE.log(ex);
}
}
}
protected void commitStarted()
{
for (SynchronizerListener listener : listeners)
{
try
{
listener.commitStarted(synchronization);
}
catch (Throwable ex)
{
SetupSyncPlugin.INSTANCE.log(ex);
}
}
}
protected void commitFinished(Throwable exception)
{
for (SynchronizerListener listener : listeners)
{
try
{
listener.commitFinished(synchronization, exception);
}
catch (Throwable ex)
{
SetupSyncPlugin.INSTANCE.log(ex);
}
}
}
protected synchronized void releaseLock()
{
if (synchronization != null)
{
Synchronization oldSynchronization = synchronization;
synchronization = null;
doReleaseLock();
for (SynchronizerListener listener : listeners)
{
try
{
listener.lockReleased(oldSynchronization);
}
catch (Throwable ex)
{
SetupSyncPlugin.INSTANCE.log(ex);
}
}
}
}
private void doReleaseLock()
{
if (lockFile != null)
{
lockFile.unlock();
}
}
/**
* @author Eike Stepper
*/
public static class LockException extends SynchronizerException
{
private static final long serialVersionUID = 1L;
public LockException(File file)
{
super(NLS.bind(Messages.Synchronizer_OtherSyncLock_exception, file));
}
}
}