3790ba3a60abcf64beb0837f4426547a6c18a110
[pub/Android/ownCloud.git] / oc_framework / src / com / owncloud / android / oc_framework / operations / RemoteOperationResult.java
1 /* ownCloud webDAV Library for Android is available under MIT license
2 * Copyright (C) 2012 Bartek Przybylski
3 * Copyright (C) 2014 ownCloud (http://www.owncloud.org/)
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.oc_framework.operations;
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
44 import com.owncloud.android.oc_framework.accounts.AccountUtils.AccountNotFoundException;
45 import com.owncloud.android.oc_framework.network.CertificateCombinedException;
46
47 import android.accounts.Account;
48 import android.accounts.AccountsException;
49 import android.util.Log;
50
51
52 /**
53 * The result of a remote operation required to an ownCloud server.
54 *
55 * Provides a common classification of remote operation results for all the
56 * application.
57 *
58 * @author David A. Velasco
59 */
60 public class RemoteOperationResult implements Serializable {
61
62 /** Generated - should be refreshed every time the class changes!! */
63 private static final long serialVersionUID = -2469951225222759283L;
64
65 private static final String TAG = "RemoteOperationResult";
66
67 public enum ResultCode {
68 OK,
69 OK_SSL,
70 OK_NO_SSL,
71 UNHANDLED_HTTP_CODE,
72 UNAUTHORIZED,
73 FILE_NOT_FOUND,
74 INSTANCE_NOT_CONFIGURED,
75 UNKNOWN_ERROR,
76 WRONG_CONNECTION,
77 TIMEOUT,
78 INCORRECT_ADDRESS,
79 HOST_NOT_AVAILABLE,
80 NO_NETWORK_CONNECTION,
81 SSL_ERROR,
82 SSL_RECOVERABLE_PEER_UNVERIFIED,
83 BAD_OC_VERSION,
84 CANCELLED,
85 INVALID_LOCAL_FILE_NAME,
86 INVALID_OVERWRITE,
87 CONFLICT,
88 OAUTH2_ERROR,
89 SYNC_CONFLICT,
90 LOCAL_STORAGE_FULL,
91 LOCAL_STORAGE_NOT_MOVED,
92 LOCAL_STORAGE_NOT_COPIED,
93 OAUTH2_ERROR_ACCESS_DENIED,
94 QUOTA_EXCEEDED,
95 ACCOUNT_NOT_FOUND,
96 ACCOUNT_EXCEPTION,
97 ACCOUNT_NOT_NEW,
98 ACCOUNT_NOT_THE_SAME,
99 INVALID_CHARACTER_IN_NAME
100 }
101
102 private boolean mSuccess = false;
103 private int mHttpCode = -1;
104 private Exception mException = null;
105 private ResultCode mCode = ResultCode.UNKNOWN_ERROR;
106 private String mRedirectedLocation;
107
108 private ArrayList<RemoteFile> mFiles;
109
110 public RemoteOperationResult(ResultCode code) {
111 mCode = code;
112 mSuccess = (code == ResultCode.OK || code == ResultCode.OK_SSL || code == ResultCode.OK_NO_SSL);
113 mFiles = null;
114 }
115
116 private RemoteOperationResult(boolean success, int httpCode) {
117 mSuccess = success;
118 mHttpCode = httpCode;
119
120 if (success) {
121 mCode = ResultCode.OK;
122
123 } else if (httpCode > 0) {
124 switch (httpCode) {
125 case HttpStatus.SC_UNAUTHORIZED:
126 mCode = ResultCode.UNAUTHORIZED;
127 break;
128 case HttpStatus.SC_NOT_FOUND:
129 mCode = ResultCode.FILE_NOT_FOUND;
130 break;
131 case HttpStatus.SC_INTERNAL_SERVER_ERROR:
132 mCode = ResultCode.INSTANCE_NOT_CONFIGURED;
133 break;
134 case HttpStatus.SC_CONFLICT:
135 mCode = ResultCode.CONFLICT;
136 break;
137 case HttpStatus.SC_INSUFFICIENT_STORAGE:
138 mCode = ResultCode.QUOTA_EXCEEDED;
139 break;
140 default:
141 mCode = ResultCode.UNHANDLED_HTTP_CODE;
142 Log.d(TAG, "RemoteOperationResult has processed UNHANDLED_HTTP_CODE: " + httpCode);
143 }
144 }
145 }
146
147 public RemoteOperationResult(boolean success, int httpCode, Header[] headers) {
148 this(success, httpCode);
149 if (headers != null) {
150 Header current;
151 for (int i=0; i<headers.length; i++) {
152 current = headers[i];
153 if ("Location".equals(current.getName())) {
154 mRedirectedLocation = current.getValue();
155 break;
156 }
157 }
158 }
159 }
160
161 public RemoteOperationResult(Exception e) {
162 mException = e;
163
164 if (e instanceof OperationCancelledException) {
165 mCode = ResultCode.CANCELLED;
166
167 } else if (e instanceof SocketException) {
168 mCode = ResultCode.WRONG_CONNECTION;
169
170 } else if (e instanceof SocketTimeoutException) {
171 mCode = ResultCode.TIMEOUT;
172
173 } else if (e instanceof ConnectTimeoutException) {
174 mCode = ResultCode.TIMEOUT;
175
176 } else if (e instanceof MalformedURLException) {
177 mCode = ResultCode.INCORRECT_ADDRESS;
178
179 } else if (e instanceof UnknownHostException) {
180 mCode = ResultCode.HOST_NOT_AVAILABLE;
181
182 } else if (e instanceof AccountNotFoundException) {
183 mCode = ResultCode.ACCOUNT_NOT_FOUND;
184
185 } else if (e instanceof AccountsException) {
186 mCode = ResultCode.ACCOUNT_EXCEPTION;
187
188 } else if (e instanceof SSLException || e instanceof RuntimeException) {
189 CertificateCombinedException se = getCertificateCombinedException(e);
190 if (se != null) {
191 mException = se;
192 if (se.isRecoverable()) {
193 mCode = ResultCode.SSL_RECOVERABLE_PEER_UNVERIFIED;
194 }
195 } else if (e instanceof RuntimeException) {
196 mCode = ResultCode.HOST_NOT_AVAILABLE;
197
198 } else {
199 mCode = ResultCode.SSL_ERROR;
200 }
201
202 } else {
203 mCode = ResultCode.UNKNOWN_ERROR;
204 }
205
206 }
207
208
209 public void setData(ArrayList<RemoteFile> files){
210 mFiles = files;
211 }
212
213 public ArrayList<RemoteFile> getData(){
214 return mFiles;
215 }
216
217 public boolean isSuccess() {
218 return mSuccess;
219 }
220
221 public boolean isCancelled() {
222 return mCode == ResultCode.CANCELLED;
223 }
224
225 public int getHttpCode() {
226 return mHttpCode;
227 }
228
229 public ResultCode getCode() {
230 return mCode;
231 }
232
233 public Exception getException() {
234 return mException;
235 }
236
237 public boolean isSslRecoverableException() {
238 return mCode == ResultCode.SSL_RECOVERABLE_PEER_UNVERIFIED;
239 }
240
241 private CertificateCombinedException getCertificateCombinedException(Exception e) {
242 CertificateCombinedException result = null;
243 if (e instanceof CertificateCombinedException) {
244 return (CertificateCombinedException) e;
245 }
246 Throwable cause = mException.getCause();
247 Throwable previousCause = null;
248 while (cause != null && cause != previousCause && !(cause instanceof CertificateCombinedException)) {
249 previousCause = cause;
250 cause = cause.getCause();
251 }
252 if (cause != null && cause instanceof CertificateCombinedException) {
253 result = (CertificateCombinedException) cause;
254 }
255 return result;
256 }
257
258 public String getLogMessage() {
259
260 if (mException != null) {
261 if (mException instanceof OperationCancelledException) {
262 return "Operation cancelled by the caller";
263
264 } else if (mException instanceof SocketException) {
265 return "Socket exception";
266
267 } else if (mException instanceof SocketTimeoutException) {
268 return "Socket timeout exception";
269
270 } else if (mException instanceof ConnectTimeoutException) {
271 return "Connect timeout exception";
272
273 } else if (mException instanceof MalformedURLException) {
274 return "Malformed URL exception";
275
276 } else if (mException instanceof UnknownHostException) {
277 return "Unknown host exception";
278
279 } else if (mException instanceof CertificateCombinedException) {
280 if (((CertificateCombinedException) mException).isRecoverable())
281 return "SSL recoverable exception";
282 else
283 return "SSL exception";
284
285 } else if (mException instanceof SSLException) {
286 return "SSL exception";
287
288 } else if (mException instanceof DavException) {
289 return "Unexpected WebDAV exception";
290
291 } else if (mException instanceof HttpException) {
292 return "HTTP violation";
293
294 } else if (mException instanceof IOException) {
295 return "Unrecovered transport exception";
296
297 } else if (mException instanceof AccountNotFoundException) {
298 Account failedAccount = ((AccountNotFoundException)mException).getFailedAccount();
299 return mException.getMessage() + " (" + (failedAccount != null ? failedAccount.name : "NULL") + ")";
300
301 } else if (mException instanceof AccountsException) {
302 return "Exception while using account";
303
304 } else {
305 return "Unexpected exception";
306 }
307 }
308
309 if (mCode == ResultCode.INSTANCE_NOT_CONFIGURED) {
310 return "The ownCloud server is not configured!";
311
312 } else if (mCode == ResultCode.NO_NETWORK_CONNECTION) {
313 return "No network connection";
314
315 } else if (mCode == ResultCode.BAD_OC_VERSION) {
316 return "No valid ownCloud version was found at the server";
317
318 } else if (mCode == ResultCode.LOCAL_STORAGE_FULL) {
319 return "Local storage full";
320
321 } else if (mCode == ResultCode.LOCAL_STORAGE_NOT_MOVED) {
322 return "Error while moving file to final directory";
323
324 } else if (mCode == ResultCode.ACCOUNT_NOT_NEW) {
325 return "Account already existing when creating a new one";
326
327 } else if (mCode == ResultCode.ACCOUNT_NOT_THE_SAME) {
328 return "Authenticated with a different account than the one updating";
329 } else if (mCode == ResultCode.INVALID_CHARACTER_IN_NAME) {
330 return "The file name contains an forbidden character";
331 }
332
333 return "Operation finished with HTTP status code " + mHttpCode + " (" + (isSuccess() ? "success" : "fail") + ")";
334
335 }
336
337 public boolean isServerFail() {
338 return (mHttpCode >= HttpStatus.SC_INTERNAL_SERVER_ERROR);
339 }
340
341 public boolean isException() {
342 return (mException != null);
343 }
344
345 public boolean isTemporalRedirection() {
346 return (mHttpCode == 302 || mHttpCode == 307);
347 }
348
349 public String getRedirectedLocation() {
350 return mRedirectedLocation;
351 }
352
353 public boolean isIdPRedirection() {
354 return (mRedirectedLocation != null &&
355 (mRedirectedLocation.toUpperCase().contains("SAML") ||
356 mRedirectedLocation.toLowerCase().contains("wayf")));
357 }
358
359 }