1 /* ownCloud Android client application 
   2  *   Copyright (C) 2012 Bartek Przybylski 
   3  *   Copyright (C) 2012-2013 ownCloud Inc. 
   5  *   This program is free software: you can redistribute it and/or modify 
   6  *   it under the terms of the GNU General Public License version 2, 
   7  *   as published by the Free Software Foundation. 
   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. 
  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/>. 
  19 package com
.owncloud
.android
.operations
; 
  21 import java
.io
.IOException
; 
  22 import java
.io
.Serializable
; 
  23 import java
.net
.MalformedURLException
; 
  24 import java
.net
.SocketException
; 
  25 import java
.net
.SocketTimeoutException
; 
  26 import java
.net
.UnknownHostException
; 
  28 import javax
.net
.ssl
.SSLException
; 
  30 import org
.apache
.commons
.httpclient
.ConnectTimeoutException
; 
  31 import org
.apache
.commons
.httpclient
.Header
; 
  32 import org
.apache
.commons
.httpclient
.HttpException
; 
  33 import org
.apache
.commons
.httpclient
.HttpStatus
; 
  34 import org
.apache
.jackrabbit
.webdav
.DavException
; 
  36 import com
.owncloud
.android
.Log_OC
; 
  37 import com
.owncloud
.android
.authentication
.AccountUtils
.AccountNotFoundException
; 
  38 import com
.owncloud
.android
.network
.CertificateCombinedException
; 
  40 import android
.accounts
.Account
; 
  41 import android
.accounts
.AccountsException
; 
  45  * The result of a remote operation required to an ownCloud server. 
  47  * Provides a common classification of remote operation results for all the 
  50  * @author David A. Velasco 
  52 public class RemoteOperationResult 
implements Serializable 
{ 
  54     /** Generated - should be refreshed every time the class changes!! */ 
  55     private static final long serialVersionUID 
= -4415103901492836870L; 
  59     private static final String TAG 
