mirror of
https://github.com/nextcloud/android.git
synced 2024-11-23 13:45:35 +03:00
Refactoring FileContentProvider and FileDataStorageManager: deletion of subfolders in provider & transactions on database connection
This commit is contained in:
parent
47b7a164de
commit
af62f9857d
7 changed files with 357 additions and 157 deletions
|
@ -20,9 +20,9 @@ package com.owncloud.android.datamodel;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Vector;
|
import java.util.Vector;
|
||||||
|
|
||||||
import com.owncloud.android.Log_OC;
|
import com.owncloud.android.Log_OC;
|
||||||
|
@ -35,6 +35,7 @@ import android.content.ContentProviderClient;
|
||||||
import android.content.ContentProviderOperation;
|
import android.content.ContentProviderOperation;
|
||||||
import android.content.ContentProviderResult;
|
import android.content.ContentProviderResult;
|
||||||
import android.content.ContentResolver;
|
import android.content.ContentResolver;
|
||||||
|
import android.content.ContentUris;
|
||||||
import android.content.ContentValues;
|
import android.content.ContentValues;
|
||||||
import android.content.OperationApplicationException;
|
import android.content.OperationApplicationException;
|
||||||
import android.database.Cursor;
|
import android.database.Cursor;
|
||||||
|
@ -249,15 +250,21 @@ public class FileDataStorageManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void saveFiles(List<OCFile> files) {
|
/**
|
||||||
|
* Inserts or updates the list of files contained in a given folder.
|
||||||
|
*
|
||||||
|
* @param folder
|
||||||
|
* @param files
|
||||||
|
* @param removeNotUpdated
|
||||||
|
*/
|
||||||
|
public void saveFolder(OCFile folder, Collection<OCFile> updatedFiles, Collection<OCFile> filesToRemove) {
|
||||||
|
|
||||||
Iterator<OCFile> filesIt = files.iterator();
|
Log_OC.d(TAG, "Saving folder " + folder.getRemotePath() + " with " + updatedFiles.size() + " children and " + filesToRemove.size() + " files to remove");
|
||||||
ArrayList<ContentProviderOperation> operations = new ArrayList<ContentProviderOperation>(files.size());
|
|
||||||
OCFile file = null;
|
|
||||||
|
|
||||||
// prepare operations to perform
|
ArrayList<ContentProviderOperation> operations = new ArrayList<ContentProviderOperation>(updatedFiles.size());
|
||||||
while (filesIt.hasNext()) {
|
|
||||||
file = filesIt.next();
|
// prepare operations to insert or update files to save in the given folder
|
||||||
|
for (OCFile file : updatedFiles) {
|
||||||
ContentValues cv = new ContentValues();
|
ContentValues cv = new ContentValues();
|
||||||
cv.put(ProviderTableMeta.FILE_MODIFIED, file.getModificationTimestamp());
|
cv.put(ProviderTableMeta.FILE_MODIFIED, file.getModificationTimestamp());
|
||||||
cv.put(ProviderTableMeta.FILE_MODIFIED_AT_LAST_SYNC_FOR_DATA, file.getModificationTimestampAtLastSyncForData());
|
cv.put(ProviderTableMeta.FILE_MODIFIED_AT_LAST_SYNC_FOR_DATA, file.getModificationTimestampAtLastSyncForData());
|
||||||
|
@ -265,43 +272,47 @@ public class FileDataStorageManager {
|
||||||
cv.put(ProviderTableMeta.FILE_CONTENT_LENGTH, file.getFileLength());
|
cv.put(ProviderTableMeta.FILE_CONTENT_LENGTH, file.getFileLength());
|
||||||
cv.put(ProviderTableMeta.FILE_CONTENT_TYPE, file.getMimetype());
|
cv.put(ProviderTableMeta.FILE_CONTENT_TYPE, file.getMimetype());
|
||||||
cv.put(ProviderTableMeta.FILE_NAME, file.getFileName());
|
cv.put(ProviderTableMeta.FILE_NAME, file.getFileName());
|
||||||
if (file.getParentId() != FileDataStorageManager.ROOT_PARENT_ID)
|
//cv.put(ProviderTableMeta.FILE_PARENT, file.getParentId());
|
||||||
cv.put(ProviderTableMeta.FILE_PARENT, file.getParentId());
|
cv.put(ProviderTableMeta.FILE_PARENT, folder.getFileId());
|
||||||
cv.put(ProviderTableMeta.FILE_PATH, file.getRemotePath());
|
cv.put(ProviderTableMeta.FILE_PATH, file.getRemotePath());
|
||||||
if (!file.isFolder())
|
if (!file.isFolder()) {
|
||||||
cv.put(ProviderTableMeta.FILE_STORAGE_PATH, file.getStoragePath());
|
cv.put(ProviderTableMeta.FILE_STORAGE_PATH, file.getStoragePath());
|
||||||
|
}
|
||||||
cv.put(ProviderTableMeta.FILE_ACCOUNT_OWNER, mAccount.name);
|
cv.put(ProviderTableMeta.FILE_ACCOUNT_OWNER, mAccount.name);
|
||||||
cv.put(ProviderTableMeta.FILE_LAST_SYNC_DATE, file.getLastSyncDateForProperties());
|
cv.put(ProviderTableMeta.FILE_LAST_SYNC_DATE, file.getLastSyncDateForProperties());
|
||||||
cv.put(ProviderTableMeta.FILE_LAST_SYNC_DATE_FOR_DATA, file.getLastSyncDateForData());
|
cv.put(ProviderTableMeta.FILE_LAST_SYNC_DATE_FOR_DATA, file.getLastSyncDateForData());
|
||||||
cv.put(ProviderTableMeta.FILE_KEEP_IN_SYNC, file.keepInSync() ? 1 : 0);
|
cv.put(ProviderTableMeta.FILE_KEEP_IN_SYNC, file.keepInSync() ? 1 : 0);
|
||||||
cv.put(ProviderTableMeta.FILE_ETAG, file.getEtag());
|
cv.put(ProviderTableMeta.FILE_ETAG, file.getEtag());
|
||||||
|
|
||||||
if (fileExists(file.getRemotePath())) {
|
boolean existsByPath = fileExists(file.getRemotePath());
|
||||||
OCFile oldFile = getFileByPath(file.getRemotePath());
|
if (existsByPath || fileExists(file.getFileId())) {
|
||||||
|
// updating an existing file
|
||||||
|
|
||||||
|
/* CALLER IS THE RESPONSIBLE FOR GRANTING RIGHT UPDATE OF INFORMATION, NOT THIS METHOD.
|
||||||
|
*
|
||||||
|
* HERE ONLY DATA CONSISTENCY SHOULD BE GRANTED
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
OCFile oldFile = null;
|
||||||
|
if (existsByPath) {
|
||||||
|
// grant same id
|
||||||
|
oldFile = getFileByPath(file.getRemotePath());
|
||||||
file.setFileId(oldFile.getFileId());
|
file.setFileId(oldFile.getFileId());
|
||||||
|
} else {
|
||||||
|
oldFile = getFileById(file.getFileId());
|
||||||
|
}
|
||||||
|
|
||||||
if (file.isFolder()) {
|
if (file.isFolder()) {
|
||||||
cv.put(ProviderTableMeta.FILE_CONTENT_LENGTH, oldFile.getFileLength());
|
// folders keep size information, since it's calculated
|
||||||
file.setFileLength(oldFile.getFileLength());
|
file.setFileLength(oldFile.getFileLength());
|
||||||
}
|
cv.put(ProviderTableMeta.FILE_CONTENT_LENGTH, oldFile.getFileLength());
|
||||||
|
|
||||||
operations.add(ContentProviderOperation.newUpdate(ProviderTableMeta.CONTENT_URI).
|
} else if (file.getStoragePath() == null && oldFile.getStoragePath() != null) {
|
||||||
withValues(cv).
|
// regular files keep access to local contents, although it's lost in the new OCFile
|
||||||
withSelection( ProviderTableMeta._ID + "=?",
|
|
||||||
new String[] { String.valueOf(file.getFileId()) })
|
|
||||||
.build());
|
|
||||||
|
|
||||||
} else if (fileExists(file.getFileId())) {
|
|
||||||
OCFile oldFile = getFileById(file.getFileId());
|
|
||||||
if (file.getStoragePath() == null && oldFile.getStoragePath() != null)
|
|
||||||
file.setStoragePath(oldFile.getStoragePath());
|
file.setStoragePath(oldFile.getStoragePath());
|
||||||
|
cv.put(ProviderTableMeta.FILE_STORAGE_PATH, oldFile.getStoragePath());
|
||||||
if (!file.isFolder())
|
|
||||||
cv.put(ProviderTableMeta.FILE_STORAGE_PATH, file.getStoragePath());
|
|
||||||
else {
|
|
||||||
cv.put(ProviderTableMeta.FILE_CONTENT_LENGTH, oldFile.getFileLength());
|
|
||||||
file.setFileLength(oldFile.getFileLength());
|
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
operations.add(ContentProviderOperation.newUpdate(ProviderTableMeta.CONTENT_URI).
|
operations.add(ContentProviderOperation.newUpdate(ProviderTableMeta.CONTENT_URI).
|
||||||
withValues(cv).
|
withValues(cv).
|
||||||
|
@ -310,12 +321,62 @@ public class FileDataStorageManager {
|
||||||
.build());
|
.build());
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
// adding a new file
|
||||||
operations.add(ContentProviderOperation.newInsert(ProviderTableMeta.CONTENT_URI).withValues(cv).build());
|
operations.add(ContentProviderOperation.newInsert(ProviderTableMeta.CONTENT_URI).withValues(cv).build());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// prepare operations to remove files in the given folder
|
||||||
|
String where = ProviderTableMeta.FILE_ACCOUNT_OWNER + "=?" + " AND " + ProviderTableMeta.FILE_PATH + "=?";
|
||||||
|
String [] whereArgs = null;
|
||||||
|
for (OCFile file : filesToRemove) {
|
||||||
|
if (file.getParentId() == folder.getFileId()) {
|
||||||
|
whereArgs = new String[]{mAccount.name, file.getRemotePath()};
|
||||||
|
//Uri.withAppendedPath(ProviderTableMeta.CONTENT_URI_FILE, "" + file.getFileId());
|
||||||
|
if (file.isFolder()) {
|
||||||
|
operations.add(ContentProviderOperation
|
||||||
|
.newDelete(ContentUris.withAppendedId(ProviderTableMeta.CONTENT_URI_DIR, file.getFileId())).withSelection(where, whereArgs)
|
||||||
|
.build());
|
||||||
|
// TODO remove local folder
|
||||||
|
} else {
|
||||||
|
operations.add(ContentProviderOperation
|
||||||
|
.newDelete(ContentUris.withAppendedId(ProviderTableMeta.CONTENT_URI_FILE, file.getFileId())).withSelection(where, whereArgs)
|
||||||
|
.build());
|
||||||
|
if (file.isDown()) {
|
||||||
|
new File(file.getStoragePath()).delete();
|
||||||
|
// TODO move the deletion of local contents after success of deletions
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// update metadata of folder --> TODO MOVE UPDATE OF SIZE TO CONTENTPROVIDER
|
||||||
|
ContentValues cv = new ContentValues();
|
||||||
|
cv.put(ProviderTableMeta.FILE_MODIFIED, folder.getModificationTimestamp());
|
||||||
|
cv.put(ProviderTableMeta.FILE_MODIFIED_AT_LAST_SYNC_FOR_DATA, folder.getModificationTimestampAtLastSyncForData());
|
||||||
|
cv.put(ProviderTableMeta.FILE_CREATION, folder.getCreationTimestamp());
|
||||||
|
cv.put(ProviderTableMeta.FILE_CONTENT_LENGTH, folder.getFileLength());
|
||||||
|
cv.put(ProviderTableMeta.FILE_CONTENT_TYPE, folder.getMimetype());
|
||||||
|
cv.put(ProviderTableMeta.FILE_NAME, folder.getFileName());
|
||||||
|
cv.put(ProviderTableMeta.FILE_PARENT, folder.getParentId());
|
||||||
|
cv.put(ProviderTableMeta.FILE_PATH, folder.getRemotePath());
|
||||||
|
if (!folder.isFolder()) {
|
||||||
|
cv.put(ProviderTableMeta.FILE_STORAGE_PATH, folder.getStoragePath());
|
||||||
|
}
|
||||||
|
cv.put(ProviderTableMeta.FILE_ACCOUNT_OWNER, mAccount.name);
|
||||||
|
cv.put(ProviderTableMeta.FILE_LAST_SYNC_DATE, folder.getLastSyncDateForProperties());
|
||||||
|
cv.put(ProviderTableMeta.FILE_LAST_SYNC_DATE_FOR_DATA, folder.getLastSyncDateForData());
|
||||||
|
cv.put(ProviderTableMeta.FILE_KEEP_IN_SYNC, folder.keepInSync() ? 1 : 0);
|
||||||
|
cv.put(ProviderTableMeta.FILE_ETAG, folder.getEtag());
|
||||||
|
operations.add(ContentProviderOperation.newUpdate(ProviderTableMeta.CONTENT_URI).
|
||||||
|
withValues(cv).
|
||||||
|
withSelection( ProviderTableMeta._ID + "=?",
|
||||||
|
new String[] { String.valueOf(folder.getFileId()) })
|
||||||
|
.build());
|
||||||
|
|
||||||
// apply operations in batch
|
// apply operations in batch
|
||||||
ContentProviderResult[] results = null;
|
ContentProviderResult[] results = null;
|
||||||
|
Log_OC.d(TAG, "Sending " + operations.size() + " operations to FileContentProvider");
|
||||||
try {
|
try {
|
||||||
if (getContentResolver() != null) {
|
if (getContentResolver() != null) {
|
||||||
results = getContentResolver().applyBatch(ProviderMeta.AUTHORITY_FILES, operations);
|
results = getContentResolver().applyBatch(ProviderMeta.AUTHORITY_FILES, operations);
|
||||||
|
@ -325,27 +386,31 @@ public class FileDataStorageManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (OperationApplicationException e) {
|
} catch (OperationApplicationException e) {
|
||||||
Log_OC.e(TAG, "Fail to update/insert list of files to database " + e.getMessage());
|
Log_OC.e(TAG, "Exception in batch of operations " + e.getMessage());
|
||||||
|
|
||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
Log_OC.e(TAG, "Fail to update/insert list of files to database " + e.getMessage());
|
Log_OC.e(TAG, "Exception in batch of operations " + e.getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
// update new id in file objects for insertions
|
// update new id in file objects for insertions
|
||||||
if (results != null) {
|
if (results != null) {
|
||||||
long newId;
|
long newId;
|
||||||
|
Iterator<OCFile> filesIt = updatedFiles.iterator();
|
||||||
|
OCFile file = null;
|
||||||
for (int i=0; i<results.length; i++) {
|
for (int i=0; i<results.length; i++) {
|
||||||
|
if (filesIt.hasNext()) {
|
||||||
|
file = filesIt.next();
|
||||||
|
} else {
|
||||||
|
file = null;
|
||||||
|
}
|
||||||
if (results[i].uri != null) {
|
if (results[i].uri != null) {
|
||||||
newId = Long.parseLong(results[i].uri.getPathSegments().get(1));
|
newId = Long.parseLong(results[i].uri.getPathSegments().get(1));
|
||||||
files.get(i).setFileId(newId);
|
//updatedFiles.get(i).setFileId(newId);
|
||||||
//Log_OC.v(TAG, "Found and added id in insertion for " + files.get(i).getRemotePath());
|
if (file != null) {
|
||||||
|
file.setFileId(newId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (OCFile aFile : files) {
|
|
||||||
if (aFile.isFolder() && aFile.needsUpdatingWhileSaving())
|
|
||||||
saveFiles(getFolderContent(aFile));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -369,67 +434,88 @@ public class FileDataStorageManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void removeFile(OCFile file, boolean removeLocalCopy) {
|
public void removeFile(OCFile file, boolean removeDBData, boolean removeLocalCopy) {
|
||||||
Uri file_uri = Uri.withAppendedPath(ProviderTableMeta.CONTENT_URI_FILE, ""+file.getFileId());
|
if (file != null) {
|
||||||
|
if (file.isFolder()) {
|
||||||
|
removeFolder(file, removeDBData, removeLocalCopy);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
if (removeDBData) {
|
||||||
|
//Uri file_uri = Uri.withAppendedPath(ProviderTableMeta.CONTENT_URI_FILE, ""+file.getFileId());
|
||||||
|
Uri file_uri = ContentUris.withAppendedId(ProviderTableMeta.CONTENT_URI_FILE, file.getFileId());
|
||||||
|
String where = ProviderTableMeta.FILE_ACCOUNT_OWNER + "=?" + " AND " + ProviderTableMeta.FILE_PATH + "=?";
|
||||||
|
String [] whereArgs = new String[]{mAccount.name, file.getRemotePath()};
|
||||||
if (getContentProviderClient() != null) {
|
if (getContentProviderClient() != null) {
|
||||||
try {
|
try {
|
||||||
getContentProviderClient().delete(file_uri,
|
getContentProviderClient().delete(file_uri, where, whereArgs);
|
||||||
ProviderTableMeta.FILE_ACCOUNT_OWNER+"=?",
|
|
||||||
new String[]{mAccount.name});
|
|
||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
getContentResolver().delete(file_uri,
|
getContentResolver().delete(file_uri, where, whereArgs);
|
||||||
ProviderTableMeta.FILE_ACCOUNT_OWNER+"=?",
|
}
|
||||||
new String[]{mAccount.name});
|
if (file.getFileLength() > 0) {
|
||||||
|
updateSizesToTheRoot(file.getParentId()); // TODO move to content provider
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (removeLocalCopy && file.isDown()) {
|
||||||
|
boolean success = new File(file.getStoragePath()).delete();
|
||||||
|
if (!removeDBData && success) {
|
||||||
|
// maybe unnecessary, but should be checked TODO remove if unnecessary
|
||||||
|
file.setStoragePath(null);
|
||||||
|
saveFile(file);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (file.isDown() && removeLocalCopy) {
|
|
||||||
new File(file.getStoragePath()).delete();
|
|
||||||
}
|
}
|
||||||
if (file.isFolder() && removeLocalCopy) {
|
|
||||||
File f = new File(FileStorageUtils.getDefaultSavePathFor(mAccount.name, file));
|
|
||||||
if (f.exists() && f.isDirectory() && (f.list() == null || f.list().length == 0)) {
|
|
||||||
f.delete();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (file.getFileLength() > 0) {
|
|
||||||
updateSizesToTheRoot(file.getParentId());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void removeFolder(OCFile folder, boolean removeDBData, boolean removeLocalContent) {
|
public void removeFolder(OCFile folder, boolean removeDBData, boolean removeLocalContent) {
|
||||||
// TODO consider possible failures
|
if (folder != null && folder.isFolder()) {
|
||||||
if (folder != null && folder.isFolder() && folder.getFileId() != -1) {
|
if (removeDBData && folder.getFileId() != -1) {
|
||||||
Vector<OCFile> children = getFolderContent(folder);
|
removeFolderInDb(folder);
|
||||||
if (children.size() > 0) {
|
}
|
||||||
OCFile child = null;
|
if (removeLocalContent) {
|
||||||
for (int i=0; i<children.size(); i++) {
|
File localFolder = new File(FileStorageUtils.getDefaultSavePathFor(mAccount.name, folder));
|
||||||
child = children.get(i);
|
removeLocalFolder(localFolder);
|
||||||
if (child.isFolder()) {
|
}
|
||||||
removeFolder(child, removeDBData, removeLocalContent);
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void removeFolderInDb(OCFile folder) {
|
||||||
|
Uri folder_uri = Uri.withAppendedPath(ProviderTableMeta.CONTENT_URI_DIR, ""+ folder.getFileId()); // URI for recursive deletion
|
||||||
|
String where = ProviderTableMeta.FILE_ACCOUNT_OWNER + "=?" + " AND " + ProviderTableMeta.FILE_PATH + "=?";
|
||||||
|
String [] whereArgs = new String[]{mAccount.name, folder.getRemotePath()};
|
||||||
|
if (getContentProviderClient() != null) {
|
||||||
|
try {
|
||||||
|
getContentProviderClient().delete(folder_uri, where, whereArgs);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
if (removeDBData) {
|
getContentResolver().delete(folder_uri, where, whereArgs);
|
||||||
removeFile(child, removeLocalContent);
|
|
||||||
} else if (removeLocalContent) {
|
|
||||||
if (child.isDown()) {
|
|
||||||
new File(child.getStoragePath()).delete();
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (removeDBData) {
|
|
||||||
removeFile(folder, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (folder.getFileLength() > 0) {
|
if (folder.getFileLength() > 0) {
|
||||||
updateSizesToTheRoot(folder.getParentId());
|
updateSizesToTheRoot(folder.getParentId()); // TODO move to FileContentProvider
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void removeLocalFolder(File folder) {
|
||||||
|
if (folder.exists()) {
|
||||||
|
File[] files = folder.listFiles();
|
||||||
|
if (files != null) {
|
||||||
|
for (File file : files) {
|
||||||
|
if (file.isDirectory()) {
|
||||||
|
removeLocalFolder(file);
|
||||||
|
} else {
|
||||||
|
file.delete();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
folder.delete();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates database for a folder that was moved to a different location.
|
* Updates database for a folder that was moved to a different location.
|
||||||
|
|
|
@ -81,11 +81,7 @@ public class RemoveFileOperation extends RemoteOperation {
|
||||||
delete = new DeleteMethod(client.getBaseUri() + WebdavUtils.encodePath(mFileToRemove.getRemotePath()));
|
delete = new DeleteMethod(client.getBaseUri() + WebdavUtils.encodePath(mFileToRemove.getRemotePath()));
|
||||||
int status = client.executeMethod(delete, REMOVE_READ_TIMEOUT, REMOVE_CONNECTION_TIMEOUT);
|
int status = client.executeMethod(delete, REMOVE_READ_TIMEOUT, REMOVE_CONNECTION_TIMEOUT);
|
||||||
if (delete.succeeded() || status == HttpStatus.SC_NOT_FOUND) {
|
if (delete.succeeded() || status == HttpStatus.SC_NOT_FOUND) {
|
||||||
if (mFileToRemove.isFolder()) {
|
mDataStorageManager.removeFile(mFileToRemove, true, mDeleteLocalCopy);
|
||||||
mDataStorageManager.removeFolder(mFileToRemove, true, mDeleteLocalCopy);
|
|
||||||
} else {
|
|
||||||
mDataStorageManager.removeFile(mFileToRemove, mDeleteLocalCopy);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
delete.getResponseBodyAsString(); // exhaust the response, although not interesting
|
delete.getResponseBodyAsString(); // exhaust the response, although not interesting
|
||||||
result = new RemoteOperationResult((delete.succeeded() || status == HttpStatus.SC_NOT_FOUND), status, delete.getResponseHeaders());
|
result = new RemoteOperationResult((delete.succeeded() || status == HttpStatus.SC_NOT_FOUND), status, delete.getResponseHeaders());
|
||||||
|
|
|
@ -251,13 +251,22 @@ public class SynchronizeFolderOperation extends RemoteOperation {
|
||||||
mStorageManager.saveFile(remoteFolder);
|
mStorageManager.saveFile(remoteFolder);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Log_OC.d(TAG, "Remote folder " + mLocalFolder.getRemotePath() + " didn't change");
|
||||||
mChildren = mStorageManager.getFolderContent(mLocalFolder);
|
mChildren = mStorageManager.getFolderContent(mLocalFolder);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// read info of folder contents
|
Log_OC.d(TAG, "Remote folder " + mLocalFolder.getRemotePath() + " changed - starting update of local data ");
|
||||||
|
|
||||||
List<OCFile> updatedFiles = new Vector<OCFile>(dataInServer.getResponses().length - 1);
|
List<OCFile> updatedFiles = new Vector<OCFile>(dataInServer.getResponses().length - 1);
|
||||||
List<SynchronizeFileOperation> filesToSyncContents = new Vector<SynchronizeFileOperation>();
|
List<SynchronizeFileOperation> filesToSyncContents = new Vector<SynchronizeFileOperation>();
|
||||||
|
|
||||||
|
// get current data about local contents of the folder to synchronize
|
||||||
|
List<OCFile> localFiles = mStorageManager.getFolderContent(mLocalFolder);
|
||||||
|
Map<String, OCFile> localFilesMap = new HashMap<String, OCFile>(localFiles.size());
|
||||||
|
for (OCFile file : localFiles) {
|
||||||
|
localFilesMap.put(file.getRemotePath(), file);
|
||||||
|
}
|
||||||
|
|
||||||
// loop to update every child
|
// loop to update every child
|
||||||
OCFile remoteFile = null, localFile = null;
|
OCFile remoteFile = null, localFile = null;
|
||||||
for (int i = 1; i < dataInServer.getResponses().length; ++i) {
|
for (int i = 1; i < dataInServer.getResponses().length; ++i) {
|
||||||
|
@ -267,12 +276,14 @@ public class SynchronizeFolderOperation extends RemoteOperation {
|
||||||
remoteFile.setParentId(mLocalFolder.getFileId());
|
remoteFile.setParentId(mLocalFolder.getFileId());
|
||||||
|
|
||||||
/// retrieve local data for the read file
|
/// retrieve local data for the read file
|
||||||
localFile = mStorageManager.getFileByPath(remoteFile.getRemotePath());
|
//localFile = mStorageManager.getFileByPath(remoteFile.getRemotePath());
|
||||||
|
localFile = localFilesMap.remove(remoteFile.getRemotePath());
|
||||||
|
|
||||||
/// add to the remoteFile (the new one) data about LOCAL STATE (not existing in the server side)
|
/// add to the remoteFile (the new one) data about LOCAL STATE (not existing in the server side)
|
||||||
remoteFile.setLastSyncDateForProperties(mCurrentSyncTime);
|
remoteFile.setLastSyncDateForProperties(mCurrentSyncTime);
|
||||||
if (localFile != null) {
|
if (localFile != null) {
|
||||||
// properties of local state are kept unmodified
|
// some properties of local state are kept unmodified
|
||||||
|
remoteFile.setFileId(localFile.getFileId());
|
||||||
remoteFile.setKeepInSync(localFile.keepInSync());
|
remoteFile.setKeepInSync(localFile.keepInSync());
|
||||||
remoteFile.setLastSyncDateForData(localFile.getLastSyncDateForData());
|
remoteFile.setLastSyncDateForData(localFile.getLastSyncDateForData());
|
||||||
remoteFile.setModificationTimestampAtLastSyncForData(localFile.getModificationTimestampAtLastSyncForData());
|
remoteFile.setModificationTimestampAtLastSyncForData(localFile.getModificationTimestampAtLastSyncForData());
|
||||||
|
@ -282,7 +293,7 @@ public class SynchronizeFolderOperation extends RemoteOperation {
|
||||||
remoteFile.setEtag(""); // remote eTag will not be updated unless contents are synchronized (Synchronize[File|Folder]Operation with remoteFile as parameter)
|
remoteFile.setEtag(""); // remote eTag will not be updated unless contents are synchronized (Synchronize[File|Folder]Operation with remoteFile as parameter)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// check and fix, if need, local storage path
|
/// check and fix, if needed, local storage path
|
||||||
checkAndFixForeignStoragePath(remoteFile); // fixing old policy - now local files must be copied into the ownCloud local folder
|
checkAndFixForeignStoragePath(remoteFile); // fixing old policy - now local files must be copied into the ownCloud local folder
|
||||||
searchForLocalFileInDefaultPath(remoteFile); // legacy
|
searchForLocalFileInDefaultPath(remoteFile); // legacy
|
||||||
|
|
||||||
|
@ -303,16 +314,17 @@ public class SynchronizeFolderOperation extends RemoteOperation {
|
||||||
}
|
}
|
||||||
|
|
||||||
// save updated contents in local database; all at once, trying to get a best performance in database update (not a big deal, indeed)
|
// save updated contents in local database; all at once, trying to get a best performance in database update (not a big deal, indeed)
|
||||||
mStorageManager.saveFiles(updatedFiles);
|
mStorageManager.saveFolder(remoteFolder, updatedFiles, localFilesMap.values());
|
||||||
|
|
||||||
// request for the synchronization of file contents AFTER saving current remote properties
|
// request for the synchronization of file contents AFTER saving current remote properties
|
||||||
startContentSynchronizations(filesToSyncContents, client);
|
startContentSynchronizations(filesToSyncContents, client);
|
||||||
|
|
||||||
// removal of obsolete files
|
// removal of obsolete files
|
||||||
removeObsoleteFiles();
|
//removeObsoleteFiles();
|
||||||
|
|
||||||
// must be done AFTER saving all the children information, so that eTag is not updated in the database in case of unexpected exceptions
|
// must be done AFTER saving all the children information, so that eTag is not updated in the database in case of unexpected exceptions
|
||||||
mStorageManager.saveFile(remoteFolder);
|
//mStorageManager.saveFile(remoteFolder);
|
||||||
|
mChildren = updatedFiles;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -320,31 +332,6 @@ public class SynchronizeFolderOperation extends RemoteOperation {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Removes obsolete children in the folder after saving all the new data.
|
|
||||||
*/
|
|
||||||
private void removeObsoleteFiles() {
|
|
||||||
mChildren = mStorageManager.getFolderContent(mLocalFolder);
|
|
||||||
OCFile file;
|
|
||||||
for (int i=0; i < mChildren.size(); ) {
|
|
||||||
file = mChildren.get(i);
|
|
||||||
if (file.getLastSyncDateForProperties() != mCurrentSyncTime) {
|
|
||||||
if (file.isFolder()) {
|
|
||||||
Log_OC.d(TAG, "removing folder: " + file);
|
|
||||||
mStorageManager.removeFolder(file, true, true);
|
|
||||||
} else {
|
|
||||||
Log_OC.d(TAG, "removing file: " + file);
|
|
||||||
mStorageManager.removeFile(file, true);
|
|
||||||
}
|
|
||||||
mChildren.remove(i);
|
|
||||||
} else {
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Performs a list of synchronization operations, determining if a download or upload is needed or
|
* Performs a list of synchronization operations, determining if a download or upload is needed or
|
||||||
* if exists conflict due to changes both in local and remote contents of the each file.
|
* if exists conflict due to changes both in local and remote contents of the each file.
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
|
|
||||||
package com.owncloud.android.providers;
|
package com.owncloud.android.providers;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
|
||||||
import com.owncloud.android.Log_OC;
|
import com.owncloud.android.Log_OC;
|
||||||
|
@ -26,9 +27,12 @@ import com.owncloud.android.db.ProviderMeta.ProviderTableMeta;
|
||||||
|
|
||||||
|
|
||||||
import android.content.ContentProvider;
|
import android.content.ContentProvider;
|
||||||
|
import android.content.ContentProviderOperation;
|
||||||
|
import android.content.ContentProviderResult;
|
||||||
import android.content.ContentUris;
|
import android.content.ContentUris;
|
||||||
import android.content.ContentValues;
|
import android.content.ContentValues;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.content.OperationApplicationException;
|
||||||
import android.content.UriMatcher;
|
import android.content.UriMatcher;
|
||||||
import android.database.Cursor;
|
import android.database.Cursor;
|
||||||
import android.database.SQLException;
|
import android.database.SQLException;
|
||||||
|
@ -37,11 +41,13 @@ import android.database.sqlite.SQLiteOpenHelper;
|
||||||
import android.database.sqlite.SQLiteQueryBuilder;
|
import android.database.sqlite.SQLiteQueryBuilder;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The ContentProvider for the ownCloud App.
|
* The ContentProvider for the ownCloud App.
|
||||||
*
|
*
|
||||||
* @author Bartek Przybylski
|
* @author Bartek Przybylski
|
||||||
|
* @author David A. Velasco
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class FileContentProvider extends ContentProvider {
|
public class FileContentProvider extends ContentProvider {
|
||||||
|
@ -82,6 +88,7 @@ public class FileContentProvider extends ContentProvider {
|
||||||
ProviderTableMeta.FILE_ETAG);
|
ProviderTableMeta.FILE_ETAG);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static final String TAG = FileContentProvider.class.getSimpleName();
|
||||||
private static final int SINGLE_FILE = 1;
|
private static final int SINGLE_FILE = 1;
|
||||||
private static final int DIRECTORY = 2;
|
private static final int DIRECTORY = 2;
|
||||||
private static final int ROOT_DIRECTORY = 3;
|
private static final int ROOT_DIRECTORY = 3;
|
||||||
|
@ -96,27 +103,99 @@ public class FileContentProvider extends ContentProvider {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int delete(Uri uri, String where, String[] whereArgs) {
|
public int delete(Uri uri, String where, String[] whereArgs) {
|
||||||
|
//Log_OC.d(TAG, "Deleting " + uri + " at provider " + this);
|
||||||
|
int count = 0;
|
||||||
SQLiteDatabase db = mDbHelper.getWritableDatabase();
|
SQLiteDatabase db = mDbHelper.getWritableDatabase();
|
||||||
|
db.beginTransaction();
|
||||||
|
try {
|
||||||
|
count = delete(db, uri, where, whereArgs);
|
||||||
|
db.setTransactionSuccessful();
|
||||||
|
} finally {
|
||||||
|
db.endTransaction();
|
||||||
|
}
|
||||||
|
getContext().getContentResolver().notifyChange(uri, null);
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private int delete(SQLiteDatabase db, Uri uri, String where, String[] whereArgs) {
|
||||||
int count = 0;
|
int count = 0;
|
||||||
switch (mUriMatcher.match(uri)) {
|
switch (mUriMatcher.match(uri)) {
|
||||||
case SINGLE_FILE:
|
case SINGLE_FILE:
|
||||||
|
/*Cursor c = query(db, uri, null, where, whereArgs, null);
|
||||||
|
String remotePath = "(unexisting)";
|
||||||
|
if (c != null && c.moveToFirst()) {
|
||||||
|
remotePath = c.getString(c.getColumnIndex(ProviderTableMeta.FILE_PATH));
|
||||||
|
}
|
||||||
|
Log_OC.d(TAG, "Removing FILE " + remotePath);
|
||||||
|
*/
|
||||||
count = db.delete(ProviderTableMeta.DB_NAME,
|
count = db.delete(ProviderTableMeta.DB_NAME,
|
||||||
ProviderTableMeta._ID
|
ProviderTableMeta._ID
|
||||||
+ "="
|
+ "="
|
||||||
+ uri.getPathSegments().get(1)
|
+ uri.getPathSegments().get(1)
|
||||||
+ (!TextUtils.isEmpty(where) ? " AND (" + where
|
+ (!TextUtils.isEmpty(where) ? " AND (" + where
|
||||||
+ ")" : ""), whereArgs);
|
+ ")" : ""), whereArgs);
|
||||||
|
/* just for log
|
||||||
|
if (c!=null) {
|
||||||
|
c.close();
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
break;
|
||||||
|
case DIRECTORY:
|
||||||
|
// deletion of folder is recursive
|
||||||
|
/*
|
||||||
|
Uri folderUri = ContentUris.withAppendedId(ProviderTableMeta.CONTENT_URI_FILE, Long.parseLong(uri.getPathSegments().get(1)));
|
||||||
|
Cursor folder = query(db, folderUri, null, null, null, null);
|
||||||
|
String folderName = "(unknown)";
|
||||||
|
if (folder != null && folder.moveToFirst()) {
|
||||||
|
folderName = folder.getString(folder.getColumnIndex(ProviderTableMeta.FILE_PATH));
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
Cursor children = query(uri, null, null, null, null);
|
||||||
|
if (children != null && children.moveToFirst()) {
|
||||||
|
long childId;
|
||||||
|
boolean isDir;
|
||||||
|
String remotePath;
|
||||||
|
while (!children.isAfterLast()) {
|
||||||
|
childId = children.getLong(children.getColumnIndex(ProviderTableMeta._ID));
|
||||||
|
isDir = "DIR".equals(children.getString(children.getColumnIndex(ProviderTableMeta.FILE_CONTENT_TYPE)));
|
||||||
|
remotePath = children.getString(children.getColumnIndex(ProviderTableMeta.FILE_PATH));
|
||||||
|
if (isDir) {
|
||||||
|
count += delete(db, ContentUris.withAppendedId(ProviderTableMeta.CONTENT_URI_DIR, childId), null, null);
|
||||||
|
} else {
|
||||||
|
count += delete(db, ContentUris.withAppendedId(ProviderTableMeta.CONTENT_URI_FILE, childId), null, null);
|
||||||
|
}
|
||||||
|
children.moveToNext();
|
||||||
|
}
|
||||||
|
children.close();
|
||||||
|
} /*else {
|
||||||
|
Log_OC.d(TAG, "No child to remove in DIRECTORY " + folderName);
|
||||||
|
}
|
||||||
|
Log_OC.d(TAG, "Removing DIRECTORY " + folderName + " (or maybe not) ");
|
||||||
|
*/
|
||||||
|
count += db.delete(ProviderTableMeta.DB_NAME,
|
||||||
|
ProviderTableMeta._ID
|
||||||
|
+ "="
|
||||||
|
+ uri.getPathSegments().get(1)
|
||||||
|
+ (!TextUtils.isEmpty(where) ? " AND (" + where
|
||||||
|
+ ")" : ""), whereArgs);
|
||||||
|
/* Just for log
|
||||||
|
if (folder != null) {
|
||||||
|
folder.close();
|
||||||
|
}*/
|
||||||
break;
|
break;
|
||||||
case ROOT_DIRECTORY:
|
case ROOT_DIRECTORY:
|
||||||
|
//Log_OC.d(TAG, "Removing ROOT!");
|
||||||
count = db.delete(ProviderTableMeta.DB_NAME, where, whereArgs);
|
count = db.delete(ProviderTableMeta.DB_NAME, where, whereArgs);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
//Log_OC.e(TAG, "Unknown uri " + uri);
|
||||||
throw new IllegalArgumentException("Unknown uri: " + uri.toString());
|
throw new IllegalArgumentException("Unknown uri: " + uri.toString());
|
||||||
}
|
}
|
||||||
getContext().getContentResolver().notifyChange(uri, null);
|
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getType(Uri uri) {
|
public String getType(Uri uri) {
|
||||||
switch (mUriMatcher.match(uri)) {
|
switch (mUriMatcher.match(uri)) {
|
||||||
|
@ -132,23 +211,38 @@ public class FileContentProvider extends ContentProvider {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Uri insert(Uri uri, ContentValues values) {
|
public Uri insert(Uri uri, ContentValues values) {
|
||||||
|
//Log_OC.d(TAG, "Inserting " + values.getAsString(ProviderTableMeta.FILE_PATH) + " at provider " + this);
|
||||||
|
Uri newUri = null;
|
||||||
|
SQLiteDatabase db = mDbHelper.getWritableDatabase();
|
||||||
|
db.beginTransaction();
|
||||||
|
try {
|
||||||
|
newUri = insert(db, uri, values);
|
||||||
|
db.setTransactionSuccessful();
|
||||||
|
} finally {
|
||||||
|
db.endTransaction();
|
||||||
|
}
|
||||||
|
getContext().getContentResolver().notifyChange(newUri, null);
|
||||||
|
return newUri;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Uri insert(SQLiteDatabase db, Uri uri, ContentValues values) {
|
||||||
if (mUriMatcher.match(uri) != SINGLE_FILE &&
|
if (mUriMatcher.match(uri) != SINGLE_FILE &&
|
||||||
mUriMatcher.match(uri) != ROOT_DIRECTORY) {
|
mUriMatcher.match(uri) != ROOT_DIRECTORY) {
|
||||||
|
//Log_OC.e(TAG, "Inserting invalid URI: " + uri);
|
||||||
throw new IllegalArgumentException("Unknown uri id: " + uri);
|
throw new IllegalArgumentException("Unknown uri id: " + uri);
|
||||||
}
|
}
|
||||||
|
|
||||||
SQLiteDatabase db = mDbHelper.getWritableDatabase();
|
|
||||||
long rowId = db.insert(ProviderTableMeta.DB_NAME, null, values);
|
long rowId = db.insert(ProviderTableMeta.DB_NAME, null, values);
|
||||||
if (rowId > 0) {
|
if (rowId > 0) {
|
||||||
Uri insertedFileUri = ContentUris.withAppendedId(
|
Uri insertedFileUri = ContentUris.withAppendedId(ProviderTableMeta.CONTENT_URI_FILE, rowId);
|
||||||
ProviderTableMeta.CONTENT_URI_FILE, rowId);
|
//Log_OC.d(TAG, "Inserted " + values.getAsString(ProviderTableMeta.FILE_PATH) + " at provider " + this);
|
||||||
getContext().getContentResolver().notifyChange(insertedFileUri,
|
|
||||||
null);
|
|
||||||
return insertedFileUri;
|
return insertedFileUri;
|
||||||
}
|
} else {
|
||||||
|
//Log_OC.d(TAG, "Error while inserting " + values.getAsString(ProviderTableMeta.FILE_PATH) + " at provider " + this);
|
||||||
throw new SQLException("ERROR " + uri);
|
throw new SQLException("ERROR " + uri);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onCreate() {
|
public boolean onCreate() {
|
||||||
|
@ -156,9 +250,22 @@ public class FileContentProvider extends ContentProvider {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Cursor query(Uri uri, String[] projection, String selection,
|
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
|
||||||
String[] selectionArgs, String sortOrder) {
|
Cursor result = null;
|
||||||
|
SQLiteDatabase db = mDbHelper.getReadableDatabase();
|
||||||
|
db.beginTransaction();
|
||||||
|
try {
|
||||||
|
result = query(db, uri, projection, selection, selectionArgs, sortOrder);
|
||||||
|
db.setTransactionSuccessful();
|
||||||
|
} finally {
|
||||||
|
db.endTransaction();
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Cursor query(SQLiteDatabase db, Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
|
||||||
SQLiteQueryBuilder sqlQuery = new SQLiteQueryBuilder();
|
SQLiteQueryBuilder sqlQuery = new SQLiteQueryBuilder();
|
||||||
|
|
||||||
sqlQuery.setTables(ProviderTableMeta.DB_NAME);
|
sqlQuery.setTables(ProviderTableMeta.DB_NAME);
|
||||||
|
@ -188,23 +295,58 @@ public class FileContentProvider extends ContentProvider {
|
||||||
order = sortOrder;
|
order = sortOrder;
|
||||||
}
|
}
|
||||||
|
|
||||||
SQLiteDatabase db = mDbHelper.getReadableDatabase();
|
|
||||||
// DB case_sensitive
|
// DB case_sensitive
|
||||||
db.execSQL("PRAGMA case_sensitive_like = true");
|
db.execSQL("PRAGMA case_sensitive_like = true");
|
||||||
Cursor c = sqlQuery.query(db, projection, selection, selectionArgs,
|
Cursor c = sqlQuery.query(db, projection, selection, selectionArgs, null, null, order);
|
||||||
null, null, order);
|
|
||||||
|
|
||||||
c.setNotificationUri(getContext().getContentResolver(), uri);
|
c.setNotificationUri(getContext().getContentResolver(), uri);
|
||||||
|
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int update(Uri uri, ContentValues values, String selection,
|
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
|
||||||
String[] selectionArgs) {
|
|
||||||
return mDbHelper.getWritableDatabase().update(
|
//Log_OC.d(TAG, "Updating " + values.getAsString(ProviderTableMeta.FILE_PATH) + " at provider " + this);
|
||||||
ProviderTableMeta.DB_NAME, values, selection, selectionArgs);
|
int count = 0;
|
||||||
|
SQLiteDatabase db = mDbHelper.getWritableDatabase();
|
||||||
|
db.beginTransaction();
|
||||||
|
try {
|
||||||
|
count = update(db, uri, values, selection, selectionArgs);
|
||||||
|
db.setTransactionSuccessful();
|
||||||
|
} finally {
|
||||||
|
db.endTransaction();
|
||||||
}
|
}
|
||||||
|
getContext().getContentResolver().notifyChange(uri, null);
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private int update(SQLiteDatabase db, Uri uri, ContentValues values, String selection, String[] selectionArgs) {
|
||||||
|
return db.update(ProviderTableMeta.DB_NAME, values, selection, selectionArgs);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ContentProviderResult[] applyBatch (ArrayList<ContentProviderOperation> operations) throws OperationApplicationException {
|
||||||
|
//Log.d(TAG, "applying batch in provider " + this + " (temporary: " + isTemporary() + ")" );
|
||||||
|
ContentProviderResult[] results = new ContentProviderResult[operations.size()];
|
||||||
|
int i=0;
|
||||||
|
|
||||||
|
SQLiteDatabase db = mDbHelper.getWritableDatabase();
|
||||||
|
db.beginTransaction(); // it's supposed that transactions can be nested
|
||||||
|
try {
|
||||||
|
for (ContentProviderOperation operation : operations) {
|
||||||
|
results[i] = operation.apply(this, results, i);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
db.setTransactionSuccessful();
|
||||||
|
} finally {
|
||||||
|
db.endTransaction();
|
||||||
|
}
|
||||||
|
//Log.d(TAG, "applied batch in provider " + this);
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
class DataBaseHelper extends SQLiteOpenHelper {
|
class DataBaseHelper extends SQLiteOpenHelper {
|
||||||
|
|
||||||
|
|
|
@ -877,8 +877,6 @@ OCFileListFragment.ContainerActivity, FileDetailFragment.ContainerActivity, OnNa
|
||||||
String accountName = intent.getStringExtra(FileSyncService.ACCOUNT_NAME);
|
String accountName = intent.getStringExtra(FileSyncService.ACCOUNT_NAME);
|
||||||
RemoteOperationResult synchResult = (RemoteOperationResult)intent.getSerializableExtra(FileSyncService.SYNC_RESULT);
|
RemoteOperationResult synchResult = (RemoteOperationResult)intent.getSerializableExtra(FileSyncService.SYNC_RESULT);
|
||||||
|
|
||||||
Log_OC.d(TAG, "sync of account " + accountName + " is in_progress: " + inProgress);
|
|
||||||
|
|
||||||
if (getAccount() != null && accountName.equals(getAccount().name)) {
|
if (getAccount() != null && accountName.equals(getAccount().name)) {
|
||||||
|
|
||||||
String synchFolderRemotePath = intent.getStringExtra(FileSyncService.SYNC_FOLDER_REMOTE_PATH);
|
String synchFolderRemotePath = intent.getStringExtra(FileSyncService.SYNC_FOLDER_REMOTE_PATH);
|
||||||
|
|
|
@ -483,16 +483,7 @@ public class OCFileListFragment extends ExtendedListFragment implements EditName
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onNeutral(String callerTag) {
|
public void onNeutral(String callerTag) {
|
||||||
File f = null;
|
mContainerActivity.getStorageManager().removeFile(mTargetFile, false, true); // TODO perform in background task / new thread
|
||||||
if (mTargetFile.isFolder()) {
|
|
||||||
// TODO run in a secondary thread?
|
|
||||||
mContainerActivity.getStorageManager().removeFolder(mTargetFile, false, true);
|
|
||||||
|
|
||||||
} else if (mTargetFile.isDown() && (f = new File(mTargetFile.getStoragePath())).exists()) {
|
|
||||||
f.delete();
|
|
||||||
mTargetFile.setStoragePath(null);
|
|
||||||
mContainerActivity.getStorageManager().saveFile(mTargetFile);
|
|
||||||
}
|
|
||||||
listDirectory();
|
listDirectory();
|
||||||
mContainerActivity.onTransferStateChanged(mTargetFile, false, false);
|
mContainerActivity.onTransferStateChanged(mTargetFile, false, false);
|
||||||
}
|
}
|
||||||
|
|
|
@ -168,7 +168,7 @@ public class WebdavClient extends HttpClient {
|
||||||
try {
|
try {
|
||||||
method.setFollowRedirects(mFollowRedirects);
|
method.setFollowRedirects(mFollowRedirects);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
if (mFollowRedirects) Log_OC.d(TAG, "setFollowRedirects failed for " + method.getName() + " method, custom redirection will be used");
|
//if (mFollowRedirects) Log_OC.d(TAG, "setFollowRedirects failed for " + method.getName() + " method, custom redirection will be used if needed");
|
||||||
customRedirectionNeeded = mFollowRedirects;
|
customRedirectionNeeded = mFollowRedirects;
|
||||||
}
|
}
|
||||||
if (mSsoSessionCookie != null && mSsoSessionCookie.length() > 0) {
|
if (mSsoSessionCookie != null && mSsoSessionCookie.length() > 0) {
|
||||||
|
|
Loading…
Reference in a new issue