b4f04be20309687502ee28b3cb730cc7ef7fa916
[pub/Android/ownCloud.git] / src / com / owncloud / android / operations / RemoteOperation.java
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
20 import java.io.IOException;
21
22 import com.owncloud.android.network.OwnCloudClientUtils;
23
24 import android.accounts.Account;
25 import android.accounts.AccountsException;
26 import android.accounts.AuthenticatorException;
27 import android.accounts.OperationCanceledException;
28 import android.content.Context;
29 import android.os.Handler;
30 import android.util.Log;
31
32 import eu.alefzero.webdav.WebdavClient;
33
34 /**
35 * Operation which execution involves one or several interactions with an ownCloud server.
36 *
37 * Provides methods to execute the operation both synchronously or asynchronously.
38 *
39 * @author David A. Velasco
40 */
41 public abstract class RemoteOperation implements Runnable {
42
43 private static final String TAG = RemoteOperation.class.getSimpleName();
44
45 /** ownCloud account in the remote ownCloud server to operate */
46 private Account mAccount = null;
47
48 /** Android Application context */
49 private Context mContext = null;
50
51 /** Object to interact with the remote server */
52 private WebdavClient mClient = null;
53
54 /** Callback object to notify about the execution of the remote operation */
55 private OnRemoteOperationListener mListener = null;
56
57 /** Handler to the thread where mListener methods will be called */
58 private Handler mListenerHandler = null;
59
60
61 /**
62 * Abstract method to implement the operation in derived classes.
63 */
64 protected abstract RemoteOperationResult run(WebdavClient client);
65
66
67 /**
68 * Synchronously executes the remote operation on the received ownCloud account.
69 *
70 * Do not call this method from the main thread.
71 *
72 * This method should be used whenever an ownCloud account is available, instead of {@link #execute(WebdavClient)}.
73 *
74 * @param account ownCloud account in remote ownCloud server to reach during the execution of the operation.
75 * @param context Android context for the component calling the method.
76 * @return Result of the operation.
77 */
78 public final RemoteOperationResult execute(Account account, Context context) {
79 if (account == null)
80 throw new IllegalArgumentException("Trying to execute a remote operation with a NULL Account");
81 if (context == null)
82 throw new IllegalArgumentException("Trying to execute a remote operation with a NULL Context");
83 mAccount = account;
84 mContext = context.getApplicationContext();
85 try {
86 mClient = OwnCloudClientUtils.createOwnCloudClient(mAccount, mContext);
87 } catch (Exception e) {
88 Log.e(TAG, "Error while trying to access to " + mAccount.name, e);
89 return new RemoteOperationResult(e);
90 }
91 return run(mClient);
92 }
93
94
95 /**
96 * Synchronously executes the remote operation
97 *
98 * Do not call this method from the main thread.
99 *
100 * @param client Client object to reach an ownCloud server during the execution of the operation.
101 * @return Result of the operation.
102 */
103 public final RemoteOperationResult execute(WebdavClient client) {
104 if (client == null)
105 throw new IllegalArgumentException("Trying to execute a remote operation with a NULL WebdavClient");
106 mClient = client;
107 return run(client);
108 }
109
110
111 /**
112 * Asynchronously executes the remote operation
113 *
114 * This method should be used whenever an ownCloud account is available, instead of {@link #execute(WebdavClient)}.
115 *
116 * @param account ownCloud account in remote ownCloud server to reach during the execution of the operation.
117 * @param context Android context for the component calling the method.
118 * @param listener Listener to be notified about the execution of the operation.
119 * @param listenerHandler Handler associated to the thread where the methods of the listener objects must be called.
120 * @return Thread were the remote operation is executed.
121 */
122 public final Thread execute(Account account, Context context, OnRemoteOperationListener listener, Handler listenerHandler) {
123 if (account == null)
124 throw new IllegalArgumentException("Trying to execute a remote operation with a NULL Account");
125 if (context == null)
126 throw new IllegalArgumentException("Trying to execute a remote operation with a NULL Context");
127 mAccount = account;
128 mContext = context.getApplicationContext();
129 mClient = null; // the client instance will be created from mAccount and mContext in the runnerThread to create below
130
131 if (listener == null) {
132 throw new IllegalArgumentException("Trying to execute a remote operation asynchronously without a listener to notiy the result");
133 }
134 mListener = listener;
135
136 if (listenerHandler == null) {
137 throw new IllegalArgumentException("Trying to execute a remote operation asynchronously without a handler to the listener's thread");
138 }
139 mListenerHandler = listenerHandler;
140
141 Thread runnerThread = new Thread(this);
142 runnerThread.start();
143 return runnerThread;
144 }
145
146
147 /**
148 * Asynchronously executes the remote operation
149 *
150 * @param client Client object to reach an ownCloud server during the execution of the operation.
151 * @param listener Listener to be notified about the execution of the operation.
152 * @param listenerHandler Handler associated to the thread where the methods of the listener objects must be called.
153 * @return Thread were the remote operation is executed.
154 */
155 public final Thread execute(WebdavClient client, OnRemoteOperationListener listener, Handler listenerHandler) {
156 if (client == null) {
157 throw new IllegalArgumentException("Trying to execute a remote operation with a NULL WebdavClient");
158 }
159 mClient = client;
160
161 if (listener == null) {
162 throw new IllegalArgumentException("Trying to execute a remote operation asynchronously without a listener to notiy the result");
163 }
164 mListener = listener;
165
166 if (listenerHandler == null) {
167 throw new IllegalArgumentException("Trying to execute a remote operation asynchronously without a handler to the listener's thread");
168 }
169 mListenerHandler = listenerHandler;
170
171 Thread runnerThread = new Thread(this);
172 runnerThread.start();
173 return runnerThread;
174 }
175
176 /**
177 * Synchronously retries the remote operation using the same WebdavClient in the last call to {@link RemoteOperation#execute(WebdavClient)}
178 *
179 * @param listener Listener to be notified about the execution of the operation.
180 * @param listenerHandler Handler associated to the thread where the methods of the listener objects must be called.
181 * @return Thread were the remote operation is executed.
182 */
183 public final RemoteOperationResult retry() {
184 return execute(mClient);
185 }
186
187 /**
188 * Asynchronously retries the remote operation using the same WebdavClient in the last call to {@link RemoteOperation#execute(WebdavClient, OnRemoteOperationListener, Handler)}
189 *
190 * @param listener Listener to be notified about the execution of the operation.
191 * @param listenerHandler Handler associated to the thread where the methods of the listener objects must be called.
192 * @return Thread were the remote operation is executed.
193 */
194 public final Thread retry(OnRemoteOperationListener listener, Handler listenerHandler) {
195 return execute(mClient, listener, listenerHandler);
196 }
197
198
199 /**
200 * Asynchronous execution of the operation
201 * started by {@link RemoteOperation#execute(WebdavClient, OnRemoteOperationListener, Handler)},
202 * and result posting.
203 */
204 @Override
205 public final void run() {
206 RemoteOperationResult result = null;
207 try{
208 if (mClient == null) {
209 if (mAccount != null && mContext != null) {
210 mClient = OwnCloudClientUtils.createOwnCloudClient(mAccount, mContext);
211 } else {
212 throw new IllegalStateException("Trying to run a remote operation asynchronously with no client instance or account");
213 }
214 }
215 result = run(mClient);
216
217 } catch (IOException e) {
218 Log.e(TAG, "Error while trying to access to " + mAccount.name, e);
219 result = new RemoteOperationResult(e);
220
221 } catch (AccountsException e) {
222 Log.e(TAG, "Error while trying to access to " + mAccount.name, e);
223 result = new RemoteOperationResult(e);
224 }
225
226 final RemoteOperationResult resultToSend = result;
227 if (mListenerHandler != null && mListener != null) {
228 mListenerHandler.post(new Runnable() {
229 @Override
230 public void run() {
231 mListener.onRemoteOperationFinish(RemoteOperation.this, resultToSend);
232 }
233 });
234 }
235 }
236
237
238 }