RemoteOperation.java 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256
  1. /* ownCloud Android client application
  2. * Copyright (C) 2011 Bartek Przybylski
  3. *
  4. * This program is free software: you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation, either version 3 of the License, or
  7. * (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  16. *
  17. */
  18. package com.owncloud.android.operations;
  19. import java.io.IOException;
  20. import com.owncloud.android.network.OwnCloudClientUtils;
  21. import android.accounts.Account;
  22. import android.accounts.AccountsException;
  23. import android.app.Activity;
  24. import android.content.Context;
  25. import android.os.Handler;
  26. import android.util.Log;
  27. import eu.alefzero.webdav.WebdavClient;
  28. /**
  29. * Operation which execution involves one or several interactions with an ownCloud server.
  30. *
  31. * Provides methods to execute the operation both synchronously or asynchronously.
  32. *
  33. * @author David A. Velasco
  34. */
  35. public abstract class RemoteOperation implements Runnable {
  36. private static final String TAG = RemoteOperation.class.getSimpleName();
  37. /** ownCloud account in the remote ownCloud server to operate */
  38. private Account mAccount = null;
  39. /** Android Application context */
  40. private Context mContext = null;
  41. /** Object to interact with the remote server */
  42. private WebdavClient mClient = null;
  43. /** Callback object to notify about the execution of the remote operation */
  44. private OnRemoteOperationListener mListener = null;
  45. /** Handler to the thread where mListener methods will be called */
  46. private Handler mListenerHandler = null;
  47. /** Activity */
  48. private Activity mCallerActivity;
  49. /**
  50. * Abstract method to implement the operation in derived classes.
  51. */
  52. protected abstract RemoteOperationResult run(WebdavClient client);
  53. /**
  54. * Synchronously executes the remote operation on the received ownCloud account.
  55. *
  56. * Do not call this method from the main thread.
  57. *
  58. * This method should be used whenever an ownCloud account is available, instead of {@link #execute(WebdavClient)}.
  59. *
  60. * @param account ownCloud account in remote ownCloud server to reach during the execution of the operation.
  61. * @param context Android context for the component calling the method.
  62. * @return Result of the operation.
  63. */
  64. public final RemoteOperationResult execute(Account account, Context context) {
  65. if (account == null)
  66. throw new IllegalArgumentException("Trying to execute a remote operation with a NULL Account");
  67. if (context == null)
  68. throw new IllegalArgumentException("Trying to execute a remote operation with a NULL Context");
  69. mAccount = account;
  70. mContext = context.getApplicationContext();
  71. try {
  72. mClient = OwnCloudClientUtils.createOwnCloudClient(mAccount, mContext);
  73. } catch (Exception e) {
  74. Log.e(TAG, "Error while trying to access to " + mAccount.name, e);
  75. return new RemoteOperationResult(e);
  76. }
  77. return run(mClient);
  78. }
  79. /**
  80. * Synchronously executes the remote operation
  81. *
  82. * Do not call this method from the main thread.
  83. *
  84. * @param client Client object to reach an ownCloud server during the execution of the operation.
  85. * @return Result of the operation.
  86. */
  87. public final RemoteOperationResult execute(WebdavClient client) {
  88. if (client == null)
  89. throw new IllegalArgumentException("Trying to execute a remote operation with a NULL WebdavClient");
  90. mClient = client;
  91. return run(client);
  92. }
  93. /**
  94. * Asynchronously executes the remote operation
  95. *
  96. * This method should be used whenever an ownCloud account is available, instead of {@link #execute(WebdavClient)}.
  97. *
  98. * @param account ownCloud account in remote ownCloud server to reach during the execution of the operation.
  99. * @param context Android context for the component calling the method.
  100. * @param listener Listener to be notified about the execution of the operation.
  101. * @param listenerHandler Handler associated to the thread where the methods of the listener objects must be called.
  102. * @return Thread were the remote operation is executed.
  103. */
  104. public final Thread execute(Account account, Context context, OnRemoteOperationListener listener, Handler listenerHandler, Activity callerActivity) {
  105. if (account == null)
  106. throw new IllegalArgumentException("Trying to execute a remote operation with a NULL Account");
  107. if (context == null)
  108. throw new IllegalArgumentException("Trying to execute a remote operation with a NULL Context");
  109. mAccount = account;
  110. mContext = context.getApplicationContext();
  111. mCallerActivity = callerActivity;
  112. mClient = null; // the client instance will be created from mAccount and mContext in the runnerThread to create below
  113. if (listener == null) {
  114. throw new IllegalArgumentException("Trying to execute a remote operation asynchronously without a listener to notiy the result");
  115. }
  116. mListener = listener;
  117. if (listenerHandler == null) {
  118. throw new IllegalArgumentException("Trying to execute a remote operation asynchronously without a handler to the listener's thread");
  119. }
  120. mListenerHandler = listenerHandler;
  121. Thread runnerThread = new Thread(this);
  122. runnerThread.start();
  123. return runnerThread;
  124. }
  125. /**
  126. * Asynchronously executes the remote operation
  127. *
  128. * @param client Client object to reach an ownCloud server during the execution of the operation.
  129. * @param listener Listener to be notified about the execution of the operation.
  130. * @param listenerHandler Handler associated to the thread where the methods of the listener objects must be called.
  131. * @return Thread were the remote operation is executed.
  132. */
  133. public final Thread execute(WebdavClient client, OnRemoteOperationListener listener, Handler listenerHandler) {
  134. if (client == null) {
  135. throw new IllegalArgumentException("Trying to execute a remote operation with a NULL WebdavClient");
  136. }
  137. mClient = client;
  138. if (listener == null) {
  139. throw new IllegalArgumentException("Trying to execute a remote operation asynchronously without a listener to notiy the result");
  140. }
  141. mListener = listener;
  142. if (listenerHandler == null) {
  143. throw new IllegalArgumentException("Trying to execute a remote operation asynchronously without a handler to the listener's thread");
  144. }
  145. mListenerHandler = listenerHandler;
  146. Thread runnerThread = new Thread(this);
  147. runnerThread.start();
  148. return runnerThread;
  149. }
  150. /**
  151. * Synchronously retries the remote operation using the same WebdavClient in the last call to {@link RemoteOperation#execute(WebdavClient)}
  152. *
  153. * @param listener Listener to be notified about the execution of the operation.
  154. * @param listenerHandler Handler associated to the thread where the methods of the listener objects must be called.
  155. * @return Thread were the remote operation is executed.
  156. */
  157. public final RemoteOperationResult retry() {
  158. return execute(mClient);
  159. }
  160. /**
  161. * Asynchronously retries the remote operation using the same WebdavClient in the last call to {@link RemoteOperation#execute(WebdavClient, OnRemoteOperationListener, Handler)}
  162. *
  163. * @param listener Listener to be notified about the execution of the operation.
  164. * @param listenerHandler Handler associated to the thread where the methods of the listener objects must be called.
  165. * @return Thread were the remote operation is executed.
  166. */
  167. public final Thread retry(OnRemoteOperationListener listener, Handler listenerHandler) {
  168. return execute(mClient, listener, listenerHandler);
  169. }
  170. /**
  171. * Asynchronous execution of the operation
  172. * started by {@link RemoteOperation#execute(WebdavClient, OnRemoteOperationListener, Handler)},
  173. * and result posting.
  174. */
  175. @Override
  176. public final void run() {
  177. RemoteOperationResult result = null;
  178. try{
  179. if (mClient == null) {
  180. if (mAccount != null && mContext != null) {
  181. if (mCallerActivity != null) {
  182. mClient = OwnCloudClientUtils.createOwnCloudClient(mAccount, mContext, mCallerActivity);
  183. } else {
  184. mClient = OwnCloudClientUtils.createOwnCloudClient(mAccount, mContext);
  185. }
  186. } else {
  187. throw new IllegalStateException("Trying to run a remote operation asynchronously with no client instance or account");
  188. }
  189. }
  190. } catch (IOException e) {
  191. Log.e(TAG, "Error while trying to access to " + mAccount.name, new AccountsException("I/O exception while trying to authorize the account", e));
  192. result = new RemoteOperationResult(e);
  193. } catch (AccountsException e) {
  194. Log.e(TAG, "Error while trying to access to " + mAccount.name, e);
  195. result = new RemoteOperationResult(e);
  196. }
  197. if (result == null)
  198. result = run(mClient);
  199. final RemoteOperationResult resultToSend = result;
  200. if (mListenerHandler != null && mListener != null) {
  201. mListenerHandler.post(new Runnable() {
  202. @Override
  203. public void run() {
  204. mListener.onRemoteOperationFinish(RemoteOperation.this, resultToSend);
  205. }
  206. });
  207. }
  208. }
  209. /**
  210. * Returns the current client instance to access the remote server.
  211. *
  212. * @return Current client instance to access the remote server.
  213. */
  214. public final WebdavClient getClient() {
  215. return mClient;
  216. }
  217. }