= "RemoteOperationResult"; 
  61     public enum ResultCode 
{  
  68         INSTANCE_NOT_CONFIGURED
,  
  74         NO_NETWORK_CONNECTION
,  
  76         SSL_RECOVERABLE_PEER_UNVERIFIED
, 
  79         INVALID_LOCAL_FILE_NAME
,  
  85         LOCAL_STORAGE_NOT_MOVED
,  
  86         LOCAL_STORAGE_NOT_COPIED
,  
  87         OAUTH2_ERROR_ACCESS_DENIED
, 
  95     private boolean mSuccess 
= false
; 
  96     private int mHttpCode 
= -1; 
  97     private Exception mException 
= null
; 
  98     private ResultCode mCode 
= ResultCode
.UNKNOWN_ERROR
; 
  99     private String mRedirectedLocation
; 
 101     public RemoteOperationResult(ResultCode code
) { 
 103         mSuccess 
= (code 
== ResultCode
.OK 
|| code 
== ResultCode
.OK_SSL 
|| code 
== ResultCode
.OK_NO_SSL
); 
 106     private RemoteOperationResult(boolean success
, int httpCode
) { 
 108         mHttpCode 
= httpCode
; 
 111             mCode 
= ResultCode
.OK
; 
 113         } else if (httpCode 
> 0) { 
 115             case HttpStatus
.SC_UNAUTHORIZED
: 
 116                 mCode 
= ResultCode
.UNAUTHORIZED
; 
 118             case HttpStatus
.SC_NOT_FOUND
: 
 119                 mCode 
= ResultCode
.FILE_NOT_FOUND
; 
 121             case HttpStatus
.SC_INTERNAL_SERVER_ERROR
: 
 122                 mCode 
= ResultCode
.INSTANCE_NOT_CONFIGURED
; 
 124             case HttpStatus
.SC_CONFLICT
: 
 125                 mCode 
= ResultCode
.CONFLICT
; 
 127             case HttpStatus
.SC_INSUFFICIENT_STORAGE
: 
 128                 mCode 
= ResultCode
.QUOTA_EXCEEDED
; 
 131                 mCode 
= ResultCode
.UNHANDLED_HTTP_CODE
; 
 132                 Log_OC
.d(TAG
, "RemoteOperationResult has processed UNHANDLED_HTTP_CODE: " + httpCode
); 
 137     public RemoteOperationResult(boolean success
, int httpCode
, Header
[] headers
) { 
 138         this(success
, httpCode
); 
 139         if (headers 
!= null
) { 
 141             for (int i
=0; i
<headers
.length
; i
++) { 
 142                 current 
= headers
[i
]; 
 143                 if ("Location".equals(current
.getName())) { 
 144                     mRedirectedLocation 
= current
.getValue(); 
 151     public RemoteOperationResult(Exception e
) { 
 154         if (e 
instanceof OperationCancelledException
) { 
 155             mCode 
= ResultCode
.CANCELLED
; 
 157         } else if (e 
instanceof SocketException
) { 
 158             mCode 
= ResultCode
.WRONG_CONNECTION
; 
 160         } else if (e 
instanceof SocketTimeoutException
) { 
 161             mCode 
= ResultCode
.TIMEOUT
; 
 163         } else if (e 
instanceof ConnectTimeoutException
) { 
 164             mCode 
= ResultCode
.TIMEOUT
; 
 166         } else if (e 
instanceof MalformedURLException
) { 
 167             mCode 
= ResultCode
.INCORRECT_ADDRESS
; 
 169         } else if (e 
instanceof UnknownHostException
) { 
 170             mCode 
= ResultCode
.HOST_NOT_AVAILABLE
; 
 172         } else if (e 
instanceof AccountNotFoundException
) { 
 173             mCode 
= ResultCode
.ACCOUNT_NOT_FOUND
; 
 175         } else if (e 
instanceof AccountsException
) { 
 176             mCode 
= ResultCode
.ACCOUNT_EXCEPTION
; 
 178         } else if (e 
instanceof SSLException 
|| e 
instanceof RuntimeException
) { 
 179             CertificateCombinedException se 
= getCertificateCombinedException(e
); 
 182                 if (se
.isRecoverable()) { 
 183                     mCode 
= ResultCode
.SSL_RECOVERABLE_PEER_UNVERIFIED
; 
 185             } else if (e 
instanceof RuntimeException
) { 
 186                 mCode 
= ResultCode
.HOST_NOT_AVAILABLE
; 
 189                 mCode 
= ResultCode
.SSL_ERROR
; 
 193             mCode 
= ResultCode
.UNKNOWN_ERROR
; 
 198     public boolean isSuccess() { 
 202     public boolean isCancelled() { 
 203         return mCode 
== ResultCode
.CANCELLED
; 
 206     public int getHttpCode() { 
 210     public ResultCode 
getCode() { 
 214     public Exception 
getException() { 
 218     public boolean isSslRecoverableException() { 
 219         return mCode 
== ResultCode
.SSL_RECOVERABLE_PEER_UNVERIFIED
; 
 222     private CertificateCombinedException 
getCertificateCombinedException(Exception e
) { 
 223         CertificateCombinedException result 
= null
; 
 224         if (e 
instanceof CertificateCombinedException
) { 
 225             return (CertificateCombinedException
) e
; 
 227         Throwable cause 
= mException
.getCause(); 
 228         Throwable previousCause 
= null
; 
 229         while (cause 
!= null 
&& cause 
!= previousCause 
&& !(cause 
instanceof CertificateCombinedException
)) { 
 230             previousCause 
= cause
; 
 231             cause 
= cause
.getCause(); 
 233         if (cause 
!= null 
&& cause 
instanceof CertificateCombinedException
) { 
 234             result 
= (CertificateCombinedException
) cause
; 
 239     public String 
getLogMessage() { 
 241         if (mException 
!= null
) { 
 242             if (mException 
instanceof OperationCancelledException
) { 
 243                 return "Operation cancelled by the caller"; 
 245             } else if (mException 
instanceof SocketException
) { 
 246                 return "Socket exception"; 
 248             } else if (mException 
instanceof SocketTimeoutException
) { 
 249                 return "Socket timeout exception"; 
 251             } else if (mException 
instanceof ConnectTimeoutException
) { 
 252                 return "Connect timeout exception"; 
 254             } else if (mException 
instanceof MalformedURLException
) { 
 255                 return "Malformed URL exception"; 
 257             } else if (mException 
instanceof UnknownHostException
) { 
 258                 return "Unknown host exception"; 
 260             } else if (mException 
instanceof CertificateCombinedException
) { 
 261                 if (((CertificateCombinedException
) mException
).isRecoverable()) 
 262                     return "SSL recoverable exception"; 
 264                     return "SSL exception"; 
 266             } else if (mException 
instanceof SSLException
) { 
 267                 return "SSL exception"; 
 269             } else if (mException 
instanceof DavException
) { 
 270                 return "Unexpected WebDAV exception"; 
 272             } else if (mException 
instanceof HttpException
) { 
 273                 return "HTTP violation"; 
 275             } else if (mException 
instanceof IOException
) { 
 276                 return "Unrecovered transport exception"; 
 278             } else if (mException 
instanceof AccountNotFoundException
) { 
 279                 Account failedAccount 
= ((AccountNotFoundException
)mException
).getFailedAccount(); 
 280                 return mException
.getMessage() + " (" + (failedAccount 
!= null ? failedAccount
.name 
: "NULL") + ")"; 
 282             } else if (mException 
instanceof AccountsException
) { 
 283                 return "Exception while using account"; 
 286                 return "Unexpected exception"; 
 290         if (mCode 
== ResultCode
.INSTANCE_NOT_CONFIGURED
) { 
 291             return "The ownCloud server is not configured!"; 
 293         } else if (mCode 
== ResultCode
.NO_NETWORK_CONNECTION
) { 
 294             return "No network connection"; 
 296         } else if (mCode 
== ResultCode
.BAD_OC_VERSION
) { 
 297             return "No valid ownCloud version was found at the server"; 
 299         } else if (mCode 
== ResultCode
.LOCAL_STORAGE_FULL
) { 
 300             return "Local storage full"; 
 302         } else if (mCode 
== ResultCode
.LOCAL_STORAGE_NOT_MOVED
) { 
 303             return "Error while moving file to final directory"; 
 305         } else if (mCode 
== ResultCode
.ACCOUNT_NOT_NEW
) { 
 306             return "Account already existing when creating a new one"; 
 308         } else if (mCode 
== ResultCode
.ACCOUNT_NOT_THE_SAME
) { 
 309             return "Authenticated with a different account than the one updating"; 
 312         return "Operation finished with HTTP status code " + mHttpCode 
+ " (" + (isSuccess() ? 
"success" : "fail") + ")"; 
 316     public boolean isServerFail() { 
 317         return (mHttpCode 
>= HttpStatus
.SC_INTERNAL_SERVER_ERROR
); 
 320     public boolean isException() { 
 321         return (mException 
!= null
); 
 324     public boolean isTemporalRedirection() { 
 325         return (mHttpCode 
== 302 || mHttpCode 
== 307); 
 328     public String 
getRedirectedLocation() { 
 329         return mRedirectedLocation
; 
 332     public boolean isIdPRedirection() { 
 333         return (mRedirectedLocation 
!= null 
&& 
 334                 (mRedirectedLocation
.toUpperCase().contains("SAML") ||  
 335                 mRedirectedLocation
.toLowerCase().contains("wayf")));