From: David A. Velasco Date: Fri, 27 Sep 2013 12:34:43 +0000 (+0200) Subject: Check and creation for InstantUploads folder fixed and rewritten X-Git-Tag: oc-android-1.4.6~10^2~1 X-Git-Url: http://git.linex4red.de/pub/Android/ownCloud.git/commitdiff_plain/ea26ae434990a71e88d7dc4d9454c21b8cf9bf02 Check and creation for InstantUploads folder fixed and rewritten --- diff --git a/src/com/owncloud/android/datamodel/FileDataStorageManager.java b/src/com/owncloud/android/datamodel/FileDataStorageManager.java index f4611936..5f6321d8 100644 --- a/src/com/owncloud/android/datamodel/FileDataStorageManager.java +++ b/src/com/owncloud/android/datamodel/FileDataStorageManager.java @@ -676,7 +676,6 @@ public class FileDataStorageManager implements DataStorageManager { while (parentId != 0) { - Log_OC.d(TAG, "parent = " + parentId); // Update the size of the parent calculateFolderSize(parentId); diff --git a/src/com/owncloud/android/db/DbHandler.java b/src/com/owncloud/android/db/DbHandler.java index 889d1dbf..1f9cf9ca 100644 --- a/src/com/owncloud/android/db/DbHandler.java +++ b/src/com/owncloud/android/db/DbHandler.java @@ -37,7 +37,7 @@ public class DbHandler { private final String mDatabaseName = "ownCloud"; private final int mDatabaseVersion = 3; - private final String TABLE_INSTANT_UPLOAD = "instant_upload"; + private final String TABLE_INSTANT_UPLOAD = "DbHandler"; public static final int UPLOAD_STATUS_UPLOAD_LATER = 0; public static final int UPLOAD_STATUS_UPLOAD_FAILED = 1; diff --git a/src/com/owncloud/android/files/InstantUploadBroadcastReceiver.java b/src/com/owncloud/android/files/InstantUploadBroadcastReceiver.java index 21ee975d..6eb6ec7b 100644 --- a/src/com/owncloud/android/files/InstantUploadBroadcastReceiver.java +++ b/src/com/owncloud/android/files/InstantUploadBroadcastReceiver.java @@ -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; @@ -70,6 +70,7 @@ public class InstantUploadBroadcastReceiver extends BroadcastReceiver { 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); @@ -78,6 +79,7 @@ public class InstantUploadBroadcastReceiver extends BroadcastReceiver { } db.close(); } + */ } private void handleNewPhotoAction(Context context, Intent intent) { @@ -123,8 +125,8 @@ public class InstantUploadBroadcastReceiver extends BroadcastReceiver { // 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); @@ -149,8 +151,8 @@ public class InstantUploadBroadcastReceiver extends BroadcastReceiver { 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")); diff --git a/src/com/owncloud/android/files/services/FileUploader.java b/src/com/owncloud/android/files/services/FileUploader.java index a02e74a5..0f1e9cdb 100644 --- a/src/com/owncloud/android/files/services/FileUploader.java +++ b/src/com/owncloud/android/files/services/FileUploader.java @@ -38,6 +38,7 @@ import com.owncloud.android.datamodel.FileDataStorageManager; 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 @@ public class FileUploader extends Service implements OnDatatransferProgressListe 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; @@ -277,7 +269,7 @@ public class FileUploader extends Service implements OnDatatransferProgressListe } else { newUpload = new UploadFileOperation(account, files[i], isInstant, forceOverwrite, localAction); } - if (fixed && i == 0) { + if (isInstant) { newUpload.setRemoteFolderToBeCreated(); } mPendingUploads.putIfAbsent(uploadKey, newUpload); @@ -497,7 +489,7 @@ public class FileUploader extends Service implements OnDatatransferProgressListe notifyUploadStart(mCurrentUpload); - RemoteOperationResult uploadResult = null; + RemoteOperationResult uploadResult = null, grantResult = null; try { /// prepare client object to send requests to the ownCloud server @@ -506,20 +498,22 @@ public class FileUploader extends Service implements OnDatatransferProgressListe 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) { @@ -547,6 +541,58 @@ public class FileUploader extends Service implements OnDatatransferProgressListe } /** + * 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 @@ -618,28 +664,6 @@ public class FileUploader extends Service implements OnDatatransferProgressListe // 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); @@ -669,12 +693,6 @@ public class FileUploader extends Service implements OnDatatransferProgressListe } 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; } @@ -781,7 +799,7 @@ public class FileUploader extends Service implements OnDatatransferProgressListe 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 { @@ -851,10 +869,10 @@ public class FileUploader extends Service implements OnDatatransferProgressListe 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) { diff --git a/src/com/owncloud/android/operations/CreateFolderOperation.java b/src/com/owncloud/android/operations/CreateFolderOperation.java index 1a38cdbf..5745ec21 100644 --- a/src/com/owncloud/android/operations/CreateFolderOperation.java +++ b/src/com/owncloud/android/operations/CreateFolderOperation.java @@ -17,6 +17,9 @@ package com.owncloud.android.operations; +import java.io.File; + +import org.apache.commons.httpclient.HttpStatus; import org.apache.jackrabbit.webdav.client.methods.MkColMethod; import com.owncloud.android.Log_OC; @@ -39,25 +42,25 @@ public class CreateFolderOperation extends RemoteOperation { private static final int CONNECTION_TIMEOUT = 5000; protected String mRemotePath; - protected long mParentDirId; + protected boolean mCreateFullPath; protected DataStorageManager mStorageManager; /** * Constructor * - * @param remoetPath Full path to the new directory to create in the remote server. - * @param parentDirId Local database id for the parent folder. + * @param remotePath Full path to the new directory to create in the remote server. + * @param createFullPath 'True' means that all the ancestor folders should be created if don't exist yet. * @param storageManager Reference to the local database corresponding to the account where the file is contained. */ - public CreateFolderOperation(String remotePath, long parentDirId, DataStorageManager storageManager) { + public CreateFolderOperation(String remotePath, boolean createFullPath, DataStorageManager storageManager) { mRemotePath = remotePath; - mParentDirId = parentDirId; + mCreateFullPath = createFullPath; mStorageManager = storageManager; } /** - * Performs the remove operation + * Performs the operation * * @param client Client object to communicate with the remote ownCloud server. */ @@ -68,15 +71,19 @@ public class CreateFolderOperation extends RemoteOperation { try { mkcol = new MkColMethod(client.getBaseUri() + WebdavUtils.encodePath(mRemotePath)); int status = client.executeMethod(mkcol, READ_TIMEOUT, CONNECTION_TIMEOUT); + if (!mkcol.succeeded() && mkcol.getStatusCode() == HttpStatus.SC_CONFLICT && mCreateFullPath) { + result = createParentFolder(getParentPath(), client); + status = client.executeMethod(mkcol, READ_TIMEOUT, CONNECTION_TIMEOUT); // second (and last) try + } if (mkcol.succeeded()) { // Save new directory in local database OCFile newDir = new OCFile(mRemotePath); newDir.setMimetype("DIR"); - newDir.setParentId(mParentDirId); + long parentId = mStorageManager.getFileByPath(getParentPath()).getFileId(); + newDir.setParentId(parentId); newDir.setModificationTimestamp(System.currentTimeMillis()); mStorageManager.saveFile(newDir); } - result = new RemoteOperationResult(mkcol.succeeded(), status, mkcol.getResponseHeaders()); Log_OC.d(TAG, "Create directory " + mRemotePath + ": " + result.getLogMessage()); client.exhaustResponse(mkcol.getResponseBodyAsStream()); @@ -91,5 +98,20 @@ public class CreateFolderOperation extends RemoteOperation { } return result; } + + + private String getParentPath() { + String parentPath = new File(mRemotePath).getParent(); + parentPath = parentPath.endsWith(OCFile.PATH_SEPARATOR) ? parentPath : parentPath + OCFile.PATH_SEPARATOR; + return parentPath; + } + + private RemoteOperationResult createParentFolder(String parentPath, WebdavClient client) { + RemoteOperation operation = new CreateFolderOperation( parentPath, + mCreateFullPath, + mStorageManager ); + return operation.execute(client); + } + } diff --git a/src/com/owncloud/android/ui/activity/FileDisplayActivity.java b/src/com/owncloud/android/ui/activity/FileDisplayActivity.java index 6bacaaba..db47d465 100644 --- a/src/com/owncloud/android/ui/activity/FileDisplayActivity.java +++ b/src/com/owncloud/android/ui/activity/FileDisplayActivity.java @@ -1328,7 +1328,7 @@ OCFileListFragment.ContainerActivity, FileDetailFragment.ContainerActivity, OnNa // Create directory path += newDirectoryName + OCFile.PATH_SEPARATOR; - RemoteOperation operation = new CreateFolderOperation(path, getCurrentDir().getFileId(), mStorageManager); + RemoteOperation operation = new CreateFolderOperation(path, false, mStorageManager); operation.execute( getAccount(), FileDisplayActivity.this, FileDisplayActivity.this,