Merge pull request #266 from owncloud/fix_fake_creation_of_InstantUploads_folder_when_app_is_offline

Fix fake creation of instant uploads folder when app is offline
This commit is contained in:
masensio 2013-09-30 04:46:42 -07:00
commit 8b13784522
5 changed files with 113 additions and 72 deletions

View file

@ -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);

View file

@ -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"));

View file

@ -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) {
@ -546,6 +540,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.
*
@ -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) {

View file

@ -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);
}
}

View file

@ -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,