Browse Source

Refactoring UploadFileOperation.java

David A. Velasco 9 years ago
parent
commit
e5fbc8fed9
1 changed files with 154 additions and 155 deletions
  1. 154 155
      src/com/owncloud/android/operations/UploadFileOperation.java

+ 154 - 155
src/com/owncloud/android/operations/UploadFileOperation.java

@@ -306,128 +306,40 @@ public class UploadFileOperation extends RemoteOperation {
         mCancellationRequested.set(false);
         mUploadStarted.set(true);
         RemoteOperationResult result = null;
-        boolean localCopyPassed = false, nameCheckPassed = false;
         File temporalFile = null, originalFile = new File(mOriginalStoragePath), expectedFile = null;
         try {
-            // / rename the file to upload, if necessary
+            /// automatic rename of file to upload in case of name collision in server
+            Log_OC.d(TAG, "Checking name collision in server");
             if (!mForceOverwrite) {
                 String remotePath = getAvailableRemotePath(client, mRemotePath);
                 mWasRenamed = !remotePath.equals(mRemotePath);
                 if (mWasRenamed) {
                     createNewOCFile(remotePath);
+                    Log_OC.d(TAG, "File renamed as " + remotePath);
                 }
             }
-            nameCheckPassed = true;
 
-            String expectedPath = FileStorageUtils.getDefaultSavePathFor(mAccount.name, mFile); // /
-                                                                                                // not
-                                                                                                // before
-                                                                                                // getAvailableRemotePath()
-                                                                                                // !!!
-            expectedFile = new File(expectedPath);
-            
             if (mCancellationRequested.get()) {
                 throw new OperationCancelledException();
             }
 
-            // check location of local file; if not the expected, copy to a
-            // temporal file before upload (if COPY is the expected behaviour)
-            if (!mOriginalStoragePath.equals(expectedPath) &&
-                    mLocalBehaviour == FileUploader.LOCAL_BEHAVIOUR_COPY) {
-
-
-                if (FileStorageUtils.getUsableSpace(mAccount.name) < originalFile.length()) {
-                    result = new RemoteOperationResult(ResultCode.LOCAL_STORAGE_FULL);
-                    return result; // error condition when the file should be
-                                   // copied
-
-                } else {
-
-                    String temporalPath = FileStorageUtils.getTemporalPath(mAccount.name) +
-                            mFile.getRemotePath();
-                    mFile.setStoragePath(temporalPath);
-                    temporalFile = new File(temporalPath);
-
-                    File temporalParent = temporalFile.getParentFile();
-                    temporalParent.mkdirs();
-                    if (!temporalParent.isDirectory()) {
-                        throw new IOException(
-                                "Unexpected error: parent directory could not be created");
-                    }
-                    temporalFile.createNewFile();
-                    if (!temporalFile.isFile()) {
-                        throw new IOException(
-                                "Unexpected error: target file could not be created");
-                    }
+            String expectedPath = FileStorageUtils.getDefaultSavePathFor(mAccount.name, mFile);
+            expectedFile = new File(expectedPath);
 
-                    InputStream in = null;
-                    OutputStream out = null;
+            /// copy the file locally before uploading
+            if (mLocalBehaviour == FileUploader.LOCAL_BEHAVIOUR_COPY &&
+                    !mOriginalStoragePath.equals(expectedPath)) {
 
-                    try {
+                String temporalPath = FileStorageUtils.getTemporalPath(mAccount.name) + mFile.getRemotePath();
+                mFile.setStoragePath(temporalPath);
+                temporalFile = new File(temporalPath);
 
-                        // In case document provider schema as 'content://'
-                        if (mOriginalStoragePath.startsWith(UriUtils.URI_CONTENT_SCHEME)) {
-
-                            Uri uri = Uri.parse(mOriginalStoragePath);
-
-                            in = MainApp.getAppContext().getContentResolver().openInputStream(uri);
-                            out = new FileOutputStream(temporalFile);
-
-                            int nRead;
-                            byte[] data = new byte[16384];
-
-                            while (!mCancellationRequested.get() &&
-                                    (nRead = in.read(data, 0, data.length)) != -1) {
-                                out.write(data, 0, nRead);
-                            }
-                            out.flush();
-
-                        } else {
-                            if (!mOriginalStoragePath.equals(temporalPath)) { // preventing
-                                                                          // weird
-                                                                          // but
-                                                                          // possible
-                                                                          // situation
-
-                                in = new FileInputStream(originalFile);
-                                out = new FileOutputStream(temporalFile);
-                                byte[] buf = new byte[1024];
-                                int len;
-                                while (!mCancellationRequested.get() && (len = in.read(buf)) > 0) {
-                                    out.write(buf, 0, len);
-                                }
-                            }
-                        }
-
-                        if (mCancellationRequested.get()) {
-                            result = new RemoteOperationResult(new OperationCancelledException());
-                        }
-
-
-                    } catch (Exception e) {
-                        result = new RemoteOperationResult(ResultCode.LOCAL_STORAGE_NOT_COPIED);
-                        return result;
-
-                    } finally {
-                        try {
-                            if (in != null)
-                                in.close();
-                        } catch (Exception e) {
-                            Log_OC.d(TAG, "Weird exception while closing input stream for " +
-                                    mOriginalStoragePath + " (ignoring)", e);
-                        }
-                        try {
-                            if (out != null)
-                                out.close();
-                        } catch (Exception e) {
-                            Log_OC.d(TAG, "Weird exception while closing output stream for " +
-                                    expectedPath + " (ignoring)", e);
-                        }
-                    }
+                result = copy(originalFile, temporalFile);
+                if (result != null) {
+                    return result;
                 }
             }
-            localCopyPassed = (result == null);
-            
+
             if (mCancellationRequested.get()) {
                 throw new OperationCancelledException();
             }
@@ -460,53 +372,17 @@ public class UploadFileOperation extends RemoteOperation {
                     mFile.setStoragePath("");
                 } else {
                     mFile.setStoragePath(expectedPath);
-                    File fileToMove = null;
-                    if (temporalFile != null) { // FileUploader.LOCAL_BEHAVIOUR_COPY
-                                                // ; see where temporalFile was
-                                                // set
+                    File fileToMove;
+                    if (temporalFile != null) {         // FileUploader.LOCAL_BEHAVIOUR_COPY
                         fileToMove = temporalFile;
-                    } else { // FileUploader.LOCAL_BEHAVIOUR_MOVE
+                    } else {                            // FileUploader.LOCAL_BEHAVIOUR_MOVE
                         fileToMove = originalFile;
                     }
-                    if (!expectedFile.equals(fileToMove)) {
-                        File expectedFolder = expectedFile.getParentFile();
-                        expectedFolder.mkdirs();
-
-                        if (expectedFolder.isDirectory()){
-                            if (!fileToMove.renameTo(expectedFile)){
-                                // try to copy and then delete
-                                expectedFile.createNewFile();
-                                FileChannel inChannel = new FileInputStream(fileToMove).getChannel();
-                                FileChannel outChannel = new FileOutputStream(expectedFile).getChannel();
-
-                                try {
-                                    inChannel.transferTo(0, inChannel.size(), outChannel);
-                                    fileToMove.delete();
-                                } catch (Exception e){
-                                    mFile.setStoragePath(null); // forget the local file
-                                    // by now, treat this as a success; the file was
-                                    // uploaded; the user won't like that the local file
-                                    // is not linked, but this should be a very rare
-                                    // fail;
-                                    // the best option could be show a warning message
-                                    // (but not a fail)
-                                    // result = new
-                                    // RemoteOperationResult(ResultCode.LOCAL_STORAGE_NOT_MOVED);
-                                    // return result;
-                                }
-                                finally {
-                                    if (inChannel != null) inChannel.close();
-                                    if (outChannel != null) outChannel.close();
-                                }
-                            }
-
-                        } else {
-                            mFile.setStoragePath(null);
-                        }
-                    }
+                    move(fileToMove, expectedFile);
                 }
                 FileDataStorageManager.triggerMediaScan(originalFile.getAbsolutePath());
                 FileDataStorageManager.triggerMediaScan(expectedFile.getAbsolutePath());
+
             } else if (result.getHttpCode() == HttpStatus.SC_PRECONDITION_FAILED ) {
                 result = new RemoteOperationResult(ResultCode.SYNC_CONFLICT);
             }
@@ -524,20 +400,12 @@ public class UploadFileOperation extends RemoteOperation {
                         result.getLogMessage());
             } else {
                 if (result.getException() != null) {
-                    String complement = "";
-                    if (!nameCheckPassed) {
-                        complement = " (while checking file existence in server)";
-                    } else if (!localCopyPassed) {
-                        complement = " (while copying local file to " +
-                                FileStorageUtils.getSavePath(mAccount.name)
-                                + ")";
-                    }
                     if(result.isCancelled()){
                         Log_OC.w(TAG, "Upload of " + mOriginalStoragePath + " to " + mRemotePath +
                                 ": " + result.getLogMessage());
                     } else {
                         Log_OC.e(TAG, "Upload of " + mOriginalStoragePath + " to " + mRemotePath +
-                                ": " + result.getLogMessage() + complement, result.getException());
+                                ": " + result.getLogMessage(), result.getException());
                     }                    
 
                 } else {
@@ -563,7 +431,8 @@ public class UploadFileOperation extends RemoteOperation {
         newFile.setMimetype(mFile.getMimetype());
         newFile.setModificationTimestamp(mFile.getModificationTimestamp());
         newFile.setModificationTimestampAtLastSyncForData(
-                mFile.getModificationTimestampAtLastSyncForData());
+                mFile.getModificationTimestampAtLastSyncForData()
+        );
         newFile.setEtag(mFile.getEtag());
         newFile.setFavorite(mFile.isFavorite());
         newFile.setLastSyncDateForProperties(mFile.getLastSyncDateForProperties());
@@ -582,7 +451,7 @@ public class UploadFileOperation extends RemoteOperation {
      * @param remotePath
      * @return
      */
-    private String getAvailableRemotePath(OwnCloudClient wc, String remotePath) throws Exception {
+    private String getAvailableRemotePath(OwnCloudClient wc, String remotePath) {
         boolean check = existsFile(wc, remotePath);
         if (!check) {
             return remotePath;
@@ -647,4 +516,134 @@ public class UploadFileOperation extends RemoteOperation {
         return mUploadStarted.get();
 
     }
+
+    /**
+     * TODO rewrite with homogeneous fail handling, remove dependency on {@link RemoteOperationResult},
+     * TODO     use Exceptions instead
+     *
+     * @param   sourceFile      Source file to copy.
+     * @param   targetFile      Target location to copy the file.
+     * @return  {@link RemoteOperationResult}
+     * @throws  IOException
+     */
+    private RemoteOperationResult copy(File sourceFile, File targetFile) throws IOException {
+        Log_OC.d(TAG, "Copying local file");
+
+        RemoteOperationResult result = null;
+
+        if (FileStorageUtils.getUsableSpace(mAccount.name) < sourceFile.length()) {
+            result = new RemoteOperationResult(ResultCode.LOCAL_STORAGE_FULL);
+            return result;  // error condition when the file should be copied
+
+        } else {
+            Log_OC.d(TAG, "Creating temporal folder");
+            File temporalParent = targetFile.getParentFile();
+            temporalParent.mkdirs();
+            if (!temporalParent.isDirectory()) {
+                throw new IOException(
+                        "Unexpected error: parent directory could not be created");
+            }
+            Log_OC.d(TAG, "Creating temporal file");
+            targetFile.createNewFile();
+            if (!targetFile.isFile()) {
+                throw new IOException(
+                        "Unexpected error: target file could not be created");
+            }
+
+            Log_OC.d(TAG, "Copying file contents");
+            InputStream in = null;
+            OutputStream out = null;
+
+            try {
+                if (!mOriginalStoragePath.equals(targetFile.getAbsolutePath())) {
+                    // In case document provider schema as 'content://'
+                    if (mOriginalStoragePath.startsWith(UriUtils.URI_CONTENT_SCHEME)) {
+                        Uri uri = Uri.parse(mOriginalStoragePath);
+                        in = mContext.getContentResolver().openInputStream(uri);
+                    } else {
+                        in = new FileInputStream(sourceFile);
+                    }
+                    out = new FileOutputStream(targetFile);
+                    int nRead;
+                    byte[] buf = new byte[4096];
+                    while (!mCancellationRequested.get() &&
+                            (nRead = in.read(buf)) > -1) {
+                        out.write(buf, 0, nRead);
+                    }
+                    out.flush();
+
+                } // else: weird but possible situation, nothing to copy
+
+                if (mCancellationRequested.get()) {
+                    result = new RemoteOperationResult(new OperationCancelledException());
+                    return result;
+                }
+
+            } catch (Exception e) {
+                result = new RemoteOperationResult(ResultCode.LOCAL_STORAGE_NOT_COPIED);
+                return result;
+
+            } finally {
+                try {
+                    if (in != null)
+                        in.close();
+                } catch (Exception e) {
+                    Log_OC.d(TAG, "Weird exception while closing input stream for " +
+                            mOriginalStoragePath + " (ignoring)", e);
+                }
+                try {
+                    if (out != null)
+                        out.close();
+                } catch (Exception e) {
+                    Log_OC.d(TAG, "Weird exception while closing output stream for " +
+                            targetFile.getAbsolutePath() + " (ignoring)", e);
+                }
+            }
+        }
+        return result;
+    }
+
+
+    /**
+     * TODO rewrite with homogeneous fail handling, remove dependency on {@link RemoteOperationResult},
+     * TODO     use Exceptions instead
+     *
+     * TODO refactor both this and 'copy' in a single method
+     *
+     * @param   sourceFile      Source file to move.
+     * @param   targetFile      Target location to move the file.
+     * @return  {@link RemoteOperationResult}
+     * @throws  IOException
+     */
+    private void move(File sourceFile, File targetFile) throws IOException {
+
+        if (!targetFile.equals(sourceFile)) {
+            File expectedFolder = targetFile.getParentFile();
+            expectedFolder.mkdirs();
+
+            if (expectedFolder.isDirectory()){
+                if (!sourceFile.renameTo(targetFile)){
+                    // try to copy and then delete
+                    targetFile.createNewFile();
+                    FileChannel inChannel = new FileInputStream(sourceFile).getChannel();
+                    FileChannel outChannel = new FileOutputStream(targetFile).getChannel();
+                    try {
+                        inChannel.transferTo(0, inChannel.size(), outChannel);
+                        sourceFile.delete();
+                    } catch (Exception e){
+                        mFile.setStoragePath(""); // forget the local file
+                        // by now, treat this as a success; the file was uploaded
+                        // the best option could be show a warning message
+                    }
+                    finally {
+                        if (inChannel != null) inChannel.close();
+                        if (outChannel != null) outChannel.close();
+                    }
+                }
+
+            } else {
+                mFile.setStoragePath("");
+            }
+        }
+    }
 }