/**
* Aptana Studio
* Copyright (c) 2005-2011 by Appcelerator, Inc. All Rights Reserved.
* Licensed under the terms of the GNU Public License (GPL) v3 (with exceptions).
* Please see the license.html included with this distribution for details.
* Any modifications to this file must keep this entire header intact.
*/
package com.aptana.ide.syncing.core.old;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.SubMonitor;
import org.eclipse.core.runtime.jobs.Job;
import com.aptana.core.io.efs.EFSUtils;
import com.aptana.ide.core.io.IConnectionPoint;
/**
* @author Kevin Sawicki (ksawicki@aptana.com)
* @author Michael Xia (mxia@aptana.com)
*/
public class SyncJob extends Job implements ISyncEventHandler
{
/**
* The feedback client.
*/
public static interface Client
{
/**
* Indicates the job started syncing the specified pair.
*
* @param item
* the pair being synced
*/
public void syncItem(VirtualFileSyncPair item);
/**
* Indicates a certain number of bytes has been synced for a specific pair.
*
* @param item
* the pair being synced
* @param bytes
* the number of bytes transferred
*/
public void syncProgress(VirtualFileSyncPair item, long bytes);
/**
* Indicates the specified pair has completed.
*
* @param item
* the completed pair
* @param allDone
* true if all pairs have been completed, false otherwise
*/
public void syncDone(VirtualFileSyncPair item, boolean allDone);
/**
* Indicates the specified pair has error during transfer.
*
* @param item
* the error pair
* @param allDone
* true if all pairs have been completed, false otherwise
*/
public void syncError(VirtualFileSyncPair item, boolean allDone);
}
/**
* BOTH
*/
public static final int BOTH = 0;
/**
* UPLOAD
*/
public static final int UPLOAD = 1;
/**
* DOWNLOAD
*/
public static final int DOWNLOAD = 2;
private Synchronizer fSyncer;
private List<VirtualFileSyncPair> fPairs;
private int fDirection;
private boolean fDeleteRemote;
private boolean fDeleteLocal;
private List<VirtualFileSyncPair> fCompletedPairs;
private int fErrorPairs;
private Client fClient;
/**
* Constructor.
*
* @param syncer
* the synchronizer
* @param pairs
* the list of pairs to sync
* @param direction
* the direction which the pairs should be synced (BOTH, UPLOAD, or DOWNLOAD)
* @param deleteRemote
* indicates if the remote files should be deleted
* @param deleteLocal
* indicates if the local files should be deleted
* @param client
* the client to receive feedbacks on the progress of syncing
*/
public SyncJob(Synchronizer syncer, List<VirtualFileSyncPair> pairs, int direction, boolean deleteRemote,
boolean deleteLocal, Client client, String name)
{
super(MessageFormat.format("Synchronizing {0}", name)); //$NON-NLS-1$
fSyncer = syncer;
fPairs = pairs;
fDirection = direction;
fDeleteRemote = deleteRemote;
fDeleteLocal = deleteLocal;
fClient = client;
fCompletedPairs = new ArrayList<VirtualFileSyncPair>();
sortPairs();
fSyncer.setEventHandler(this);
}
/**
* Returns an array of completed pairs.
*
* @return the array of completed pairs
*/
public VirtualFileSyncPair[] getCompletedPairs()
{
return fCompletedPairs.toArray(new VirtualFileSyncPair[fCompletedPairs.size()]);
}
/**
* Returns the total number of bytes for the entire transfer.
*
* @return the total number of bytes for the entire transfer
*/
public long getTotalTransferBytes()
{
long bytes = 0;
int size = fPairs.size();
for (int i = 0; i < size; ++i)
{
bytes += getTransferBytes(fPairs.get(i));
}
return bytes;
}
public long getTransferBytes(VirtualFileSyncPair pair)
{
switch (fDirection)
{
case BOTH:
int state = pair.getSyncState();
if (state == SyncState.ClientItemIsNewer || state == SyncState.ClientItemOnly
|| state == SyncState.ClientItemDeleted)
{
return pair.getSourceFile().fetchInfo().getLength();
}
if (state == SyncState.ServerItemIsNewer || state == SyncState.ServerItemOnly
|| state == SyncState.ServerItemDeleted)
{
return pair.getDestinationFile().fetchInfo().getLength();
}
return 0;
case UPLOAD:
return pair.getSourceFile().fetchInfo().getLength();
case DOWNLOAD:
return pair.getDestinationFile().fetchInfo().getLength();
}
return 0;
}
public int getErrorCount()
{
return fPairs.size() - fCompletedPairs.size();
}
/**
* @see com.aptana.ide.syncing.core.events.sync.ISyncEventHandler#syncContinue(IProgressMonitor)
*/
public boolean syncContinue(IProgressMonitor monitor)
{
return !monitor.isCanceled();
}
/**
* @see com.aptana.ide.syncing.core.events.sync.ISyncEventHandler#syncDone(VirtualFileSyncPair, IProgressMonitor)
*/
public void syncDone(VirtualFileSyncPair item, IProgressMonitor monitor)
{
if (monitor.isCanceled())
{
return;
}
fCompletedPairs.add(item);
int syncState = item.getSyncState();
if (syncState == SyncState.ClientItemOnly && fDeleteLocal && (fDirection == BOTH || fDirection == DOWNLOAD))
{
item.setSyncState(SyncState.ClientItemDeleted);
}
else if (syncState == SyncState.ServerItemOnly && fDeleteRemote && (fDirection == BOTH || fDirection == UPLOAD))
{
item.setSyncState(SyncState.ServerItemDeleted);
}
if (fClient != null)
{
fClient.syncDone(item, isDone());
}
}
/**
* @see com.aptana.ide.syncing.core.events.sync.ISyncEventHandler#syncErrorEvent(VirtualFileSyncPair, Exception,
* IProgressMonitor)
*/
public boolean syncErrorEvent(VirtualFileSyncPair item, Exception e, IProgressMonitor monitor)
{
if (monitor.isCanceled())
{
return false;
}
fErrorPairs++;
if (fClient != null)
{
fClient.syncError(item, isDone());
}
return true;
}
/**
* @see com.aptana.ide.syncing.core.events.sync.ISyncEventHandler#syncEvent(VirtualFileSyncPair, int, int,
* IProgressMonitor)
*/
public boolean syncEvent(VirtualFileSyncPair item, int index, int totalItems, IProgressMonitor monitor)
{
if (monitor.isCanceled())
{
return false;
}
if (fClient != null)
{
fClient.syncItem(item);
}
return true;
}
/**
* @see com.aptana.ide.syncing.core.events.sync.ISyncEventHandler#syncTransferring(VirtualFileSyncPair, long,
* IProgressMonitor)
*/
public void syncTransferring(VirtualFileSyncPair item, long bytes, IProgressMonitor monitor)
{
if (monitor.isCanceled())
{
return;
}
if (fClient != null)
{
fClient.syncProgress(item, bytes);
}
}
/**
* @see com.aptana.ide.syncing.core.events.sync.ISyncEventHandler#getFilesEvent(IConnectionPoint, String)
*/
public boolean getFilesEvent(IConnectionPoint manager, String path)
{
return true;
}
/**
* @see org.eclipse.core.runtime.jobs.Job#run(org.eclipse.core.runtime.IProgressMonitor)
*/
@Override
protected IStatus run(IProgressMonitor monitor)
{
if (fPairs.size() == 0)
{
// nothing to be synced (likely because all files are skipped), so considers it finished
if (fClient != null)
{
fClient.syncDone(null, true);
}
}
else
{
SubMonitor sub = SubMonitor.convert(monitor, "Syncing files", fPairs.size()); //$NON-NLS-1$
VirtualFileSyncPair[] pairs = fPairs.toArray(new VirtualFileSyncPair[fPairs.size()]);
switch (fDirection)
{
case BOTH:
fullSync(pairs, sub.newChild(fPairs.size()));
break;
case UPLOAD:
upload(pairs, sub.newChild(fPairs.size()));
break;
case DOWNLOAD:
download(pairs, sub.newChild(fPairs.size()));
break;
}
}
return Status.OK_STATUS;
}
private boolean fullSync(VirtualFileSyncPair[] pairs, IProgressMonitor sub)
{
return fSyncer.fullSyncAndDelete(pairs, fDeleteLocal, fDeleteRemote, sub);
}
private boolean download(VirtualFileSyncPair[] pairs, IProgressMonitor sub)
{
try
{
fSyncer.downloadAndDelete(pairs, fDeleteLocal, sub);
return true;
}
catch (Exception e)
{
}
return false;
}
private boolean upload(VirtualFileSyncPair[] pairs, IProgressMonitor sub)
{
try
{
fSyncer.uploadAndDelete(pairs, fDeleteRemote, sub);
return true;
}
catch (Exception e)
{
}
return false;
}
private boolean isDone()
{
return fCompletedPairs.size() + fErrorPairs == fPairs.size();
}
private void sortPairs()
{
Collections.sort(fPairs, new Comparator<VirtualFileSyncPair>()
{
public int compare(VirtualFileSyncPair pair1, VirtualFileSyncPair pair2)
{
try
{
if (pair1 != null && pair2 != null)
{
if (fDeleteLocal && pair1.getSyncState() == SyncState.ClientItemOnly
&& pair2.getSyncState() == SyncState.ClientItemOnly && pair1.getSourceFile() != null
&& pair2.getSourceFile() != null)
{
String s1 = EFSUtils.getAbsolutePath(pair1.getSourceFile());
String s2 = EFSUtils.getAbsolutePath(pair2.getSourceFile());
if (s1 != null)
{
return -1 * s1.compareToIgnoreCase(s2);
}
}
else if (fDeleteRemote && pair1.getSyncState() == SyncState.ServerItemOnly
&& pair2.getSyncState() == SyncState.ServerItemOnly
&& pair1.getDestinationFile() != null && pair2.getDestinationFile() != null)
{
String s1 = EFSUtils.getAbsolutePath(pair1.getDestinationFile());
String s2 = EFSUtils.getAbsolutePath(pair2.getDestinationFile());
if (s1 != null)
{
return -1 * s1.compareToIgnoreCase(s2);
}
}
}
}
catch (Exception e)
{
// Do nothing and move on
}
return 0;
}
});
}
}