SyncFolderHandler.java 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. /**
  2. * ownCloud Android client application
  3. *
  4. * Copyright (C) 2016 ownCloud Inc.
  5. *
  6. * This program is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License version 2,
  8. * as published by the Free Software Foundation.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. *
  18. */
  19. package com.owncloud.android.services;
  20. import android.accounts.Account;
  21. import android.accounts.AccountsException;
  22. import android.content.Intent;
  23. import android.os.Handler;
  24. import android.os.Looper;
  25. import android.os.Message;
  26. import android.util.Pair;
  27. import com.owncloud.android.datamodel.FileDataStorageManager;
  28. import com.owncloud.android.datamodel.OCFile;
  29. import com.owncloud.android.files.services.FileDownloader;
  30. import com.owncloud.android.files.services.IndexedForest;
  31. import com.owncloud.android.lib.common.OwnCloudAccount;
  32. import com.owncloud.android.lib.common.OwnCloudClient;
  33. import com.owncloud.android.lib.common.OwnCloudClientManagerFactory;
  34. import com.owncloud.android.lib.common.operations.RemoteOperationResult;
  35. import com.owncloud.android.lib.common.utils.Log_OC;
  36. import com.owncloud.android.operations.SynchronizeFolderOperation;
  37. import com.owncloud.android.utils.FileStorageUtils;
  38. import java.io.IOException;
  39. /**
  40. * SyncFolder worker. Performs the pending operations in the order they were requested.
  41. *
  42. * Created with the Looper of a new thread, started in
  43. * {@link com.owncloud.android.services.OperationsService#onCreate()}.
  44. */
  45. class SyncFolderHandler extends Handler {
  46. private static final String TAG = SyncFolderHandler.class.getSimpleName();
  47. OperationsService mService;
  48. private IndexedForest<SynchronizeFolderOperation> mPendingOperations =
  49. new IndexedForest<SynchronizeFolderOperation>();
  50. private OwnCloudClient mOwnCloudClient = null;
  51. private Account mCurrentAccount = null;
  52. private FileDataStorageManager mStorageManager;
  53. private SynchronizeFolderOperation mCurrentSyncOperation;
  54. public SyncFolderHandler(Looper looper, OperationsService service) {
  55. super(looper);
  56. if (service == null) {
  57. throw new IllegalArgumentException("Received invalid NULL in parameter 'service'");
  58. }
  59. mService = service;
  60. }
  61. /**
  62. * Returns True when the folder located in 'remotePath' in the ownCloud account 'account', or any of its
  63. * descendants, is being synchronized (or waiting for it).
  64. *
  65. * @param account ownCloud account where the remote folder is stored.
  66. * @param remotePath The path to a folder that could be in the queue of synchronizations.
  67. */
  68. public boolean isSynchronizing(Account account, String remotePath) {
  69. if (account == null || remotePath == null) return false;
  70. return (mPendingOperations.contains(account.name, remotePath));
  71. }
  72. @Override
  73. public void handleMessage(Message msg) {
  74. Pair<Account, String> itemSyncKey = (Pair<Account, String>) msg.obj;
  75. doOperation(itemSyncKey.first, itemSyncKey.second);
  76. Log_OC.d(TAG, "Stopping after command with id " + msg.arg1);
  77. mService.stopSelf(msg.arg1);
  78. }
  79. /**
  80. * Performs the next operation in the queue
  81. */
  82. private void doOperation(Account account, String remotePath) {
  83. mCurrentSyncOperation = mPendingOperations.get(account.name, remotePath);
  84. if (mCurrentSyncOperation != null) {
  85. RemoteOperationResult result = null;
  86. try {
  87. if (mCurrentAccount == null || !mCurrentAccount.equals(account)) {
  88. mCurrentAccount = account;
  89. mStorageManager = new FileDataStorageManager(
  90. account,
  91. mService.getContentResolver()
  92. );
  93. } // else, reuse storage manager from previous operation
  94. // always get client from client manager, to get fresh credentials in case of update
  95. OwnCloudAccount ocAccount = new OwnCloudAccount(account, mService);
  96. mOwnCloudClient = OwnCloudClientManagerFactory.getDefaultSingleton().
  97. getClientFor(ocAccount, mService);
  98. result = mCurrentSyncOperation.execute(mOwnCloudClient, mStorageManager);
  99. } catch (AccountsException e) {
  100. Log_OC.e(TAG, "Error while trying to get authorization", e);
  101. } catch (IOException e) {
  102. Log_OC.e(TAG, "Error while trying to get authorization", e);
  103. } finally {
  104. mPendingOperations.removePayload(account.name, remotePath);
  105. mService.dispatchResultToOperationListeners(mCurrentSyncOperation, result);
  106. sendBroadcastFinishedSyncFolder(account, remotePath, result.isSuccess());
  107. }
  108. }
  109. }
  110. public void add(Account account, String remotePath,
  111. SynchronizeFolderOperation syncFolderOperation){
  112. Pair<String, String> putResult =
  113. mPendingOperations.putIfAbsent(account.name, remotePath, syncFolderOperation);
  114. if (putResult != null) {
  115. sendBroadcastNewSyncFolder(account, remotePath); // TODO upgrade!
  116. }
  117. }
  118. /**
  119. * Cancels a pending or current sync' operation.
  120. *
  121. * @param account ownCloud {@link Account} where the remote file is stored.
  122. * @param file A file in the queue of pending synchronizations
  123. */
  124. public void cancel(Account account, OCFile file){
  125. if (account == null || file == null) {
  126. Log_OC.e(TAG, "Cannot cancel with NULL parameters");
  127. return;
  128. }
  129. Pair<SynchronizeFolderOperation, String> removeResult =
  130. mPendingOperations.remove(account.name, file.getRemotePath());
  131. SynchronizeFolderOperation synchronization = removeResult.first;
  132. if (synchronization != null) {
  133. synchronization.cancel();
  134. } else {
  135. // TODO synchronize?
  136. if (mCurrentSyncOperation != null && mCurrentAccount != null &&
  137. mCurrentSyncOperation.getRemotePath().startsWith(file.getRemotePath()) &&
  138. account.name.equals(mCurrentAccount.name)) {
  139. mCurrentSyncOperation.cancel();
  140. }
  141. }
  142. //sendBroadcastFinishedSyncFolder(account, file.getRemotePath());
  143. }
  144. /**
  145. * TODO review this method when "folder synchronization" replaces "folder download";
  146. * this is a fast and ugly patch.
  147. */
  148. private void sendBroadcastNewSyncFolder(Account account, String remotePath) {
  149. Intent added = new Intent(FileDownloader.getDownloadAddedMessage());
  150. added.putExtra(FileDownloader.ACCOUNT_NAME, account.name);
  151. added.putExtra(FileDownloader.EXTRA_REMOTE_PATH, remotePath);
  152. added.putExtra(FileDownloader.EXTRA_FILE_PATH, FileStorageUtils.getSavePath(account.name)
  153. + remotePath);
  154. mService.sendStickyBroadcast(added);
  155. }
  156. /**
  157. * TODO review this method when "folder synchronization" replaces "folder download";
  158. * this is a fast and ugly patch.
  159. */
  160. private void sendBroadcastFinishedSyncFolder(Account account, String remotePath,
  161. boolean success) {
  162. Intent finished = new Intent(FileDownloader.getDownloadFinishMessage());
  163. finished.putExtra(FileDownloader.ACCOUNT_NAME, account.name);
  164. finished.putExtra(FileDownloader.EXTRA_REMOTE_PATH, remotePath);
  165. finished.putExtra(FileDownloader.EXTRA_FILE_PATH,
  166. FileStorageUtils.getSavePath(account.name) + remotePath);
  167. finished.putExtra(FileDownloader.EXTRA_DOWNLOAD_RESULT, success);
  168. mService.sendStickyBroadcast(finished);
  169. }
  170. }