Merge branch 'develop' into fix_instant_uploads_in_Samsung_4.x_devices
authorDavid A. Velasco <dvelasco@solidgear.es>
Mon, 30 Sep 2013 11:49:50 +0000 (13:49 +0200)
committerDavid A. Velasco <dvelasco@solidgear.es>
Mon, 30 Sep 2013 11:49:50 +0000 (13:49 +0200)
1  2 
src/com/owncloud/android/files/InstantUploadBroadcastReceiver.java
src/com/owncloud/android/files/services/FileUploader.java

@@@ -29,7 -29,7 +29,7 @@@ import android.accounts.Account
  import android.content.BroadcastReceiver;
  import android.content.Context;
  import android.content.Intent;
- import android.content.IntentFilter;
//import android.content.IntentFilter;
  import android.database.Cursor;
  import android.net.ConnectivityManager;
  import android.net.NetworkInfo.State;
@@@ -54,7 -54,8 +54,7 @@@ public class InstantUploadBroadcastRece
          Log_OC.d(TAG, "Received: " + intent.getAction());
          if (intent.getAction().equals(android.net.ConnectivityManager.CONNECTIVITY_ACTION)) {
              handleConnectivityAction(context, intent);
 -        } else if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.ICE_CREAM_SANDWICH && 
 -                intent.getAction().equals(NEW_PHOTO_ACTION_UNOFFICIAL)) {
 +        }else if (intent.getAction().equals(NEW_PHOTO_ACTION_UNOFFICIAL)) {
              handleNewPhotoAction(context, intent);
              Log_OC.d(TAG, "UNOFFICIAL processed: com.android.camera.NEW_PICTURE");
          } else if (intent.getAction().equals(NEW_PHOTO_ACTION)) {
@@@ -69,6 -70,7 +69,7 @@@
  
      private void handleUploadFinished(Context context, Intent intent) {
          // remove successfull uploading, ignore rest for reupload on reconnect
+         /*
          if (intent.getBooleanExtra(FileUploader.EXTRA_UPLOAD_RESULT, false)) {
              DbHandler db = new DbHandler(context);
              String localPath = intent.getStringExtra(FileUploader.EXTRA_OLD_FILE_PATH);
@@@ -77,6 -79,7 +78,7 @@@
              }
              db.close();
          }
+         */
      }
  
      private void handleNewPhotoAction(Context context, Intent intent) {
          // we can unregister from entire listenings but thats suck a bit.
          // On the other hand this might be only for dynamicly registered
          // broadcast receivers, needs investigation.
-         IntentFilter filter = new IntentFilter(FileUploader.UPLOAD_FINISH_MESSAGE);
-         context.getApplicationContext().registerReceiver(this, filter);
+         /*IntentFilter filter = new IntentFilter(FileUploader.UPLOAD_FINISH_MESSAGE);
+         context.getApplicationContext().registerReceiver(this, filter);*/
  
          Intent i = new Intent(context, FileUploader.class);
          i.putExtra(FileUploader.KEY_ACCOUNT, account);
              DbHandler db = new DbHandler(context);
              Cursor c = db.getAwaitingFiles();
              if (c.moveToFirst()) {
-                 IntentFilter filter = new IntentFilter(FileUploader.UPLOAD_FINISH_MESSAGE);
-                 context.getApplicationContext().registerReceiver(this, filter);
+                 //IntentFilter filter = new IntentFilter(FileUploader.UPLOAD_FINISH_MESSAGE);
+                 //context.getApplicationContext().registerReceiver(this, filter);
                  do {
                      String account_name = c.getString(c.getColumnIndex("account"));
                      String file_path = c.getString(c.getColumnIndex("path"));
@@@ -38,6 -38,7 +38,7 @@@ import com.owncloud.android.datamodel.F
  import com.owncloud.android.datamodel.OCFile;
  import com.owncloud.android.operations.ChunkedUploadFileOperation;
  import com.owncloud.android.operations.CreateFolderOperation;
+ import com.owncloud.android.operations.ExistenceCheckOperation;
  import com.owncloud.android.operations.RemoteOperation;
  import com.owncloud.android.operations.RemoteOperationResult;
  import com.owncloud.android.operations.UploadFileOperation;
@@@ -223,16 -224,7 +224,7 @@@ public class FileUploader extends Servi
          boolean forceOverwrite = intent.getBooleanExtra(KEY_FORCE_OVERWRITE, false);
          boolean isInstant = intent.getBooleanExtra(KEY_INSTANT_UPLOAD, false);
          int localAction = intent.getIntExtra(KEY_LOCAL_BEHAVIOUR, LOCAL_BEHAVIOUR_COPY);
-         boolean fixed = false;
-         if (isInstant) {
-             fixed = checkAndFixInstantUploadDirectory(storageManager); // MUST
-                                                                        // be
-                                                                        // done
-                                                                        // BEFORE
-                                                                        // calling
-                                                                        // obtainNewOCFileToUpload
-         }
+         
          if (intent.hasExtra(KEY_FILE) && files == null) {
              Log_OC.e(TAG, "Incorrect array for OCFiles provided in upload intent");
              return Service.START_NOT_STICKY;
                  } else {
                      newUpload = new UploadFileOperation(account, files[i], isInstant, forceOverwrite, localAction);
                  }
-                 if (fixed && i == 0) {
+                 if (isInstant) {
                      newUpload.setRemoteFolderToBeCreated();
                  }
 -                mPendingUploads.putIfAbsent(uploadKey, newUpload);
 +                mPendingUploads.putIfAbsent(uploadKey, newUpload); // Grants that the file only upload once time
 +                Log_OC.d(TAG, "Trying to update "+ uploadKey);
                  newUpload.addDatatransferProgressListener(this);
                  newUpload.addDatatransferProgressListener((FileUploaderBinder)mBinder);
                  requestedUploads.add(uploadKey);
  
              notifyUploadStart(mCurrentUpload);
  
-             RemoteOperationResult uploadResult = null;
+             RemoteOperationResult uploadResult = null, grantResult = null;
              
              try {
                  /// prepare client object to send requests to the ownCloud server
                      mStorageManager = new FileDataStorageManager(mLastAccount, getContentResolver());
                      mUploadClient = OwnCloudClientUtils.createOwnCloudClient(mLastAccount, getApplicationContext());
                  }
-             
-                 /// create remote folder for instant uploads
-                 if (mCurrentUpload.isRemoteFolderToBeCreated()) {
-                     RemoteOperation operation = new CreateFolderOperation(  FileStorageUtils.getInstantUploadFilePath(this, ""), 
-                                                                             mStorageManager.getFileByPath(OCFile.PATH_SEPARATOR).getFileId(), // TODO generalize this : INSTANT_UPLOAD_DIR could not be a child of root
-                                                                             mStorageManager);
-                     operation.execute(mUploadClient);      // ignoring result; fail could just mean that it already exists, but local database is not synchronized; the upload will be tried anyway
-                 }
+                 
+                 /// check the existence of the parent folder for the file to upload
+                 String remoteParentPath = new File(mCurrentUpload.getRemotePath()).getParent();
+                 remoteParentPath = remoteParentPath.endsWith(OCFile.PATH_SEPARATOR) ? remoteParentPath : remoteParentPath + OCFile.PATH_SEPARATOR;
+                 grantResult = grantFolderExistence(remoteParentPath);
              
                  /// perform the upload
-                 uploadResult = mCurrentUpload.execute(mUploadClient);
-                 if (uploadResult.isSuccess()) {
-                     saveUploadedFile();
+                 if (grantResult.isSuccess()) {
+                     OCFile parent = mStorageManager.getFileByPath(remoteParentPath);
+                     mCurrentUpload.getFile().setParentId(parent.getFileId());
+                     uploadResult = mCurrentUpload.execute(mUploadClient);
+                     if (uploadResult.isSuccess()) {
+                         saveUploadedFile();
+                     }
+                 } else {
+                     uploadResult = grantResult;
                  }
                  
              } catch (AccountsException e) {
      }
  
      /**
+      * Checks the existence of the folder where the current file will be uploaded both in the remote server 
+      * and in the local database.
+      * 
+      * If the upload is set to enforce the creation of the folder, the method tries to create it both remote
+      * and locally.
+      *  
+      *  @param  pathToGrant     Full remote path whose existence will be granted.
+      *  @return  An {@link OCFile} instance corresponding to the folder where the file will be uploaded.
+      */
+     private RemoteOperationResult grantFolderExistence(String pathToGrant) {
+         RemoteOperation operation = new ExistenceCheckOperation(pathToGrant, this, false);
+         RemoteOperationResult result = operation.execute(mUploadClient);
+         if (!result.isSuccess() && result.getCode() == ResultCode.FILE_NOT_FOUND && mCurrentUpload.isRemoteFolderToBeCreated()) {
+             operation = new CreateFolderOperation(  pathToGrant,
+                                                     true,
+                                                     mStorageManager    );
+             result = operation.execute(mUploadClient);
+         }
+         if (result.isSuccess()) {
+             OCFile parentDir = mStorageManager.getFileByPath(pathToGrant);
+             if (parentDir == null) {
+                 parentDir = createLocalFolder(pathToGrant);
+             }
+             if (parentDir != null) {
+                 result = new RemoteOperationResult(ResultCode.OK);
+             } else {
+                 result = new RemoteOperationResult(ResultCode.UNKNOWN_ERROR);
+             }
+         }
+         return result;
+     }
+     
+     private OCFile createLocalFolder(String remotePath) {
+         String parentPath = new File(remotePath).getParent();
+         parentPath = parentPath.endsWith(OCFile.PATH_SEPARATOR) ? parentPath : parentPath + OCFile.PATH_SEPARATOR;
+         OCFile parent = mStorageManager.getFileByPath(parentPath);
+         if (parent == null) {
+             parent = createLocalFolder(parentPath);
+         }
+         if (parent != null) {
+             OCFile createdFolder = new OCFile(remotePath);
+             createdFolder.setMimetype("DIR");
+             createdFolder.setParentId(parent.getFileId());
+             mStorageManager.saveFile(createdFolder);
+             return createdFolder;
+         }
+         return null;
+     }
+     
+     /**
       * Saves a OC File after a successful upload.
       * 
       * A PROPFIND is necessary to keep the props in the local database
          // file.setEtag(mCurrentUpload.getEtag());    // TODO Etag, where available
      }
  
-     private boolean checkAndFixInstantUploadDirectory(FileDataStorageManager storageManager) {
-         String instantUploadDirPath = FileStorageUtils.getInstantUploadFilePath(this, "");
-         OCFile instantUploadDir = storageManager.getFileByPath(instantUploadDirPath);
-         if (instantUploadDir == null) {
-             // first instant upload in the account. never account not
-             // synchronized after the remote InstantUpload folder was created
-             OCFile newDir = new OCFile(instantUploadDirPath);
-             newDir.setMimetype("DIR");
-             OCFile path = storageManager.getFileByPath(OCFile.PATH_SEPARATOR);
-             if (path != null) {
-                 newDir.setParentId(path.getFileId());
-                 storageManager.saveFile(newDir);
-                 return true;
-             } else {    // this should not happen anymore
-                 return false;
-             }
-         }
-         return false;
-     }
      private OCFile obtainNewOCFileToUpload(String remotePath, String localPath, String mimeType,
              FileDataStorageManager storageManager) {
          OCFile newFile = new OCFile(remotePath);
          }
          newFile.setMimetype(mimeType);
  
-         // parent dir
-         String parentPath = new File(remotePath).getParent();
-         parentPath = parentPath.endsWith(OCFile.PATH_SEPARATOR) ? parentPath : parentPath + OCFile.PATH_SEPARATOR;
-         OCFile parentDir = storageManager.getFileByPath(parentPath);
-         long parentDirId = parentDir.getFileId();
-         newFile.setParentId(parentDirId);
          return newFile;
      }
  
              mNotificationManager.notify(R.string.uploader_upload_in_progress_ticker, mNotification); // NOT
                                                                                                       // AN
              DbHandler db = new DbHandler(this.getBaseContext());
-             db.removeIUPendingFile(mCurrentUpload.getFile().getStoragePath());
+             db.removeIUPendingFile(mCurrentUpload.getOriginalStoragePath());
              db.close();
  
          } else {
                          Log_OC.e(TAG, message + " Http-Code: " + uploadResult.getHttpCode());
                          if (uploadResult.getCode() == ResultCode.QUOTA_EXCEEDED) {
                              message = getString(R.string.failed_upload_quota_exceeded_text);
-                         }
-                         if (db.updateFileState(upload.getOriginalStoragePath(), DbHandler.UPLOAD_STATUS_UPLOAD_FAILED,
-                                 message) == 0) {
-                             db.putFileForLater(upload.getOriginalStoragePath(), upload.getAccount().name, message);
+                             if (db.updateFileState(upload.getOriginalStoragePath(), DbHandler.UPLOAD_STATUS_UPLOAD_FAILED,
+                                     message) == 0) {
+                                 db.putFileForLater(upload.getOriginalStoragePath(), upload.getAccount().name, message);
+                             }
                          }
                      } finally {
                          if (db != null) {