X-Git-Url: http://git.linex4red.de/pub/Android/ownCloud.git/blobdiff_plain/e650fd2c6f0120080ba9b6706aa66b4783a81a17..e6fc5d13ad8aff2f70a84d9cf96b253a108b836d:/src/com/owncloud/android/operations/SynchronizeFolderOperation.java diff --git a/src/com/owncloud/android/operations/SynchronizeFolderOperation.java b/src/com/owncloud/android/operations/SynchronizeFolderOperation.java index 534e16ab..f12d5dd7 100644 --- a/src/com/owncloud/android/operations/SynchronizeFolderOperation.java +++ b/src/com/owncloud/android/operations/SynchronizeFolderOperation.java @@ -88,7 +88,6 @@ public class SynchronizeFolderOperation extends SyncOperation { /** 'True' means that the remote folder changed and should be fetched */ private boolean mRemoteFolderChanged; - private final AtomicBoolean mCancellationRequested = new AtomicBoolean(false); private List mFilesForDirectDownload; // to avoid extra PROPFINDs when there was no change in the folder @@ -101,6 +100,7 @@ public class SynchronizeFolderOperation extends SyncOperation { private List mFoldersToWalkDown; + private final AtomicBoolean mCancellationRequested; /** * Creates a new instance of {@link SynchronizeFolderOperation}. @@ -120,7 +120,7 @@ public class SynchronizeFolderOperation extends SyncOperation { mFilesToSyncContentsWithoutUpload = new Vector(); mFavouriteFilesToSyncContents = new Vector(); mFoldersToWalkDown = new Vector(); - + mCancellationRequested = new AtomicBoolean(false); } @@ -142,41 +142,64 @@ public class SynchronizeFolderOperation extends SyncOperation { RemoteOperationResult result = null; mFailsInFileSyncsFound = 0; mConflictsFound = 0; - - synchronized(mCancellationRequested) { - if (mCancellationRequested.get()) { - return new RemoteOperationResult(new OperationCancelledException()); - } - } - - // get locally cached information about folder - mLocalFolder = getStorageManager().getFileByPath(mRemotePath); - result = checkForChanges(client); - - if (result.isSuccess()) { - if (mRemoteFolderChanged) { - result = fetchAndSyncRemoteFolder(client); + try { + // get locally cached information about folder + mLocalFolder = getStorageManager().getFileByPath(mRemotePath); + + result = checkForChanges(client); + + if (result.isSuccess()) { + if (mRemoteFolderChanged) { + result = fetchAndSyncRemoteFolder(client); + + } else { + prepareOpsFromLocalKnowledge(); + } - } else { - prepareOpsFromLocalKnowledge(); + if (result.isSuccess()) { + syncContents(client); + } + + if (mFilesForDirectDownload.isEmpty()) { + sendBroadcastForNotifyingUIUpdate(result.isSuccess()); + } } - if (result.isSuccess()) { - syncContents(client); + if (mCancellationRequested.get()) { + throw new OperationCancelledException(); } + + } catch (OperationCancelledException e) { + result = new RemoteOperationResult(e); + + // Needed in case that cancellation occurs before starting any download. + // If not, yellow arrow continues being shown. + sendBroadcastForNotifyingUIUpdate(result.isSuccess()); + + /// cancellation of download needs to be done separately in any case; a SynchronizeFolderOperation + // may finish much sooner than the real download of the files in the folder + Intent intent = new Intent(mContext, FileDownloader.class); + intent.setAction(FileDownloader.ACTION_CANCEL_FILE_DOWNLOAD); + intent.putExtra(FileDownloader.EXTRA_ACCOUNT, mAccount); + intent.putExtra(FileDownloader.EXTRA_FILE, mLocalFolder); + mContext.startService(intent); } return result; } - private RemoteOperationResult checkForChanges(OwnCloudClient client) { + private RemoteOperationResult checkForChanges(OwnCloudClient client) throws OperationCancelledException { Log_OC.d(TAG, "Checking changes in " + mAccount.name + mRemotePath); mRemoteFolderChanged = true; RemoteOperationResult result = null; + if (mCancellationRequested.get()) { + throw new OperationCancelledException(); + } + // remote request ReadRemoteFileOperation operation = new ReadRemoteFileOperation(mRemotePath); result = operation.execute(client); @@ -204,13 +227,19 @@ public class SynchronizeFolderOperation extends SyncOperation { Log_OC.e(TAG, "Checked " + mAccount.name + mRemotePath + " : " + result.getLogMessage()); } + + sendBroadcastForNotifyingUIUpdate(result.isSuccess()); } return result; } - private RemoteOperationResult fetchAndSyncRemoteFolder(OwnCloudClient client) { + private RemoteOperationResult fetchAndSyncRemoteFolder(OwnCloudClient client) throws OperationCancelledException { + if (mCancellationRequested.get()) { + throw new OperationCancelledException(); + } + ReadRemoteFolderOperation operation = new ReadRemoteFolderOperation(mRemotePath); RemoteOperationResult result = operation.execute(client); Log_OC.d(TAG, "Synchronizing " + mAccount.name + mRemotePath); @@ -258,7 +287,8 @@ public class SynchronizeFolderOperation extends SyncOperation { * retrieved. * @return 'True' when any change was made in the local data, 'false' otherwise */ - private void synchronizeData(ArrayList folderAndFiles, OwnCloudClient client) { + private void synchronizeData(ArrayList folderAndFiles, OwnCloudClient client) + throws OperationCancelledException { FileDataStorageManager storageManager = getStorageManager(); // parse data from remote folder @@ -273,7 +303,13 @@ public class SynchronizeFolderOperation extends SyncOperation { mFilesForDirectDownload.clear(); mFilesToSyncContentsWithoutUpload.clear(); mFavouriteFilesToSyncContents.clear(); - mFoldersToWalkDown.clear(); + + synchronized(mFoldersToWalkDown) { + if (mCancellationRequested.get()) { + throw new OperationCancelledException(); + } + mFoldersToWalkDown.clear(); + } // get current data about local contents of the folder to synchronize List localFiles = storageManager.getFolderContent(mLocalFolder); @@ -335,8 +371,14 @@ public class SynchronizeFolderOperation extends SyncOperation { mAccount, mCurrentSyncTime ); - mFoldersToWalkDown.add(synchFolderOp); - + + synchronized(mFoldersToWalkDown) { + if (mCancellationRequested.get()) { + throw new OperationCancelledException(); + } + mFoldersToWalkDown.add(synchFolderOp); + } + } else if (remoteFile.keepInSync()) { /// prepare content synchronization for kept-in-sync files SynchronizeFileOperation operation = new SynchronizeFileOperation( @@ -370,7 +412,7 @@ public class SynchronizeFolderOperation extends SyncOperation { } - private void prepareOpsFromLocalKnowledge() { + private void prepareOpsFromLocalKnowledge() throws OperationCancelledException { List children = getStorageManager().getFolderContent(mLocalFolder); for (OCFile child : children) { /// classify file to sync/download contents later @@ -382,8 +424,14 @@ public class SynchronizeFolderOperation extends SyncOperation { mAccount, mCurrentSyncTime ); - mFoldersToWalkDown.add(synchFolderOp); - + + synchronized(mFoldersToWalkDown) { + if (mCancellationRequested.get()) { + throw new OperationCancelledException(); + } + mFoldersToWalkDown.add(synchFolderOp); + } + } else { /// prepare limited synchronization for regular files if (!child.isDown()) { @@ -394,7 +442,7 @@ public class SynchronizeFolderOperation extends SyncOperation { } - private void syncContents(OwnCloudClient client) { + private void syncContents(OwnCloudClient client) throws OperationCancelledException { startDirectDownloads(); startContentSynchronizations(mFilesToSyncContentsWithoutUpload, client); startContentSynchronizations(mFavouriteFilesToSyncContents, client); @@ -402,8 +450,11 @@ public class SynchronizeFolderOperation extends SyncOperation { } - private void startDirectDownloads() { + private void startDirectDownloads() throws OperationCancelledException { for (OCFile file : mFilesForDirectDownload) { + if (mCancellationRequested.get()) { + throw new OperationCancelledException(); + } Intent i = new Intent(mContext, FileDownloader.class); i.putExtra(FileDownloader.EXTRA_ACCOUNT, mAccount); i.putExtra(FileDownloader.EXTRA_FILE, file); @@ -421,9 +472,14 @@ public class SynchronizeFolderOperation extends SyncOperation { * @param filesToSyncContents Synchronization operations to execute. * @param client Interface to the remote ownCloud server. */ - private void startContentSynchronizations(List filesToSyncContents, OwnCloudClient client) { + private void startContentSynchronizations(List filesToSyncContents, OwnCloudClient client) + throws OperationCancelledException { + RemoteOperationResult contentsResult = null; for (SyncOperation op: filesToSyncContents) { + if (mCancellationRequested.get()) { + throw new OperationCancelledException(); + } contentsResult = op.execute(getStorageManager(), mContext); if (!contentsResult.isSuccess()) { if (contentsResult.getCode() == ResultCode.SYNC_CONFLICT) { @@ -444,9 +500,12 @@ public class SynchronizeFolderOperation extends SyncOperation { } - private void walkSubfolders(OwnCloudClient client) { + private void walkSubfolders(OwnCloudClient client) throws OperationCancelledException { RemoteOperationResult contentsResult = null; for (SyncOperation op: mFoldersToWalkDown) { + if (mCancellationRequested.get()) { + throw new OperationCancelledException(); + } contentsResult = op.execute(client, getStorageManager()); // to watch out: possibly deep recursion if (!contentsResult.isSuccess()) { // TODO - some kind of error count, and use it with notifications @@ -460,7 +519,7 @@ public class SynchronizeFolderOperation extends SyncOperation { } } - + /** * Creates and populates a new {@link com.owncloud.android.datamodel.OCFile} object with the data read from the server. * @@ -497,13 +556,36 @@ public class SynchronizeFolderOperation extends SyncOperation { } } + private void sendBroadcastForNotifyingUIUpdate(boolean result) { + // Send a broadcast message for notifying UI update + Intent uiUpdate = new Intent(FileDownloader.getDownloadFinishMessage()); + uiUpdate.putExtra(FileDownloader.EXTRA_DOWNLOAD_RESULT, result); + uiUpdate.putExtra(FileDownloader.ACCOUNT_NAME, mAccount.name); + uiUpdate.putExtra(FileDownloader.EXTRA_REMOTE_PATH, mRemotePath); + uiUpdate.putExtra(FileDownloader.EXTRA_FILE_PATH, mLocalFolder.getRemotePath()); + mContext.sendStickyBroadcast(uiUpdate); + } + /** * Cancel operation */ - public void cancel(){ - // WIP Cancel the sync operation + public void cancel() { mCancellationRequested.set(true); + + synchronized(mFoldersToWalkDown) { + // cancel 'child' synchronizations + for (SyncOperation synchOp : mFoldersToWalkDown) { + ((SynchronizeFolderOperation) synchOp).cancel(); + } + } } + public String getFolderPath() { + String path = mLocalFolder.getStoragePath(); + if (path != null && path.length() > 0) { + return path; + } + return FileStorageUtils.getDefaultSavePathFor(mAccount.name, mLocalFolder); + } }