df6d747171cceb6583f8b3961b3b462856934377
[pub/Android/ownCloud.git] / oc_framework / src / com / owncloud / android / lib / operations / common / RemoteOperationResult.java
1 /* ownCloud Android Library is available under MIT license
2 * Copyright (C) 2014 ownCloud (http://www.owncloud.org/)
3 * Copyright (C) 2012 Bartek Przybylski
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a copy
6 * of this software and associated documentation files (the "Software"), to deal
7 * in the Software without restriction, including without limitation the rights
8 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 * copies of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
19 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
20 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
23 *
24 */
25
26 package com.owncloud.android.lib.operations.common;
27
28 import java.io.IOException;
29 import java.io.Serializable;
30 import java.net.MalformedURLException;
31 import java.net.SocketException;
32 import java.net.SocketTimeoutException;
33 import java.net.UnknownHostException;
34 import java.util.ArrayList;
35
36 import javax.net.ssl.SSLException;
37
38 import org.apache.commons.httpclient.ConnectTimeoutException;
39 import org.apache.commons.httpclient.Header;
40 import org.apache.commons.httpclient.HttpException;
41 import org.apache.commons.httpclient.HttpStatus;
42 import org.apache.jackrabbit.webdav.DavException;
43 import org.json.JSONException;
44
45 import com.owncloud.android.lib.accounts.AccountUtils.AccountNotFoundException;
46 import com.owncloud.android.lib.network.CertificateCombinedException;
47
48 import android.accounts.Account;
49 import android.accounts.AccountsException;
50 import android.util.Log;
51
52
53 /**
54 * The result of a remote operation required to an ownCloud server.
55 *
56 * Provides a common classification of remote operation results for all the
57 * application.
58 *
59 * @author David A. Velasco
60 */
61 public class RemoteOperationResult implements Serializable {
62
63 /** Generated - should be refreshed every time the class changes!! */
64 private static final long serialVersionUID = -8257349554488668693L;
65
66 private static final String TAG = "RemoteOperationResult";
67
68 public enum ResultCode {
69 OK,
70 OK_SSL,
71 OK_NO_SSL,
72 UNHANDLED_HTTP_CODE,
73 UNAUTHORIZED,
74 FILE_NOT_FOUND,
75 INSTANCE_NOT_CONFIGURED,
76 UNKNOWN_ERROR,
77 WRONG_CONNECTION,
78 TIMEOUT,
79 INCORRECT_ADDRESS,
80 HOST_NOT_AVAILABLE,
81 NO_NETWORK_CONNECTION,
82 SSL_ERROR,
83 SSL_RECOVERABLE_PEER_UNVERIFIED,
84 BAD_OC_VERSION,
85 CANCELLED,
86 INVALID_LOCAL_FILE_NAME,
87 INVALID_OVERWRITE,
88 CONFLICT,
89 OAUTH2_ERROR,
90 SYNC_CONFLICT,
91 LOCAL_STORAGE_FULL,
92 LOCAL_STORAGE_NOT_MOVED,
93 LOCAL_STORAGE_NOT_COPIED,
94 OAUTH2_ERROR_ACCESS_DENIED,
95 QUOTA_EXCEEDED,
96 ACCOUNT_NOT_FOUND,
97 ACCOUNT_EXCEPTION,
98 ACCOUNT_NOT_NEW,
99 ACCOUNT_NOT_THE_SAME,
100 INVALID_CHARACTER_IN_NAME
101 }
102
103 private boolean mSuccess = false;
104 private int mHttpCode = -1;
105 private Exception mException = null;
106 private ResultCode mCode = ResultCode.UNKNOWN_ERROR;
107 private String mRedirectedLocation;
108
109 private ArrayList<RemoteFile> mFiles;
110
111 public RemoteOperationResult(ResultCode code) {
112 mCode = code;
113 mSuccess = (code == ResultCode.OK || code == ResultCode.OK_SSL || code == ResultCode.OK_NO_SSL);
114 mFiles = null;
115 }
116
117 private RemoteOperationResult(boolean success, int httpCode) {
118 mSuccess = success;
119 mHttpCode = httpCode;
120
121 if (success) {
122 mCode = ResultCode.OK;
123
124 } else if (httpCode > 0) {
125 switch (httpCode) {
126 case HttpStatus.SC_UNAUTHORIZED:
127 mCode = ResultCode.UNAUTHORIZED;
128 break;
129 case HttpStatus.SC_NOT_FOUND:
130 mCode = ResultCode.FILE_NOT_FOUND;
131 break;
132 case HttpStatus.SC_INTERNAL_SERVER_ERROR:
133 mCode = ResultCode.INSTANCE_NOT_CONFIGURED;
134 break;
135 case HttpStatus.SC_CONFLICT:
136 mCode = ResultCode.CONFLICT;
137 break;
138 case HttpStatus.SC_INSUFFICIENT_STORAGE:
139 mCode = ResultCode.QUOTA_EXCEEDED;
140 break;
141 default:
142 mCode = ResultCode.UNHANDLED_HTTP_CODE;
143 Log.d(TAG, "RemoteOperationResult has processed UNHANDLED_HTTP_CODE: " + httpCode);
144 }
145 }
146 }
147
148 public RemoteOperationResult(boolean success, int httpCode, Header[] headers) {
149 this(success, httpCode);
150 if (headers != null) {
151 Header current;
152 for (int i=0; i<headers.length; i++) {
153 current = headers[i];
154 if ("Location".equals(current.getName())) {
155 mRedirectedLocation = current.getValue();
156 break;
157 }
158 }
159 }
160 }
161
162 public RemoteOperationResult(Exception e) {
163 mException = e;
164
165 if (e instanceof OperationCancelledException) {
166 mCode = ResultCode.CANCELLED;
167
168 } else if (e instanceof SocketException) {
169 mCode = ResultCode.WRONG_CONNECTION;
170
171 } else if (e instanceof SocketTimeoutException) {
172 mCode = ResultCode.TIMEOUT;
173
174 } else if (e instanceof ConnectTimeoutException) {
175 mCode = ResultCode.TIMEOUT;
176
177 } else if (e instanceof MalformedURLException) {
178 mCode = ResultCode.INCORRECT_ADDRESS;
179
180 } else if (e instanceof UnknownHostException) {
181 mCode = ResultCode.HOST_NOT_AVAILABLE;
182
183 } else if (e instanceof AccountNotFoundException) {
184 mCode = ResultCode.ACCOUNT_NOT_FOUND;
185
186 } else if (e instanceof AccountsException) {
187 mCode = ResultCode.ACCOUNT_EXCEPTION;
188
189 } else if (e instanceof SSLException || e instanceof RuntimeException) {
190 CertificateCombinedException se = getCertificateCombinedException(e);
191 if (se != null) {
192 mException = se;
193 if (se.isRecoverable()) {
194 mCode = ResultCode.SSL_RECOVERABLE_PEER_UNVERIFIED;
195 }
196 } else if (e instanceof RuntimeException) {
197 mCode = ResultCode.HOST_NOT_AVAILABLE;
198
199 } else {
200 mCode = ResultCode.SSL_ERROR;
201 }
202
203 } else {
204 mCode = ResultCode.UNKNOWN_ERROR;
205 }
206
207 }
208
209
210 public void setData(ArrayList<RemoteFile> files){
211 mFiles = files;
212 }
213
214 public ArrayList<RemoteFile> getData(){
215 return mFiles;
216 }
217
218 public boolean isSuccess() {
219 return mSuccess;
220 }
221
222 public boolean isCancelled() {
223 return mCode == ResultCode.CANCELLED;
224 }
225
226 public int getHttpCode() {
227 return mHttpCode;
228 }
229
230 public ResultCode getCode() {
231 return mCode;
232 }
233
234 public Exception getException() {
235 return mException;
236 }
237
238 public boolean isSslRecoverableException() {
239 return mCode == ResultCode.SSL_RECOVERABLE_PEER_UNVERIFIED;
240 }
241
242 private CertificateCombinedException getCertificateCombinedException(Exception e) {
243 CertificateCombinedException result = null;
244 if (e instanceof CertificateCombinedException) {
245 return (CertificateCombinedException) e;
246 }
247 Throwable cause = mException.getCause();
248 Throwable previousCause = null;
249 while (cause != null && cause != previousCause && !(cause instanceof CertificateCombinedException)) {
250 previousCause = cause;
251 cause = cause.getCause();
252 }
253 if (cause != null && cause instanceof CertificateCombinedException) {
254 result = (CertificateCombinedException) cause;
255 }
256 return result;
257 }
258
259 public String getLogMessage() {
260
261 if (mException != null) {
262 if (mException instanceof OperationCancelledException) {
263 return "Operation cancelled by the caller";
264
265 } else if (mException instanceof SocketException) {
266 return "Socket exception";
267
268 } else if (mException instanceof SocketTimeoutException) {
269 return "Socket timeout exception";
270
271 } else if (mException instanceof ConnectTimeoutException) {
272 return "Connect timeout exception";
273
274 } else if (mException instanceof MalformedURLException) {
275 return "Malformed URL exception";
276
277 } else if (mException instanceof UnknownHostException) {
278 return "Unknown host exception";
279
280 } else if (mException instanceof CertificateCombinedException) {
281 if (((CertificateCombinedException) mException).isRecoverable())
282 return "SSL recoverable exception";
283 else
284 return "SSL exception";
285
286 } else if (mException instanceof SSLException) {
287 return "SSL exception";
288
289 } else if (mException instanceof DavException) {
290 return "Unexpected WebDAV exception";
291
292 } else if (mException instanceof HttpException) {
293 return "HTTP violation";
294
295 } else if (mException instanceof IOException) {
296 return "Unrecovered transport exception";
297
298 } else if (mException instanceof AccountNotFoundException) {
299 Account failedAccount = ((AccountNotFoundException)mException).getFailedAccount();
300 return mException.getMessage() + " (" + (failedAccount != null ? failedAccount.name : "NULL") + ")";
301
302 } else if (mException instanceof AccountsException) {
303 return "Exception while using account";
304
305 } else if (mException instanceof JSONException) {
306 return "JSON exception";
307
308 } else {
309 return "Unexpected exception";
310 }
311 }
312
313 if (mCode == ResultCode.INSTANCE_NOT_CONFIGURED) {
314 return "The ownCloud server is not configured!";
315
316 } else if (mCode == ResultCode.NO_NETWORK_CONNECTION) {
317 return "No network connection";
318
319 } else if (mCode == ResultCode.BAD_OC_VERSION) {
320 return "No valid ownCloud version was found at the server";
321
322 } else if (mCode == ResultCode.LOCAL_STORAGE_FULL) {
323 return "Local storage full";
324
325 } else if (mCode == ResultCode.LOCAL_STORAGE_NOT_MOVED) {
326 return "Error while moving file to final directory";
327
328 } else if (mCode == ResultCode.ACCOUNT_NOT_NEW) {
329 return "Account already existing when creating a new one";
330
331 } else if (mCode == ResultCode.ACCOUNT_NOT_THE_SAME) {
332 return "Authenticated with a different account than the one updating";
333 } else if (mCode == ResultCode.INVALID_CHARACTER_IN_NAME) {
334 return "The file name contains an forbidden character";
335 }
336
337 return "Operation finished with HTTP status code " + mHttpCode + " (" + (isSuccess() ? "success" : "fail") + ")";
338
339 }
340
341 public boolean isServerFail() {
342 return (mHttpCode >= HttpStatus.SC_INTERNAL_SERVER_ERROR);
343 }
344
345 public boolean isException() {
346 return (mException != null);
347 }
348
349 public boolean isTemporalRedirection() {
350 return (mHttpCode == 302 || mHttpCode == 307);
351 }
352
353 public String getRedirectedLocation() {
354 return mRedirectedLocation;
355 }
356
357 public boolean isIdPRedirection() {
358 return (mRedirectedLocation != null &&
359 (mRedirectedLocation.toUpperCase().contains("SAML") ||
360 mRedirectedLocation.toLowerCase().contains("wayf")));
361 }
362
363 }