From ebf22f67d2182f3f9cc5ab0d8d81b4c63c039597 Mon Sep 17 00:00:00 2001 From: tobiasKaminsky Date: Thu, 14 Feb 2019 14:22:02 +0100 Subject: [PATCH 1/6] test CreateFolderOperation without server Signed-off-by: tobiasKaminsky --- .idea/codeStyles/Project.xml | 2 +- .../java/com/owncloud/android/AbstractIT.java | 3 +- .../preferences/AppPreferencesImpl.java | 4 +- .../datamodel/FileDataStorageManager.java | 2277 +--------------- .../datamodel/FileDataStorageManagerImpl.java | 2301 +++++++++++++++++ .../datamodel/ThumbnailsCacheManager.java | 2 +- .../files/services/FileDownloader.java | 8 +- .../android/files/services/FileUploader.java | 6 +- .../android/jobs/AccountRemovalJob.java | 3 +- .../android/jobs/ContactsBackupJob.java | 3 +- .../owncloud/android/jobs/OfflineSyncJob.java | 4 +- .../operations/CreateFolderOperation.java | 18 +- .../operations/DownloadFileOperation.java | 3 +- .../operations/RenameFileOperation.java | 3 +- .../operations/UploadFileOperation.java | 7 +- .../operations/common/SyncOperation.java | 10 +- .../DiskLruImageCacheFileProvider.java | 6 +- .../providers/DocumentsStorageProvider.java | 8 +- .../providers/FileContentProvider.java | 2 +- .../UsersAndGroupsSearchProvider.java | 5 +- .../android/services/OperationsService.java | 7 +- .../android/services/SyncFolderHandler.java | 8 +- .../AbstractOwnCloudSyncAdapter.java | 2 +- .../android/syncadapter/FileSyncAdapter.java | 4 +- .../ui/activities/ActivitiesActivity.java | 3 +- .../data/files/FilesServiceApiImpl.java | 2 +- .../android/ui/activity/BaseActivity.java | 3 +- .../android/ui/activity/ComponentsGetter.java | 8 +- .../android/ui/activity/DrawerActivity.java | 4 +- .../ErrorsWhileCopyingHandlerActivity.java | 10 +- .../ui/activity/FileDisplayActivity.java | 3 +- .../android/ui/activity/ShareActivity.java | 3 +- .../android/ui/activity/StorageMigration.java | 3 +- .../android/ui/adapter/OCFileListAdapter.java | 7 +- .../android/ui/adapter/UploaderAdapter.java | 10 +- .../android/ui/adapter/UserListAdapter.java | 20 +- .../ui/asynctasks/FetchRemoteFileTask.java | 2 +- .../ui/fragment/EditShareFragment.java | 9 +- .../FileDetailActivitiesFragment.java | 3 +- .../fragment/FileDetailSharingFragment.java | 3 +- .../ui/fragment/SearchShareesFragment.java | 3 +- .../ui/fragment/ShareFileFragment.java | 7 +- .../contactsbackup/ContactListFragment.java | 5 +- .../ContactsBackupFragment.java | 5 +- .../ui/helpers/FileOperationsHelper.java | 7 +- .../ui/preview/PreviewImageActivity.java | 2 - .../ui/preview/PreviewImagePagerAdapter.java | 9 +- .../utils/GetShareWithUsersAsyncTask.java | 5 +- .../owncloud/android/utils/ThemeUtils.java | 3 +- .../android/FileDataStorageManagerLocal.java | 149 ++ .../operations/CreateFolderOperationTest.java | 72 + 51 files changed, 2705 insertions(+), 2351 deletions(-) create mode 100644 src/main/java/com/owncloud/android/datamodel/FileDataStorageManagerImpl.java create mode 100644 src/test/java/com/owncloud/android/FileDataStorageManagerLocal.java create mode 100644 src/test/java/com/owncloud/android/operations/CreateFolderOperationTest.java diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml index 59ad8e8d5438..3fd34d857ad8 100644 --- a/.idea/codeStyles/Project.xml +++ b/.idea/codeStyles/Project.xml @@ -193,4 +193,4 @@ - \ No newline at end of file + diff --git a/src/androidTest/java/com/owncloud/android/AbstractIT.java b/src/androidTest/java/com/owncloud/android/AbstractIT.java index 25fc902922ca..dcd44bffca58 100644 --- a/src/androidTest/java/com/owncloud/android/AbstractIT.java +++ b/src/androidTest/java/com/owncloud/android/AbstractIT.java @@ -12,6 +12,7 @@ import com.nextcloud.client.account.UserAccountManager; import com.nextcloud.client.account.UserAccountManagerImpl; import com.owncloud.android.datamodel.FileDataStorageManager; +import com.owncloud.android.datamodel.FileDataStorageManagerImpl; import com.owncloud.android.lib.common.OwnCloudClient; import com.owncloud.android.lib.common.OwnCloudClientFactory; import com.owncloud.android.lib.common.accounts.AccountUtils; @@ -88,7 +89,7 @@ public static void beforeAll() { } FileDataStorageManager getStorageManager() { - return new FileDataStorageManager(account, targetContext.getContentResolver()); + return new FileDataStorageManagerImpl(account, targetContext.getContentResolver()); } private static void createDummyFiles() throws IOException { diff --git a/src/main/java/com/nextcloud/client/preferences/AppPreferencesImpl.java b/src/main/java/com/nextcloud/client/preferences/AppPreferencesImpl.java index a231116b182a..3bc6b7eed183 100644 --- a/src/main/java/com/nextcloud/client/preferences/AppPreferencesImpl.java +++ b/src/main/java/com/nextcloud/client/preferences/AppPreferencesImpl.java @@ -30,6 +30,7 @@ import com.nextcloud.client.account.UserAccountManagerImpl; import com.owncloud.android.datamodel.ArbitraryDataProvider; import com.owncloud.android.datamodel.FileDataStorageManager; +import com.owncloud.android.datamodel.FileDataStorageManagerImpl; import com.owncloud.android.datamodel.OCFile; import com.owncloud.android.ui.activity.PassCodeActivity; import com.owncloud.android.ui.activity.SettingsActivity; @@ -585,7 +586,8 @@ private static String getFolderPreference(final Context context, } ArbitraryDataProvider dataProvider = new ArbitraryDataProvider(context.getContentResolver()); - FileDataStorageManager storageManager = new FileDataStorageManager(user.toPlatformAccount(), context.getContentResolver()); + FileDataStorageManager storageManager = new FileDataStorageManagerImpl(user.toPlatformAccount(), + context); String value = dataProvider.getValue(user.getAccountName(), getKeyFromFolder(preferenceName, folder)); OCFile prefFolder = folder; diff --git a/src/main/java/com/owncloud/android/datamodel/FileDataStorageManager.java b/src/main/java/com/owncloud/android/datamodel/FileDataStorageManager.java index 60bbc4652923..64c5e6a18868 100644 --- a/src/main/java/com/owncloud/android/datamodel/FileDataStorageManager.java +++ b/src/main/java/com/owncloud/android/datamodel/FileDataStorageManager.java @@ -1,2297 +1,100 @@ -/* - * ownCloud Android client application - * - * Copyright (C) 2012 Bartek Przybylski - * Copyright (C) 2015 ownCloud Inc. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2, - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - package com.owncloud.android.datamodel; import android.accounts.Account; -import android.content.ContentProviderClient; -import android.content.ContentProviderOperation; -import android.content.ContentProviderResult; -import android.content.ContentResolver; -import android.content.ContentUris; import android.content.ContentValues; -import android.content.Context; -import android.content.Intent; import android.content.OperationApplicationException; -import android.database.Cursor; -import android.net.Uri; import android.os.RemoteException; -import android.provider.MediaStore; -import android.text.TextUtils; -import com.google.gson.Gson; -import com.google.gson.JsonSyntaxException; -import com.owncloud.android.MainApp; -import com.owncloud.android.db.ProviderMeta.ProviderTableMeta; -import com.owncloud.android.lib.common.network.WebdavEntry; -import com.owncloud.android.lib.common.operations.RemoteOperationResult; -import com.owncloud.android.lib.common.utils.Log_OC; -import com.owncloud.android.lib.resources.files.ReadFileRemoteOperation; -import com.owncloud.android.lib.resources.files.model.RemoteFile; import com.owncloud.android.lib.resources.shares.OCShare; import com.owncloud.android.lib.resources.shares.ShareType; -import com.owncloud.android.lib.resources.shares.ShareeUser; -import com.owncloud.android.lib.resources.status.CapabilityBooleanType; import com.owncloud.android.lib.resources.status.OCCapability; -import com.owncloud.android.operations.RemoteOperationFailedException; -import com.owncloud.android.utils.FileStorageUtils; -import com.owncloud.android.utils.MimeType; -import com.owncloud.android.utils.MimeTypeUtil; -import java.io.File; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collection; -import java.util.Collections; -import java.util.HashSet; -import java.util.Iterator; import java.util.List; -import java.util.Locale; -import java.util.Set; import androidx.annotation.NonNull; import androidx.annotation.Nullable; -import lombok.Getter; -import lombok.Setter; - - -@Getter -public class FileDataStorageManager { - private static final String TAG = FileDataStorageManager.class.getSimpleName(); - - private static final String AND = "=? AND "; - private static final String FAILED_TO_INSERT_MSG = "Fail to insert insert file to database "; - private static final String SENDING_TO_FILECONTENTPROVIDER_MSG = "Sending %d operations to FileContentProvider"; - private static final String EXCEPTION_MSG = "Exception in batch of operations "; +public interface FileDataStorageManager { public static final int ROOT_PARENT_ID = 0; - public static final String NULL_STRING = "null"; - - private ContentResolver contentResolver; - private ContentProviderClient contentProviderClient; - @Setter private Account account; - - public FileDataStorageManager(Account account, ContentResolver cr) { - contentProviderClient = null; - contentResolver = cr; - this.account = account; - } - - public FileDataStorageManager(Account account, ContentProviderClient cp) { - contentProviderClient = cp; - contentResolver = null; - this.account = account; - } - - public OCFile getFileByPath(String path) { - Cursor c = getFileCursorForValue(ProviderTableMeta.FILE_PATH, path); - OCFile file = null; - if (c.moveToFirst()) { - file = createFileInstance(c); - } - c.close(); - if (file == null && OCFile.ROOT_PATH.equals(path)) { - return createRootDir(); // root should always exist - } - return file; - } - - public @Nullable - OCFile getFileById(long id) { - Cursor c = getFileCursorForValue(ProviderTableMeta._ID, String.valueOf(id)); - OCFile file = null; - if (c.moveToFirst()) { - file = createFileInstance(c); - } - c.close(); - return file; - } - - public OCFile getFileByLocalPath(String path) { - Cursor c = getFileCursorForValue(ProviderTableMeta.FILE_STORAGE_PATH, path); - OCFile file = null; - if (c.moveToFirst()) { - file = createFileInstance(c); - } - c.close(); - return file; - } - - public @Nullable - OCFile getFileByRemoteId(String remoteId) { - Cursor c = getFileCursorForValue(ProviderTableMeta.FILE_REMOTE_ID, remoteId); - OCFile file = null; - if (c.moveToFirst()) { - file = createFileInstance(c); - } - c.close(); - return file; - } - - public boolean fileExists(long id) { - return fileExists(ProviderTableMeta._ID, String.valueOf(id)); - } - - public boolean fileExists(String path) { - return fileExists(ProviderTableMeta.FILE_PATH, path); - } - - - public List getFolderContent(OCFile f, boolean onlyOnDevice) { - if (f != null && f.isFolder() && f.getFileId() != -1) { - return getFolderContent(f.getFileId(), onlyOnDevice); - } else { - return new ArrayList<>(); - } - } - - - public List getFolderImages(OCFile folder, boolean onlyOnDevice) { - List ret = new ArrayList<>(); - - if (folder != null) { - // TODO better implementation, filtering in the access to database instead of here - List tmp = getFolderContent(folder, onlyOnDevice); - - for (OCFile file : tmp) { - if (MimeTypeUtil.isImage(file)) { - ret.add(file); - } - } - } - return ret; - } - - public boolean saveFile(OCFile file) { - boolean overridden = false; - ContentValues cv = new ContentValues(); - cv.put(ProviderTableMeta.FILE_MODIFIED, file.getModificationTimestamp()); - cv.put( - ProviderTableMeta.FILE_MODIFIED_AT_LAST_SYNC_FOR_DATA, - file.getModificationTimestampAtLastSyncForData() - ); - cv.put(ProviderTableMeta.FILE_CREATION, file.getCreationTimestamp()); - cv.put(ProviderTableMeta.FILE_CONTENT_LENGTH, file.getFileLength()); - cv.put(ProviderTableMeta.FILE_CONTENT_TYPE, file.getMimeType()); - cv.put(ProviderTableMeta.FILE_NAME, file.getFileName()); - cv.put(ProviderTableMeta.FILE_ENCRYPTED_NAME, file.getEncryptedFileName()); - cv.put(ProviderTableMeta.FILE_PARENT, file.getParentId()); - cv.put(ProviderTableMeta.FILE_PATH, file.getRemotePath()); - if (!file.isFolder()) { - cv.put(ProviderTableMeta.FILE_IS_ENCRYPTED, file.isEncrypted()); - cv.put(ProviderTableMeta.FILE_STORAGE_PATH, file.getStoragePath()); - } - cv.put(ProviderTableMeta.FILE_ACCOUNT_OWNER, account.name); - cv.put(ProviderTableMeta.FILE_LAST_SYNC_DATE, file.getLastSyncDateForProperties()); - cv.put(ProviderTableMeta.FILE_LAST_SYNC_DATE_FOR_DATA, file.getLastSyncDateForData()); - cv.put(ProviderTableMeta.FILE_ETAG, file.getEtag()); - cv.put(ProviderTableMeta.FILE_ETAG_ON_SERVER, file.getEtagOnServer()); - cv.put(ProviderTableMeta.FILE_SHARED_VIA_LINK, file.isSharedViaLink() ? 1 : 0); - cv.put(ProviderTableMeta.FILE_SHARED_WITH_SHAREE, file.isSharedWithSharee() ? 1 : 0); - cv.put(ProviderTableMeta.FILE_PUBLIC_LINK, file.getPublicLink()); - cv.put(ProviderTableMeta.FILE_PERMISSIONS, file.getPermissions()); - cv.put(ProviderTableMeta.FILE_REMOTE_ID, file.getRemoteId()); - cv.put(ProviderTableMeta.FILE_UPDATE_THUMBNAIL, file.isUpdateThumbnailNeeded()); - cv.put(ProviderTableMeta.FILE_IS_DOWNLOADING, file.isDownloading()); - cv.put(ProviderTableMeta.FILE_ETAG_IN_CONFLICT, file.getEtagInConflict()); - cv.put(ProviderTableMeta.FILE_UNREAD_COMMENTS_COUNT, file.getUnreadCommentsCount()); - cv.put(ProviderTableMeta.FILE_OWNER_ID, file.getOwnerId()); - cv.put(ProviderTableMeta.FILE_OWNER_DISPLAY_NAME, file.getOwnerDisplayName()); - cv.put(ProviderTableMeta.FILE_NOTE, file.getNote()); - cv.put(ProviderTableMeta.FILE_SHAREES, new Gson().toJson(file.getSharees())); - cv.put(ProviderTableMeta.FILE_RICH_WORKSPACE, file.getRichWorkspace()); - - boolean sameRemotePath = fileExists(file.getRemotePath()); - if (sameRemotePath || - fileExists(file.getFileId())) { // for renamed files; no more delete and create - - - if (sameRemotePath) { - OCFile oldFile = getFileByPath(file.getRemotePath()); - file.setFileId(oldFile.getFileId()); - } - - overridden = true; - if (getContentResolver() != null) { - getContentResolver().update(ProviderTableMeta.CONTENT_URI, cv, - ProviderTableMeta._ID + "=?", - new String[]{String.valueOf(file.getFileId())}); - } else { - try { - getContentProviderClient().update(ProviderTableMeta.CONTENT_URI, - cv, ProviderTableMeta._ID + "=?", - new String[]{String.valueOf(file.getFileId())}); - } catch (RemoteException e) { - Log_OC.e(TAG, FAILED_TO_INSERT_MSG + e.getMessage(), e); - } - } - } else { - Uri result_uri = null; - if (getContentResolver() != null) { - result_uri = getContentResolver().insert(ProviderTableMeta.CONTENT_URI_FILE, cv); - } else { - try { - result_uri = getContentProviderClient().insert(ProviderTableMeta.CONTENT_URI_FILE, cv); - } catch (RemoteException e) { - Log_OC.e(TAG, FAILED_TO_INSERT_MSG + e.getMessage(), e); - } - } - if (result_uri != null) { - long new_id = Long.parseLong(result_uri.getPathSegments().get(1)); - file.setFileId(new_id); - } - } - - return overridden; - } - - /** - * traverses a files parent tree to be able to store a file with its parents. - * Throws a RemoteOperationFailedException in case the parent can't be retrieved. - * - * @param file the file - * @param context the app context - * @return the parent file - */ - public OCFile saveFileWithParent(OCFile file, Context context) { - if (file.getParentId() == 0 && !OCFile.ROOT_PATH.equals(file.getRemotePath())) { - String remotePath = file.getRemotePath(); - String parentPath = remotePath.substring(0, remotePath.lastIndexOf(file.getFileName())); - - OCFile parentFile = getFileByPath(parentPath); - - OCFile returnFile; - if (parentFile == null) { - // remote request - ReadFileRemoteOperation operation = new ReadFileRemoteOperation(parentPath); - RemoteOperationResult result = operation.execute(getAccount(), context); - if (result.isSuccess()) { - OCFile remoteFolder = FileStorageUtils.fillOCFile((RemoteFile) result.getData().get(0)); - - returnFile = saveFileWithParent(remoteFolder, context); - } else { - Exception exception = result.getException(); - String message = "Error during saving file with parents: " + file.getRemotePath() + " / " - + result.getLogMessage(); - - if (exception != null) { - throw new RemoteOperationFailedException(message, exception); - } else { - throw new RemoteOperationFailedException(message); - } - } - } else { - returnFile = saveFileWithParent(parentFile, context); - } - - file.setParentId(returnFile.getFileId()); - saveFile(file); - } - - return file; - } - - public void saveNewFile(OCFile newFile) { - String remoteParentPath = new File(newFile.getRemotePath()).getParent(); - remoteParentPath = remoteParentPath.endsWith(OCFile.PATH_SEPARATOR) ? - remoteParentPath : remoteParentPath + OCFile.PATH_SEPARATOR; - OCFile parent = getFileByPath(remoteParentPath); - if (parent != null) { - newFile.setParentId(parent.getFileId()); - saveFile(newFile); - } else { - throw new IllegalArgumentException("Saving a new file in an unexisting folder"); - } - } - - - /** - * Inserts or updates the list of files contained in a given folder. - * - * CALLER IS RESPONSIBLE FOR GRANTING RIGHT UPDATE OF INFORMATION, NOT THIS METHOD. - * HERE ONLY DATA CONSISTENCY SHOULD BE GRANTED - * - * @param folder - * @param updatedFiles - * @param filesToRemove - */ - public void saveFolder(OCFile folder, Collection updatedFiles, Collection filesToRemove) { - Log_OC.d(TAG, "Saving folder " + folder.getRemotePath() + " with " + updatedFiles.size() - + " children and " + filesToRemove.size() + " files to remove"); - - ArrayList operations = new ArrayList<>(updatedFiles.size()); - - // prepare operations to insert or update files to save in the given folder - for (OCFile file : updatedFiles) { - ContentValues cv = createContentValueForFile(file, folder); - - if (fileExists(file.getFileId()) || fileExists(file.getRemotePath())) { - long fileId; - if (file.getFileId() != -1) { - fileId = file.getFileId(); - } else { - fileId = getFileByPath(file.getRemotePath()).getFileId(); - } - // updating an existing file - operations.add(ContentProviderOperation.newUpdate(ProviderTableMeta.CONTENT_URI) - .withValues(cv) - .withSelection(ProviderTableMeta._ID + "=?", new String[]{String.valueOf(fileId)}) - .build()); - } else { - // adding a new file - 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 = new String[2]; - for (OCFile file : filesToRemove) { - if (file.getParentId() == folder.getFileId()) { - whereArgs[0] = account.name; - whereArgs[1] = file.getRemotePath(); - if (file.isFolder()) { - operations.add(ContentProviderOperation.newDelete( - ContentUris.withAppendedId(ProviderTableMeta.CONTENT_URI_DIR, file.getFileId())) - .withSelection(where, whereArgs).build()); - - File localFolder = new File(FileStorageUtils.getDefaultSavePathFor(account.name, file)); - if (localFolder.exists()) { - removeLocalFolder(localFolder); - } - } else { - operations.add(ContentProviderOperation.newDelete( - ContentUris.withAppendedId(ProviderTableMeta.CONTENT_URI_FILE, file.getFileId())) - .withSelection(where, whereArgs).build()); - - if (file.isDown()) { - String path = file.getStoragePath(); - if (new File(path).delete() && MimeTypeUtil.isMedia(file.getMimeType())) { - triggerMediaScan(path); // notify MediaScanner about removed file - } - } - } - } - } - - // update metadata of folder - ContentValues cv = createContentValueForFile(folder); - - operations.add(ContentProviderOperation.newUpdate(ProviderTableMeta.CONTENT_URI) - .withValues(cv) - .withSelection(ProviderTableMeta._ID + "=?", new String[]{String.valueOf(folder.getFileId())}) - .build()); - - // apply operations in batch - ContentProviderResult[] results = null; - Log_OC.d(TAG, String.format(Locale.ENGLISH, SENDING_TO_FILECONTENTPROVIDER_MSG, operations.size())); - - try { - if (getContentResolver() != null) { - results = getContentResolver().applyBatch(MainApp.getAuthority(), operations); - - } else { - results = getContentProviderClient().applyBatch(operations); - } - - } catch (OperationApplicationException | RemoteException e) { - Log_OC.e(TAG, EXCEPTION_MSG + e.getMessage(), e); - } - - // update new id in file objects for insertions - if (results != null) { - long newId; - Iterator filesIt = updatedFiles.iterator(); - OCFile file; - for (ContentProviderResult result : results) { - if (filesIt.hasNext()) { - file = filesIt.next(); - } else { - file = null; - } - if (result.uri != null) { - newId = Long.parseLong(result.uri.getPathSegments().get(1)); - //updatedFiles.get(i).setFileId(newId); - if (file != null) { - file.setFileId(newId); - } - } - } - } - } - - private ContentValues createContentValueForFile(OCFile folder) { - 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, 0); - 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()); - cv.put(ProviderTableMeta.FILE_ACCOUNT_OWNER, account.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_ETAG, folder.getEtag()); - cv.put(ProviderTableMeta.FILE_ETAG_ON_SERVER, folder.getEtagOnServer()); - cv.put(ProviderTableMeta.FILE_SHARED_VIA_LINK, folder.isSharedViaLink() ? 1 : 0); - cv.put(ProviderTableMeta.FILE_SHARED_WITH_SHAREE, folder.isSharedWithSharee() ? 1 : 0); - cv.put(ProviderTableMeta.FILE_PUBLIC_LINK, folder.getPublicLink()); - cv.put(ProviderTableMeta.FILE_PERMISSIONS, folder.getPermissions()); - cv.put(ProviderTableMeta.FILE_REMOTE_ID, folder.getRemoteId()); - cv.put(ProviderTableMeta.FILE_FAVORITE, folder.isFavorite()); - cv.put(ProviderTableMeta.FILE_IS_ENCRYPTED, folder.isEncrypted()); - cv.put(ProviderTableMeta.FILE_UNREAD_COMMENTS_COUNT, folder.getUnreadCommentsCount()); - cv.put(ProviderTableMeta.FILE_OWNER_ID, folder.getOwnerId()); - cv.put(ProviderTableMeta.FILE_OWNER_DISPLAY_NAME, folder.getOwnerDisplayName()); - cv.put(ProviderTableMeta.FILE_NOTE, folder.getNote()); - cv.put(ProviderTableMeta.FILE_SHAREES, new Gson().toJson(folder.getSharees())); - cv.put(ProviderTableMeta.FILE_RICH_WORKSPACE, folder.getRichWorkspace()); - - return cv; - } - private ContentValues createContentValueForFile(OCFile file, OCFile folder) { - ContentValues cv = new ContentValues(); - cv.put(ProviderTableMeta.FILE_MODIFIED, file.getModificationTimestamp()); - cv.put(ProviderTableMeta.FILE_MODIFIED_AT_LAST_SYNC_FOR_DATA, file.getModificationTimestampAtLastSyncForData()); - cv.put(ProviderTableMeta.FILE_CREATION, file.getCreationTimestamp()); - cv.put(ProviderTableMeta.FILE_CONTENT_LENGTH, file.getFileLength()); - cv.put(ProviderTableMeta.FILE_CONTENT_TYPE, file.getMimeType()); - cv.put(ProviderTableMeta.FILE_NAME, file.getFileName()); - cv.put(ProviderTableMeta.FILE_ENCRYPTED_NAME, file.getEncryptedFileName()); - cv.put(ProviderTableMeta.FILE_PARENT, folder.getFileId()); - cv.put(ProviderTableMeta.FILE_PATH, file.getRemotePath()); - if (!file.isFolder()) { - cv.put(ProviderTableMeta.FILE_STORAGE_PATH, file.getStoragePath()); - } - cv.put(ProviderTableMeta.FILE_ACCOUNT_OWNER, account.name); - cv.put(ProviderTableMeta.FILE_LAST_SYNC_DATE, file.getLastSyncDateForProperties()); - cv.put(ProviderTableMeta.FILE_LAST_SYNC_DATE_FOR_DATA, file.getLastSyncDateForData()); - cv.put(ProviderTableMeta.FILE_ETAG, file.getEtag()); - cv.put(ProviderTableMeta.FILE_ETAG_ON_SERVER, file.getEtagOnServer()); - cv.put(ProviderTableMeta.FILE_SHARED_VIA_LINK, file.isSharedViaLink() ? 1 : 0); - cv.put(ProviderTableMeta.FILE_SHARED_WITH_SHAREE, file.isSharedWithSharee() ? 1 : 0); - cv.put(ProviderTableMeta.FILE_PUBLIC_LINK, file.getPublicLink()); - cv.put(ProviderTableMeta.FILE_PERMISSIONS, file.getPermissions()); - cv.put(ProviderTableMeta.FILE_REMOTE_ID, file.getRemoteId()); - cv.put(ProviderTableMeta.FILE_UPDATE_THUMBNAIL, file.isUpdateThumbnailNeeded()); - cv.put(ProviderTableMeta.FILE_IS_DOWNLOADING, file.isDownloading()); - cv.put(ProviderTableMeta.FILE_ETAG_IN_CONFLICT, file.getEtagInConflict()); - cv.put(ProviderTableMeta.FILE_FAVORITE, file.isFavorite()); - cv.put(ProviderTableMeta.FILE_IS_ENCRYPTED, file.isEncrypted()); - cv.put(ProviderTableMeta.FILE_MOUNT_TYPE, file.getMountType().ordinal()); - cv.put(ProviderTableMeta.FILE_HAS_PREVIEW, file.isPreviewAvailable() ? 1 : 0); - cv.put(ProviderTableMeta.FILE_UNREAD_COMMENTS_COUNT, file.getUnreadCommentsCount()); - cv.put(ProviderTableMeta.FILE_OWNER_ID, file.getOwnerId()); - cv.put(ProviderTableMeta.FILE_OWNER_DISPLAY_NAME, file.getOwnerDisplayName()); - cv.put(ProviderTableMeta.FILE_NOTE, file.getNote()); - cv.put(ProviderTableMeta.FILE_SHAREES, new Gson().toJson(file.getSharees())); - cv.put(ProviderTableMeta.FILE_RICH_WORKSPACE, file.getRichWorkspace()); + OCFile getFileByPath(String path); - return cv; - } - - - public boolean removeFile(OCFile file, boolean removeDBData, boolean removeLocalCopy) { - boolean success = true; - if (file != null) { - if (file.isFolder()) { - success = 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[]{account.name, file.getRemotePath()}; - int deleted = 0; - if (getContentProviderClient() != null) { - try { - deleted = getContentProviderClient().delete(file_uri, where, whereArgs); - } catch (RemoteException e) { - Log_OC.d(TAG, e.getMessage(), e); - } - } else { - deleted = getContentResolver().delete(file_uri, where, whereArgs); - } - success = deleted > 0; - } - String localPath = file.getStoragePath(); - if (removeLocalCopy && file.isDown() && localPath != null && success) { - success = new File(localPath).delete(); - if (success) { - deleteFileInMediaScan(localPath); - } - if (!removeDBData && success) { - // maybe unnecessary, but should be checked TODO remove if unnecessary - file.setStoragePath(null); - saveFile(file); - saveConflict(file, null); - } - } - } - } else { - return false; - } - - return success; - } - - - public boolean removeFolder(OCFile folder, boolean removeDBData, boolean removeLocalContent) { - boolean success = true; - if (folder != null && folder.isFolder()) { - if (removeDBData && folder.getFileId() != -1) { - success = removeFolderInDb(folder); - } - if (removeLocalContent && success) { - success = removeLocalFolder(folder); - } - } else { - success = false; - } - - return success; - } - - private boolean removeFolderInDb(OCFile folder) { - Uri folder_uri = Uri.withAppendedPath(ProviderTableMeta.CONTENT_URI_DIR, String.valueOf(folder.getFileId())); // URI - // for recursive deletion - String where = ProviderTableMeta.FILE_ACCOUNT_OWNER + AND + ProviderTableMeta.FILE_PATH + "=?"; - String[] whereArgs = new String[]{account.name, folder.getRemotePath()}; - int deleted = 0; - if (getContentProviderClient() != null) { - try { - deleted = getContentProviderClient().delete(folder_uri, where, whereArgs); - } catch (RemoteException e) { - Log_OC.d(TAG, e.getMessage(), e); - } - } else { - deleted = getContentResolver().delete(folder_uri, where, whereArgs); - } - return deleted > 0; - } - - private boolean removeLocalFolder(OCFile folder) { - boolean success = true; - String localFolderPath = FileStorageUtils.getDefaultSavePathFor(account.name, folder); - File localFolder = new File(localFolderPath); - if (localFolder.exists()) { - // stage 1: remove the local files already registered in the files database - List files = getFolderContent(folder.getFileId(), false); - if (files != null) { - for (OCFile file : files) { - if (file.isFolder()) { - success &= removeLocalFolder(file); - } else { - if (file.isDown()) { - File localFile = new File(file.getStoragePath()); - success &= localFile.delete(); - if (success) { - // notify MediaScanner about removed file - deleteFileInMediaScan(file.getStoragePath()); - file.setStoragePath(null); - saveFile(file); - } - } - } - } - } - - // stage 2: remove the folder itself and any local file inside out of sync; - // for instance, after clearing the app cache or reinstalling - success &= removeLocalFolder(localFolder); - } - return success; - } - - private boolean removeLocalFolder(File localFolder) { - boolean success = true; - File[] localFiles = localFolder.listFiles(); - if (localFiles != null) { - for (File localFile : localFiles) { - if (localFile.isDirectory()) { - success &= removeLocalFolder(localFile); - } else { - success &= localFile.delete(); - } - } - } - success &= localFolder.delete(); - return success; - } - - /** - * Updates database and file system for a file or folder that was moved to a different location. - * - * TODO explore better (faster) implementations - * TODO throw exceptions up ! - */ - public void moveLocalFile(OCFile file, String targetPath, String targetParentPath) { - - if (file != null && file.fileExists() && !OCFile.ROOT_PATH.equals(file.getFileName())) { - - OCFile targetParent = getFileByPath(targetParentPath); - if (targetParent == null) { - throw new IllegalStateException("Parent folder of the target path does not exist!!"); - } - - /// 1. get all the descendants of the moved element in a single QUERY - Cursor c = null; - if (getContentProviderClient() != null) { - try { - c = getContentProviderClient().query( - ProviderTableMeta.CONTENT_URI, - null, - ProviderTableMeta.FILE_ACCOUNT_OWNER + AND + ProviderTableMeta.FILE_PATH + " LIKE ? ", - new String[]{account.name, file.getRemotePath() + "%"}, - ProviderTableMeta.FILE_PATH + " ASC " - ); - } catch (RemoteException e) { - Log_OC.e(TAG, e.getMessage(), e); - } - - } else { - c = getContentResolver().query( - ProviderTableMeta.CONTENT_URI, - null, - ProviderTableMeta.FILE_ACCOUNT_OWNER + AND + ProviderTableMeta.FILE_PATH + " LIKE ? ", - new String[]{account.name, file.getRemotePath() + "%"}, - ProviderTableMeta.FILE_PATH + " ASC " - ); - } - - /// 2. prepare a batch of update operations to change all the descendants - ArrayList operations = new ArrayList<>(c.getCount()); - String defaultSavePath = FileStorageUtils.getSavePath(account.name); - List originalPathsToTriggerMediaScan = new ArrayList<>(); - List newPathsToTriggerMediaScan = new ArrayList<>(); - if (c.moveToFirst()) { - int lengthOfOldPath = file.getRemotePath().length(); - int lengthOfOldStoragePath = defaultSavePath.length() + lengthOfOldPath; - String[] fileId = new String[1]; - do { - ContentValues cv = new ContentValues(); // keep construction in the loop - OCFile child = createFileInstance(c); - cv.put( - ProviderTableMeta.FILE_PATH, - targetPath + child.getRemotePath().substring(lengthOfOldPath) - ); - if (child.getStoragePath() != null && child.getStoragePath().startsWith(defaultSavePath)) { - // update link to downloaded content - but local move is not done here! - String targetLocalPath = defaultSavePath + targetPath + - child.getStoragePath().substring(lengthOfOldStoragePath); - - cv.put(ProviderTableMeta.FILE_STORAGE_PATH, targetLocalPath); - - if (MimeTypeUtil.isMedia(child.getMimeType())) { - originalPathsToTriggerMediaScan.add(child.getStoragePath()); - newPathsToTriggerMediaScan.add(targetLocalPath); - } - - } - if (child.getRemotePath().equals(file.getRemotePath())) { - cv.put(ProviderTableMeta.FILE_PARENT, targetParent.getFileId()); - } - fileId[0] = String.valueOf(child.getFileId()); - operations.add( - ContentProviderOperation.newUpdate(ProviderTableMeta.CONTENT_URI). - withValues(cv). - withSelection(ProviderTableMeta._ID + "=?", fileId) - .build()); - - } while (c.moveToNext()); - } - c.close(); - - /// 3. apply updates in batch - try { - if (getContentResolver() != null) { - getContentResolver().applyBatch(MainApp.getAuthority(), operations); - } else { - getContentProviderClient().applyBatch(operations); - } - - } catch (Exception e) { - Log_OC.e(TAG, "Fail to update " + file.getFileId() + " and descendants in database", e); - } - - /// 4. move in local file system - String originalLocalPath = FileStorageUtils.getDefaultSavePathFor(account.name, file); - String targetLocalPath = defaultSavePath + targetPath; - File localFile = new File(originalLocalPath); - boolean renamed = false; - if (localFile.exists()) { - File targetFile = new File(targetLocalPath); - File targetFolder = targetFile.getParentFile(); - if (!targetFolder.exists() && !targetFolder.mkdirs()) { - Log_OC.e(TAG, "Unable to create parent folder " + targetFolder.getAbsolutePath()); - } - renamed = localFile.renameTo(targetFile); - } - - if (renamed) { - Iterator it = originalPathsToTriggerMediaScan.iterator(); - while (it.hasNext()) { - // Notify MediaScanner about removed file - deleteFileInMediaScan(it.next()); - } - it = newPathsToTriggerMediaScan.iterator(); - while (it.hasNext()) { - // Notify MediaScanner about new file/folder - triggerMediaScan(it.next()); - } - } - } - } - - public void copyLocalFile(OCFile file, String targetPath) { - - if (file != null && file.fileExists() && !OCFile.ROOT_PATH.equals(file.getFileName())) { - String localPath = FileStorageUtils.getDefaultSavePathFor(account.name, file); - File localFile = new File(localPath); - boolean copied = false; - String defaultSavePath = FileStorageUtils.getSavePath(account.name); - if (localFile.exists()) { - File targetFile = new File(defaultSavePath + targetPath); - File targetFolder = targetFile.getParentFile(); - if (!targetFolder.exists() && !targetFolder.mkdirs()) { - Log_OC.e(TAG, "Unable to create parent folder " + targetFolder.getAbsolutePath()); - } - copied = FileStorageUtils.copyFile(localFile, targetFile); - } - Log_OC.d(TAG, "Local file COPIED : " + copied); - } - } - - public void migrateStoredFiles(String srcPath, String dstPath) - throws RemoteException, OperationApplicationException { - Cursor cursor; - try { - if (getContentResolver() != null) { - cursor = getContentResolver().query(ProviderTableMeta.CONTENT_URI_FILE, - null, - ProviderTableMeta.FILE_STORAGE_PATH + " IS NOT NULL", - null, - null); - - } else { - cursor = getContentProviderClient().query(ProviderTableMeta.CONTENT_URI_FILE, - new String[]{ProviderTableMeta._ID, ProviderTableMeta.FILE_STORAGE_PATH}, - ProviderTableMeta.FILE_STORAGE_PATH + " IS NOT NULL", - null, - null); - } - } catch (RemoteException e) { - Log_OC.e(TAG, e.getMessage(), e); - throw e; - } - - ArrayList operations = new ArrayList<>(cursor.getCount()); - if (cursor.moveToFirst()) { - String[] fileId = new String[1]; - do { - ContentValues cv = new ContentValues(); - fileId[0] = String.valueOf(cursor.getLong(cursor.getColumnIndex(ProviderTableMeta._ID))); - String oldFileStoragePath = - cursor.getString(cursor.getColumnIndex(ProviderTableMeta.FILE_STORAGE_PATH)); - - if (oldFileStoragePath.startsWith(srcPath)) { - - cv.put(ProviderTableMeta.FILE_STORAGE_PATH, oldFileStoragePath.replaceFirst(srcPath, dstPath)); - - operations.add( - ContentProviderOperation.newUpdate(ProviderTableMeta.CONTENT_URI). - withValues(cv). - withSelection(ProviderTableMeta._ID + "=?", fileId) - .build()); - } - - } while (cursor.moveToNext()); - } - cursor.close(); - - /// 3. apply updates in batch - if (getContentResolver() != null) { - getContentResolver().applyBatch(MainApp.getAuthority(), operations); - } else { - getContentProviderClient().applyBatch(operations); - } - } - - private List getFolderContent(long parentId, boolean onlyOnDevice) { - - List ret = new ArrayList<>(); - - Uri req_uri = Uri.withAppendedPath(ProviderTableMeta.CONTENT_URI_DIR, String.valueOf(parentId)); - Cursor c; - - if (getContentProviderClient() != null) { - try { - c = getContentProviderClient().query( - req_uri, - null, - ProviderTableMeta.FILE_PARENT + "=?", - new String[]{String.valueOf(parentId)}, - null - ); - } catch (RemoteException e) { - Log_OC.e(TAG, e.getMessage(), e); - return ret; - } - } else { - c = getContentResolver().query( - req_uri, - null, - ProviderTableMeta.FILE_PARENT + "=?", - new String[]{String.valueOf(parentId)}, - null - ); - } - - if (c != null) { - if (c.moveToFirst()) { - do { - OCFile child = createFileInstance(c); - if (!onlyOnDevice || child.existsOnDevice()) { - ret.add(child); - } - } while (c.moveToNext()); - } - - c.close(); - } - - return ret; - } - - - private OCFile createRootDir() { - OCFile file = new OCFile(OCFile.ROOT_PATH); - file.setMimeType(MimeType.DIRECTORY); - file.setParentId(FileDataStorageManager.ROOT_PARENT_ID); - saveFile(file); - return file; - } - - private boolean fileExists(String cmp_key, String value) { - Cursor c; - if (getContentResolver() != null) { - c = getContentResolver() - .query(ProviderTableMeta.CONTENT_URI, - null, - cmp_key + AND - + ProviderTableMeta.FILE_ACCOUNT_OWNER - + "=?", - new String[]{value, account.name}, null); - } else { - try { - c = getContentProviderClient().query( - ProviderTableMeta.CONTENT_URI, - null, - cmp_key + AND - + ProviderTableMeta.FILE_ACCOUNT_OWNER + "=?", - new String[]{value, account.name}, null); - } catch (RemoteException e) { - Log_OC.e(TAG, "Couldn't determine file existance, assuming non existance: " + e.getMessage(), e); - return false; - } - } - boolean retval = c.moveToFirst(); - c.close(); - return retval; - } - - private Cursor getFileCursorForValue(String key, String value) { - Cursor c; - if (getContentResolver() != null) { - c = getContentResolver() - .query(ProviderTableMeta.CONTENT_URI, - null, - key + AND - + ProviderTableMeta.FILE_ACCOUNT_OWNER - + "=?", - new String[]{value, account.name}, null); - } else { - try { - c = getContentProviderClient().query( - ProviderTableMeta.CONTENT_URI, - null, - key + AND + ProviderTableMeta.FILE_ACCOUNT_OWNER - + "=?", new String[]{value, account.name}, - null); - } catch (RemoteException e) { - Log_OC.e(TAG, "Could not get file details: " + e.getMessage(), e); - c = null; - } - } - return c; - } + Account getAccount(); @Nullable - private OCFile createFileInstanceFromVirtual(Cursor c) { - OCFile file = null; - if (c != null) { - long fileId = c.getLong(c.getColumnIndex(ProviderTableMeta.VIRTUAL_OCFILE_ID)); - file = getFileById(fileId); - } - - return file; - } - - private OCFile createFileInstance(Cursor c) { - OCFile file = null; - if (c != null) { - file = new OCFile(c.getString(c.getColumnIndex(ProviderTableMeta.FILE_PATH))); - file.setFileId(c.getLong(c.getColumnIndex(ProviderTableMeta._ID))); - file.setParentId(c.getLong(c.getColumnIndex(ProviderTableMeta.FILE_PARENT))); - file.setEncryptedFileName(c.getString(c.getColumnIndex(ProviderTableMeta.FILE_ENCRYPTED_NAME))); - file.setMimeType(c.getString(c.getColumnIndex(ProviderTableMeta.FILE_CONTENT_TYPE))); - file.setStoragePath(c.getString(c.getColumnIndex(ProviderTableMeta.FILE_STORAGE_PATH))); - if (file.getStoragePath() == null) { - // try to find existing file and bind it with current account; - // with the current update of SynchronizeFolderOperation, this won't be - // necessary anymore after a full synchronization of the account - File f = new File(FileStorageUtils.getDefaultSavePathFor(account.name, file)); - if (f.exists()) { - file.setStoragePath(f.getAbsolutePath()); - file.setLastSyncDateForData(f.lastModified()); - } - } - file.setFileLength(c.getLong(c.getColumnIndex(ProviderTableMeta.FILE_CONTENT_LENGTH))); - file.setCreationTimestamp(c.getLong(c.getColumnIndex(ProviderTableMeta.FILE_CREATION))); - file.setModificationTimestamp(c.getLong(c.getColumnIndex(ProviderTableMeta.FILE_MODIFIED))); - file.setModificationTimestampAtLastSyncForData(c.getLong( - c.getColumnIndex(ProviderTableMeta.FILE_MODIFIED_AT_LAST_SYNC_FOR_DATA))); - file.setLastSyncDateForProperties(c.getLong(c.getColumnIndex(ProviderTableMeta.FILE_LAST_SYNC_DATE))); - file.setLastSyncDateForData(c.getLong(c.getColumnIndex(ProviderTableMeta.FILE_LAST_SYNC_DATE_FOR_DATA))); - file.setEtag(c.getString(c.getColumnIndex(ProviderTableMeta.FILE_ETAG))); - file.setEtagOnServer(c.getString(c.getColumnIndex(ProviderTableMeta.FILE_ETAG_ON_SERVER))); - file.setSharedViaLink(c.getInt(c.getColumnIndex(ProviderTableMeta.FILE_SHARED_VIA_LINK)) == 1); - file.setSharedWithSharee(c.getInt(c.getColumnIndex(ProviderTableMeta.FILE_SHARED_WITH_SHAREE)) == 1); - file.setPublicLink(c.getString(c.getColumnIndex(ProviderTableMeta.FILE_PUBLIC_LINK))); - file.setPermissions(c.getString(c.getColumnIndex(ProviderTableMeta.FILE_PERMISSIONS))); - file.setRemoteId(c.getString(c.getColumnIndex(ProviderTableMeta.FILE_REMOTE_ID))); - file.setUpdateThumbnailNeeded(c.getInt(c.getColumnIndex(ProviderTableMeta.FILE_UPDATE_THUMBNAIL)) == 1); - file.setDownloading(c.getInt(c.getColumnIndex(ProviderTableMeta.FILE_IS_DOWNLOADING)) == 1); - file.setEtagInConflict(c.getString(c.getColumnIndex(ProviderTableMeta.FILE_ETAG_IN_CONFLICT))); - file.setFavorite(c.getInt(c.getColumnIndex(ProviderTableMeta.FILE_FAVORITE)) == 1); - file.setEncrypted(c.getInt(c.getColumnIndex(ProviderTableMeta.FILE_IS_ENCRYPTED)) == 1); - if (file.isEncrypted()) { - file.setFileName(c.getString(c.getColumnIndex(ProviderTableMeta.FILE_NAME))); - } - file.setMountType(WebdavEntry.MountType.values()[c.getInt( - c.getColumnIndex(ProviderTableMeta.FILE_MOUNT_TYPE))]); - file.setPreviewAvailable(c.getInt(c.getColumnIndex(ProviderTableMeta.FILE_HAS_PREVIEW)) == 1); - file.setUnreadCommentsCount(c.getInt(c.getColumnIndex(ProviderTableMeta.FILE_UNREAD_COMMENTS_COUNT))); - file.setOwnerId(c.getString(c.getColumnIndex(ProviderTableMeta.FILE_OWNER_ID))); - file.setOwnerDisplayName(c.getString(c.getColumnIndex(ProviderTableMeta.FILE_OWNER_DISPLAY_NAME))); - file.setNote(c.getString(c.getColumnIndex(ProviderTableMeta.FILE_NOTE))); - file.setRichWorkspace(c.getString(c.getColumnIndex(ProviderTableMeta.FILE_RICH_WORKSPACE))); - - String sharees = c.getString(c.getColumnIndex(ProviderTableMeta.FILE_SHAREES)); - - if (sharees == null || NULL_STRING.equals(sharees) || sharees.isEmpty()) { - file.setSharees(new ArrayList<>()); - } else { - try { - ShareeUser[] shareesArray = new Gson().fromJson(sharees, ShareeUser[].class); + OCFile getFileById(long id); - file.setSharees(new ArrayList<>(Arrays.asList(shareesArray))); - } catch (JsonSyntaxException e) { - // ignore saved value due to api change - file.setSharees(new ArrayList<>()); - } - } - } + void saveConflict(OCFile file, String etagInConflict); - return file; - } + void deleteFileInMediaScan(String path); - // Methods for Shares - public boolean saveShare(OCShare share) { - boolean overridden = false; - ContentValues cv = new ContentValues(); - cv.put(ProviderTableMeta.OCSHARES_FILE_SOURCE, share.getFileSource()); - cv.put(ProviderTableMeta.OCSHARES_ITEM_SOURCE, share.getItemSource()); - cv.put(ProviderTableMeta.OCSHARES_SHARE_TYPE, share.getShareType().getValue()); - cv.put(ProviderTableMeta.OCSHARES_SHARE_WITH, share.getShareWith()); - cv.put(ProviderTableMeta.OCSHARES_PATH, share.getPath()); - cv.put(ProviderTableMeta.OCSHARES_PERMISSIONS, share.getPermissions()); - cv.put(ProviderTableMeta.OCSHARES_SHARED_DATE, share.getSharedDate()); - cv.put(ProviderTableMeta.OCSHARES_EXPIRATION_DATE, share.getExpirationDate()); - cv.put(ProviderTableMeta.OCSHARES_TOKEN, share.getToken()); - cv.put(ProviderTableMeta.OCSHARES_SHARE_WITH_DISPLAY_NAME, share.getSharedWithDisplayName()); - cv.put(ProviderTableMeta.OCSHARES_IS_DIRECTORY, share.isFolder() ? 1 : 0); - cv.put(ProviderTableMeta.OCSHARES_USER_ID, share.getUserId()); - cv.put(ProviderTableMeta.OCSHARES_ID_REMOTE_SHARED, share.getRemoteId()); - cv.put(ProviderTableMeta.OCSHARES_ACCOUNT_OWNER, account.name); - cv.put(ProviderTableMeta.OCSHARES_IS_PASSWORD_PROTECTED, share.isPasswordProtected() ? 1 : 0); - cv.put(ProviderTableMeta.OCSHARES_NOTE, share.getNote()); - cv.put(ProviderTableMeta.OCSHARES_HIDE_DOWNLOAD, share.isHideFileDownload()); + boolean saveFile(OCFile file); - if (shareExistsForRemoteId(share.getRemoteId())) {// for renamed files; no more delete and create - overridden = true; - if (getContentResolver() != null) { - getContentResolver().update(ProviderTableMeta.CONTENT_URI_SHARE, cv, - ProviderTableMeta.OCSHARES_ID_REMOTE_SHARED + "=?", - new String[]{String.valueOf(share.getRemoteId())}); - } else { - try { - getContentProviderClient().update(ProviderTableMeta.CONTENT_URI_SHARE, - cv, ProviderTableMeta.OCSHARES_ID_REMOTE_SHARED + "=?", - new String[]{String.valueOf(share.getRemoteId())}); - } catch (RemoteException e) { - Log_OC.e(TAG, FAILED_TO_INSERT_MSG + e.getMessage(), e); - } - } - } else { - Uri result_uri = null; - if (getContentResolver() != null) { - result_uri = getContentResolver().insert(ProviderTableMeta.CONTENT_URI_SHARE, cv); - } else { - try { - result_uri = getContentProviderClient().insert(ProviderTableMeta.CONTENT_URI_SHARE, cv); - } catch (RemoteException e) { - Log_OC.e(TAG, FAILED_TO_INSERT_MSG + e.getMessage(), e); - } - } - if (result_uri != null) { - long new_id = Long.parseLong(result_uri.getPathSegments().get(1)); - share.setId(new_id); - } - } + boolean fileExists(long id); - return overridden; - } + boolean fileExists(String path); - /** - * Retrieves an stored {@link OCShare} given its id. - * - * @param id Identifier. - * @return Stored {@link OCShare} given its id. - */ - public OCShare getShareById(long id) { - OCShare share = null; - Cursor c = getShareCursorForValue(ProviderTableMeta._ID, String.valueOf(id)); - if (c != null) { - if (c.moveToFirst()) { - share = createShareInstance(c); - } - c.close(); - } - return share; - } + List getFolderContent(OCFile f, boolean onlyOnDevice); + void saveFolder(OCFile folder, Collection updatedFiles, Collection filesToRemove); - /** - * Checks the existance of an stored {@link OCShare} matching the given remote id (not to be confused with - * the local id) in the current account. - * - * @param remoteId Remote of the share in the server. - * @return 'True' if a matching {@link OCShare} is stored in the current account. - */ - private boolean shareExistsForRemoteId(long remoteId) { - return shareExistsForValue(ProviderTableMeta.OCSHARES_ID_REMOTE_SHARED, String.valueOf(remoteId)); - } + boolean removeFile(OCFile file, boolean removeDBData, boolean removeLocalCopy); + boolean removeFolder(OCFile folder, boolean removeDBData, boolean removeLocalContent); - /** - * Checks the existance of an stored {@link OCShare} in the current account - * matching a given column and a value for that column - * - * @param key Name of the column to match. - * @param value Value of the column to match. - * @return 'True' if a matching {@link OCShare} is stored in the current account. - */ - private boolean shareExistsForValue(String key, String value) { - Cursor c = getShareCursorForValue(key, value); - boolean retval = c.moveToFirst(); - c.close(); - return retval; - } + void moveLocalFile(OCFile file, String targetPath, String targetParentPath); + boolean saveShare(OCShare share); - /** - * Gets a {@link Cursor} for an stored {@link OCShare} in the current account - * matching a given column and a value for that column - * - * @param key Name of the column to match. - * @param value Value of the column to match. - * @return 'True' if a matching {@link OCShare} is stored in the current account. - */ - private Cursor getShareCursorForValue(String key, String value) { - Cursor c; - if (getContentResolver() != null) { - c = getContentResolver() - .query(ProviderTableMeta.CONTENT_URI_SHARE, - null, - key + AND - + ProviderTableMeta.OCSHARES_ACCOUNT_OWNER + "=?", - new String[]{value, account.name}, - null - ); - } else { - try { - c = getContentProviderClient().query( - ProviderTableMeta.CONTENT_URI_SHARE, - null, - key + AND + ProviderTableMeta.OCSHARES_ACCOUNT_OWNER + "=?", - new String[]{value, account.name}, - null - ); - } catch (RemoteException e) { - Log_OC.w(TAG, "Could not get details, assuming share does not exist: " + e.getMessage()); - c = null; - } - } - return c; - } + List getSharesWithForAFile(String filePath, String accountName); + void removeShare(OCShare share); - /** - * Get first share bound to a file with a known path and given {@link ShareType}. - * - * @param path Path of the file. - * @param type Type of the share to get - * @param shareWith Target of the share. Ignored in type is {@link ShareType#PUBLIC_LINK} - * @return First {@link OCShare} instance found in DB bound to the file in 'path' - */ - public OCShare getFirstShareByPathAndType(String path, ShareType type, String shareWith) { - Cursor cursor; - if (shareWith == null) { - shareWith = ""; - } + void copyLocalFile(OCFile file, String targetPath); - String selection = ProviderTableMeta.OCSHARES_PATH + AND - + ProviderTableMeta.OCSHARES_SHARE_TYPE + AND - + ProviderTableMeta.OCSHARES_ACCOUNT_OWNER + "=?"; - if (!ShareType.PUBLIC_LINK.equals(type)) { - selection += " AND " + ProviderTableMeta.OCSHARES_SHARE_WITH + "=?"; - } + OCShare getFirstShareByPathAndType(String path, ShareType type, String shareWith); - String[] selectionArgs; - if (ShareType.PUBLIC_LINK.equals(type)) { - selectionArgs = new String[]{ - path, - Integer.toString(type.getValue()), - account.name - }; - } else { - selectionArgs = new String[]{ - path, - Integer.toString(type.getValue()), - account.name, - shareWith - }; - } - - if (getContentResolver() != null) { - cursor = getContentResolver().query( - ProviderTableMeta.CONTENT_URI_SHARE, - null, - selection, selectionArgs, - null); - } else { - try { - cursor = getContentProviderClient().query( - ProviderTableMeta.CONTENT_URI_SHARE, - null, - selection, selectionArgs, - null); - - } catch (RemoteException e) { - Log_OC.e(TAG, "Could not get file details: " + e.getMessage(), e); - cursor = null; - } - } - - OCShare share = null; - if (cursor != null) { - if (cursor.moveToFirst()) { - share = createShareInstance(cursor); - } - cursor.close(); - } - return share; - } - - private OCShare createShareInstance(Cursor c) { - OCShare share = null; - if (c != null) { - share = new OCShare(c.getString(c.getColumnIndex(ProviderTableMeta.OCSHARES_PATH))); - share.setId(c.getLong(c.getColumnIndex(ProviderTableMeta._ID))); - share.setFileSource(c.getLong(c.getColumnIndex(ProviderTableMeta.OCSHARES_ITEM_SOURCE))); - share.setShareType(ShareType.fromValue(c.getInt(c.getColumnIndex(ProviderTableMeta.OCSHARES_SHARE_TYPE)))); - share.setShareWith(c.getString(c.getColumnIndex(ProviderTableMeta.OCSHARES_SHARE_WITH))); - share.setPermissions(c.getInt(c.getColumnIndex(ProviderTableMeta.OCSHARES_PERMISSIONS))); - share.setSharedDate(c.getLong(c.getColumnIndex(ProviderTableMeta.OCSHARES_SHARED_DATE))); - share.setExpirationDate(c.getLong(c.getColumnIndex(ProviderTableMeta.OCSHARES_EXPIRATION_DATE))); - share.setToken(c.getString(c.getColumnIndex(ProviderTableMeta.OCSHARES_TOKEN))); - share.setSharedWithDisplayName( - c.getString(c.getColumnIndex(ProviderTableMeta.OCSHARES_SHARE_WITH_DISPLAY_NAME))); - share.setFolder(c.getInt(c.getColumnIndex(ProviderTableMeta.OCSHARES_IS_DIRECTORY)) == 1); - share.setUserId(c.getString(c.getColumnIndex(ProviderTableMeta.OCSHARES_USER_ID))); - share.setRemoteId(c.getLong(c.getColumnIndex(ProviderTableMeta.OCSHARES_ID_REMOTE_SHARED))); - share.setPasswordProtected(c.getInt(c.getColumnIndex(ProviderTableMeta.OCSHARES_IS_PASSWORD_PROTECTED)) == 1); - share.setNote(c.getString(c.getColumnIndex(ProviderTableMeta.OCSHARES_NOTE))); - share.setHideFileDownload(c.getInt(c.getColumnIndex(ProviderTableMeta.OCSHARES_HIDE_DOWNLOAD)) == 1); - } - return share; - } - - private void resetShareFlagsInAllFiles() { - ContentValues cv = new ContentValues(); - cv.put(ProviderTableMeta.FILE_SHARED_VIA_LINK, Boolean.FALSE); - cv.put(ProviderTableMeta.FILE_SHARED_WITH_SHAREE, Boolean.FALSE); - cv.put(ProviderTableMeta.FILE_PUBLIC_LINK, ""); - String where = ProviderTableMeta.FILE_ACCOUNT_OWNER + "=?"; - String[] whereArgs = new String[]{account.name}; - - if (getContentResolver() != null) { - getContentResolver().update(ProviderTableMeta.CONTENT_URI, cv, where, whereArgs); - - } else { - try { - getContentProviderClient().update(ProviderTableMeta.CONTENT_URI, cv, where, whereArgs); - } catch (RemoteException e) { - Log_OC.e(TAG, "Exception in resetShareFlagsInAllFiles" + e.getMessage(), e); - } - } - } - - private void resetShareFlagsInFolder(OCFile folder) { - ContentValues cv = new ContentValues(); - cv.put(ProviderTableMeta.FILE_SHARED_VIA_LINK, Boolean.FALSE); - cv.put(ProviderTableMeta.FILE_SHARED_WITH_SHAREE, Boolean.FALSE); - cv.put(ProviderTableMeta.FILE_PUBLIC_LINK, ""); - String where = ProviderTableMeta.FILE_ACCOUNT_OWNER + AND + ProviderTableMeta.FILE_PARENT + "=?"; - String[] whereArgs = new String[]{account.name, String.valueOf(folder.getFileId())}; - - if (getContentResolver() != null) { - getContentResolver().update(ProviderTableMeta.CONTENT_URI, cv, where, whereArgs); - - } else { - try { - getContentProviderClient().update(ProviderTableMeta.CONTENT_URI, cv, where, whereArgs); - } catch (RemoteException e) { - Log_OC.e(TAG, "Exception in resetShareFlagsInFolder " + e.getMessage(), e); - } - } - } - - private void resetShareFlagInAFile(String filePath) { - ContentValues cv = new ContentValues(); - cv.put(ProviderTableMeta.FILE_SHARED_VIA_LINK, Boolean.FALSE); - cv.put(ProviderTableMeta.FILE_SHARED_WITH_SHAREE, Boolean.FALSE); - cv.put(ProviderTableMeta.FILE_PUBLIC_LINK, ""); - String where = ProviderTableMeta.FILE_ACCOUNT_OWNER + AND + ProviderTableMeta.FILE_PATH + "=?"; - String[] whereArgs = new String[]{account.name, filePath}; - - if (getContentResolver() != null) { - getContentResolver().update(ProviderTableMeta.CONTENT_URI, cv, where, whereArgs); - - } else { - try { - getContentProviderClient().update(ProviderTableMeta.CONTENT_URI, cv, where, whereArgs); - } catch (RemoteException e) { - Log_OC.e(TAG, "Exception in resetShareFlagsInFolder " + e.getMessage(), e); - } - } - } - - private void cleanShares() { - String where = ProviderTableMeta.OCSHARES_ACCOUNT_OWNER + "=?"; - String[] whereArgs = new String[]{account.name}; - - if (getContentResolver() != null) { - getContentResolver().delete(ProviderTableMeta.CONTENT_URI_SHARE, where, whereArgs); - - } else { - try { - getContentProviderClient().delete(ProviderTableMeta.CONTENT_URI_SHARE, where, whereArgs); - } catch (RemoteException e) { - Log_OC.e(TAG, "Exception in cleanShares" + e.getMessage(), e); - } - } - } - - public void saveShares(Collection shares) { - cleanShares(); - if (shares != null) { - ArrayList operations = - new ArrayList(shares.size()); - - // prepare operations to insert or update files to save in the given folder - for (OCShare share : shares) { - ContentValues cv = new ContentValues(); - cv.put(ProviderTableMeta.OCSHARES_FILE_SOURCE, share.getFileSource()); - cv.put(ProviderTableMeta.OCSHARES_ITEM_SOURCE, share.getItemSource()); - cv.put(ProviderTableMeta.OCSHARES_SHARE_TYPE, share.getShareType().getValue()); - cv.put(ProviderTableMeta.OCSHARES_SHARE_WITH, share.getShareWith()); - cv.put(ProviderTableMeta.OCSHARES_PATH, share.getPath()); - cv.put(ProviderTableMeta.OCSHARES_PERMISSIONS, share.getPermissions()); - cv.put(ProviderTableMeta.OCSHARES_SHARED_DATE, share.getSharedDate()); - cv.put(ProviderTableMeta.OCSHARES_EXPIRATION_DATE, share.getExpirationDate()); - cv.put(ProviderTableMeta.OCSHARES_TOKEN, share.getToken()); - cv.put(ProviderTableMeta.OCSHARES_SHARE_WITH_DISPLAY_NAME, share.getSharedWithDisplayName()); - cv.put(ProviderTableMeta.OCSHARES_IS_DIRECTORY, share.isFolder() ? 1 : 0); - cv.put(ProviderTableMeta.OCSHARES_USER_ID, share.getUserId()); - cv.put(ProviderTableMeta.OCSHARES_ID_REMOTE_SHARED, share.getRemoteId()); - cv.put(ProviderTableMeta.OCSHARES_ACCOUNT_OWNER, account.name); - cv.put(ProviderTableMeta.OCSHARES_IS_PASSWORD_PROTECTED, share.isPasswordProtected() ? 1 : 0); - cv.put(ProviderTableMeta.OCSHARES_NOTE, share.getNote()); - cv.put(ProviderTableMeta.OCSHARES_HIDE_DOWNLOAD, share.isHideFileDownload()); - - if (shareExistsForRemoteId(share.getRemoteId())) { - // updating an existing file - operations.add( - ContentProviderOperation.newUpdate(ProviderTableMeta.CONTENT_URI_SHARE). - withValues(cv). - withSelection(ProviderTableMeta.OCSHARES_ID_REMOTE_SHARED + "=?", - new String[]{String.valueOf(share.getRemoteId())}) - .build()); - } else { - // adding a new file - operations.add( - ContentProviderOperation.newInsert(ProviderTableMeta.CONTENT_URI_SHARE). - withValues(cv). - build() - ); - } - } - - // apply operations in batch - if (operations.size() > 0) { - @SuppressWarnings("unused") - ContentProviderResult[] results = null; - Log_OC.d(TAG, String.format(Locale.ENGLISH, SENDING_TO_FILECONTENTPROVIDER_MSG, operations.size())); - try { - if (getContentResolver() != null) { - results = getContentResolver().applyBatch(MainApp.getAuthority(), - operations); - } else { - results = getContentProviderClient().applyBatch(operations); - } - - } catch (OperationApplicationException | RemoteException e) { - Log_OC.e(TAG, EXCEPTION_MSG + e.getMessage(), e); - } - } - } - - } - - public void updateSharedFiles(Collection sharedFiles) { - resetShareFlagsInAllFiles(); - - if (sharedFiles != null) { - ArrayList operations = new ArrayList<>(sharedFiles.size()); - - // prepare operations to insert or update files to save in the given folder - for (OCFile file : sharedFiles) { - ContentValues cv = new ContentValues(); - cv.put(ProviderTableMeta.FILE_MODIFIED, file.getModificationTimestamp()); - cv.put( - ProviderTableMeta.FILE_MODIFIED_AT_LAST_SYNC_FOR_DATA, - file.getModificationTimestampAtLastSyncForData() - ); - cv.put(ProviderTableMeta.FILE_CREATION, file.getCreationTimestamp()); - cv.put(ProviderTableMeta.FILE_CONTENT_LENGTH, file.getFileLength()); - cv.put(ProviderTableMeta.FILE_CONTENT_TYPE, file.getMimeType()); - cv.put(ProviderTableMeta.FILE_NAME, file.getFileName()); - cv.put(ProviderTableMeta.FILE_PARENT, file.getParentId()); - cv.put(ProviderTableMeta.FILE_PATH, file.getRemotePath()); - if (!file.isFolder()) { - cv.put(ProviderTableMeta.FILE_STORAGE_PATH, file.getStoragePath()); - } - cv.put(ProviderTableMeta.FILE_ACCOUNT_OWNER, account.name); - cv.put(ProviderTableMeta.FILE_LAST_SYNC_DATE, file.getLastSyncDateForProperties()); - cv.put( - ProviderTableMeta.FILE_LAST_SYNC_DATE_FOR_DATA, - file.getLastSyncDateForData() - ); - cv.put(ProviderTableMeta.FILE_ETAG, file.getEtag()); - cv.put(ProviderTableMeta.FILE_ETAG_ON_SERVER, file.getEtagOnServer()); - cv.put(ProviderTableMeta.FILE_SHARED_VIA_LINK, file.isSharedViaLink() ? 1 : 0); - cv.put(ProviderTableMeta.FILE_SHARED_WITH_SHAREE, file.isSharedWithSharee() ? 1 : 0); - cv.put(ProviderTableMeta.FILE_PUBLIC_LINK, file.getPublicLink()); - cv.put(ProviderTableMeta.FILE_PERMISSIONS, file.getPermissions()); - cv.put(ProviderTableMeta.FILE_REMOTE_ID, file.getRemoteId()); - cv.put(ProviderTableMeta.FILE_FAVORITE, file.isFavorite()); - cv.put(ProviderTableMeta.FILE_UPDATE_THUMBNAIL, file.isUpdateThumbnailNeeded() ? 1 : 0); - cv.put(ProviderTableMeta.FILE_IS_DOWNLOADING, file.isDownloading() ? 1 : 0); - cv.put(ProviderTableMeta.FILE_ETAG_IN_CONFLICT, file.getEtagInConflict()); - - boolean existsByPath = fileExists(file.getRemotePath()); - if (existsByPath || fileExists(file.getFileId())) { - // updating an existing file - operations.add( - ContentProviderOperation.newUpdate(ProviderTableMeta.CONTENT_URI). - withValues(cv). - withSelection(ProviderTableMeta._ID + "=?", - new String[]{String.valueOf(file.getFileId())}) - .build()); - - } else { - // adding a new file - operations.add( - ContentProviderOperation.newInsert(ProviderTableMeta.CONTENT_URI). - withValues(cv). - build() - ); - } - } - - // apply operations in batch - if (operations.size() > 0) { - @SuppressWarnings("unused") - ContentProviderResult[] results = null; - Log_OC.d(TAG, String.format(Locale.ENGLISH, SENDING_TO_FILECONTENTPROVIDER_MSG, operations.size())); - try { - if (getContentResolver() != null) { - results = getContentResolver().applyBatch(MainApp.getAuthority(), operations); - } else { - results = getContentProviderClient().applyBatch(operations); - } - - } catch (OperationApplicationException | RemoteException e) { - Log_OC.e(TAG, EXCEPTION_MSG + e.getMessage(), e); - } - } - } - - } - - public void removeShare(OCShare share) { - Uri share_uri = ProviderTableMeta.CONTENT_URI_SHARE; - String where = ProviderTableMeta.OCSHARES_ACCOUNT_OWNER + AND + - ProviderTableMeta._ID + "=?"; - String[] whereArgs = new String[]{account.name, Long.toString(share.getId())}; - if (getContentProviderClient() != null) { - try { - getContentProviderClient().delete(share_uri, where, whereArgs); - } catch (RemoteException e) { - Log_OC.d(TAG, e.getMessage(), e); - } - } else { - getContentResolver().delete(share_uri, where, whereArgs); - } - } - - public void saveSharesDB(List shares) { - ArrayList operations = new ArrayList<>(); - - // Reset flags & Remove shares for this files - String filePath = ""; - for (OCShare share : shares) { - if (!filePath.equals(share.getPath())) { - filePath = share.getPath(); - resetShareFlagInAFile(filePath); - operations = prepareRemoveSharesInFile(filePath, operations); - } - } - - // Add operations to insert shares - operations = prepareInsertShares(shares, operations); - - // apply operations in batch - if (operations.size() > 0) { - Log_OC.d(TAG, String.format(Locale.ENGLISH, SENDING_TO_FILECONTENTPROVIDER_MSG, operations.size())); - try { - if (getContentResolver() != null) { - getContentResolver().applyBatch(MainApp.getAuthority(), operations); - - } else { - getContentProviderClient().applyBatch(operations); - } - - } catch (OperationApplicationException | RemoteException e) { - Log_OC.e(TAG, EXCEPTION_MSG + e.getMessage(), e); - } - } - -// // TODO: review if it is needed -// // Update shared files -// ArrayList sharedFiles = new ArrayList(); -// -// for (OCShare share : shares) { -// // Get the path -// String path = share.getPath(); -// if (share.isFolder()) { -// path = path + FileUtils.PATH_SEPARATOR; -// } -// -// // Update OCFile with data from share: ShareByLink, publicLink and -// OCFile file = getFileByPath(path); -// if (file != null) { -// if (share.getShareType().equals(ShareType.PUBLIC_LINK)) { -// file.setShareViaLink(true); -// sharedFiles.add(file); -// } -// } -// } -// -// // TODO: Review -// updateSharedFiles(sharedFiles); - } - - public void removeSharesForFile(String remotePath) { - resetShareFlagInAFile(remotePath); - ArrayList operations = new ArrayList<>(); - operations = prepareRemoveSharesInFile(remotePath, operations); - // apply operations in batch - if (operations.size() > 0) { - Log_OC.d(TAG, String.format(Locale.ENGLISH, SENDING_TO_FILECONTENTPROVIDER_MSG, operations.size())); - try { - if (getContentResolver() != null) { - getContentResolver().applyBatch(MainApp.getAuthority(), operations); - - } else { - getContentProviderClient().applyBatch(operations); - } - - } catch (OperationApplicationException | RemoteException e) { - Log_OC.e(TAG, EXCEPTION_MSG + e.getMessage(), e); - } - } - } - - - public void saveSharesInFolder(ArrayList shares, OCFile folder) { - resetShareFlagsInFolder(folder); - ArrayList operations = new ArrayList<>(); - operations = prepareRemoveSharesInFolder(folder, operations); - - if (shares != null) { - // prepare operations to insert or update files to save in the given folder - operations = prepareInsertShares(shares, operations); - } - - // apply operations in batch - if (operations.size() > 0) { - Log_OC.d(TAG, String.format(Locale.ENGLISH, SENDING_TO_FILECONTENTPROVIDER_MSG, operations.size())); - try { - if (getContentResolver() != null) { - getContentResolver().applyBatch(MainApp.getAuthority(), operations); - - } else { - - getContentProviderClient().applyBatch(operations); - } - - } catch (OperationApplicationException | RemoteException e) { - Log_OC.e(TAG, EXCEPTION_MSG + e.getMessage(), e); - } - } - - } - - /** - * Prepare operations to insert or update files to save in the given folder - * @param shares List of shares to insert - * @param operations List of operations - * @return - */ - private ArrayList prepareInsertShares( - List shares, ArrayList operations) { - - if (shares != null) { - ContentValues cv; - // prepare operations to insert or update files to save in the given folder - for (OCShare share : shares) { - cv = new ContentValues(); - cv.put(ProviderTableMeta.OCSHARES_FILE_SOURCE, share.getFileSource()); - cv.put(ProviderTableMeta.OCSHARES_ITEM_SOURCE, share.getItemSource()); - cv.put(ProviderTableMeta.OCSHARES_SHARE_TYPE, share.getShareType().getValue()); - cv.put(ProviderTableMeta.OCSHARES_SHARE_WITH, share.getShareWith()); - cv.put(ProviderTableMeta.OCSHARES_PATH, share.getPath()); - cv.put(ProviderTableMeta.OCSHARES_PERMISSIONS, share.getPermissions()); - cv.put(ProviderTableMeta.OCSHARES_SHARED_DATE, share.getSharedDate()); - cv.put(ProviderTableMeta.OCSHARES_EXPIRATION_DATE, share.getExpirationDate()); - cv.put(ProviderTableMeta.OCSHARES_TOKEN, share.getToken()); - cv.put(ProviderTableMeta.OCSHARES_SHARE_WITH_DISPLAY_NAME, share.getSharedWithDisplayName()); - cv.put(ProviderTableMeta.OCSHARES_IS_DIRECTORY, share.isFolder() ? 1 : 0); - cv.put(ProviderTableMeta.OCSHARES_USER_ID, share.getUserId()); - cv.put(ProviderTableMeta.OCSHARES_ID_REMOTE_SHARED, share.getRemoteId()); - cv.put(ProviderTableMeta.OCSHARES_ACCOUNT_OWNER, account.name); - cv.put(ProviderTableMeta.OCSHARES_IS_PASSWORD_PROTECTED, share.isPasswordProtected() ? 1 : 0); - cv.put(ProviderTableMeta.OCSHARES_NOTE, share.getNote()); - cv.put(ProviderTableMeta.OCSHARES_HIDE_DOWNLOAD, share.isHideFileDownload()); - - // adding a new share resource - operations.add(ContentProviderOperation.newInsert( - ProviderTableMeta.CONTENT_URI_SHARE).withValues(cv).build()); - } - } - return operations; - } - - private ArrayList prepareRemoveSharesInFolder( - OCFile folder, ArrayList preparedOperations) { - if (folder != null) { - String where = ProviderTableMeta.OCSHARES_PATH + AND - + ProviderTableMeta.OCSHARES_ACCOUNT_OWNER + "=?"; - String[] whereArgs = new String[]{"", account.name}; - - List files = getFolderContent(folder, false); - - for (OCFile file : files) { - whereArgs[0] = file.getRemotePath(); - preparedOperations.add( - ContentProviderOperation.newDelete(ProviderTableMeta.CONTENT_URI_SHARE). - withSelection(where, whereArgs). - build() - ); - } - } - return preparedOperations; - - } - - private ArrayList prepareRemoveSharesInFile( - String filePath, ArrayList preparedOperations) { - - String where = ProviderTableMeta.OCSHARES_PATH + AND - + ProviderTableMeta.OCSHARES_ACCOUNT_OWNER + "=?"; - String[] whereArgs = new String[]{filePath, account.name}; - - preparedOperations.add( - ContentProviderOperation.newDelete(ProviderTableMeta.CONTENT_URI_SHARE). - withSelection(where, whereArgs). - build() - ); - - return preparedOperations; - - } - - public List getSharesWithForAFile(String filePath, String accountName) { - // Condition - String where = ProviderTableMeta.OCSHARES_PATH + AND - + ProviderTableMeta.OCSHARES_ACCOUNT_OWNER + AND - + " (" + ProviderTableMeta.OCSHARES_SHARE_TYPE + "=? OR " - + ProviderTableMeta.OCSHARES_SHARE_TYPE + "=? OR " - + ProviderTableMeta.OCSHARES_SHARE_TYPE + "=? OR " - + ProviderTableMeta.OCSHARES_SHARE_TYPE + "=? OR " - + ProviderTableMeta.OCSHARES_SHARE_TYPE + "=? ) "; - String[] whereArgs = new String[]{filePath, accountName, - Integer.toString(ShareType.USER.getValue()), - Integer.toString(ShareType.GROUP.getValue()), - Integer.toString(ShareType.EMAIL.getValue()), - Integer.toString(ShareType.FEDERATED.getValue()), - Integer.toString(ShareType.ROOM.getValue())}; - - Cursor cursor = null; - if (getContentResolver() != null) { - cursor = getContentResolver().query(ProviderTableMeta.CONTENT_URI_SHARE, null, where, whereArgs, null); - } else { - try { - cursor = getContentProviderClient().query(ProviderTableMeta.CONTENT_URI_SHARE, null, where, - whereArgs, null); - - } catch (RemoteException e) { - Log_OC.e(TAG, "Could not get list of shares with: " + e.getMessage(), e); - cursor = null; - } - } - ArrayList shares = new ArrayList<>(); - OCShare share; - if (cursor != null) { - if (cursor.moveToFirst()) { - do { - share = createShareInstance(cursor); - shares.add(share); - } while (cursor.moveToNext()); - } - - cursor.close(); - } - - return shares; - } - - public static void triggerMediaScan(String path) { - if (path != null) { - Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE); - intent.setData(Uri.fromFile(new File(path))); - MainApp.getAppContext().sendBroadcast(intent); - } - } - - public void deleteFileInMediaScan(String path) { - - String mimetypeString = FileStorageUtils.getMimeTypeFromName(path); - ContentResolver contentResolver = getContentResolver(); - - if (contentResolver != null) { - if (MimeTypeUtil.isImage(mimetypeString)) { - // Images - contentResolver.delete(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, - MediaStore.Images.Media.DATA + "=?", new String[]{path}); - } else if (MimeTypeUtil.isAudio(mimetypeString)) { - // Audio - contentResolver.delete(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, - MediaStore.Audio.Media.DATA + "=?", new String[]{path}); - } else if (MimeTypeUtil.isVideo(mimetypeString)) { - // Video - contentResolver.delete(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, - MediaStore.Video.Media.DATA + "=?", new String[]{path}); - } - } else { - ContentProviderClient contentProviderClient = getContentProviderClient(); - try { - if (MimeTypeUtil.isImage(mimetypeString)) { - // Images - contentProviderClient.delete(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, - MediaStore.Images.Media.DATA + "=?", new String[]{path}); - } else if (MimeTypeUtil.isAudio(mimetypeString)) { - // Audio - contentProviderClient.delete(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, - MediaStore.Audio.Media.DATA + "=?", new String[]{path}); - } else if (MimeTypeUtil.isVideo(mimetypeString)) { - // Video - contentProviderClient.delete(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, - MediaStore.Video.Media.DATA + "=?", new String[]{path}); - } - } catch (RemoteException e) { - Log_OC.e(TAG, "Exception deleting media file in MediaStore " + e.getMessage(), e); - } - } - } - - public void saveConflict(OCFile file, String etagInConflict) { - if (!file.isDown()) { - etagInConflict = null; - } - ContentValues cv = new ContentValues(); - cv.put(ProviderTableMeta.FILE_ETAG_IN_CONFLICT, etagInConflict); - int updated = 0; - if (getContentResolver() != null) { - updated = getContentResolver().update( - ProviderTableMeta.CONTENT_URI_FILE, - cv, - ProviderTableMeta._ID + "=?", - new String[]{String.valueOf(file.getFileId())} - ); - } else { - try { - updated = getContentProviderClient().update( - ProviderTableMeta.CONTENT_URI_FILE, - cv, - ProviderTableMeta._ID + "=?", - new String[]{String.valueOf(file.getFileId())} - ); - } catch (RemoteException e) { - Log_OC.e(TAG, "Failed saving conflict in database " + e.getMessage(), e); - } - } - - Log_OC.d(TAG, "Number of files updated with CONFLICT: " + updated); - - if (updated > 0) { - if (etagInConflict != null) { - /// set conflict in all ancestor folders - - long parentId = file.getParentId(); - Set ancestorIds = new HashSet<>(); - while (parentId != FileDataStorageManager.ROOT_PARENT_ID) { - ancestorIds.add(Long.toString(parentId)); - parentId = getFileById(parentId).getParentId(); - } - - if (ancestorIds.size() > 0) { - final StringBuffer whereBuffer = new StringBuffer(); - whereBuffer.append(ProviderTableMeta._ID).append(" IN ("); - for (int i = 0; i < ancestorIds.size() - 1; i++) { - whereBuffer.append("?,"); - } - whereBuffer.append("?)"); - - if (getContentResolver() != null) { - updated = getContentResolver().update( - ProviderTableMeta.CONTENT_URI_FILE, - cv, - whereBuffer.toString(), - ancestorIds.toArray(new String[]{}) - ); - } else { - try { - updated = getContentProviderClient().update( - ProviderTableMeta.CONTENT_URI_FILE, - cv, - whereBuffer.toString(), - ancestorIds.toArray(new String[]{}) - ); - } catch (RemoteException e) { - Log_OC.e(TAG, "Failed saving conflict in database " + e.getMessage(), e); - } - } - } // else file is ROOT folder, no parent to set in conflict - - } else { - /// update conflict in ancestor folders - // (not directly unset; maybe there are more conflicts below them) - String parentPath = file.getRemotePath(); - if (parentPath.endsWith(OCFile.PATH_SEPARATOR)) { - parentPath = parentPath.substring(0, parentPath.length() - 1); - } - parentPath = parentPath.substring(0, parentPath.lastIndexOf(OCFile.PATH_SEPARATOR) + 1); - - Log_OC.d(TAG, "checking parents to remove conflict; STARTING with " + parentPath); - String[] projection = new String[]{ProviderTableMeta._ID}; - while (parentPath.length() > 0) { - - String whereForDescencentsInConflict = - ProviderTableMeta.FILE_ETAG_IN_CONFLICT + " IS NOT NULL AND " + - ProviderTableMeta.FILE_CONTENT_TYPE + " != 'DIR' AND " + - ProviderTableMeta.FILE_ACCOUNT_OWNER + AND + - ProviderTableMeta.FILE_PATH + " LIKE ?"; - Cursor descendentsInConflict = null; - if (getContentResolver() != null) { - descendentsInConflict = getContentResolver().query( - ProviderTableMeta.CONTENT_URI_FILE, - projection, - whereForDescencentsInConflict, - new String[]{account.name, parentPath + "%"}, - null - ); - } else { - try { - descendentsInConflict = getContentProviderClient().query( - ProviderTableMeta.CONTENT_URI_FILE, - projection, - whereForDescencentsInConflict, - new String[]{account.name, parentPath + "%"}, - null - ); - } catch (RemoteException e) { - Log_OC.e(TAG, "Failed querying for descendents in conflict " + e.getMessage(), e); - } - } - if (descendentsInConflict == null || descendentsInConflict.getCount() == 0) { - Log_OC.d(TAG, "NO MORE conflicts in " + parentPath); - if (getContentResolver() != null) { - updated = getContentResolver().update( - ProviderTableMeta.CONTENT_URI_FILE, - cv, - ProviderTableMeta.FILE_ACCOUNT_OWNER + AND + - ProviderTableMeta.FILE_PATH + "=?", - new String[]{account.name, parentPath} - ); - } else { - try { - updated = getContentProviderClient().update( - ProviderTableMeta.CONTENT_URI_FILE, - cv, - ProviderTableMeta.FILE_ACCOUNT_OWNER + AND + - ProviderTableMeta.FILE_PATH + "=?" - , new String[]{account.name, parentPath} - ); - } catch (RemoteException e) { - Log_OC.e(TAG, "Failed saving conflict in database " + e.getMessage(), e); - } - } - - } else { - Log_OC.d(TAG, "STILL " + descendentsInConflict.getCount() + " in " + parentPath); - } - - if (descendentsInConflict != null) { - descendentsInConflict.close(); - } - - parentPath = parentPath.substring(0, parentPath.length() - 1); // trim last / - parentPath = parentPath.substring(0, parentPath.lastIndexOf(OCFile.PATH_SEPARATOR) + 1); - Log_OC.d(TAG, "checking parents to remove conflict; NEXT " + parentPath); - } - } - } - - } - - public OCCapability saveCapabilities(OCCapability capability) { - - // Prepare capabilities data - ContentValues cv = createContentValues(account.name, capability); - - if (capabilityExists(account.name)) { - if (getContentResolver() != null) { - getContentResolver().update(ProviderTableMeta.CONTENT_URI_CAPABILITIES, cv, - ProviderTableMeta.CAPABILITIES_ACCOUNT_NAME + "=?", - new String[]{account.name}); - } else { - try { - getContentProviderClient().update(ProviderTableMeta.CONTENT_URI_CAPABILITIES, - cv, ProviderTableMeta.CAPABILITIES_ACCOUNT_NAME + "=?", - new String[]{account.name}); - } catch (RemoteException e) { - Log_OC.e(TAG, FAILED_TO_INSERT_MSG + e.getMessage(), e); - } - } - } else { - Uri result_uri = null; - if (getContentResolver() != null) { - result_uri = getContentResolver().insert( - ProviderTableMeta.CONTENT_URI_CAPABILITIES, cv); - } else { - try { - result_uri = getContentProviderClient().insert( - ProviderTableMeta.CONTENT_URI_CAPABILITIES, cv); - } catch (RemoteException e) { - Log_OC.e(TAG, FAILED_TO_INSERT_MSG + e.getMessage(), e); - } - } - if (result_uri != null) { - long new_id = Long.parseLong(result_uri.getPathSegments() - .get(1)); - capability.setId(new_id); - capability.setAccountName(account.name); - } - } - - return capability; - } - - @NonNull - private ContentValues createContentValues(String accountName, OCCapability capability) { - ContentValues cv = new ContentValues(); - cv.put(ProviderTableMeta.CAPABILITIES_ACCOUNT_NAME, accountName); - cv.put(ProviderTableMeta.CAPABILITIES_VERSION_MAYOR, capability.getVersionMayor()); - cv.put(ProviderTableMeta.CAPABILITIES_VERSION_MINOR, capability.getVersionMinor()); - cv.put(ProviderTableMeta.CAPABILITIES_VERSION_MICRO, capability.getVersionMicro()); - cv.put(ProviderTableMeta.CAPABILITIES_VERSION_STRING, capability.getVersionString()); - cv.put(ProviderTableMeta.CAPABILITIES_VERSION_EDITION, capability.getVersionEdition()); - cv.put(ProviderTableMeta.CAPABILITIES_EXTENDED_SUPPORT, capability.getExtendedSupport().getValue()); - cv.put(ProviderTableMeta.CAPABILITIES_CORE_POLLINTERVAL, capability.getCorePollInterval()); - cv.put(ProviderTableMeta.CAPABILITIES_SHARING_API_ENABLED, capability.getFilesSharingApiEnabled().getValue()); - cv.put(ProviderTableMeta.CAPABILITIES_SHARING_PUBLIC_ENABLED, - capability.getFilesSharingPublicEnabled().getValue()); - cv.put(ProviderTableMeta.CAPABILITIES_SHARING_PUBLIC_PASSWORD_ENFORCED, - capability.getFilesSharingPublicPasswordEnforced().getValue()); - cv.put(ProviderTableMeta.CAPABILITIES_SHARING_PUBLIC_ASK_FOR_OPTIONAL_PASSWORD, - capability.getFilesSharingPublicAskForOptionalPassword().getValue()); - cv.put(ProviderTableMeta.CAPABILITIES_SHARING_PUBLIC_EXPIRE_DATE_ENABLED, - capability.getFilesSharingPublicExpireDateEnabled().getValue()); - cv.put(ProviderTableMeta.CAPABILITIES_SHARING_PUBLIC_EXPIRE_DATE_DAYS, - capability.getFilesSharingPublicExpireDateDays()); - cv.put(ProviderTableMeta.CAPABILITIES_SHARING_PUBLIC_EXPIRE_DATE_ENFORCED, - capability.getFilesSharingPublicExpireDateEnforced().getValue()); - cv.put(ProviderTableMeta.CAPABILITIES_SHARING_PUBLIC_SEND_MAIL, - capability.getFilesSharingPublicSendMail().getValue()); - cv.put(ProviderTableMeta.CAPABILITIES_SHARING_PUBLIC_UPLOAD, - capability.getFilesSharingPublicUpload().getValue()); - cv.put(ProviderTableMeta.CAPABILITIES_SHARING_USER_SEND_MAIL, - capability.getFilesSharingUserSendMail().getValue()); - cv.put(ProviderTableMeta.CAPABILITIES_SHARING_RESHARING, capability.getFilesSharingResharing().getValue()); - cv.put(ProviderTableMeta.CAPABILITIES_SHARING_FEDERATION_OUTGOING, - capability.getFilesSharingFederationOutgoing().getValue()); - cv.put(ProviderTableMeta.CAPABILITIES_SHARING_FEDERATION_INCOMING, - capability.getFilesSharingFederationIncoming().getValue()); - cv.put(ProviderTableMeta.CAPABILITIES_FILES_BIGFILECHUNKING, capability.getFilesBigFileChunking().getValue()); - cv.put(ProviderTableMeta.CAPABILITIES_FILES_UNDELETE, capability.getFilesUndelete().getValue()); - cv.put(ProviderTableMeta.CAPABILITIES_FILES_VERSIONING, capability.getFilesVersioning().getValue()); - cv.put(ProviderTableMeta.CAPABILITIES_FILES_DROP, capability.getFilesFileDrop().getValue()); - cv.put(ProviderTableMeta.CAPABILITIES_EXTERNAL_LINKS, capability.getExternalLinks().getValue()); - cv.put(ProviderTableMeta.CAPABILITIES_SERVER_NAME, capability.getServerName()); - cv.put(ProviderTableMeta.CAPABILITIES_SERVER_COLOR, capability.getServerColor()); - cv.put(ProviderTableMeta.CAPABILITIES_SERVER_TEXT_COLOR, capability.getServerTextColor()); - cv.put(ProviderTableMeta.CAPABILITIES_SERVER_ELEMENT_COLOR, capability.getServerElementColor()); - cv.put(ProviderTableMeta.CAPABILITIES_SERVER_BACKGROUND_URL, capability.getServerBackground()); - cv.put(ProviderTableMeta.CAPABILITIES_SERVER_SLOGAN, capability.getServerSlogan()); - cv.put(ProviderTableMeta.CAPABILITIES_END_TO_END_ENCRYPTION, capability.getEndToEndEncryption().getValue()); - cv.put(ProviderTableMeta.CAPABILITIES_SERVER_BACKGROUND_DEFAULT, capability.getServerBackgroundDefault() - .getValue()); - cv.put(ProviderTableMeta.CAPABILITIES_SERVER_BACKGROUND_PLAIN, capability.getServerBackgroundPlain() - .getValue()); - cv.put(ProviderTableMeta.CAPABILITIES_ACTIVITY, capability.getActivity().getValue()); - cv.put(ProviderTableMeta.CAPABILITIES_RICHDOCUMENT, capability.getRichDocuments().getValue()); - cv.put(ProviderTableMeta.CAPABILITIES_RICHDOCUMENT_MIMETYPE_LIST, - TextUtils.join(",", capability.getRichDocumentsMimeTypeList())); - cv.put(ProviderTableMeta.CAPABILITIES_RICHDOCUMENT_OPTIONAL_MIMETYPE_LIST, - TextUtils.join(",", capability.getRichDocumentsOptionalMimeTypeList())); - cv.put(ProviderTableMeta.CAPABILITIES_RICHDOCUMENT_DIRECT_EDITING, capability.getRichDocumentsDirectEditing() - .getValue()); - cv.put(ProviderTableMeta.CAPABILITIES_RICHDOCUMENT_TEMPLATES, capability.getRichDocumentsTemplatesAvailable() - .getValue()); - cv.put(ProviderTableMeta.CAPABILITIES_RICHDOCUMENT_PRODUCT_NAME, capability.getRichDocumentsProductName()); - cv.put(ProviderTableMeta.CAPABILITIES_DIRECT_EDITING_ETAG, capability.getDirectEditingEtag()); - - return cv; - } - - private boolean capabilityExists(String accountName) { - Cursor c = getCapabilityCursorForAccount(accountName); - boolean exists = false; - if (c != null) { - exists = c.moveToFirst(); - c.close(); - } - return exists; - } - - private Cursor getCapabilityCursorForAccount(String accountName) { - Cursor c = null; - if (getContentResolver() != null) { - c = getContentResolver() - .query(ProviderTableMeta.CONTENT_URI_CAPABILITIES, - null, - ProviderTableMeta.CAPABILITIES_ACCOUNT_NAME + "=? ", - new String[]{accountName}, null); - } else { - try { - c = getContentProviderClient().query( - ProviderTableMeta.CONTENT_URI_CAPABILITIES, - null, - ProviderTableMeta.CAPABILITIES_ACCOUNT_NAME + "=? ", - new String[]{accountName}, null); - } catch (RemoteException e) { - Log_OC.e(TAG, "Couldn't determine capability existence, assuming non existance: " + e.getMessage(), e); - } - } - - return c; - } + OCCapability saveCapabilities(OCCapability capability); @NonNull - public OCCapability getCapability(String accountName) { - OCCapability capability; - Cursor c = getCapabilityCursorForAccount(accountName); - - if (c.moveToFirst()) { - capability = createCapabilityInstance(c); - } else { - capability = new OCCapability(); // return default with all UNKNOWN - } - c.close(); - return capability; - } - - private OCCapability createCapabilityInstance(Cursor c) { - OCCapability capability = null; - if (c != null) { - capability = new OCCapability(); - capability.setId(getLong(c, ProviderTableMeta._ID)); - capability.setAccountName(getString(c, ProviderTableMeta.CAPABILITIES_ACCOUNT_NAME)); - capability.setVersionMayor(getInt(c, ProviderTableMeta.CAPABILITIES_VERSION_MAYOR)); - capability.setVersionMinor(getInt(c, ProviderTableMeta.CAPABILITIES_VERSION_MINOR)); - capability.setVersionMicro(getInt(c, ProviderTableMeta.CAPABILITIES_VERSION_MICRO)); - capability.setVersionString(getString(c, ProviderTableMeta.CAPABILITIES_VERSION_STRING)); - capability.setVersionEdition(getString(c, ProviderTableMeta.CAPABILITIES_VERSION_EDITION)); - capability.setExtendedSupport(getBoolean(c, ProviderTableMeta.CAPABILITIES_EXTENDED_SUPPORT)); - capability.setCorePollInterval(getInt(c, ProviderTableMeta.CAPABILITIES_CORE_POLLINTERVAL)); - capability.setFilesSharingApiEnabled(getBoolean(c, ProviderTableMeta.CAPABILITIES_SHARING_API_ENABLED)); - capability.setFilesSharingPublicEnabled( - getBoolean(c, ProviderTableMeta.CAPABILITIES_SHARING_PUBLIC_ENABLED)); - capability.setFilesSharingPublicPasswordEnforced( - getBoolean(c, ProviderTableMeta.CAPABILITIES_SHARING_PUBLIC_PASSWORD_ENFORCED)); - capability.setFilesSharingPublicAskForOptionalPassword( - getBoolean(c, ProviderTableMeta.CAPABILITIES_SHARING_PUBLIC_ASK_FOR_OPTIONAL_PASSWORD)); - capability.setFilesSharingPublicExpireDateEnabled( - getBoolean(c, ProviderTableMeta.CAPABILITIES_SHARING_PUBLIC_EXPIRE_DATE_ENABLED)); - capability.setFilesSharingPublicExpireDateDays( - getInt(c, ProviderTableMeta.CAPABILITIES_SHARING_PUBLIC_EXPIRE_DATE_DAYS)); - capability.setFilesSharingPublicExpireDateEnforced( - getBoolean(c, ProviderTableMeta.CAPABILITIES_SHARING_PUBLIC_EXPIRE_DATE_ENFORCED)); - capability.setFilesSharingPublicSendMail( - getBoolean(c, ProviderTableMeta.CAPABILITIES_SHARING_PUBLIC_SEND_MAIL)); - capability.setFilesSharingPublicUpload(getBoolean(c, ProviderTableMeta.CAPABILITIES_SHARING_PUBLIC_UPLOAD)); - capability.setFilesSharingUserSendMail(getBoolean(c, ProviderTableMeta.CAPABILITIES_SHARING_USER_SEND_MAIL)); - capability.setFilesSharingResharing(getBoolean(c, ProviderTableMeta.CAPABILITIES_SHARING_RESHARING)); - capability.setFilesSharingFederationOutgoing( - getBoolean(c, ProviderTableMeta.CAPABILITIES_SHARING_FEDERATION_OUTGOING)); - capability.setFilesSharingFederationIncoming( - getBoolean(c, ProviderTableMeta.CAPABILITIES_SHARING_FEDERATION_INCOMING)); - capability.setFilesBigFileChunking(getBoolean(c, ProviderTableMeta.CAPABILITIES_FILES_BIGFILECHUNKING)); - capability.setFilesUndelete(getBoolean(c, ProviderTableMeta.CAPABILITIES_FILES_UNDELETE)); - capability.setFilesVersioning(getBoolean(c, ProviderTableMeta.CAPABILITIES_FILES_VERSIONING)); - capability.setFilesFileDrop(getBoolean(c, ProviderTableMeta.CAPABILITIES_FILES_DROP)); - capability.setExternalLinks(getBoolean(c, ProviderTableMeta.CAPABILITIES_EXTERNAL_LINKS)); - capability.setServerName(getString(c, ProviderTableMeta.CAPABILITIES_SERVER_NAME)); - capability.setServerColor(getString(c, ProviderTableMeta.CAPABILITIES_SERVER_COLOR)); - capability.setServerTextColor(getString(c, ProviderTableMeta.CAPABILITIES_SERVER_TEXT_COLOR)); - capability.setServerElementColor(getString(c, ProviderTableMeta.CAPABILITIES_SERVER_ELEMENT_COLOR)); - capability.setServerBackground(getString(c, ProviderTableMeta.CAPABILITIES_SERVER_BACKGROUND_URL)); - capability.setServerSlogan(getString(c, ProviderTableMeta.CAPABILITIES_SERVER_SLOGAN)); - capability.setEndToEndEncryption(getBoolean(c, ProviderTableMeta.CAPABILITIES_END_TO_END_ENCRYPTION)); - capability.setServerBackgroundDefault( - getBoolean(c, ProviderTableMeta.CAPABILITIES_SERVER_BACKGROUND_DEFAULT)); - capability.setServerBackgroundPlain(getBoolean(c, ProviderTableMeta.CAPABILITIES_SERVER_BACKGROUND_PLAIN)); - capability.setActivity(getBoolean(c, ProviderTableMeta.CAPABILITIES_ACTIVITY)); - capability.setRichDocuments(getBoolean(c, ProviderTableMeta.CAPABILITIES_RICHDOCUMENT)); - capability.setRichDocumentsDirectEditing( - getBoolean(c, ProviderTableMeta.CAPABILITIES_RICHDOCUMENT_DIRECT_EDITING)); - capability.setRichDocumentsTemplatesAvailable( - getBoolean(c, ProviderTableMeta.CAPABILITIES_RICHDOCUMENT_TEMPLATES)); - String mimetypes = c.getString(c.getColumnIndex(ProviderTableMeta.CAPABILITIES_RICHDOCUMENT_MIMETYPE_LIST)); - if (mimetypes == null) { - mimetypes = ""; - } - capability.setRichDocumentsMimeTypeList(Arrays.asList(mimetypes.split(","))); + OCCapability getCapability(String accountName); - String optionalMimetypes = getString(c, ProviderTableMeta.CAPABILITIES_RICHDOCUMENT_OPTIONAL_MIMETYPE_LIST); - if (optionalMimetypes == null) { - optionalMimetypes = ""; - } - capability.setRichDocumentsOptionalMimeTypeList(Arrays.asList(optionalMimetypes.split(","))); - capability.setRichDocumentsProductName(getString(c, ProviderTableMeta.CAPABILITIES_RICHDOCUMENT_PRODUCT_NAME)); - capability.setDirectEditingEtag(getString(c, ProviderTableMeta.CAPABILITIES_DIRECT_EDITING_ETAG)); - } - return capability; - } + void saveSharesDB(List shares); - public void deleteVirtuals(VirtualFolderType type) { - if (getContentResolver() != null) { - getContentResolver().delete(ProviderTableMeta.CONTENT_URI_VIRTUAL, - ProviderTableMeta.VIRTUAL_TYPE + "=?", new String[]{String.valueOf(type)}); - } else { - try { - getContentProviderClient().delete(ProviderTableMeta.CONTENT_URI_VIRTUAL, - ProviderTableMeta.VIRTUAL_TYPE + "=?", new String[]{String.valueOf(type)}); - } catch (RemoteException e) { - Log_OC.e(TAG, FAILED_TO_INSERT_MSG + e.getMessage(), e); - } - } - } + void removeSharesForFile(String remotePath); - public void saveVirtuals(VirtualFolderType type, List values) { + OCShare getShareById(long id); - if (getContentResolver() != null) { - getContentResolver().bulkInsert(ProviderTableMeta.CONTENT_URI_VIRTUAL, values.toArray(new ContentValues[0])); - } else { - try { - getContentProviderClient().bulkInsert(ProviderTableMeta.CONTENT_URI_VIRTUAL, values.toArray(new ContentValues[0])); - } catch (RemoteException e) { - Log_OC.e(TAG, FAILED_TO_INSERT_MSG + e.getMessage(), e); - } - } - } + void triggerMediaScan(String path); - public void saveVirtual(VirtualFolderType type, OCFile file) { - ContentValues cv = new ContentValues(); - cv.put(ProviderTableMeta.VIRTUAL_TYPE, type.toString()); - cv.put(ProviderTableMeta.VIRTUAL_OCFILE_ID, file.getFileId()); + OCFile getFileByLocalPath(String path); - if (getContentResolver() != null) { - getContentResolver().insert(ProviderTableMeta.CONTENT_URI_VIRTUAL, cv); - } else { - try { - getContentProviderClient().insert(ProviderTableMeta.CONTENT_URI_VIRTUAL, cv); - } catch (RemoteException e) { - Log_OC.e(TAG, FAILED_TO_INSERT_MSG + e.getMessage(), e); - } - } - } - - public List getVirtualFolderContent(VirtualFolderType type, boolean onlyImages) { - List ocFiles = new ArrayList<>(); - Uri req_uri = ProviderTableMeta.CONTENT_URI_VIRTUAL; - Cursor c; - - if (getContentProviderClient() != null) { - try { - c = getContentProviderClient().query( - req_uri, - null, - ProviderTableMeta.VIRTUAL_TYPE + "=?", - new String[]{String.valueOf(type)}, - null - ); - } catch (RemoteException e) { - Log_OC.e(TAG, e.getMessage(), e); - return ocFiles; - } - } else { - c = getContentResolver().query( - req_uri, - null, - ProviderTableMeta.VIRTUAL_TYPE + "=?", - new String[]{String.valueOf(type)}, - null - ); - } + @Nullable + OCFile getFileByRemoteId(String remoteId); - if (c != null) { - if (c.moveToFirst()) { - do { - OCFile child = createFileInstanceFromVirtual(c); + List getFolderImages(OCFile folder, boolean onlyOnDevice); - if (child != null) { - ocFiles.add(child); - } - } while (c.moveToNext()); - } - c.close(); - } + OCFile saveFileWithParent(OCFile file); - if (onlyImages) { - List temp = new ArrayList<>(); + void saveNewFile(OCFile newFile); - for (OCFile file : ocFiles) { - if (MimeTypeUtil.isImage(file)) { - temp.add(file); - } - } - ocFiles = temp; - } + void migrateStoredFiles(String srcPath, String dstPath) throws RemoteException, OperationApplicationException; - if (ocFiles.size() > 0) { - Collections.sort(ocFiles); - } + void saveShares(Collection shares); - return ocFiles; - } + void updateSharedFiles(Collection sharedFiles); - public void deleteAllFiles() { - String where = ProviderTableMeta.FILE_ACCOUNT_OWNER + "= ? AND " + - ProviderTableMeta.FILE_PATH + "= ?"; - String[] whereArgs = new String[]{account.name, OCFile.ROOT_PATH}; + void saveSharesInFolder(ArrayList shares, OCFile folder); - if (getContentResolver() != null) { - getContentResolver().delete(ProviderTableMeta.CONTENT_URI_DIR, where, whereArgs); - } else { - try { - getContentProviderClient().delete(ProviderTableMeta.CONTENT_URI_DIR, where, whereArgs); - } catch (RemoteException e) { - Log_OC.e(TAG, "Exception in deleteAllFiles for account " + account.name + ": " + e.getMessage(), e); - } - } - } + void deleteVirtuals(VirtualFolderType type); - private String getString(Cursor cursor, String columnName) { - return cursor.getString(cursor.getColumnIndex(columnName)); - } + void saveVirtuals(VirtualFolderType type, List values); - private int getInt(Cursor cursor, String columnName) { - return cursor.getInt(cursor.getColumnIndex(columnName)); - } + void saveVirtual(VirtualFolderType type, OCFile file); - private long getLong(Cursor cursor, String columnName) { - return cursor.getLong(cursor.getColumnIndex(columnName)); - } + List getVirtualFolderContent(VirtualFolderType type, boolean onlyImages); - private CapabilityBooleanType getBoolean(Cursor cursor, String columnName) { - return CapabilityBooleanType.fromValue(cursor.getInt(cursor.getColumnIndex(columnName))); - } + void deleteAllFiles(); } diff --git a/src/main/java/com/owncloud/android/datamodel/FileDataStorageManagerImpl.java b/src/main/java/com/owncloud/android/datamodel/FileDataStorageManagerImpl.java new file mode 100644 index 000000000000..c2ea1f1928c7 --- /dev/null +++ b/src/main/java/com/owncloud/android/datamodel/FileDataStorageManagerImpl.java @@ -0,0 +1,2301 @@ +/* + * ownCloud Android client application + * + * Copyright (C) 2012 Bartek Przybylski + * Copyright (C) 2015 ownCloud Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.owncloud.android.datamodel; + +import android.accounts.Account; +import android.content.ContentProviderClient; +import android.content.ContentProviderOperation; +import android.content.ContentProviderResult; +import android.content.ContentResolver; +import android.content.ContentUris; +import android.content.ContentValues; +import android.content.Context; +import android.content.Intent; +import android.content.OperationApplicationException; +import android.database.Cursor; +import android.net.Uri; +import android.os.RemoteException; +import android.provider.MediaStore; +import android.text.TextUtils; + +import com.google.gson.Gson; +import com.google.gson.JsonSyntaxException; +import com.owncloud.android.MainApp; +import com.owncloud.android.db.ProviderMeta.ProviderTableMeta; +import com.owncloud.android.lib.common.network.WebdavEntry; +import com.owncloud.android.lib.common.operations.RemoteOperationResult; +import com.owncloud.android.lib.common.utils.Log_OC; +import com.owncloud.android.lib.resources.files.ReadFileRemoteOperation; +import com.owncloud.android.lib.resources.files.model.RemoteFile; +import com.owncloud.android.lib.resources.shares.OCShare; +import com.owncloud.android.lib.resources.shares.ShareType; +import com.owncloud.android.lib.resources.shares.ShareeUser; +import com.owncloud.android.lib.resources.status.CapabilityBooleanType; +import com.owncloud.android.lib.resources.status.OCCapability; +import com.owncloud.android.operations.RemoteOperationFailedException; +import com.owncloud.android.utils.FileStorageUtils; +import com.owncloud.android.utils.MimeType; +import com.owncloud.android.utils.MimeTypeUtil; + +import java.io.File; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Locale; +import java.util.Set; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import lombok.Getter; +import lombok.Setter; + + +@Getter +public class FileDataStorageManagerImpl implements FileDataStorageManager { + private static final String TAG = FileDataStorageManagerImpl.class.getSimpleName(); + + private static final String AND = "=? AND "; + private static final String FAILED_TO_INSERT_MSG = "Fail to insert insert file to database "; + private static final String SENDING_TO_FILECONTENTPROVIDER_MSG = "Sending %d operations to FileContentProvider"; + private static final String EXCEPTION_MSG = "Exception in batch of operations "; + + public static final String NULL_STRING = "null"; + + private ContentResolver contentResolver; + private ContentProviderClient contentProviderClient; + @Setter private Account account; + private Context context; + + public FileDataStorageManagerImpl(Account account, Context context) { + contentProviderClient = null; + this.contentResolver = context.getContentResolver(); + this.account = account; + this.context = context; + } + + public FileDataStorageManagerImpl(Account account, ContentProviderClient contentProviderClient, Context context) { + this.contentProviderClient = contentProviderClient; + contentResolver = null; + this.account = account; + this.context = context; + } + + public OCFile getFileByPath(String path) { + Cursor c = getFileCursorForValue(ProviderTableMeta.FILE_PATH, path); + OCFile file = null; + if (c.moveToFirst()) { + file = createFileInstance(c); + } + c.close(); + if (file == null && OCFile.ROOT_PATH.equals(path)) { + return createRootDir(); // root should always exist + } + return file; + } + + public @Nullable + OCFile getFileById(long id) { + Cursor c = getFileCursorForValue(ProviderTableMeta._ID, String.valueOf(id)); + OCFile file = null; + if (c.moveToFirst()) { + file = createFileInstance(c); + } + c.close(); + return file; + } + + public OCFile getFileByLocalPath(String path) { + Cursor c = getFileCursorForValue(ProviderTableMeta.FILE_STORAGE_PATH, path); + OCFile file = null; + if (c.moveToFirst()) { + file = createFileInstance(c); + } + c.close(); + return file; + } + + public @Nullable + OCFile getFileByRemoteId(String remoteId) { + Cursor c = getFileCursorForValue(ProviderTableMeta.FILE_REMOTE_ID, remoteId); + OCFile file = null; + if (c.moveToFirst()) { + file = createFileInstance(c); + } + c.close(); + return file; + } + + public boolean fileExists(long id) { + return fileExists(ProviderTableMeta._ID, String.valueOf(id)); + } + + public boolean fileExists(String path) { + return fileExists(ProviderTableMeta.FILE_PATH, path); + } + + + public List getFolderContent(OCFile f, boolean onlyOnDevice) { + if (f != null && f.isFolder() && f.getFileId() != -1) { + return getFolderContent(f.getFileId(), onlyOnDevice); + } else { + return new ArrayList<>(); + } + } + + + public List getFolderImages(OCFile folder, boolean onlyOnDevice) { + List ret = new ArrayList<>(); + + if (folder != null) { + // TODO better implementation, filtering in the access to database instead of here + List tmp = getFolderContent(folder, onlyOnDevice); + + for (OCFile file : tmp) { + if (MimeTypeUtil.isImage(file)) { + ret.add(file); + } + } + } + return ret; + } + + public boolean saveFile(OCFile file) { + boolean overridden = false; + ContentValues cv = new ContentValues(); + cv.put(ProviderTableMeta.FILE_MODIFIED, file.getModificationTimestamp()); + cv.put( + ProviderTableMeta.FILE_MODIFIED_AT_LAST_SYNC_FOR_DATA, + file.getModificationTimestampAtLastSyncForData() + ); + cv.put(ProviderTableMeta.FILE_CREATION, file.getCreationTimestamp()); + cv.put(ProviderTableMeta.FILE_CONTENT_LENGTH, file.getFileLength()); + cv.put(ProviderTableMeta.FILE_CONTENT_TYPE, file.getMimeType()); + cv.put(ProviderTableMeta.FILE_NAME, file.getFileName()); + cv.put(ProviderTableMeta.FILE_ENCRYPTED_NAME, file.getEncryptedFileName()); + cv.put(ProviderTableMeta.FILE_PARENT, file.getParentId()); + cv.put(ProviderTableMeta.FILE_PATH, file.getRemotePath()); + if (!file.isFolder()) { + cv.put(ProviderTableMeta.FILE_IS_ENCRYPTED, file.isEncrypted()); + cv.put(ProviderTableMeta.FILE_STORAGE_PATH, file.getStoragePath()); + } + cv.put(ProviderTableMeta.FILE_ACCOUNT_OWNER, account.name); + cv.put(ProviderTableMeta.FILE_LAST_SYNC_DATE, file.getLastSyncDateForProperties()); + cv.put(ProviderTableMeta.FILE_LAST_SYNC_DATE_FOR_DATA, file.getLastSyncDateForData()); + cv.put(ProviderTableMeta.FILE_ETAG, file.getEtag()); + cv.put(ProviderTableMeta.FILE_ETAG_ON_SERVER, file.getEtagOnServer()); + cv.put(ProviderTableMeta.FILE_SHARED_VIA_LINK, file.isSharedViaLink() ? 1 : 0); + cv.put(ProviderTableMeta.FILE_SHARED_WITH_SHAREE, file.isSharedWithSharee() ? 1 : 0); + cv.put(ProviderTableMeta.FILE_PUBLIC_LINK, file.getPublicLink()); + cv.put(ProviderTableMeta.FILE_PERMISSIONS, file.getPermissions()); + cv.put(ProviderTableMeta.FILE_REMOTE_ID, file.getRemoteId()); + cv.put(ProviderTableMeta.FILE_UPDATE_THUMBNAIL, file.isUpdateThumbnailNeeded()); + cv.put(ProviderTableMeta.FILE_IS_DOWNLOADING, file.isDownloading()); + cv.put(ProviderTableMeta.FILE_ETAG_IN_CONFLICT, file.getEtagInConflict()); + cv.put(ProviderTableMeta.FILE_UNREAD_COMMENTS_COUNT, file.getUnreadCommentsCount()); + cv.put(ProviderTableMeta.FILE_OWNER_ID, file.getOwnerId()); + cv.put(ProviderTableMeta.FILE_OWNER_DISPLAY_NAME, file.getOwnerDisplayName()); + cv.put(ProviderTableMeta.FILE_NOTE, file.getNote()); + cv.put(ProviderTableMeta.FILE_SHAREES, new Gson().toJson(file.getSharees())); + + boolean sameRemotePath = fileExists(file.getRemotePath()); + if (sameRemotePath || + fileExists(file.getFileId())) { // for renamed files; no more delete and create + + + if (sameRemotePath) { + OCFile oldFile = getFileByPath(file.getRemotePath()); + file.setFileId(oldFile.getFileId()); + } + + overridden = true; + if (getContentResolver() != null) { + getContentResolver().update(ProviderTableMeta.CONTENT_URI, cv, + ProviderTableMeta._ID + "=?", + new String[]{String.valueOf(file.getFileId())}); + } else { + try { + getContentProviderClient().update(ProviderTableMeta.CONTENT_URI, + cv, ProviderTableMeta._ID + "=?", + new String[]{String.valueOf(file.getFileId())}); + } catch (RemoteException e) { + Log_OC.e(TAG, FAILED_TO_INSERT_MSG + e.getMessage(), e); + } + } + } else { + Uri result_uri = null; + if (getContentResolver() != null) { + result_uri = getContentResolver().insert(ProviderTableMeta.CONTENT_URI_FILE, cv); + } else { + try { + result_uri = getContentProviderClient().insert(ProviderTableMeta.CONTENT_URI_FILE, cv); + } catch (RemoteException e) { + Log_OC.e(TAG, FAILED_TO_INSERT_MSG + e.getMessage(), e); + } + } + if (result_uri != null) { + long new_id = Long.parseLong(result_uri.getPathSegments().get(1)); + file.setFileId(new_id); + } + } + + return overridden; + } + + /** + * traverses a files parent tree to be able to store a file with its parents. Throws a + * RemoteOperationFailedException in case the parent can't be retrieved. + * + * @param file the file + * @return the parent file + */ + public OCFile saveFileWithParent(OCFile file) { + if (file.getParentId() == 0 && !OCFile.ROOT_PATH.equals(file.getRemotePath())) { + String remotePath = file.getRemotePath(); + String parentPath = remotePath.substring(0, remotePath.lastIndexOf(file.getFileName())); + + OCFile parentFile = getFileByPath(parentPath); + + OCFile returnFile; + if (parentFile == null) { + // remote request + ReadFileRemoteOperation operation = new ReadFileRemoteOperation(parentPath); + RemoteOperationResult result = operation.execute(getAccount(), context); + if (result.isSuccess()) { + OCFile remoteFolder = FileStorageUtils.fillOCFile((RemoteFile) result.getData().get(0)); + + returnFile = saveFileWithParent(remoteFolder); + } else { + Exception exception = result.getException(); + String message = "Error during saving file with parents: " + file.getRemotePath() + " / " + + result.getLogMessage(); + + if (exception != null) { + throw new RemoteOperationFailedException(message, exception); + } else { + throw new RemoteOperationFailedException(message); + } + } + } else { + returnFile = saveFileWithParent(parentFile); + } + + file.setParentId(returnFile.getFileId()); + saveFile(file); + } + + return file; + } + + public void saveNewFile(OCFile newFile) { + String remoteParentPath = new File(newFile.getRemotePath()).getParent(); + remoteParentPath = remoteParentPath.endsWith(OCFile.PATH_SEPARATOR) ? + remoteParentPath : remoteParentPath + OCFile.PATH_SEPARATOR; + OCFile parent = getFileByPath(remoteParentPath); + if (parent != null) { + newFile.setParentId(parent.getFileId()); + saveFile(newFile); + } else { + throw new IllegalArgumentException("Saving a new file in an unexisting folder"); + } + } + + + /** + * Inserts or updates the list of files contained in a given folder. + *

+ * CALLER IS RESPONSIBLE FOR GRANTING RIGHT UPDATE OF INFORMATION, NOT THIS METHOD. HERE ONLY DATA CONSISTENCY + * SHOULD BE GRANTED + * + * @param folder + * @param updatedFiles + * @param filesToRemove + */ + public void saveFolder(OCFile folder, Collection updatedFiles, Collection filesToRemove) { + Log_OC.d(TAG, "Saving folder " + folder.getRemotePath() + " with " + updatedFiles.size() + + " children and " + filesToRemove.size() + " files to remove"); + + ArrayList operations = new ArrayList<>(updatedFiles.size()); + + // prepare operations to insert or update files to save in the given folder + for (OCFile file : updatedFiles) { + ContentValues cv = createContentValueForFile(file, folder); + + if (fileExists(file.getFileId()) || fileExists(file.getRemotePath())) { + long fileId; + if (file.getFileId() != -1) { + fileId = file.getFileId(); + } else { + fileId = getFileByPath(file.getRemotePath()).getFileId(); + } + // updating an existing file + operations.add(ContentProviderOperation.newUpdate(ProviderTableMeta.CONTENT_URI) + .withValues(cv) + .withSelection(ProviderTableMeta._ID + "=?", new String[]{String.valueOf(fileId)}) + .build()); + } else { + // adding a new file + 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 = new String[2]; + for (OCFile file : filesToRemove) { + if (file.getParentId() == folder.getFileId()) { + whereArgs[0] = account.name; + whereArgs[1] = file.getRemotePath(); + if (file.isFolder()) { + operations.add(ContentProviderOperation.newDelete( + ContentUris.withAppendedId(ProviderTableMeta.CONTENT_URI_DIR, file.getFileId())) + .withSelection(where, whereArgs).build()); + + File localFolder = new File(FileStorageUtils.getDefaultSavePathFor(account.name, file)); + if (localFolder.exists()) { + removeLocalFolder(localFolder); + } + } else { + operations.add(ContentProviderOperation.newDelete( + ContentUris.withAppendedId(ProviderTableMeta.CONTENT_URI_FILE, file.getFileId())) + .withSelection(where, whereArgs).build()); + + if (file.isDown()) { + String path = file.getStoragePath(); + if (new File(path).delete()) { + triggerMediaScan(path); // notify MediaScanner about removed file + } + } + } + } + } + + // update metadata of folder + ContentValues cv = createContentValueForFile(folder); + + operations.add(ContentProviderOperation.newUpdate(ProviderTableMeta.CONTENT_URI) + .withValues(cv) + .withSelection(ProviderTableMeta._ID + "=?", new String[]{String.valueOf(folder.getFileId())}) + .build()); + + // apply operations in batch + ContentProviderResult[] results = null; + Log_OC.d(TAG, String.format(Locale.ENGLISH, SENDING_TO_FILECONTENTPROVIDER_MSG, operations.size())); + + try { + if (getContentResolver() != null) { + results = getContentResolver().applyBatch(MainApp.getAuthority(), operations); + + } else { + results = getContentProviderClient().applyBatch(operations); + } + + } catch (OperationApplicationException | RemoteException e) { + Log_OC.e(TAG, EXCEPTION_MSG + e.getMessage(), e); + } + + // update new id in file objects for insertions + if (results != null) { + long newId; + Iterator filesIt = updatedFiles.iterator(); + OCFile file; + for (ContentProviderResult result : results) { + if (filesIt.hasNext()) { + file = filesIt.next(); + } else { + file = null; + } + if (result.uri != null) { + newId = Long.parseLong(result.uri.getPathSegments().get(1)); + //updatedFiles.get(i).setFileId(newId); + if (file != null) { + file.setFileId(newId); + } + } + } + } + } + + private ContentValues createContentValueForFile(OCFile folder) { + 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, 0); + 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()); + cv.put(ProviderTableMeta.FILE_ACCOUNT_OWNER, account.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_ETAG, folder.getEtag()); + cv.put(ProviderTableMeta.FILE_ETAG_ON_SERVER, folder.getEtagOnServer()); + cv.put(ProviderTableMeta.FILE_SHARED_VIA_LINK, folder.isSharedViaLink() ? 1 : 0); + cv.put(ProviderTableMeta.FILE_SHARED_WITH_SHAREE, folder.isSharedWithSharee() ? 1 : 0); + cv.put(ProviderTableMeta.FILE_PUBLIC_LINK, folder.getPublicLink()); + cv.put(ProviderTableMeta.FILE_PERMISSIONS, folder.getPermissions()); + cv.put(ProviderTableMeta.FILE_REMOTE_ID, folder.getRemoteId()); + cv.put(ProviderTableMeta.FILE_FAVORITE, folder.isFavorite()); + cv.put(ProviderTableMeta.FILE_IS_ENCRYPTED, folder.isEncrypted()); + cv.put(ProviderTableMeta.FILE_UNREAD_COMMENTS_COUNT, folder.getUnreadCommentsCount()); + cv.put(ProviderTableMeta.FILE_OWNER_ID, folder.getOwnerId()); + cv.put(ProviderTableMeta.FILE_OWNER_DISPLAY_NAME, folder.getOwnerDisplayName()); + cv.put(ProviderTableMeta.FILE_NOTE, folder.getNote()); + cv.put(ProviderTableMeta.FILE_SHAREES, new Gson().toJson(folder.getSharees())); + + return cv; + } + + private ContentValues createContentValueForFile(OCFile file, OCFile folder) { + ContentValues cv = new ContentValues(); + cv.put(ProviderTableMeta.FILE_MODIFIED, file.getModificationTimestamp()); + cv.put(ProviderTableMeta.FILE_MODIFIED_AT_LAST_SYNC_FOR_DATA, file.getModificationTimestampAtLastSyncForData()); + cv.put(ProviderTableMeta.FILE_CREATION, file.getCreationTimestamp()); + cv.put(ProviderTableMeta.FILE_CONTENT_LENGTH, file.getFileLength()); + cv.put(ProviderTableMeta.FILE_CONTENT_TYPE, file.getMimeType()); + cv.put(ProviderTableMeta.FILE_NAME, file.getFileName()); + cv.put(ProviderTableMeta.FILE_ENCRYPTED_NAME, file.getEncryptedFileName()); + cv.put(ProviderTableMeta.FILE_PARENT, folder.getFileId()); + cv.put(ProviderTableMeta.FILE_PATH, file.getRemotePath()); + if (!file.isFolder()) { + cv.put(ProviderTableMeta.FILE_STORAGE_PATH, file.getStoragePath()); + } + cv.put(ProviderTableMeta.FILE_ACCOUNT_OWNER, account.name); + cv.put(ProviderTableMeta.FILE_LAST_SYNC_DATE, file.getLastSyncDateForProperties()); + cv.put(ProviderTableMeta.FILE_LAST_SYNC_DATE_FOR_DATA, file.getLastSyncDateForData()); + cv.put(ProviderTableMeta.FILE_ETAG, file.getEtag()); + cv.put(ProviderTableMeta.FILE_ETAG_ON_SERVER, file.getEtagOnServer()); + cv.put(ProviderTableMeta.FILE_SHARED_VIA_LINK, file.isSharedViaLink() ? 1 : 0); + cv.put(ProviderTableMeta.FILE_SHARED_WITH_SHAREE, file.isSharedWithSharee() ? 1 : 0); + cv.put(ProviderTableMeta.FILE_PUBLIC_LINK, file.getPublicLink()); + cv.put(ProviderTableMeta.FILE_PERMISSIONS, file.getPermissions()); + cv.put(ProviderTableMeta.FILE_REMOTE_ID, file.getRemoteId()); + cv.put(ProviderTableMeta.FILE_UPDATE_THUMBNAIL, file.isUpdateThumbnailNeeded()); + cv.put(ProviderTableMeta.FILE_IS_DOWNLOADING, file.isDownloading()); + cv.put(ProviderTableMeta.FILE_ETAG_IN_CONFLICT, file.getEtagInConflict()); + cv.put(ProviderTableMeta.FILE_FAVORITE, file.isFavorite()); + cv.put(ProviderTableMeta.FILE_IS_ENCRYPTED, file.isEncrypted()); + cv.put(ProviderTableMeta.FILE_MOUNT_TYPE, file.getMountType().ordinal()); + cv.put(ProviderTableMeta.FILE_HAS_PREVIEW, file.isPreviewAvailable() ? 1 : 0); + cv.put(ProviderTableMeta.FILE_UNREAD_COMMENTS_COUNT, file.getUnreadCommentsCount()); + cv.put(ProviderTableMeta.FILE_OWNER_ID, file.getOwnerId()); + cv.put(ProviderTableMeta.FILE_OWNER_DISPLAY_NAME, file.getOwnerDisplayName()); + cv.put(ProviderTableMeta.FILE_NOTE, file.getNote()); + cv.put(ProviderTableMeta.FILE_SHAREES, new Gson().toJson(file.getSharees())); + + return cv; + } + + + public boolean removeFile(OCFile file, boolean removeDBData, boolean removeLocalCopy) { + boolean success = true; + if (file != null) { + if (file.isFolder()) { + success = 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[]{account.name, file.getRemotePath()}; + int deleted = 0; + if (getContentProviderClient() != null) { + try { + deleted = getContentProviderClient().delete(file_uri, where, whereArgs); + } catch (RemoteException e) { + Log_OC.d(TAG, e.getMessage(), e); + } + } else { + deleted = getContentResolver().delete(file_uri, where, whereArgs); + } + success = deleted > 0; + } + String localPath = file.getStoragePath(); + if (removeLocalCopy && file.isDown() && localPath != null && success) { + success = new File(localPath).delete(); + if (success) { + deleteFileInMediaScan(localPath); + } + if (!removeDBData && success) { + // maybe unnecessary, but should be checked TODO remove if unnecessary + file.setStoragePath(null); + saveFile(file); + saveConflict(file, null); + } + } + } + } else { + return false; + } + + return success; + } + + + public boolean removeFolder(OCFile folder, boolean removeDBData, boolean removeLocalContent) { + boolean success = true; + if (folder != null && folder.isFolder()) { + if (removeDBData && folder.getFileId() != -1) { + success = removeFolderInDb(folder); + } + if (removeLocalContent && success) { + success = removeLocalFolder(folder); + } + } else { + success = false; + } + + return success; + } + + private boolean removeFolderInDb(OCFile folder) { + Uri folder_uri = Uri.withAppendedPath(ProviderTableMeta.CONTENT_URI_DIR, String.valueOf(folder.getFileId())); // URI + // for recursive deletion + String where = ProviderTableMeta.FILE_ACCOUNT_OWNER + AND + ProviderTableMeta.FILE_PATH + "=?"; + String[] whereArgs = new String[]{account.name, folder.getRemotePath()}; + int deleted = 0; + if (getContentProviderClient() != null) { + try { + deleted = getContentProviderClient().delete(folder_uri, where, whereArgs); + } catch (RemoteException e) { + Log_OC.d(TAG, e.getMessage(), e); + } + } else { + deleted = getContentResolver().delete(folder_uri, where, whereArgs); + } + return deleted > 0; + } + + private boolean removeLocalFolder(OCFile folder) { + boolean success = true; + String localFolderPath = FileStorageUtils.getDefaultSavePathFor(account.name, folder); + File localFolder = new File(localFolderPath); + if (localFolder.exists()) { + // stage 1: remove the local files already registered in the files database + List files = getFolderContent(folder.getFileId(), false); + if (files != null) { + for (OCFile file : files) { + if (file.isFolder()) { + success &= removeLocalFolder(file); + } else { + if (file.isDown()) { + File localFile = new File(file.getStoragePath()); + success &= localFile.delete(); + if (success) { + // notify MediaScanner about removed file + deleteFileInMediaScan(file.getStoragePath()); + file.setStoragePath(null); + saveFile(file); + } + } + } + } + } + + // stage 2: remove the folder itself and any local file inside out of sync; + // for instance, after clearing the app cache or reinstalling + success &= removeLocalFolder(localFolder); + } + return success; + } + + private boolean removeLocalFolder(File localFolder) { + boolean success = true; + File[] localFiles = localFolder.listFiles(); + if (localFiles != null) { + for (File localFile : localFiles) { + if (localFile.isDirectory()) { + success &= removeLocalFolder(localFile); + } else { + success &= localFile.delete(); + } + } + } + success &= localFolder.delete(); + return success; + } + + /** + * Updates database and file system for a file or folder that was moved to a different location. + *

+ * TODO explore better (faster) implementations TODO throw exceptions up ! + */ + public void moveLocalFile(OCFile file, String targetPath, String targetParentPath) { + + if (file != null && file.fileExists() && !OCFile.ROOT_PATH.equals(file.getFileName())) { + + OCFile targetParent = getFileByPath(targetParentPath); + if (targetParent == null) { + throw new IllegalStateException("Parent folder of the target path does not exist!!"); + } + + /// 1. get all the descendants of the moved element in a single QUERY + Cursor c = null; + if (getContentProviderClient() != null) { + try { + c = getContentProviderClient().query( + ProviderTableMeta.CONTENT_URI, + null, + ProviderTableMeta.FILE_ACCOUNT_OWNER + AND + ProviderTableMeta.FILE_PATH + " LIKE ? ", + new String[]{account.name, file.getRemotePath() + "%"}, + ProviderTableMeta.FILE_PATH + " ASC " + ); + } catch (RemoteException e) { + Log_OC.e(TAG, e.getMessage(), e); + } + + } else { + c = getContentResolver().query( + ProviderTableMeta.CONTENT_URI, + null, + ProviderTableMeta.FILE_ACCOUNT_OWNER + AND + ProviderTableMeta.FILE_PATH + " LIKE ? ", + new String[]{account.name, file.getRemotePath() + "%"}, + ProviderTableMeta.FILE_PATH + " ASC " + ); + } + + /// 2. prepare a batch of update operations to change all the descendants + ArrayList operations = new ArrayList<>(c.getCount()); + String defaultSavePath = FileStorageUtils.getSavePath(account.name); + List originalPathsToTriggerMediaScan = new ArrayList<>(); + List newPathsToTriggerMediaScan = new ArrayList<>(); + if (c.moveToFirst()) { + int lengthOfOldPath = file.getRemotePath().length(); + int lengthOfOldStoragePath = defaultSavePath.length() + lengthOfOldPath; + String[] fileId = new String[1]; + do { + ContentValues cv = new ContentValues(); // keep construction in the loop + OCFile child = createFileInstance(c); + cv.put( + ProviderTableMeta.FILE_PATH, + targetPath + child.getRemotePath().substring(lengthOfOldPath) + ); + if (child.getStoragePath() != null && child.getStoragePath().startsWith(defaultSavePath)) { + // update link to downloaded content - but local move is not done here! + String targetLocalPath = defaultSavePath + targetPath + + child.getStoragePath().substring(lengthOfOldStoragePath); + + cv.put(ProviderTableMeta.FILE_STORAGE_PATH, targetLocalPath); + + originalPathsToTriggerMediaScan.add(child.getStoragePath()); + newPathsToTriggerMediaScan.add(targetLocalPath); + + } + if (child.getRemotePath().equals(file.getRemotePath())) { + cv.put(ProviderTableMeta.FILE_PARENT, targetParent.getFileId()); + } + fileId[0] = String.valueOf(child.getFileId()); + operations.add( + ContentProviderOperation.newUpdate(ProviderTableMeta.CONTENT_URI). + withValues(cv). + withSelection(ProviderTableMeta._ID + "=?", fileId) + .build()); + + } while (c.moveToNext()); + } + c.close(); + + /// 3. apply updates in batch + try { + if (getContentResolver() != null) { + getContentResolver().applyBatch(MainApp.getAuthority(), operations); + } else { + getContentProviderClient().applyBatch(operations); + } + + } catch (Exception e) { + Log_OC.e(TAG, "Fail to update " + file.getFileId() + " and descendants in database", e); + } + + /// 4. move in local file system + String originalLocalPath = FileStorageUtils.getDefaultSavePathFor(account.name, file); + String targetLocalPath = defaultSavePath + targetPath; + File localFile = new File(originalLocalPath); + boolean renamed = false; + if (localFile.exists()) { + File targetFile = new File(targetLocalPath); + File targetFolder = targetFile.getParentFile(); + if (!targetFolder.exists() && !targetFolder.mkdirs()) { + Log_OC.e(TAG, "Unable to create parent folder " + targetFolder.getAbsolutePath()); + } + renamed = localFile.renameTo(targetFile); + } + + if (renamed) { + Iterator it = originalPathsToTriggerMediaScan.iterator(); + while (it.hasNext()) { + // Notify MediaScanner about removed file + deleteFileInMediaScan(it.next()); + } + it = newPathsToTriggerMediaScan.iterator(); + while (it.hasNext()) { + // Notify MediaScanner about new file/folder + triggerMediaScan(it.next()); + } + } + } + } + + public void copyLocalFile(OCFile file, String targetPath) { + + if (file != null && file.fileExists() && !OCFile.ROOT_PATH.equals(file.getFileName())) { + String localPath = FileStorageUtils.getDefaultSavePathFor(account.name, file); + File localFile = new File(localPath); + boolean copied = false; + String defaultSavePath = FileStorageUtils.getSavePath(account.name); + if (localFile.exists()) { + File targetFile = new File(defaultSavePath + targetPath); + File targetFolder = targetFile.getParentFile(); + if (!targetFolder.exists() && !targetFolder.mkdirs()) { + Log_OC.e(TAG, "Unable to create parent folder " + targetFolder.getAbsolutePath()); + } + copied = FileStorageUtils.copyFile(localFile, targetFile); + } + Log_OC.d(TAG, "Local file COPIED : " + copied); + } + } + + public void migrateStoredFiles(String srcPath, String dstPath) + throws RemoteException, OperationApplicationException { + Cursor cursor; + try { + if (getContentResolver() != null) { + cursor = getContentResolver().query(ProviderTableMeta.CONTENT_URI_FILE, + null, + ProviderTableMeta.FILE_STORAGE_PATH + " IS NOT NULL", + null, + null); + + } else { + cursor = getContentProviderClient().query(ProviderTableMeta.CONTENT_URI_FILE, + new String[]{ProviderTableMeta._ID, ProviderTableMeta.FILE_STORAGE_PATH}, + ProviderTableMeta.FILE_STORAGE_PATH + " IS NOT NULL", + null, + null); + } + } catch (RemoteException e) { + Log_OC.e(TAG, e.getMessage(), e); + throw e; + } + + ArrayList operations = new ArrayList<>(cursor.getCount()); + if (cursor.moveToFirst()) { + String[] fileId = new String[1]; + do { + ContentValues cv = new ContentValues(); + fileId[0] = String.valueOf(cursor.getLong(cursor.getColumnIndex(ProviderTableMeta._ID))); + String oldFileStoragePath = + cursor.getString(cursor.getColumnIndex(ProviderTableMeta.FILE_STORAGE_PATH)); + + if (oldFileStoragePath.startsWith(srcPath)) { + + cv.put(ProviderTableMeta.FILE_STORAGE_PATH, oldFileStoragePath.replaceFirst(srcPath, dstPath)); + + operations.add( + ContentProviderOperation.newUpdate(ProviderTableMeta.CONTENT_URI). + withValues(cv). + withSelection(ProviderTableMeta._ID + "=?", fileId) + .build()); + } + + } while (cursor.moveToNext()); + } + cursor.close(); + + /// 3. apply updates in batch + if (getContentResolver() != null) { + getContentResolver().applyBatch(MainApp.getAuthority(), operations); + } else { + getContentProviderClient().applyBatch(operations); + } + } + + private List getFolderContent(long parentId, boolean onlyOnDevice) { + + List ret = new ArrayList<>(); + + Uri req_uri = Uri.withAppendedPath(ProviderTableMeta.CONTENT_URI_DIR, String.valueOf(parentId)); + Cursor c; + + if (getContentProviderClient() != null) { + try { + c = getContentProviderClient().query( + req_uri, + null, + ProviderTableMeta.FILE_PARENT + "=?", + new String[]{String.valueOf(parentId)}, + null + ); + } catch (RemoteException e) { + Log_OC.e(TAG, e.getMessage(), e); + return ret; + } + } else { + c = getContentResolver().query( + req_uri, + null, + ProviderTableMeta.FILE_PARENT + "=?", + new String[]{String.valueOf(parentId)}, + null + ); + } + + if (c != null) { + if (c.moveToFirst()) { + do { + OCFile child = createFileInstance(c); + if (!onlyOnDevice || child.existsOnDevice()) { + ret.add(child); + } + } while (c.moveToNext()); + } + + c.close(); + } + + return ret; + } + + + private OCFile createRootDir() { + OCFile file = new OCFile(OCFile.ROOT_PATH); + file.setMimeType(MimeType.DIRECTORY); + file.setParentId(FileDataStorageManager.ROOT_PARENT_ID); + saveFile(file); + return file; + } + + private boolean fileExists(String cmp_key, String value) { + Cursor c; + if (getContentResolver() != null) { + c = getContentResolver() + .query(ProviderTableMeta.CONTENT_URI, + null, + cmp_key + AND + + ProviderTableMeta.FILE_ACCOUNT_OWNER + + "=?", + new String[]{value, account.name}, null); + } else { + try { + c = getContentProviderClient().query( + ProviderTableMeta.CONTENT_URI, + null, + cmp_key + AND + + ProviderTableMeta.FILE_ACCOUNT_OWNER + "=?", + new String[]{value, account.name}, null); + } catch (RemoteException e) { + Log_OC.e(TAG, "Couldn't determine file existance, assuming non existance: " + e.getMessage(), e); + return false; + } + } + boolean retval = c.moveToFirst(); + c.close(); + return retval; + } + + private Cursor getFileCursorForValue(String key, String value) { + Cursor c; + if (getContentResolver() != null) { + c = getContentResolver() + .query(ProviderTableMeta.CONTENT_URI, + null, + key + AND + + ProviderTableMeta.FILE_ACCOUNT_OWNER + + "=?", + new String[]{value, account.name}, null); + } else { + try { + c = getContentProviderClient().query( + ProviderTableMeta.CONTENT_URI, + null, + key + AND + ProviderTableMeta.FILE_ACCOUNT_OWNER + + "=?", new String[]{value, account.name}, + null); + } catch (RemoteException e) { + Log_OC.e(TAG, "Could not get file details: " + e.getMessage(), e); + c = null; + } + } + return c; + } + + @Nullable + private OCFile createFileInstanceFromVirtual(Cursor c) { + OCFile file = null; + if (c != null) { + long fileId = c.getLong(c.getColumnIndex(ProviderTableMeta.VIRTUAL_OCFILE_ID)); + file = getFileById(fileId); + } + + return file; + } + + private OCFile createFileInstance(Cursor c) { + OCFile file = null; + if (c != null) { + file = new OCFile(c.getString(c.getColumnIndex(ProviderTableMeta.FILE_PATH))); + file.setFileId(c.getLong(c.getColumnIndex(ProviderTableMeta._ID))); + file.setParentId(c.getLong(c.getColumnIndex(ProviderTableMeta.FILE_PARENT))); + file.setEncryptedFileName(c.getString(c.getColumnIndex(ProviderTableMeta.FILE_ENCRYPTED_NAME))); + file.setMimeType(c.getString(c.getColumnIndex(ProviderTableMeta.FILE_CONTENT_TYPE))); + file.setStoragePath(c.getString(c.getColumnIndex(ProviderTableMeta.FILE_STORAGE_PATH))); + if (file.getStoragePath() == null) { + // try to find existing file and bind it with current account; + // with the current update of SynchronizeFolderOperation, this won't be + // necessary anymore after a full synchronization of the account + File f = new File(FileStorageUtils.getDefaultSavePathFor(account.name, file)); + if (f.exists()) { + file.setStoragePath(f.getAbsolutePath()); + file.setLastSyncDateForData(f.lastModified()); + } + } + file.setFileLength(c.getLong(c.getColumnIndex(ProviderTableMeta.FILE_CONTENT_LENGTH))); + file.setCreationTimestamp(c.getLong(c.getColumnIndex(ProviderTableMeta.FILE_CREATION))); + file.setModificationTimestamp(c.getLong(c.getColumnIndex(ProviderTableMeta.FILE_MODIFIED))); + file.setModificationTimestampAtLastSyncForData(c.getLong( + c.getColumnIndex(ProviderTableMeta.FILE_MODIFIED_AT_LAST_SYNC_FOR_DATA))); + file.setLastSyncDateForProperties(c.getLong(c.getColumnIndex(ProviderTableMeta.FILE_LAST_SYNC_DATE))); + file.setLastSyncDateForData(c.getLong(c.getColumnIndex(ProviderTableMeta.FILE_LAST_SYNC_DATE_FOR_DATA))); + file.setEtag(c.getString(c.getColumnIndex(ProviderTableMeta.FILE_ETAG))); + file.setEtagOnServer(c.getString(c.getColumnIndex(ProviderTableMeta.FILE_ETAG_ON_SERVER))); + file.setSharedViaLink(c.getInt(c.getColumnIndex(ProviderTableMeta.FILE_SHARED_VIA_LINK)) == 1); + file.setSharedWithSharee(c.getInt(c.getColumnIndex(ProviderTableMeta.FILE_SHARED_WITH_SHAREE)) == 1); + file.setPublicLink(c.getString(c.getColumnIndex(ProviderTableMeta.FILE_PUBLIC_LINK))); + file.setPermissions(c.getString(c.getColumnIndex(ProviderTableMeta.FILE_PERMISSIONS))); + file.setRemoteId(c.getString(c.getColumnIndex(ProviderTableMeta.FILE_REMOTE_ID))); + file.setUpdateThumbnailNeeded(c.getInt(c.getColumnIndex(ProviderTableMeta.FILE_UPDATE_THUMBNAIL)) == 1); + file.setDownloading(c.getInt(c.getColumnIndex(ProviderTableMeta.FILE_IS_DOWNLOADING)) == 1); + file.setEtagInConflict(c.getString(c.getColumnIndex(ProviderTableMeta.FILE_ETAG_IN_CONFLICT))); + file.setFavorite(c.getInt(c.getColumnIndex(ProviderTableMeta.FILE_FAVORITE)) == 1); + file.setEncrypted(c.getInt(c.getColumnIndex(ProviderTableMeta.FILE_IS_ENCRYPTED)) == 1); + if (file.isEncrypted()) { + file.setFileName(c.getString(c.getColumnIndex(ProviderTableMeta.FILE_NAME))); + } + file.setMountType(WebdavEntry.MountType.values()[c.getInt( + c.getColumnIndex(ProviderTableMeta.FILE_MOUNT_TYPE))]); + file.setPreviewAvailable(c.getInt(c.getColumnIndex(ProviderTableMeta.FILE_HAS_PREVIEW)) == 1); + file.setUnreadCommentsCount(c.getInt(c.getColumnIndex(ProviderTableMeta.FILE_UNREAD_COMMENTS_COUNT))); + file.setOwnerId(c.getString(c.getColumnIndex(ProviderTableMeta.FILE_OWNER_ID))); + file.setOwnerDisplayName(c.getString(c.getColumnIndex(ProviderTableMeta.FILE_OWNER_DISPLAY_NAME))); + file.setNote(c.getString(c.getColumnIndex(ProviderTableMeta.FILE_NOTE))); + + String sharees = c.getString(c.getColumnIndex(ProviderTableMeta.FILE_SHAREES)); + + if (sharees == null || NULL_STRING.equals(sharees) || sharees.isEmpty()) { + file.setSharees(new ArrayList<>()); + } else { + try { + ShareeUser[] shareesArray = new Gson().fromJson(sharees, ShareeUser[].class); + + file.setSharees(new ArrayList<>(Arrays.asList(shareesArray))); + } catch (JsonSyntaxException e) { + // ignore saved value due to api change + file.setSharees(new ArrayList<>()); + } + } + } + + return file; + } + + // Methods for Shares + public boolean saveShare(OCShare share) { + boolean overridden = false; + ContentValues cv = new ContentValues(); + cv.put(ProviderTableMeta.OCSHARES_FILE_SOURCE, share.getFileSource()); + cv.put(ProviderTableMeta.OCSHARES_ITEM_SOURCE, share.getItemSource()); + cv.put(ProviderTableMeta.OCSHARES_SHARE_TYPE, share.getShareType().getValue()); + cv.put(ProviderTableMeta.OCSHARES_SHARE_WITH, share.getShareWith()); + cv.put(ProviderTableMeta.OCSHARES_PATH, share.getPath()); + cv.put(ProviderTableMeta.OCSHARES_PERMISSIONS, share.getPermissions()); + cv.put(ProviderTableMeta.OCSHARES_SHARED_DATE, share.getSharedDate()); + cv.put(ProviderTableMeta.OCSHARES_EXPIRATION_DATE, share.getExpirationDate()); + cv.put(ProviderTableMeta.OCSHARES_TOKEN, share.getToken()); + cv.put(ProviderTableMeta.OCSHARES_SHARE_WITH_DISPLAY_NAME, share.getSharedWithDisplayName()); + cv.put(ProviderTableMeta.OCSHARES_IS_DIRECTORY, share.isFolder() ? 1 : 0); + cv.put(ProviderTableMeta.OCSHARES_USER_ID, share.getUserId()); + cv.put(ProviderTableMeta.OCSHARES_ID_REMOTE_SHARED, share.getRemoteId()); + cv.put(ProviderTableMeta.OCSHARES_ACCOUNT_OWNER, account.name); + cv.put(ProviderTableMeta.OCSHARES_IS_PASSWORD_PROTECTED, share.isPasswordProtected() ? 1 : 0); + cv.put(ProviderTableMeta.OCSHARES_NOTE, share.getNote()); + cv.put(ProviderTableMeta.OCSHARES_HIDE_DOWNLOAD, share.isHideFileDownload()); + + if (shareExistsForRemoteId(share.getRemoteId())) {// for renamed files; no more delete and create + overridden = true; + if (getContentResolver() != null) { + getContentResolver().update(ProviderTableMeta.CONTENT_URI_SHARE, cv, + ProviderTableMeta.OCSHARES_ID_REMOTE_SHARED + "=?", + new String[]{String.valueOf(share.getRemoteId())}); + } else { + try { + getContentProviderClient().update(ProviderTableMeta.CONTENT_URI_SHARE, + cv, ProviderTableMeta.OCSHARES_ID_REMOTE_SHARED + "=?", + new String[]{String.valueOf(share.getRemoteId())}); + } catch (RemoteException e) { + Log_OC.e(TAG, FAILED_TO_INSERT_MSG + e.getMessage(), e); + } + } + } else { + Uri result_uri = null; + if (getContentResolver() != null) { + result_uri = getContentResolver().insert(ProviderTableMeta.CONTENT_URI_SHARE, cv); + } else { + try { + result_uri = getContentProviderClient().insert(ProviderTableMeta.CONTENT_URI_SHARE, cv); + } catch (RemoteException e) { + Log_OC.e(TAG, FAILED_TO_INSERT_MSG + e.getMessage(), e); + } + } + if (result_uri != null) { + long new_id = Long.parseLong(result_uri.getPathSegments().get(1)); + share.setId(new_id); + } + } + + return overridden; + } + + /** + * Retrieves an stored {@link OCShare} given its id. + * + * @param id Identifier. + * @return Stored {@link OCShare} given its id. + */ + public OCShare getShareById(long id) { + OCShare share = null; + Cursor c = getShareCursorForValue(ProviderTableMeta._ID, String.valueOf(id)); + if (c != null) { + if (c.moveToFirst()) { + share = createShareInstance(c); + } + c.close(); + } + return share; + } + + + /** + * Checks the existance of an stored {@link OCShare} matching the given remote id (not to be confused with the local + * id) in the current account. + * + * @param remoteId Remote of the share in the server. + * @return 'True' if a matching {@link OCShare} is stored in the current account. + */ + private boolean shareExistsForRemoteId(long remoteId) { + return shareExistsForValue(ProviderTableMeta.OCSHARES_ID_REMOTE_SHARED, String.valueOf(remoteId)); + } + + + /** + * Checks the existance of an stored {@link OCShare} in the current account matching a given column and a value for + * that column + * + * @param key Name of the column to match. + * @param value Value of the column to match. + * @return 'True' if a matching {@link OCShare} is stored in the current account. + */ + private boolean shareExistsForValue(String key, String value) { + Cursor c = getShareCursorForValue(key, value); + boolean retval = c.moveToFirst(); + c.close(); + return retval; + } + + + /** + * Gets a {@link Cursor} for an stored {@link OCShare} in the current account matching a given column and a value + * for that column + * + * @param key Name of the column to match. + * @param value Value of the column to match. + * @return 'True' if a matching {@link OCShare} is stored in the current account. + */ + private Cursor getShareCursorForValue(String key, String value) { + Cursor c; + if (getContentResolver() != null) { + c = getContentResolver() + .query(ProviderTableMeta.CONTENT_URI_SHARE, + null, + key + AND + + ProviderTableMeta.OCSHARES_ACCOUNT_OWNER + "=?", + new String[]{value, account.name}, + null + ); + } else { + try { + c = getContentProviderClient().query( + ProviderTableMeta.CONTENT_URI_SHARE, + null, + key + AND + ProviderTableMeta.OCSHARES_ACCOUNT_OWNER + "=?", + new String[]{value, account.name}, + null + ); + } catch (RemoteException e) { + Log_OC.w(TAG, "Could not get details, assuming share does not exist: " + e.getMessage()); + c = null; + } + } + return c; + } + + + /** + * Get first share bound to a file with a known path and given {@link ShareType}. + * + * @param path Path of the file. + * @param type Type of the share to get + * @param shareWith Target of the share. Ignored in type is {@link ShareType#PUBLIC_LINK} + * @return First {@link OCShare} instance found in DB bound to the file in 'path' + */ + public OCShare getFirstShareByPathAndType(String path, ShareType type, String shareWith) { + Cursor cursor; + if (shareWith == null) { + shareWith = ""; + } + + String selection = ProviderTableMeta.OCSHARES_PATH + AND + + ProviderTableMeta.OCSHARES_SHARE_TYPE + AND + + ProviderTableMeta.OCSHARES_ACCOUNT_OWNER + "=?"; + if (!ShareType.PUBLIC_LINK.equals(type)) { + selection += " AND " + ProviderTableMeta.OCSHARES_SHARE_WITH + "=?"; + } + + String[] selectionArgs; + if (ShareType.PUBLIC_LINK.equals(type)) { + selectionArgs = new String[]{ + path, + Integer.toString(type.getValue()), + account.name + }; + } else { + selectionArgs = new String[]{ + path, + Integer.toString(type.getValue()), + account.name, + shareWith + }; + } + + if (getContentResolver() != null) { + cursor = getContentResolver().query( + ProviderTableMeta.CONTENT_URI_SHARE, + null, + selection, selectionArgs, + null); + } else { + try { + cursor = getContentProviderClient().query( + ProviderTableMeta.CONTENT_URI_SHARE, + null, + selection, selectionArgs, + null); + + } catch (RemoteException e) { + Log_OC.e(TAG, "Could not get file details: " + e.getMessage(), e); + cursor = null; + } + } + + OCShare share = null; + if (cursor != null) { + if (cursor.moveToFirst()) { + share = createShareInstance(cursor); + } + cursor.close(); + } + return share; + } + + private OCShare createShareInstance(Cursor c) { + OCShare share = null; + if (c != null) { + share = new OCShare(c.getString(c.getColumnIndex(ProviderTableMeta.OCSHARES_PATH))); + share.setId(c.getLong(c.getColumnIndex(ProviderTableMeta._ID))); + share.setFileSource(c.getLong(c.getColumnIndex(ProviderTableMeta.OCSHARES_ITEM_SOURCE))); + share.setShareType(ShareType.fromValue(c.getInt(c.getColumnIndex(ProviderTableMeta.OCSHARES_SHARE_TYPE)))); + share.setShareWith(c.getString(c.getColumnIndex(ProviderTableMeta.OCSHARES_SHARE_WITH))); + share.setPermissions(c.getInt(c.getColumnIndex(ProviderTableMeta.OCSHARES_PERMISSIONS))); + share.setSharedDate(c.getLong(c.getColumnIndex(ProviderTableMeta.OCSHARES_SHARED_DATE))); + share.setExpirationDate(c.getLong(c.getColumnIndex(ProviderTableMeta.OCSHARES_EXPIRATION_DATE))); + share.setToken(c.getString(c.getColumnIndex(ProviderTableMeta.OCSHARES_TOKEN))); + share.setSharedWithDisplayName( + c.getString(c.getColumnIndex(ProviderTableMeta.OCSHARES_SHARE_WITH_DISPLAY_NAME))); + share.setFolder(c.getInt(c.getColumnIndex(ProviderTableMeta.OCSHARES_IS_DIRECTORY)) == 1); + share.setUserId(c.getString(c.getColumnIndex(ProviderTableMeta.OCSHARES_USER_ID))); + share.setRemoteId(c.getLong(c.getColumnIndex(ProviderTableMeta.OCSHARES_ID_REMOTE_SHARED))); + share.setPasswordProtected(c.getInt(c.getColumnIndex(ProviderTableMeta.OCSHARES_IS_PASSWORD_PROTECTED)) == 1); + share.setNote(c.getString(c.getColumnIndex(ProviderTableMeta.OCSHARES_NOTE))); + share.setHideFileDownload(c.getInt(c.getColumnIndex(ProviderTableMeta.OCSHARES_HIDE_DOWNLOAD)) == 1); + } + return share; + } + + private void resetShareFlagsInAllFiles() { + ContentValues cv = new ContentValues(); + cv.put(ProviderTableMeta.FILE_SHARED_VIA_LINK, Boolean.FALSE); + cv.put(ProviderTableMeta.FILE_SHARED_WITH_SHAREE, Boolean.FALSE); + cv.put(ProviderTableMeta.FILE_PUBLIC_LINK, ""); + String where = ProviderTableMeta.FILE_ACCOUNT_OWNER + "=?"; + String[] whereArgs = new String[]{account.name}; + + if (getContentResolver() != null) { + getContentResolver().update(ProviderTableMeta.CONTENT_URI, cv, where, whereArgs); + + } else { + try { + getContentProviderClient().update(ProviderTableMeta.CONTENT_URI, cv, where, whereArgs); + } catch (RemoteException e) { + Log_OC.e(TAG, "Exception in resetShareFlagsInAllFiles" + e.getMessage(), e); + } + } + } + + private void resetShareFlagsInFolder(OCFile folder) { + ContentValues cv = new ContentValues(); + cv.put(ProviderTableMeta.FILE_SHARED_VIA_LINK, Boolean.FALSE); + cv.put(ProviderTableMeta.FILE_SHARED_WITH_SHAREE, Boolean.FALSE); + cv.put(ProviderTableMeta.FILE_PUBLIC_LINK, ""); + String where = ProviderTableMeta.FILE_ACCOUNT_OWNER + AND + ProviderTableMeta.FILE_PARENT + "=?"; + String[] whereArgs = new String[]{account.name, String.valueOf(folder.getFileId())}; + + if (getContentResolver() != null) { + getContentResolver().update(ProviderTableMeta.CONTENT_URI, cv, where, whereArgs); + + } else { + try { + getContentProviderClient().update(ProviderTableMeta.CONTENT_URI, cv, where, whereArgs); + } catch (RemoteException e) { + Log_OC.e(TAG, "Exception in resetShareFlagsInFolder " + e.getMessage(), e); + } + } + } + + private void resetShareFlagInAFile(String filePath) { + ContentValues cv = new ContentValues(); + cv.put(ProviderTableMeta.FILE_SHARED_VIA_LINK, Boolean.FALSE); + cv.put(ProviderTableMeta.FILE_SHARED_WITH_SHAREE, Boolean.FALSE); + cv.put(ProviderTableMeta.FILE_PUBLIC_LINK, ""); + String where = ProviderTableMeta.FILE_ACCOUNT_OWNER + AND + ProviderTableMeta.FILE_PATH + "=?"; + String[] whereArgs = new String[]{account.name, filePath}; + + if (getContentResolver() != null) { + getContentResolver().update(ProviderTableMeta.CONTENT_URI, cv, where, whereArgs); + + } else { + try { + getContentProviderClient().update(ProviderTableMeta.CONTENT_URI, cv, where, whereArgs); + } catch (RemoteException e) { + Log_OC.e(TAG, "Exception in resetShareFlagsInFolder " + e.getMessage(), e); + } + } + } + + private void cleanShares() { + String where = ProviderTableMeta.OCSHARES_ACCOUNT_OWNER + "=?"; + String[] whereArgs = new String[]{account.name}; + + if (getContentResolver() != null) { + getContentResolver().delete(ProviderTableMeta.CONTENT_URI_SHARE, where, whereArgs); + + } else { + try { + getContentProviderClient().delete(ProviderTableMeta.CONTENT_URI_SHARE, where, whereArgs); + } catch (RemoteException e) { + Log_OC.e(TAG, "Exception in cleanShares" + e.getMessage(), e); + } + } + } + + public void saveShares(Collection shares) { + cleanShares(); + if (shares != null) { + ArrayList operations = + new ArrayList(shares.size()); + + // prepare operations to insert or update files to save in the given folder + for (OCShare share : shares) { + ContentValues cv = new ContentValues(); + cv.put(ProviderTableMeta.OCSHARES_FILE_SOURCE, share.getFileSource()); + cv.put(ProviderTableMeta.OCSHARES_ITEM_SOURCE, share.getItemSource()); + cv.put(ProviderTableMeta.OCSHARES_SHARE_TYPE, share.getShareType().getValue()); + cv.put(ProviderTableMeta.OCSHARES_SHARE_WITH, share.getShareWith()); + cv.put(ProviderTableMeta.OCSHARES_PATH, share.getPath()); + cv.put(ProviderTableMeta.OCSHARES_PERMISSIONS, share.getPermissions()); + cv.put(ProviderTableMeta.OCSHARES_SHARED_DATE, share.getSharedDate()); + cv.put(ProviderTableMeta.OCSHARES_EXPIRATION_DATE, share.getExpirationDate()); + cv.put(ProviderTableMeta.OCSHARES_TOKEN, share.getToken()); + cv.put(ProviderTableMeta.OCSHARES_SHARE_WITH_DISPLAY_NAME, share.getSharedWithDisplayName()); + cv.put(ProviderTableMeta.OCSHARES_IS_DIRECTORY, share.isFolder() ? 1 : 0); + cv.put(ProviderTableMeta.OCSHARES_USER_ID, share.getUserId()); + cv.put(ProviderTableMeta.OCSHARES_ID_REMOTE_SHARED, share.getRemoteId()); + cv.put(ProviderTableMeta.OCSHARES_ACCOUNT_OWNER, account.name); + cv.put(ProviderTableMeta.OCSHARES_IS_PASSWORD_PROTECTED, share.isPasswordProtected() ? 1 : 0); + cv.put(ProviderTableMeta.OCSHARES_NOTE, share.getNote()); + cv.put(ProviderTableMeta.OCSHARES_HIDE_DOWNLOAD, share.isHideFileDownload()); + + if (shareExistsForRemoteId(share.getRemoteId())) { + // updating an existing file + operations.add( + ContentProviderOperation.newUpdate(ProviderTableMeta.CONTENT_URI_SHARE). + withValues(cv). + withSelection(ProviderTableMeta.OCSHARES_ID_REMOTE_SHARED + "=?", + new String[]{String.valueOf(share.getRemoteId())}) + .build()); + } else { + // adding a new file + operations.add( + ContentProviderOperation.newInsert(ProviderTableMeta.CONTENT_URI_SHARE). + withValues(cv). + build() + ); + } + } + + // apply operations in batch + if (operations.size() > 0) { + @SuppressWarnings("unused") + ContentProviderResult[] results = null; + Log_OC.d(TAG, String.format(Locale.ENGLISH, SENDING_TO_FILECONTENTPROVIDER_MSG, operations.size())); + try { + if (getContentResolver() != null) { + results = getContentResolver().applyBatch(MainApp.getAuthority(), + operations); + } else { + results = getContentProviderClient().applyBatch(operations); + } + + } catch (OperationApplicationException | RemoteException e) { + Log_OC.e(TAG, EXCEPTION_MSG + e.getMessage(), e); + } + } + } + + } + + public void updateSharedFiles(Collection sharedFiles) { + resetShareFlagsInAllFiles(); + + if (sharedFiles != null) { + ArrayList operations = new ArrayList<>(sharedFiles.size()); + + // prepare operations to insert or update files to save in the given folder + for (OCFile file : sharedFiles) { + ContentValues cv = new ContentValues(); + cv.put(ProviderTableMeta.FILE_MODIFIED, file.getModificationTimestamp()); + cv.put( + ProviderTableMeta.FILE_MODIFIED_AT_LAST_SYNC_FOR_DATA, + file.getModificationTimestampAtLastSyncForData() + ); + cv.put(ProviderTableMeta.FILE_CREATION, file.getCreationTimestamp()); + cv.put(ProviderTableMeta.FILE_CONTENT_LENGTH, file.getFileLength()); + cv.put(ProviderTableMeta.FILE_CONTENT_TYPE, file.getMimeType()); + cv.put(ProviderTableMeta.FILE_NAME, file.getFileName()); + cv.put(ProviderTableMeta.FILE_PARENT, file.getParentId()); + cv.put(ProviderTableMeta.FILE_PATH, file.getRemotePath()); + if (!file.isFolder()) { + cv.put(ProviderTableMeta.FILE_STORAGE_PATH, file.getStoragePath()); + } + cv.put(ProviderTableMeta.FILE_ACCOUNT_OWNER, account.name); + cv.put(ProviderTableMeta.FILE_LAST_SYNC_DATE, file.getLastSyncDateForProperties()); + cv.put( + ProviderTableMeta.FILE_LAST_SYNC_DATE_FOR_DATA, + file.getLastSyncDateForData() + ); + cv.put(ProviderTableMeta.FILE_ETAG, file.getEtag()); + cv.put(ProviderTableMeta.FILE_ETAG_ON_SERVER, file.getEtagOnServer()); + cv.put(ProviderTableMeta.FILE_SHARED_VIA_LINK, file.isSharedViaLink() ? 1 : 0); + cv.put(ProviderTableMeta.FILE_SHARED_WITH_SHAREE, file.isSharedWithSharee() ? 1 : 0); + cv.put(ProviderTableMeta.FILE_PUBLIC_LINK, file.getPublicLink()); + cv.put(ProviderTableMeta.FILE_PERMISSIONS, file.getPermissions()); + cv.put(ProviderTableMeta.FILE_REMOTE_ID, file.getRemoteId()); + cv.put(ProviderTableMeta.FILE_FAVORITE, file.isFavorite()); + cv.put(ProviderTableMeta.FILE_UPDATE_THUMBNAIL, file.isUpdateThumbnailNeeded() ? 1 : 0); + cv.put(ProviderTableMeta.FILE_IS_DOWNLOADING, file.isDownloading() ? 1 : 0); + cv.put(ProviderTableMeta.FILE_ETAG_IN_CONFLICT, file.getEtagInConflict()); + + boolean existsByPath = fileExists(file.getRemotePath()); + if (existsByPath || fileExists(file.getFileId())) { + // updating an existing file + operations.add( + ContentProviderOperation.newUpdate(ProviderTableMeta.CONTENT_URI). + withValues(cv). + withSelection(ProviderTableMeta._ID + "=?", + new String[]{String.valueOf(file.getFileId())}) + .build()); + + } else { + // adding a new file + operations.add( + ContentProviderOperation.newInsert(ProviderTableMeta.CONTENT_URI). + withValues(cv). + build() + ); + } + } + + // apply operations in batch + if (operations.size() > 0) { + @SuppressWarnings("unused") + ContentProviderResult[] results = null; + Log_OC.d(TAG, String.format(Locale.ENGLISH, SENDING_TO_FILECONTENTPROVIDER_MSG, operations.size())); + try { + if (getContentResolver() != null) { + results = getContentResolver().applyBatch(MainApp.getAuthority(), operations); + } else { + results = getContentProviderClient().applyBatch(operations); + } + + } catch (OperationApplicationException | RemoteException e) { + Log_OC.e(TAG, EXCEPTION_MSG + e.getMessage(), e); + } + } + } + + } + + public void removeShare(OCShare share) { + Uri share_uri = ProviderTableMeta.CONTENT_URI_SHARE; + String where = ProviderTableMeta.OCSHARES_ACCOUNT_OWNER + AND + + ProviderTableMeta._ID + "=?"; + String[] whereArgs = new String[]{account.name, Long.toString(share.getId())}; + if (getContentProviderClient() != null) { + try { + getContentProviderClient().delete(share_uri, where, whereArgs); + } catch (RemoteException e) { + Log_OC.d(TAG, e.getMessage(), e); + } + } else { + getContentResolver().delete(share_uri, where, whereArgs); + } + } + + public void saveSharesDB(List shares) { + ArrayList operations = new ArrayList<>(); + + // Reset flags & Remove shares for this files + String filePath = ""; + for (OCShare share : shares) { + if (!filePath.equals(share.getPath())) { + filePath = share.getPath(); + resetShareFlagInAFile(filePath); + operations = prepareRemoveSharesInFile(filePath, operations); + } + } + + // Add operations to insert shares + operations = prepareInsertShares(shares, operations); + + // apply operations in batch + if (operations.size() > 0) { + Log_OC.d(TAG, String.format(Locale.ENGLISH, SENDING_TO_FILECONTENTPROVIDER_MSG, operations.size())); + try { + if (getContentResolver() != null) { + getContentResolver().applyBatch(MainApp.getAuthority(), operations); + + } else { + getContentProviderClient().applyBatch(operations); + } + + } catch (OperationApplicationException | RemoteException e) { + Log_OC.e(TAG, EXCEPTION_MSG + e.getMessage(), e); + } + } + +// // TODO: review if it is needed +// // Update shared files +// ArrayList sharedFiles = new ArrayList(); +// +// for (OCShare share : shares) { +// // Get the path +// String path = share.getPath(); +// if (share.isFolder()) { +// path = path + FileUtils.PATH_SEPARATOR; +// } +// +// // Update OCFile with data from share: ShareByLink, publicLink and +// OCFile file = getFileByPath(path); +// if (file != null) { +// if (share.getShareType().equals(ShareType.PUBLIC_LINK)) { +// file.setShareViaLink(true); +// sharedFiles.add(file); +// } +// } +// } +// +// // TODO: Review +// updateSharedFiles(sharedFiles); + } + + public void removeSharesForFile(String remotePath) { + resetShareFlagInAFile(remotePath); + ArrayList operations = new ArrayList<>(); + operations = prepareRemoveSharesInFile(remotePath, operations); + // apply operations in batch + if (operations.size() > 0) { + Log_OC.d(TAG, String.format(Locale.ENGLISH, SENDING_TO_FILECONTENTPROVIDER_MSG, operations.size())); + try { + if (getContentResolver() != null) { + getContentResolver().applyBatch(MainApp.getAuthority(), operations); + + } else { + getContentProviderClient().applyBatch(operations); + } + + } catch (OperationApplicationException | RemoteException e) { + Log_OC.e(TAG, EXCEPTION_MSG + e.getMessage(), e); + } + } + } + + + public void saveSharesInFolder(ArrayList shares, OCFile folder) { + resetShareFlagsInFolder(folder); + ArrayList operations = new ArrayList<>(); + operations = prepareRemoveSharesInFolder(folder, operations); + + if (shares != null) { + // prepare operations to insert or update files to save in the given folder + operations = prepareInsertShares(shares, operations); + } + + // apply operations in batch + if (operations.size() > 0) { + Log_OC.d(TAG, String.format(Locale.ENGLISH, SENDING_TO_FILECONTENTPROVIDER_MSG, operations.size())); + try { + if (getContentResolver() != null) { + getContentResolver().applyBatch(MainApp.getAuthority(), operations); + + } else { + + getContentProviderClient().applyBatch(operations); + } + + } catch (OperationApplicationException | RemoteException e) { + Log_OC.e(TAG, EXCEPTION_MSG + e.getMessage(), e); + } + } + + } + + /** + * Prepare operations to insert or update files to save in the given folder + * + * @param shares List of shares to insert + * @param operations List of operations + * @return + */ + private ArrayList prepareInsertShares( + List shares, ArrayList operations) { + + if (shares != null) { + ContentValues cv; + // prepare operations to insert or update files to save in the given folder + for (OCShare share : shares) { + cv = new ContentValues(); + cv.put(ProviderTableMeta.OCSHARES_FILE_SOURCE, share.getFileSource()); + cv.put(ProviderTableMeta.OCSHARES_ITEM_SOURCE, share.getItemSource()); + cv.put(ProviderTableMeta.OCSHARES_SHARE_TYPE, share.getShareType().getValue()); + cv.put(ProviderTableMeta.OCSHARES_SHARE_WITH, share.getShareWith()); + cv.put(ProviderTableMeta.OCSHARES_PATH, share.getPath()); + cv.put(ProviderTableMeta.OCSHARES_PERMISSIONS, share.getPermissions()); + cv.put(ProviderTableMeta.OCSHARES_SHARED_DATE, share.getSharedDate()); + cv.put(ProviderTableMeta.OCSHARES_EXPIRATION_DATE, share.getExpirationDate()); + cv.put(ProviderTableMeta.OCSHARES_TOKEN, share.getToken()); + cv.put(ProviderTableMeta.OCSHARES_SHARE_WITH_DISPLAY_NAME, share.getSharedWithDisplayName()); + cv.put(ProviderTableMeta.OCSHARES_IS_DIRECTORY, share.isFolder() ? 1 : 0); + cv.put(ProviderTableMeta.OCSHARES_USER_ID, share.getUserId()); + cv.put(ProviderTableMeta.OCSHARES_ID_REMOTE_SHARED, share.getRemoteId()); + cv.put(ProviderTableMeta.OCSHARES_ACCOUNT_OWNER, account.name); + cv.put(ProviderTableMeta.OCSHARES_IS_PASSWORD_PROTECTED, share.isPasswordProtected() ? 1 : 0); + cv.put(ProviderTableMeta.OCSHARES_NOTE, share.getNote()); + cv.put(ProviderTableMeta.OCSHARES_HIDE_DOWNLOAD, share.isHideFileDownload()); + + // adding a new share resource + operations.add(ContentProviderOperation.newInsert( + ProviderTableMeta.CONTENT_URI_SHARE).withValues(cv).build()); + } + } + return operations; + } + + private ArrayList prepareRemoveSharesInFolder( + OCFile folder, ArrayList preparedOperations) { + if (folder != null) { + String where = ProviderTableMeta.OCSHARES_PATH + AND + + ProviderTableMeta.OCSHARES_ACCOUNT_OWNER + "=?"; + String[] whereArgs = new String[]{"", account.name}; + + List files = getFolderContent(folder, false); + + for (OCFile file : files) { + whereArgs[0] = file.getRemotePath(); + preparedOperations.add( + ContentProviderOperation.newDelete(ProviderTableMeta.CONTENT_URI_SHARE). + withSelection(where, whereArgs). + build() + ); + } + } + return preparedOperations; + + } + + private ArrayList prepareRemoveSharesInFile( + String filePath, ArrayList preparedOperations) { + + String where = ProviderTableMeta.OCSHARES_PATH + AND + + ProviderTableMeta.OCSHARES_ACCOUNT_OWNER + "=?"; + String[] whereArgs = new String[]{filePath, account.name}; + + preparedOperations.add( + ContentProviderOperation.newDelete(ProviderTableMeta.CONTENT_URI_SHARE). + withSelection(where, whereArgs). + build() + ); + + return preparedOperations; + + } + + public List getSharesWithForAFile(String filePath, String accountName) { + // Condition + String where = ProviderTableMeta.OCSHARES_PATH + AND + + ProviderTableMeta.OCSHARES_ACCOUNT_OWNER + AND + + " (" + ProviderTableMeta.OCSHARES_SHARE_TYPE + "=? OR " + + ProviderTableMeta.OCSHARES_SHARE_TYPE + "=? OR " + + ProviderTableMeta.OCSHARES_SHARE_TYPE + "=? OR " + + ProviderTableMeta.OCSHARES_SHARE_TYPE + "=? OR " + + ProviderTableMeta.OCSHARES_SHARE_TYPE + "=? ) "; + String[] whereArgs = new String[]{filePath, accountName, + Integer.toString(ShareType.USER.getValue()), + Integer.toString(ShareType.GROUP.getValue()), + Integer.toString(ShareType.EMAIL.getValue()), + Integer.toString(ShareType.FEDERATED.getValue()), + Integer.toString(ShareType.ROOM.getValue())}; + + Cursor cursor = null; + if (getContentResolver() != null) { + cursor = getContentResolver().query(ProviderTableMeta.CONTENT_URI_SHARE, null, where, whereArgs, null); + } else { + try { + cursor = getContentProviderClient().query(ProviderTableMeta.CONTENT_URI_SHARE, null, where, + whereArgs, null); + + } catch (RemoteException e) { + Log_OC.e(TAG, "Could not get list of shares with: " + e.getMessage(), e); + cursor = null; + } + } + ArrayList shares = new ArrayList<>(); + OCShare share; + if (cursor != null) { + if (cursor.moveToFirst()) { + do { + share = createShareInstance(cursor); + shares.add(share); + } while (cursor.moveToNext()); + } + + cursor.close(); + } + + return shares; + } + + public void triggerMediaScan(String path) { + if (path != null) { + Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE); + intent.setData(Uri.fromFile(new File(path))); + context.sendBroadcast(intent); + } + } + + public void deleteFileInMediaScan(String path) { + + String mimetypeString = FileStorageUtils.getMimeTypeFromName(path); + ContentResolver contentResolver = getContentResolver(); + + if (contentResolver != null) { + if (MimeTypeUtil.isImage(mimetypeString)) { + // Images + contentResolver.delete(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, + MediaStore.Images.Media.DATA + "=?", new String[]{path}); + } else if (MimeTypeUtil.isAudio(mimetypeString)) { + // Audio + contentResolver.delete(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, + MediaStore.Audio.Media.DATA + "=?", new String[]{path}); + } else if (MimeTypeUtil.isVideo(mimetypeString)) { + // Video + contentResolver.delete(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, + MediaStore.Video.Media.DATA + "=?", new String[]{path}); + } + } else { + ContentProviderClient contentProviderClient = getContentProviderClient(); + try { + if (MimeTypeUtil.isImage(mimetypeString)) { + // Images + contentProviderClient.delete(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, + MediaStore.Images.Media.DATA + "=?", new String[]{path}); + } else if (MimeTypeUtil.isAudio(mimetypeString)) { + // Audio + contentProviderClient.delete(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, + MediaStore.Audio.Media.DATA + "=?", new String[]{path}); + } else if (MimeTypeUtil.isVideo(mimetypeString)) { + // Video + contentProviderClient.delete(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, + MediaStore.Video.Media.DATA + "=?", new String[]{path}); + } + } catch (RemoteException e) { + Log_OC.e(TAG, "Exception deleting media file in MediaStore " + e.getMessage(), e); + } + } + } + + public void saveConflict(OCFile file, String etagInConflict) { + if (!file.isDown()) { + etagInConflict = null; + } + ContentValues cv = new ContentValues(); + cv.put(ProviderTableMeta.FILE_ETAG_IN_CONFLICT, etagInConflict); + int updated = 0; + if (getContentResolver() != null) { + updated = getContentResolver().update( + ProviderTableMeta.CONTENT_URI_FILE, + cv, + ProviderTableMeta._ID + "=?", + new String[]{String.valueOf(file.getFileId())} + ); + } else { + try { + updated = getContentProviderClient().update( + ProviderTableMeta.CONTENT_URI_FILE, + cv, + ProviderTableMeta._ID + "=?", + new String[]{String.valueOf(file.getFileId())} + ); + } catch (RemoteException e) { + Log_OC.e(TAG, "Failed saving conflict in database " + e.getMessage(), e); + } + } + + Log_OC.d(TAG, "Number of files updated with CONFLICT: " + updated); + + if (updated > 0) { + if (etagInConflict != null) { + /// set conflict in all ancestor folders + + long parentId = file.getParentId(); + Set ancestorIds = new HashSet<>(); + while (parentId != FileDataStorageManager.ROOT_PARENT_ID) { + ancestorIds.add(Long.toString(parentId)); + parentId = getFileById(parentId).getParentId(); + } + + if (ancestorIds.size() > 0) { + final StringBuffer whereBuffer = new StringBuffer(); + whereBuffer.append(ProviderTableMeta._ID).append(" IN ("); + for (int i = 0; i < ancestorIds.size() - 1; i++) { + whereBuffer.append("?,"); + } + whereBuffer.append("?)"); + + if (getContentResolver() != null) { + updated = getContentResolver().update( + ProviderTableMeta.CONTENT_URI_FILE, + cv, + whereBuffer.toString(), + ancestorIds.toArray(new String[]{}) + ); + } else { + try { + updated = getContentProviderClient().update( + ProviderTableMeta.CONTENT_URI_FILE, + cv, + whereBuffer.toString(), + ancestorIds.toArray(new String[]{}) + ); + } catch (RemoteException e) { + Log_OC.e(TAG, "Failed saving conflict in database " + e.getMessage(), e); + } + } + } // else file is ROOT folder, no parent to set in conflict + + } else { + /// update conflict in ancestor folders + // (not directly unset; maybe there are more conflicts below them) + String parentPath = file.getRemotePath(); + if (parentPath.endsWith(OCFile.PATH_SEPARATOR)) { + parentPath = parentPath.substring(0, parentPath.length() - 1); + } + parentPath = parentPath.substring(0, parentPath.lastIndexOf(OCFile.PATH_SEPARATOR) + 1); + + Log_OC.d(TAG, "checking parents to remove conflict; STARTING with " + parentPath); + String[] projection = new String[]{ProviderTableMeta._ID}; + while (parentPath.length() > 0) { + + String whereForDescencentsInConflict = + ProviderTableMeta.FILE_ETAG_IN_CONFLICT + " IS NOT NULL AND " + + ProviderTableMeta.FILE_CONTENT_TYPE + " != 'DIR' AND " + + ProviderTableMeta.FILE_ACCOUNT_OWNER + AND + + ProviderTableMeta.FILE_PATH + " LIKE ?"; + Cursor descendentsInConflict = null; + if (getContentResolver() != null) { + descendentsInConflict = getContentResolver().query( + ProviderTableMeta.CONTENT_URI_FILE, + projection, + whereForDescencentsInConflict, + new String[]{account.name, parentPath + "%"}, + null + ); + } else { + try { + descendentsInConflict = getContentProviderClient().query( + ProviderTableMeta.CONTENT_URI_FILE, + projection, + whereForDescencentsInConflict, + new String[]{account.name, parentPath + "%"}, + null + ); + } catch (RemoteException e) { + Log_OC.e(TAG, "Failed querying for descendents in conflict " + e.getMessage(), e); + } + } + if (descendentsInConflict == null || descendentsInConflict.getCount() == 0) { + Log_OC.d(TAG, "NO MORE conflicts in " + parentPath); + if (getContentResolver() != null) { + updated = getContentResolver().update( + ProviderTableMeta.CONTENT_URI_FILE, + cv, + ProviderTableMeta.FILE_ACCOUNT_OWNER + AND + + ProviderTableMeta.FILE_PATH + "=?", + new String[]{account.name, parentPath} + ); + } else { + try { + updated = getContentProviderClient().update( + ProviderTableMeta.CONTENT_URI_FILE, + cv, + ProviderTableMeta.FILE_ACCOUNT_OWNER + AND + + ProviderTableMeta.FILE_PATH + "=?" + , new String[]{account.name, parentPath} + ); + } catch (RemoteException e) { + Log_OC.e(TAG, "Failed saving conflict in database " + e.getMessage(), e); + } + } + + } else { + Log_OC.d(TAG, "STILL " + descendentsInConflict.getCount() + " in " + parentPath); + } + + if (descendentsInConflict != null) { + descendentsInConflict.close(); + } + + parentPath = parentPath.substring(0, parentPath.length() - 1); // trim last / + parentPath = parentPath.substring(0, parentPath.lastIndexOf(OCFile.PATH_SEPARATOR) + 1); + Log_OC.d(TAG, "checking parents to remove conflict; NEXT " + parentPath); + } + } + } + + } + + public OCCapability saveCapabilities(OCCapability capability) { + + // Prepare capabilities data + ContentValues cv = createContentValues(account.name, capability); + + if (capabilityExists(account.name)) { + if (getContentResolver() != null) { + getContentResolver().update(ProviderTableMeta.CONTENT_URI_CAPABILITIES, cv, + ProviderTableMeta.CAPABILITIES_ACCOUNT_NAME + "=?", + new String[]{account.name}); + } else { + try { + getContentProviderClient().update(ProviderTableMeta.CONTENT_URI_CAPABILITIES, + cv, ProviderTableMeta.CAPABILITIES_ACCOUNT_NAME + "=?", + new String[]{account.name}); + } catch (RemoteException e) { + Log_OC.e(TAG, FAILED_TO_INSERT_MSG + e.getMessage(), e); + } + } + } else { + Uri result_uri = null; + if (getContentResolver() != null) { + result_uri = getContentResolver().insert( + ProviderTableMeta.CONTENT_URI_CAPABILITIES, cv); + } else { + try { + result_uri = getContentProviderClient().insert( + ProviderTableMeta.CONTENT_URI_CAPABILITIES, cv); + } catch (RemoteException e) { + Log_OC.e(TAG, FAILED_TO_INSERT_MSG + e.getMessage(), e); + } + } + if (result_uri != null) { + long new_id = Long.parseLong(result_uri.getPathSegments() + .get(1)); + capability.setId(new_id); + capability.setAccountName(account.name); + } + } + + return capability; + } + + @NonNull + private ContentValues createContentValues(String accountName, OCCapability capability) { + ContentValues cv = new ContentValues(); + cv.put(ProviderTableMeta.CAPABILITIES_ACCOUNT_NAME, accountName); + cv.put(ProviderTableMeta.CAPABILITIES_VERSION_MAYOR, capability.getVersionMayor()); + cv.put(ProviderTableMeta.CAPABILITIES_VERSION_MINOR, capability.getVersionMinor()); + cv.put(ProviderTableMeta.CAPABILITIES_VERSION_MICRO, capability.getVersionMicro()); + cv.put(ProviderTableMeta.CAPABILITIES_VERSION_STRING, capability.getVersionString()); + cv.put(ProviderTableMeta.CAPABILITIES_VERSION_EDITION, capability.getVersionEdition()); + cv.put(ProviderTableMeta.CAPABILITIES_EXTENDED_SUPPORT, capability.getExtendedSupport().getValue()); + cv.put(ProviderTableMeta.CAPABILITIES_CORE_POLLINTERVAL, capability.getCorePollInterval()); + cv.put(ProviderTableMeta.CAPABILITIES_SHARING_API_ENABLED, capability.getFilesSharingApiEnabled().getValue()); + cv.put(ProviderTableMeta.CAPABILITIES_SHARING_PUBLIC_ENABLED, + capability.getFilesSharingPublicEnabled().getValue()); + cv.put(ProviderTableMeta.CAPABILITIES_SHARING_PUBLIC_PASSWORD_ENFORCED, + capability.getFilesSharingPublicPasswordEnforced().getValue()); + cv.put(ProviderTableMeta.CAPABILITIES_SHARING_PUBLIC_ASK_FOR_OPTIONAL_PASSWORD, + capability.getFilesSharingPublicAskForOptionalPassword().getValue()); + cv.put(ProviderTableMeta.CAPABILITIES_SHARING_PUBLIC_EXPIRE_DATE_ENABLED, + capability.getFilesSharingPublicExpireDateEnabled().getValue()); + cv.put(ProviderTableMeta.CAPABILITIES_SHARING_PUBLIC_EXPIRE_DATE_DAYS, + capability.getFilesSharingPublicExpireDateDays()); + cv.put(ProviderTableMeta.CAPABILITIES_SHARING_PUBLIC_EXPIRE_DATE_ENFORCED, + capability.getFilesSharingPublicExpireDateEnforced().getValue()); + cv.put(ProviderTableMeta.CAPABILITIES_SHARING_PUBLIC_SEND_MAIL, + capability.getFilesSharingPublicSendMail().getValue()); + cv.put(ProviderTableMeta.CAPABILITIES_SHARING_PUBLIC_UPLOAD, + capability.getFilesSharingPublicUpload().getValue()); + cv.put(ProviderTableMeta.CAPABILITIES_SHARING_USER_SEND_MAIL, + capability.getFilesSharingUserSendMail().getValue()); + cv.put(ProviderTableMeta.CAPABILITIES_SHARING_RESHARING, capability.getFilesSharingResharing().getValue()); + cv.put(ProviderTableMeta.CAPABILITIES_SHARING_FEDERATION_OUTGOING, + capability.getFilesSharingFederationOutgoing().getValue()); + cv.put(ProviderTableMeta.CAPABILITIES_SHARING_FEDERATION_INCOMING, + capability.getFilesSharingFederationIncoming().getValue()); + cv.put(ProviderTableMeta.CAPABILITIES_FILES_BIGFILECHUNKING, capability.getFilesBigFileChunking().getValue()); + cv.put(ProviderTableMeta.CAPABILITIES_FILES_UNDELETE, capability.getFilesUndelete().getValue()); + cv.put(ProviderTableMeta.CAPABILITIES_FILES_VERSIONING, capability.getFilesVersioning().getValue()); + cv.put(ProviderTableMeta.CAPABILITIES_FILES_DROP, capability.getFilesFileDrop().getValue()); + cv.put(ProviderTableMeta.CAPABILITIES_EXTERNAL_LINKS, capability.getExternalLinks().getValue()); + cv.put(ProviderTableMeta.CAPABILITIES_SERVER_NAME, capability.getServerName()); + cv.put(ProviderTableMeta.CAPABILITIES_SERVER_COLOR, capability.getServerColor()); + cv.put(ProviderTableMeta.CAPABILITIES_SERVER_TEXT_COLOR, capability.getServerTextColor()); + cv.put(ProviderTableMeta.CAPABILITIES_SERVER_ELEMENT_COLOR, capability.getServerElementColor()); + cv.put(ProviderTableMeta.CAPABILITIES_SERVER_BACKGROUND_URL, capability.getServerBackground()); + cv.put(ProviderTableMeta.CAPABILITIES_SERVER_SLOGAN, capability.getServerSlogan()); + cv.put(ProviderTableMeta.CAPABILITIES_END_TO_END_ENCRYPTION, capability.getEndToEndEncryption().getValue()); + cv.put(ProviderTableMeta.CAPABILITIES_SERVER_BACKGROUND_DEFAULT, capability.getServerBackgroundDefault() + .getValue()); + cv.put(ProviderTableMeta.CAPABILITIES_SERVER_BACKGROUND_PLAIN, capability.getServerBackgroundPlain() + .getValue()); + cv.put(ProviderTableMeta.CAPABILITIES_ACTIVITY, capability.getActivity().getValue()); + cv.put(ProviderTableMeta.CAPABILITIES_RICHDOCUMENT, capability.getRichDocuments().getValue()); + cv.put(ProviderTableMeta.CAPABILITIES_RICHDOCUMENT_MIMETYPE_LIST, + TextUtils.join(",", capability.getRichDocumentsMimeTypeList())); + cv.put(ProviderTableMeta.CAPABILITIES_RICHDOCUMENT_OPTIONAL_MIMETYPE_LIST, + TextUtils.join(",", capability.getRichDocumentsOptionalMimeTypeList())); + cv.put(ProviderTableMeta.CAPABILITIES_RICHDOCUMENT_DIRECT_EDITING, capability.getRichDocumentsDirectEditing() + .getValue()); + cv.put(ProviderTableMeta.CAPABILITIES_RICHDOCUMENT_TEMPLATES, capability.getRichDocumentsTemplatesAvailable() + .getValue()); + cv.put(ProviderTableMeta.CAPABILITIES_RICHDOCUMENT_PRODUCT_NAME, capability.getRichDocumentsProductName()); + return cv; + } + + private boolean capabilityExists(String accountName) { + Cursor c = getCapabilityCursorForAccount(accountName); + boolean exists = false; + if (c != null) { + exists = c.moveToFirst(); + c.close(); + } + return exists; + } + + private Cursor getCapabilityCursorForAccount(String accountName) { + Cursor c = null; + if (getContentResolver() != null) { + c = getContentResolver() + .query(ProviderTableMeta.CONTENT_URI_CAPABILITIES, + null, + ProviderTableMeta.CAPABILITIES_ACCOUNT_NAME + "=? ", + new String[]{accountName}, null); + } else { + try { + c = getContentProviderClient().query( + ProviderTableMeta.CONTENT_URI_CAPABILITIES, + null, + ProviderTableMeta.CAPABILITIES_ACCOUNT_NAME + "=? ", + new String[]{accountName}, null); + } catch (RemoteException e) { + Log_OC.e(TAG, "Couldn't determine capability existence, assuming non existance: " + e.getMessage(), e); + } + } + + return c; + } + + @NonNull + public OCCapability getCapability(String accountName) { + OCCapability capability; + Cursor c = getCapabilityCursorForAccount(accountName); + + if (c.moveToFirst()) { + capability = createCapabilityInstance(c); + } else { + capability = new OCCapability(); // return default with all UNKNOWN + } + c.close(); + return capability; + } + + private OCCapability createCapabilityInstance(Cursor c) { + OCCapability capability = null; + if (c != null) { + capability = new OCCapability(); + capability.setId(c.getLong(c.getColumnIndex(ProviderTableMeta._ID))); + capability.setAccountName(c.getString(c + .getColumnIndex(ProviderTableMeta.CAPABILITIES_ACCOUNT_NAME))); + capability.setVersionMayor(c.getInt(c + .getColumnIndex(ProviderTableMeta.CAPABILITIES_VERSION_MAYOR))); + capability.setVersionMinor(c.getInt(c + .getColumnIndex(ProviderTableMeta.CAPABILITIES_VERSION_MINOR))); + capability.setVersionMicro(c.getInt(c + .getColumnIndex(ProviderTableMeta.CAPABILITIES_VERSION_MICRO))); + capability.setVersionString(c.getString(c + .getColumnIndex(ProviderTableMeta.CAPABILITIES_VERSION_STRING))); + capability.setVersionEdition(c.getString(c + .getColumnIndex(ProviderTableMeta.CAPABILITIES_VERSION_EDITION))); + capability.setExtendedSupport(CapabilityBooleanType.fromValue(c.getInt(c + .getColumnIndex(ProviderTableMeta.CAPABILITIES_EXTENDED_SUPPORT)))); + capability.setCorePollInterval(c.getInt(c + .getColumnIndex(ProviderTableMeta.CAPABILITIES_CORE_POLLINTERVAL))); + capability.setFilesSharingApiEnabled(CapabilityBooleanType.fromValue(c.getInt(c + .getColumnIndex(ProviderTableMeta.CAPABILITIES_SHARING_API_ENABLED)))); + capability.setFilesSharingPublicEnabled(CapabilityBooleanType.fromValue(c.getInt(c + .getColumnIndex(ProviderTableMeta.CAPABILITIES_SHARING_PUBLIC_ENABLED)))); + capability.setFilesSharingPublicPasswordEnforced(CapabilityBooleanType.fromValue(c.getInt(c + .getColumnIndex(ProviderTableMeta.CAPABILITIES_SHARING_PUBLIC_PASSWORD_ENFORCED)))); + capability.setFilesSharingPublicAskForOptionalPassword( + CapabilityBooleanType.fromValue( + c.getInt(c.getColumnIndex(ProviderTableMeta.CAPABILITIES_SHARING_PUBLIC_ASK_FOR_OPTIONAL_PASSWORD)))); + capability.setFilesSharingPublicExpireDateEnabled(CapabilityBooleanType.fromValue(c.getInt(c + .getColumnIndex(ProviderTableMeta.CAPABILITIES_SHARING_PUBLIC_EXPIRE_DATE_ENABLED)))); + capability.setFilesSharingPublicExpireDateDays(c.getInt(c + .getColumnIndex(ProviderTableMeta.CAPABILITIES_SHARING_PUBLIC_EXPIRE_DATE_DAYS))); + capability.setFilesSharingPublicExpireDateEnforced(CapabilityBooleanType.fromValue(c.getInt(c + .getColumnIndex(ProviderTableMeta.CAPABILITIES_SHARING_PUBLIC_EXPIRE_DATE_ENFORCED)))); + capability.setFilesSharingPublicSendMail(CapabilityBooleanType.fromValue(c.getInt(c + .getColumnIndex(ProviderTableMeta.CAPABILITIES_SHARING_PUBLIC_SEND_MAIL)))); + capability.setFilesSharingPublicUpload(CapabilityBooleanType.fromValue(c.getInt(c + .getColumnIndex(ProviderTableMeta.CAPABILITIES_SHARING_PUBLIC_UPLOAD)))); + capability.setFilesSharingUserSendMail(CapabilityBooleanType.fromValue(c.getInt(c + .getColumnIndex(ProviderTableMeta.CAPABILITIES_SHARING_USER_SEND_MAIL)))); + capability.setFilesSharingResharing(CapabilityBooleanType.fromValue(c.getInt(c + .getColumnIndex(ProviderTableMeta.CAPABILITIES_SHARING_RESHARING)))); + capability.setFilesSharingFederationOutgoing(CapabilityBooleanType.fromValue(c.getInt(c + .getColumnIndex(ProviderTableMeta.CAPABILITIES_SHARING_FEDERATION_OUTGOING)))); + capability.setFilesSharingFederationIncoming(CapabilityBooleanType.fromValue(c.getInt(c + .getColumnIndex(ProviderTableMeta.CAPABILITIES_SHARING_FEDERATION_INCOMING)))); + capability.setFilesBigFileChunking(CapabilityBooleanType.fromValue(c.getInt(c + .getColumnIndex(ProviderTableMeta.CAPABILITIES_FILES_BIGFILECHUNKING)))); + capability.setFilesUndelete(CapabilityBooleanType.fromValue(c.getInt(c + .getColumnIndex(ProviderTableMeta.CAPABILITIES_FILES_UNDELETE)))); + capability.setFilesVersioning(CapabilityBooleanType.fromValue(c.getInt(c + .getColumnIndex(ProviderTableMeta.CAPABILITIES_FILES_VERSIONING)))); + capability.setFilesFileDrop(CapabilityBooleanType.fromValue(c.getInt(c + .getColumnIndex(ProviderTableMeta.CAPABILITIES_FILES_DROP)))); + capability.setExternalLinks(CapabilityBooleanType.fromValue(c.getInt(c + .getColumnIndex(ProviderTableMeta.CAPABILITIES_EXTERNAL_LINKS)))); + capability.setServerName(c.getString(c.getColumnIndex(ProviderTableMeta.CAPABILITIES_SERVER_NAME))); + capability.setServerColor(c.getString(c.getColumnIndex(ProviderTableMeta.CAPABILITIES_SERVER_COLOR))); + capability.setServerTextColor( + c.getString(c.getColumnIndex(ProviderTableMeta.CAPABILITIES_SERVER_TEXT_COLOR))); + capability.setServerElementColor( + c.getString(c.getColumnIndex(ProviderTableMeta.CAPABILITIES_SERVER_ELEMENT_COLOR))); + capability.setServerBackground(c.getString(c.getColumnIndex( + ProviderTableMeta.CAPABILITIES_SERVER_BACKGROUND_URL))); + capability.setServerSlogan(c.getString(c.getColumnIndex(ProviderTableMeta.CAPABILITIES_SERVER_SLOGAN))); + capability.setEndToEndEncryption(CapabilityBooleanType.fromValue(c.getInt(c + .getColumnIndex(ProviderTableMeta.CAPABILITIES_END_TO_END_ENCRYPTION)))); + capability.setServerBackgroundDefault(CapabilityBooleanType.fromValue( + c.getInt(c.getColumnIndex(ProviderTableMeta.CAPABILITIES_SERVER_BACKGROUND_DEFAULT)))); + capability.setServerBackgroundPlain(CapabilityBooleanType.fromValue( + c.getInt(c.getColumnIndex(ProviderTableMeta.CAPABILITIES_SERVER_BACKGROUND_PLAIN)))); + capability.setActivity(CapabilityBooleanType.fromValue( + c.getInt(c.getColumnIndex(ProviderTableMeta.CAPABILITIES_ACTIVITY)))); + capability.setRichDocuments(CapabilityBooleanType.fromValue(c.getInt( + c.getColumnIndex(ProviderTableMeta.CAPABILITIES_RICHDOCUMENT)))); + capability.setRichDocumentsDirectEditing(CapabilityBooleanType.fromValue(c.getInt( + c.getColumnIndex(ProviderTableMeta.CAPABILITIES_RICHDOCUMENT_DIRECT_EDITING)))); + capability.setRichDocumentsTemplatesAvailable(CapabilityBooleanType.fromValue(c.getInt( + c.getColumnIndex(ProviderTableMeta.CAPABILITIES_RICHDOCUMENT_TEMPLATES)))); + String mimetypes = c.getString(c.getColumnIndex(ProviderTableMeta.CAPABILITIES_RICHDOCUMENT_MIMETYPE_LIST)); + if (mimetypes == null) { + mimetypes = ""; + } + capability.setRichDocumentsMimeTypeList(Arrays.asList(mimetypes.split(","))); + + String optionalMimetypes = c.getString(c.getColumnIndex( + ProviderTableMeta.CAPABILITIES_RICHDOCUMENT_OPTIONAL_MIMETYPE_LIST)); + if (optionalMimetypes == null) { + optionalMimetypes = ""; + } + capability.setRichDocumentsOptionalMimeTypeList(Arrays.asList(optionalMimetypes.split(","))); + capability.setRichDocumentsProductName( + c.getString(c.getColumnIndex(ProviderTableMeta.CAPABILITIES_RICHDOCUMENT_PRODUCT_NAME))); + } + return capability; + } + + public void deleteVirtuals(VirtualFolderType type) { + if (getContentResolver() != null) { + getContentResolver().delete(ProviderTableMeta.CONTENT_URI_VIRTUAL, + ProviderTableMeta.VIRTUAL_TYPE + "=?", new String[]{String.valueOf(type)}); + } else { + try { + getContentProviderClient().delete(ProviderTableMeta.CONTENT_URI_VIRTUAL, + ProviderTableMeta.VIRTUAL_TYPE + "=?", new String[]{String.valueOf(type)}); + } catch (RemoteException e) { + Log_OC.e(TAG, FAILED_TO_INSERT_MSG + e.getMessage(), e); + } + } + } + + public void saveVirtuals(VirtualFolderType type, List values) { + + if (getContentResolver() != null) { + getContentResolver().bulkInsert(ProviderTableMeta.CONTENT_URI_VIRTUAL, values.toArray(new ContentValues[0])); + } else { + try { + getContentProviderClient().bulkInsert(ProviderTableMeta.CONTENT_URI_VIRTUAL, values.toArray(new ContentValues[0])); + } catch (RemoteException e) { + Log_OC.e(TAG, FAILED_TO_INSERT_MSG + e.getMessage(), e); + } + } + } + + public void saveVirtual(VirtualFolderType type, OCFile file) { + ContentValues cv = new ContentValues(); + cv.put(ProviderTableMeta.VIRTUAL_TYPE, type.toString()); + cv.put(ProviderTableMeta.VIRTUAL_OCFILE_ID, file.getFileId()); + + if (getContentResolver() != null) { + getContentResolver().insert(ProviderTableMeta.CONTENT_URI_VIRTUAL, cv); + } else { + try { + getContentProviderClient().insert(ProviderTableMeta.CONTENT_URI_VIRTUAL, cv); + } catch (RemoteException e) { + Log_OC.e(TAG, FAILED_TO_INSERT_MSG + e.getMessage(), e); + } + } + } + + public List getVirtualFolderContent(VirtualFolderType type, boolean onlyImages) { + List ocFiles = new ArrayList<>(); + Uri req_uri = ProviderTableMeta.CONTENT_URI_VIRTUAL; + Cursor c; + + if (getContentProviderClient() != null) { + try { + c = getContentProviderClient().query( + req_uri, + null, + ProviderTableMeta.VIRTUAL_TYPE + "=?", + new String[]{String.valueOf(type)}, + null + ); + } catch (RemoteException e) { + Log_OC.e(TAG, e.getMessage(), e); + return ocFiles; + } + } else { + c = getContentResolver().query( + req_uri, + null, + ProviderTableMeta.VIRTUAL_TYPE + "=?", + new String[]{String.valueOf(type)}, + null + ); + } + + if (c != null) { + if (c.moveToFirst()) { + do { + OCFile child = createFileInstanceFromVirtual(c); + + if (child != null) { + ocFiles.add(child); + } + } while (c.moveToNext()); + } + c.close(); + } + + if (onlyImages) { + List temp = new ArrayList<>(); + + for (OCFile file : ocFiles) { + if (MimeTypeUtil.isImage(file)) { + temp.add(file); + } + } + ocFiles = temp; + } + + if (ocFiles.size() > 0) { + Collections.sort(ocFiles); + } + + return ocFiles; + } + + public void deleteAllFiles() { + String where = ProviderTableMeta.FILE_ACCOUNT_OWNER + "= ? AND " + + ProviderTableMeta.FILE_PATH + "= ?"; + String[] whereArgs = new String[]{account.name, OCFile.ROOT_PATH}; + + if (getContentResolver() != null) { + getContentResolver().delete(ProviderTableMeta.CONTENT_URI_DIR, where, whereArgs); + } else { + try { + getContentProviderClient().delete(ProviderTableMeta.CONTENT_URI_DIR, where, whereArgs); + } catch (RemoteException e) { + Log_OC.e(TAG, "Exception in deleteAllFiles for account " + account.name + ": " + e.getMessage(), e); + } + } + } + +} diff --git a/src/main/java/com/owncloud/android/datamodel/ThumbnailsCacheManager.java b/src/main/java/com/owncloud/android/datamodel/ThumbnailsCacheManager.java index 5db9a2960596..caaa6c87ebf4 100644 --- a/src/main/java/com/owncloud/android/datamodel/ThumbnailsCacheManager.java +++ b/src/main/java/com/owncloud/android/datamodel/ThumbnailsCacheManager.java @@ -433,7 +433,7 @@ public GetMethod getGetMethod() { return getMethod; } - public ThumbnailGenerationTask(FileDataStorageManager storageManager, Account account){ + public ThumbnailGenerationTask(FileDataStorageManager storageManager, Account account) { if (storageManager == null) { throw new IllegalArgumentException("storageManager must not be NULL"); } diff --git a/src/main/java/com/owncloud/android/files/services/FileDownloader.java b/src/main/java/com/owncloud/android/files/services/FileDownloader.java index 9b23473e1c93..cba63732a08b 100644 --- a/src/main/java/com/owncloud/android/files/services/FileDownloader.java +++ b/src/main/java/com/owncloud/android/files/services/FileDownloader.java @@ -42,6 +42,7 @@ import com.owncloud.android.R; import com.owncloud.android.authentication.AuthenticatorActivity; import com.owncloud.android.datamodel.FileDataStorageManager; +import com.owncloud.android.datamodel.FileDataStorageManagerImpl; import com.owncloud.android.datamodel.OCFile; import com.owncloud.android.lib.common.OwnCloudAccount; import com.owncloud.android.lib.common.OwnCloudClient; @@ -439,10 +440,7 @@ private void downloadFile(String downloadKey) { if (mCurrentAccount == null || !mCurrentAccount.equals(mCurrentDownload.getAccount())) { mCurrentAccount = mCurrentDownload.getAccount(); - mStorageManager = new FileDataStorageManager( - mCurrentAccount, - getContentResolver() - ); + mStorageManager = new FileDataStorageManagerImpl(mCurrentAccount, getBaseContext()); } // else, reuse storage manager from previous operation // always get client from client manager, to get fresh credentials in case @@ -506,7 +504,7 @@ private void saveDownloadedFile() { file.setRemoteId(mCurrentDownload.getFile().getRemoteId()); mStorageManager.saveFile(file); if (MimeTypeUtil.isMedia(mCurrentDownload.getMimeType())) { - FileDataStorageManager.triggerMediaScan(file.getStoragePath()); + mStorageManager.triggerMediaScan(file.getStoragePath()); } mStorageManager.saveConflict(file, null); } diff --git a/src/main/java/com/owncloud/android/files/services/FileUploader.java b/src/main/java/com/owncloud/android/files/services/FileUploader.java index 81cdb81ed350..739bb0483063 100644 --- a/src/main/java/com/owncloud/android/files/services/FileUploader.java +++ b/src/main/java/com/owncloud/android/files/services/FileUploader.java @@ -55,6 +55,7 @@ import com.owncloud.android.R; import com.owncloud.android.authentication.AuthenticatorActivity; import com.owncloud.android.datamodel.FileDataStorageManager; +import com.owncloud.android.datamodel.FileDataStorageManagerImpl; import com.owncloud.android.datamodel.OCFile; import com.owncloud.android.datamodel.ThumbnailsCacheManager; import com.owncloud.android.datamodel.UploadsStorageManager; @@ -1082,10 +1083,7 @@ public void uploadFile(String uploadKey) { /// prepare client object to send the request to the ownCloud server if (mCurrentAccount == null || !mCurrentAccount.equals(mCurrentUpload.getAccount())) { mCurrentAccount = mCurrentUpload.getAccount(); - mStorageManager = new FileDataStorageManager( - mCurrentAccount, - getContentResolver() - ); + mStorageManager = new FileDataStorageManagerImpl(mCurrentAccount, getBaseContext()); } // else, reuse storage manager from previous operation // always get client from client manager, to get fresh credentials in case of update diff --git a/src/main/java/com/owncloud/android/jobs/AccountRemovalJob.java b/src/main/java/com/owncloud/android/jobs/AccountRemovalJob.java index ab1816122dcc..dcf4d12706ba 100644 --- a/src/main/java/com/owncloud/android/jobs/AccountRemovalJob.java +++ b/src/main/java/com/owncloud/android/jobs/AccountRemovalJob.java @@ -44,6 +44,7 @@ import com.owncloud.android.R; import com.owncloud.android.datamodel.ArbitraryDataProvider; import com.owncloud.android.datamodel.FileDataStorageManager; +import com.owncloud.android.datamodel.FileDataStorageManagerImpl; import com.owncloud.android.datamodel.FilesystemDataProvider; import com.owncloud.android.datamodel.PushConfigurationState; import com.owncloud.android.datamodel.SyncedFolder; @@ -107,7 +108,7 @@ protected Result onRunJob(@NonNull Params params) { removeAccount(account, accountManager); - FileDataStorageManager storageManager = new FileDataStorageManager(account, context.getContentResolver()); + FileDataStorageManager storageManager = new FileDataStorageManagerImpl(account, context); // remove all files removeFiles(account, storageManager); diff --git a/src/main/java/com/owncloud/android/jobs/ContactsBackupJob.java b/src/main/java/com/owncloud/android/jobs/ContactsBackupJob.java index 36a5a1fd89cc..c220395812e6 100644 --- a/src/main/java/com/owncloud/android/jobs/ContactsBackupJob.java +++ b/src/main/java/com/owncloud/android/jobs/ContactsBackupJob.java @@ -37,6 +37,7 @@ import com.owncloud.android.R; import com.owncloud.android.datamodel.ArbitraryDataProvider; import com.owncloud.android.datamodel.FileDataStorageManager; +import com.owncloud.android.datamodel.FileDataStorageManagerImpl; import com.owncloud.android.datamodel.OCFile; import com.owncloud.android.files.services.FileUploader; import com.owncloud.android.lib.common.utils.Log_OC; @@ -175,7 +176,7 @@ private void backupContact(Account account, String backupFolder) { private void expireFiles(Integer daysToExpire, String backupFolderString, Account account) { // -1 disables expiration if (daysToExpire > -1) { - FileDataStorageManager storageManager = new FileDataStorageManager(account, getContext().getContentResolver()); + FileDataStorageManager storageManager = new FileDataStorageManagerImpl(account, getContext()); OCFile backupFolder = storageManager.getFileByPath(backupFolderString); Calendar cal = Calendar.getInstance(); cal.add(Calendar.DAY_OF_YEAR, -daysToExpire); diff --git a/src/main/java/com/owncloud/android/jobs/OfflineSyncJob.java b/src/main/java/com/owncloud/android/jobs/OfflineSyncJob.java index 6030fad70d3d..5cf7e0285eef 100644 --- a/src/main/java/com/owncloud/android/jobs/OfflineSyncJob.java +++ b/src/main/java/com/owncloud/android/jobs/OfflineSyncJob.java @@ -34,6 +34,7 @@ import com.nextcloud.client.network.ConnectivityService; import com.owncloud.android.MainApp; import com.owncloud.android.datamodel.FileDataStorageManager; +import com.owncloud.android.datamodel.FileDataStorageManagerImpl; import com.owncloud.android.datamodel.OCFile; import com.owncloud.android.lib.common.operations.RemoteOperationResult; import com.owncloud.android.lib.common.utils.Log_OC; @@ -92,8 +93,7 @@ protected Result onRunJob(@NonNull Params params) { Account[] accounts = userAccountManager.getAccounts(); for (Account account : accounts) { - FileDataStorageManager storageManager = new FileDataStorageManager(account, - getContext().getContentResolver()); + FileDataStorageManager storageManager = new FileDataStorageManagerImpl(account, getContext()); OCFile ocRoot = storageManager.getFileByPath(ROOT_PATH); diff --git a/src/main/java/com/owncloud/android/operations/CreateFolderOperation.java b/src/main/java/com/owncloud/android/operations/CreateFolderOperation.java index 45c8b024b93d..2e01c9415661 100644 --- a/src/main/java/com/owncloud/android/operations/CreateFolderOperation.java +++ b/src/main/java/com/owncloud/android/operations/CreateFolderOperation.java @@ -21,6 +21,7 @@ package com.owncloud.android.operations; +import com.nextcloud.client.logger.Logger; import com.owncloud.android.datamodel.OCFile; import com.owncloud.android.lib.common.OwnCloudClient; import com.owncloud.android.lib.common.operations.OnRemoteOperationListener; @@ -34,6 +35,8 @@ import com.owncloud.android.utils.FileStorageUtils; import com.owncloud.android.utils.MimeType; +import javax.inject.Inject; + import static com.owncloud.android.datamodel.OCFile.PATH_SEPARATOR; import static com.owncloud.android.datamodel.OCFile.ROOT_PATH; @@ -49,6 +52,7 @@ public class CreateFolderOperation extends SyncOperation implements OnRemoteOper protected String mRemotePath; private boolean mCreateFullPath; private RemoteFile createdRemoteFolder; + @Inject Logger logger; /** * Constructor @@ -63,8 +67,8 @@ public CreateFolderOperation(String remotePath, boolean createFullPath) { @Override - protected RemoteOperationResult run(OwnCloudClient client) { - RemoteOperationResult result = new CreateFolderRemoteOperation(mRemotePath, mCreateFullPath).execute(client); + public RemoteOperationResult run(OwnCloudClient client) { + RemoteOperationResult result = createCreateFolderRemoteOperation(mRemotePath, mCreateFullPath).execute(client); if (result.isSuccess()) { RemoteOperationResult remoteFolderOperationResult = new ReadFolderRemoteOperation(mRemotePath) @@ -79,6 +83,14 @@ protected RemoteOperationResult run(OwnCloudClient client) { return result; } + public CreateFolderRemoteOperation createCreateFolderRemoteOperation(String remotePath, boolean createFullPath) { + return new CreateFolderRemoteOperation(remotePath, createFullPath); + } + + public ReadFolderRemoteOperation createReadFolderRemoteOperation(String remotePath) { + return new ReadFolderRemoteOperation(remotePath); + } + @Override public void onRemoteOperationFinish(RemoteOperation operation, RemoteOperationResult result) { if (operation instanceof CreateFolderRemoteOperation) { @@ -124,7 +136,7 @@ private void saveFolderInDB() { newDir.setPermissions(createdRemoteFolder.getPermissions()); getStorageManager().saveFile(newDir); - Log_OC.d(TAG, "Create directory " + mRemotePath + " in Database"); + logger.d(TAG, "Create directory " + mRemotePath + " in Database"); } } diff --git a/src/main/java/com/owncloud/android/operations/DownloadFileOperation.java b/src/main/java/com/owncloud/android/operations/DownloadFileOperation.java index 73c9e5a3fe22..81910880de95 100644 --- a/src/main/java/com/owncloud/android/operations/DownloadFileOperation.java +++ b/src/main/java/com/owncloud/android/operations/DownloadFileOperation.java @@ -28,6 +28,7 @@ import com.owncloud.android.datamodel.DecryptedFolderMetadata; import com.owncloud.android.datamodel.FileDataStorageManager; +import com.owncloud.android.datamodel.FileDataStorageManagerImpl; import com.owncloud.android.datamodel.OCFile; import com.owncloud.android.lib.common.OwnCloudClient; import com.owncloud.android.lib.common.network.OnDatatransferProgressListener; @@ -171,7 +172,7 @@ protected RemoteOperationResult run(OwnCloudClient client) { // decrypt file if (file.isEncrypted() && android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.KITKAT) { - FileDataStorageManager fileDataStorageManager = new FileDataStorageManager(account, context.getContentResolver()); + FileDataStorageManager fileDataStorageManager = new FileDataStorageManagerImpl(account, context); OCFile parent = fileDataStorageManager.getFileByPath(file.getParentRemotePath()); diff --git a/src/main/java/com/owncloud/android/operations/RenameFileOperation.java b/src/main/java/com/owncloud/android/operations/RenameFileOperation.java index cddd137057e0..a66999e79b31 100644 --- a/src/main/java/com/owncloud/android/operations/RenameFileOperation.java +++ b/src/main/java/com/owncloud/android/operations/RenameFileOperation.java @@ -23,7 +23,6 @@ import android.text.TextUtils; -import com.owncloud.android.datamodel.FileDataStorageManager; import com.owncloud.android.datamodel.OCFile; import com.owncloud.android.lib.common.OwnCloudClient; import com.owncloud.android.lib.common.operations.RemoteOperationResult; @@ -133,7 +132,7 @@ private void saveLocalFile() { getStorageManager().deleteFileInMediaScan(oldPath); // notify to scan about new file, if it is a media file if (MimeTypeUtil.isMedia(file.getMimeType())) { - FileDataStorageManager.triggerMediaScan(newPath); + getStorageManager().triggerMediaScan(newPath); } } // else - NOTHING: the link to the local file is kept although the local name diff --git a/src/main/java/com/owncloud/android/operations/UploadFileOperation.java b/src/main/java/com/owncloud/android/operations/UploadFileOperation.java index cf2d893ebb28..afa088730dbc 100644 --- a/src/main/java/com/owncloud/android/operations/UploadFileOperation.java +++ b/src/main/java/com/owncloud/android/operations/UploadFileOperation.java @@ -37,7 +37,6 @@ import com.owncloud.android.datamodel.ArbitraryDataProvider; import com.owncloud.android.datamodel.DecryptedFolderMetadata; import com.owncloud.android.datamodel.EncryptedFolderMetadata; -import com.owncloud.android.datamodel.FileDataStorageManager; import com.owncloud.android.datamodel.OCFile; import com.owncloud.android.datamodel.ThumbnailsCacheManager; import com.owncloud.android.datamodel.UploadsStorageManager; @@ -968,7 +967,7 @@ private void handleSuccessfulUpload(File temporalFile, File expectedFile, File o mFile.setStoragePath(expectedFile.getAbsolutePath()); saveUploadedFile(client); if (MimeTypeUtil.isMedia(mFile.getMimeType())) { - FileDataStorageManager.triggerMediaScan(expectedFile.getAbsolutePath()); + getStorageManager().triggerMediaScan(expectedFile.getAbsolutePath()); } break; @@ -985,7 +984,7 @@ private void handleSuccessfulUpload(File temporalFile, File expectedFile, File o mFile.setStoragePath(newFile.getAbsolutePath()); saveUploadedFile(client); if (MimeTypeUtil.isMedia(mFile.getMimeType())) { - FileDataStorageManager.triggerMediaScan(newFile.getAbsolutePath()); + getStorageManager().triggerMediaScan(newFile.getAbsolutePath()); } break; } @@ -1329,7 +1328,7 @@ private void saveUploadedFile(OwnCloudClient client) { getStorageManager().saveConflict(file, null); if (MimeTypeUtil.isMedia(file.getMimeType())) { - FileDataStorageManager.triggerMediaScan(file.getStoragePath()); + getStorageManager().triggerMediaScan(file.getStoragePath()); } // generate new Thumbnail diff --git a/src/main/java/com/owncloud/android/operations/common/SyncOperation.java b/src/main/java/com/owncloud/android/operations/common/SyncOperation.java index 399ce87da668..660d77c789b8 100644 --- a/src/main/java/com/owncloud/android/operations/common/SyncOperation.java +++ b/src/main/java/com/owncloud/android/operations/common/SyncOperation.java @@ -47,7 +47,7 @@ public abstract class SyncOperation extends RemoteOperation { * Do not call this method from the main thread. * * This method should be used whenever an ownCloud account is available, instead of - * {@link #execute(OwnCloudClient, com.owncloud.android.datamodel.FileDataStorageManager)}. + * {@link #execute(OwnCloudClient, FileDataStorageManager)}. * * @param storageManager * @param context Android context for the component calling the method. @@ -77,11 +77,9 @@ public RemoteOperationResult execute(FileDataStorageManager storageManager, Cont * @param storageManager * @return Result of the operation. */ - public RemoteOperationResult execute(OwnCloudClient client, - FileDataStorageManager storageManager) { + public RemoteOperationResult execute(OwnCloudClient client, FileDataStorageManager storageManager) { if (storageManager == null) { - throw new IllegalArgumentException("Trying to execute a sync operation with a " + - "NULL storage manager"); + throw new IllegalArgumentException("Trying to execute a sync operation with a NULL storage manager"); } this.storageManager = storageManager; return super.execute(client); @@ -103,7 +101,7 @@ public RemoteOperationResult execute(OwnCloudClient client, * @return Thread were the remote operation is executed. */ /* - public Thread execute(FileDataStorageManager storageManager, + public Thread execute(FileDataStorageManagerImpl storageManager, Context context, OnRemoteOperationListener listener, Handler listenerHandler, Activity callerActivity) { if (storageManager == null) { throw new IllegalArgumentException("Trying to execute a sync operation diff --git a/src/main/java/com/owncloud/android/providers/DiskLruImageCacheFileProvider.java b/src/main/java/com/owncloud/android/providers/DiskLruImageCacheFileProvider.java index cf398a425cbf..b13fbf6a2db6 100644 --- a/src/main/java/com/owncloud/android/providers/DiskLruImageCacheFileProvider.java +++ b/src/main/java/com/owncloud/android/providers/DiskLruImageCacheFileProvider.java @@ -21,7 +21,6 @@ package com.owncloud.android.providers; -import android.accounts.Account; import android.content.ContentProvider; import android.content.ContentValues; import android.database.Cursor; @@ -35,6 +34,7 @@ import com.nextcloud.client.account.UserAccountManager; import com.owncloud.android.MainApp; import com.owncloud.android.datamodel.FileDataStorageManager; +import com.owncloud.android.datamodel.FileDataStorageManagerImpl; import com.owncloud.android.datamodel.OCFile; import com.owncloud.android.datamodel.ThumbnailsCacheManager; import com.owncloud.android.lib.common.utils.Log_OC; @@ -63,8 +63,8 @@ public boolean onCreate() { private OCFile getFile(Uri uri) { User user = accountManager.getUser(); - FileDataStorageManager fileDataStorageManager = new FileDataStorageManager(user.toPlatformAccount(), - MainApp.getAppContext().getContentResolver()); + FileDataStorageManager fileDataStorageManager = new FileDataStorageManagerImpl(user.toPlatformAccount(), + MainApp.getAppContext()); return fileDataStorageManager.getFileByPath(uri.getPath()); } diff --git a/src/main/java/com/owncloud/android/providers/DocumentsStorageProvider.java b/src/main/java/com/owncloud/android/providers/DocumentsStorageProvider.java index 9abc4e5386ec..6ba781d5d397 100644 --- a/src/main/java/com/owncloud/android/providers/DocumentsStorageProvider.java +++ b/src/main/java/com/owncloud/android/providers/DocumentsStorageProvider.java @@ -27,7 +27,6 @@ import android.accounts.OperationCanceledException; import android.annotation.SuppressLint; import android.annotation.TargetApi; -import android.content.ContentResolver; import android.content.Context; import android.content.Intent; import android.content.res.AssetFileDescriptor; @@ -55,6 +54,7 @@ import com.owncloud.android.R; import com.owncloud.android.datamodel.ArbitraryDataProvider; import com.owncloud.android.datamodel.FileDataStorageManager; +import com.owncloud.android.datamodel.FileDataStorageManagerImpl; import com.owncloud.android.datamodel.OCFile; import com.owncloud.android.datamodel.ThumbnailsCacheManager; import com.owncloud.android.files.services.FileDownloader; @@ -223,7 +223,7 @@ public ParcelFileDescriptor openDocument(String documentId, String mode, Cancell OCFile finalFile = ocFile; Thread syncThread = new Thread(() -> { try { - FileDataStorageManager storageManager = new FileDataStorageManager(account, context.getContentResolver()); + FileDataStorageManager storageManager = new FileDataStorageManagerImpl(account, context); RemoteOperationResult result = new SynchronizeFileOperation(finalFile, null, account, true, context) .execute(storageManager, context); @@ -638,10 +638,8 @@ private void initiateStorageMap() { rootIdToStorageManager.clear(); - ContentResolver contentResolver = getContext().getContentResolver(); - for (Account account : accountManager.getAccounts()) { - final FileDataStorageManager storageManager = new FileDataStorageManager(account, contentResolver); + final FileDataStorageManager storageManager = new FileDataStorageManagerImpl(account, getContext()); rootIdToStorageManager.put(account.hashCode(), storageManager); } } diff --git a/src/main/java/com/owncloud/android/providers/FileContentProvider.java b/src/main/java/com/owncloud/android/providers/FileContentProvider.java index bf3c8a9099aa..30b901cc490f 100644 --- a/src/main/java/com/owncloud/android/providers/FileContentProvider.java +++ b/src/main/java/com/owncloud/android/providers/FileContentProvider.java @@ -275,7 +275,7 @@ private Uri insert(SQLiteDatabase db, Uri uri, ContentValues values) { String[] whereArgs = new String[]{remotePath, accountName}; Cursor doubleCheck = query(db, uri, projection, where, whereArgs, null); // ugly patch; serious refactorization is needed to reduce work in - // FileDataStorageManager and bring it to FileContentProvider + // FileDataStorageManagerImpl and bring it to FileContentProvider if (doubleCheck == null || !doubleCheck.moveToFirst()) { if (doubleCheck != null) { doubleCheck.close(); diff --git a/src/main/java/com/owncloud/android/providers/UsersAndGroupsSearchProvider.java b/src/main/java/com/owncloud/android/providers/UsersAndGroupsSearchProvider.java index 0daa551ab90a..61cdc8acb61b 100644 --- a/src/main/java/com/owncloud/android/providers/UsersAndGroupsSearchProvider.java +++ b/src/main/java/com/owncloud/android/providers/UsersAndGroupsSearchProvider.java @@ -20,7 +20,6 @@ package com.owncloud.android.providers; -import android.accounts.Account; import android.app.SearchManager; import android.content.ContentProvider; import android.content.ContentValues; @@ -38,6 +37,7 @@ import com.nextcloud.client.account.UserAccountManager; import com.owncloud.android.R; import com.owncloud.android.datamodel.FileDataStorageManager; +import com.owncloud.android.datamodel.FileDataStorageManagerImpl; import com.owncloud.android.lib.common.operations.RemoteOperationResult; import com.owncloud.android.lib.common.utils.Log_OC; import com.owncloud.android.lib.resources.shares.GetShareesRemoteOperation; @@ -214,8 +214,7 @@ private Cursor searchForUsersOrGroups(Uri uri) { Uri remoteBaseUri = new Uri.Builder().scheme(CONTENT).authority(DATA_REMOTE).build(); Uri emailBaseUri = new Uri.Builder().scheme(CONTENT).authority(DATA_EMAIL).build(); - FileDataStorageManager manager = new FileDataStorageManager(user.toPlatformAccount(), - getContext().getContentResolver()); + FileDataStorageManager manager = new FileDataStorageManagerImpl(user.toPlatformAccount(), getContext()); boolean federatedShareAllowed = manager.getCapability(user.getAccountName()) .getFilesSharingFederationOutgoing() .isTrue(); diff --git a/src/main/java/com/owncloud/android/services/OperationsService.java b/src/main/java/com/owncloud/android/services/OperationsService.java index 19cca43f3d7e..43ac18385f4d 100644 --- a/src/main/java/com/owncloud/android/services/OperationsService.java +++ b/src/main/java/com/owncloud/android/services/OperationsService.java @@ -39,6 +39,7 @@ import com.owncloud.android.MainApp; import com.owncloud.android.datamodel.FileDataStorageManager; +import com.owncloud.android.datamodel.FileDataStorageManagerImpl; import com.owncloud.android.datamodel.OCFile; import com.owncloud.android.lib.common.OwnCloudAccount; import com.owncloud.android.lib.common.OwnCloudClient; @@ -435,10 +436,8 @@ private void nextOperation() { mOwnCloudClient = OwnCloudClientManagerFactory.getDefaultSingleton(). getClientFor(ocAccount, mService); - mStorageManager = new FileDataStorageManager( - mLastTarget.mAccount, - mService.getContentResolver() - ); + mStorageManager = new FileDataStorageManagerImpl(mLastTarget.mAccount, + mService.getBaseContext()); } else { OwnCloudAccount ocAccount = new OwnCloudAccount(mLastTarget.mServerUrl, null); mOwnCloudClient = OwnCloudClientManagerFactory.getDefaultSingleton(). diff --git a/src/main/java/com/owncloud/android/services/SyncFolderHandler.java b/src/main/java/com/owncloud/android/services/SyncFolderHandler.java index 8d6c42088d58..352429e4797f 100644 --- a/src/main/java/com/owncloud/android/services/SyncFolderHandler.java +++ b/src/main/java/com/owncloud/android/services/SyncFolderHandler.java @@ -28,6 +28,7 @@ import android.util.Pair; import com.owncloud.android.datamodel.FileDataStorageManager; +import com.owncloud.android.datamodel.FileDataStorageManagerImpl; import com.owncloud.android.datamodel.OCFile; import com.owncloud.android.files.services.FileDownloader; import com.owncloud.android.files.services.IndexedForest; @@ -105,10 +106,7 @@ private void doOperation(Account account, String remotePath) { if (mCurrentAccount == null || !mCurrentAccount.equals(account)) { mCurrentAccount = account; - mStorageManager = new FileDataStorageManager( - account, - mService.getContentResolver() - ); + mStorageManager = new FileDataStorageManagerImpl(account, mService.getBaseContext()); } // else, reuse storage manager from previous operation // always get client from client manager, to get fresh credentials in case of update @@ -123,7 +121,7 @@ private void doOperation(Account account, String remotePath) { } catch (AccountsException | IOException e) { sendBroadcastFinishedSyncFolder(account, remotePath, false); mService.dispatchResultToOperationListeners(mCurrentSyncOperation, new RemoteOperationResult(e)); - + Log_OC.e(TAG, "Error while trying to get authorization", e); } finally { mPendingOperations.removePayload(account.name, remotePath); diff --git a/src/main/java/com/owncloud/android/syncadapter/AbstractOwnCloudSyncAdapter.java b/src/main/java/com/owncloud/android/syncadapter/AbstractOwnCloudSyncAdapter.java index f3de82840512..1257ed9b62b2 100644 --- a/src/main/java/com/owncloud/android/syncadapter/AbstractOwnCloudSyncAdapter.java +++ b/src/main/java/com/owncloud/android/syncadapter/AbstractOwnCloudSyncAdapter.java @@ -46,7 +46,7 @@ /** * Base synchronization adapter for ownCloud designed to be subclassed for different * resource types, like FileSync, ConcatsSync, CalendarSync, etc.. - * + * * Implements the standard {@link AbstractThreadedSyncAdapter}. */ abstract class AbstractOwnCloudSyncAdapter extends diff --git a/src/main/java/com/owncloud/android/syncadapter/FileSyncAdapter.java b/src/main/java/com/owncloud/android/syncadapter/FileSyncAdapter.java index f52c22b2ce82..2523237b7b59 100644 --- a/src/main/java/com/owncloud/android/syncadapter/FileSyncAdapter.java +++ b/src/main/java/com/owncloud/android/syncadapter/FileSyncAdapter.java @@ -36,7 +36,7 @@ import com.owncloud.android.R; import com.owncloud.android.authentication.AuthenticatorActivity; -import com.owncloud.android.datamodel.FileDataStorageManager; +import com.owncloud.android.datamodel.FileDataStorageManagerImpl; import com.owncloud.android.datamodel.OCFile; import com.owncloud.android.lib.common.operations.RemoteOperationResult; import com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode; @@ -154,7 +154,7 @@ public synchronized void onPerformSync(Account account, Bundle extras, this.setAccount(account); this.setContentProviderClient(providerClient); - this.setStorageManager(new FileDataStorageManager(account, providerClient)); + this.setStorageManager(new FileDataStorageManagerImpl(account, providerClient, getContext())); try { this.initClientForCurrentAccount(); diff --git a/src/main/java/com/owncloud/android/ui/activities/ActivitiesActivity.java b/src/main/java/com/owncloud/android/ui/activities/ActivitiesActivity.java index 43687338e778..ea8236378ce8 100644 --- a/src/main/java/com/owncloud/android/ui/activities/ActivitiesActivity.java +++ b/src/main/java/com/owncloud/android/ui/activities/ActivitiesActivity.java @@ -32,6 +32,7 @@ import com.nextcloud.common.NextcloudClient; import com.owncloud.android.R; import com.owncloud.android.datamodel.FileDataStorageManager; +import com.owncloud.android.datamodel.FileDataStorageManagerImpl; import com.owncloud.android.datamodel.OCFile; import com.owncloud.android.lib.common.utils.Log_OC; import com.owncloud.android.lib.resources.activities.model.RichObject; @@ -168,7 +169,7 @@ private void setupContent() { emptyContentProgressBar.getIndeterminateDrawable().setColorFilter(ThemeUtils.primaryAccentColor(this), PorterDuff.Mode.SRC_IN); - FileDataStorageManager storageManager = new FileDataStorageManager(getAccount(), getContentResolver()); + FileDataStorageManager storageManager = new FileDataStorageManagerImpl(getAccount(), this); adapter = new ActivityListAdapter(this, getUserAccountManager(), this, storageManager, getCapabilities(), false); recyclerView.setAdapter(adapter); diff --git a/src/main/java/com/owncloud/android/ui/activities/data/files/FilesServiceApiImpl.java b/src/main/java/com/owncloud/android/ui/activities/data/files/FilesServiceApiImpl.java index 8f2fd0ba0986..663ba781c746 100644 --- a/src/main/java/com/owncloud/android/ui/activities/data/files/FilesServiceApiImpl.java +++ b/src/main/java/com/owncloud/android/ui/activities/data/files/FilesServiceApiImpl.java @@ -102,7 +102,7 @@ protected Boolean doInBackground(Void... voids) { if (resultRemoteFileOp.isSuccess()) { OCFile temp = FileStorageUtils.fillOCFile((RemoteFile) resultRemoteFileOp.getData().get(0)); - remoteOcFile = baseActivity.getStorageManager().saveFileWithParent(temp, context); + remoteOcFile = baseActivity.getStorageManager().saveFileWithParent(temp); if (remoteOcFile.isFolder()) { // perform folder synchronization diff --git a/src/main/java/com/owncloud/android/ui/activity/BaseActivity.java b/src/main/java/com/owncloud/android/ui/activity/BaseActivity.java index fb8741baf6a3..363fede22df8 100644 --- a/src/main/java/com/owncloud/android/ui/activity/BaseActivity.java +++ b/src/main/java/com/owncloud/android/ui/activity/BaseActivity.java @@ -17,6 +17,7 @@ import com.nextcloud.java.util.Optional; import com.owncloud.android.MainApp; import com.owncloud.android.datamodel.FileDataStorageManager; +import com.owncloud.android.datamodel.FileDataStorageManagerImpl; import com.owncloud.android.datamodel.OCFile; import com.owncloud.android.lib.common.utils.Log_OC; import com.owncloud.android.lib.resources.status.OCCapability; @@ -160,7 +161,7 @@ protected void setAccount(Account account, boolean savedAccount) { } if(currentAccount != null) { - storageManager = new FileDataStorageManager(currentAccount, getContentResolver()); + storageManager = new FileDataStorageManagerImpl(currentAccount, this); capabilities = storageManager.getCapability(currentAccount.name); } } diff --git a/src/main/java/com/owncloud/android/ui/activity/ComponentsGetter.java b/src/main/java/com/owncloud/android/ui/activity/ComponentsGetter.java index 8c5d35eb5233..7a27873696ff 100644 --- a/src/main/java/com/owncloud/android/ui/activity/ComponentsGetter.java +++ b/src/main/java/com/owncloud/android/ui/activity/ComponentsGetter.java @@ -34,23 +34,23 @@ public interface ComponentsGetter { */ public FileDownloaderBinder getFileDownloaderBinder(); - + /** * To be invoked when the parent activity is fully created to get a reference * to the FileUploader service API. */ public FileUploaderBinder getFileUploaderBinder(); - + /** * To be invoked when the parent activity is fully created to get a reference * to the OperationsSerivce service API. */ public OperationsServiceBinder getOperationsServiceBinder(); - + public FileDataStorageManager getStorageManager(); - + public FileOperationsHelper getFileOperationsHelper(); diff --git a/src/main/java/com/owncloud/android/ui/activity/DrawerActivity.java b/src/main/java/com/owncloud/android/ui/activity/DrawerActivity.java index b8b4ccde1815..3831be24a1a4 100644 --- a/src/main/java/com/owncloud/android/ui/activity/DrawerActivity.java +++ b/src/main/java/com/owncloud/android/ui/activity/DrawerActivity.java @@ -70,6 +70,7 @@ import com.owncloud.android.datamodel.ArbitraryDataProvider; import com.owncloud.android.datamodel.ExternalLinksProvider; import com.owncloud.android.datamodel.FileDataStorageManager; +import com.owncloud.android.datamodel.FileDataStorageManagerImpl; import com.owncloud.android.datamodel.OCFile; import com.owncloud.android.lib.common.ExternalLink; import com.owncloud.android.lib.common.ExternalLinkType; @@ -370,8 +371,7 @@ public void run() { } private void filterDrawerMenu(final Menu menu, @NonNull final User user) { - FileDataStorageManager storageManager = new FileDataStorageManager(user.toPlatformAccount(), - getContentResolver()); + FileDataStorageManager storageManager = new FileDataStorageManagerImpl(user.toPlatformAccount(), this); OCCapability capability = storageManager.getCapability(user.getAccountName()); DrawerMenuUtil.filterSearchMenuItems(menu, user.toPlatformAccount(), getResources(), true); diff --git a/src/main/java/com/owncloud/android/ui/activity/ErrorsWhileCopyingHandlerActivity.java b/src/main/java/com/owncloud/android/ui/activity/ErrorsWhileCopyingHandlerActivity.java index 286214fb829b..e552eeff23d8 100644 --- a/src/main/java/com/owncloud/android/ui/activity/ErrorsWhileCopyingHandlerActivity.java +++ b/src/main/java/com/owncloud/android/ui/activity/ErrorsWhileCopyingHandlerActivity.java @@ -38,12 +38,15 @@ import com.owncloud.android.R; import com.owncloud.android.datamodel.FileDataStorageManager; +import com.owncloud.android.datamodel.FileDataStorageManagerImpl; import com.owncloud.android.datamodel.OCFile; import com.owncloud.android.lib.common.utils.Log_OC; import com.owncloud.android.ui.dialog.IndeterminateProgressDialog; import com.owncloud.android.utils.DisplayUtils; import com.owncloud.android.utils.FileStorageUtils; +import org.jetbrains.annotations.NotNull; + import java.io.File; import java.util.List; @@ -94,7 +97,7 @@ protected void onCreate(Bundle savedInstanceState) { mAccount = intent.getParcelableExtra(EXTRA_ACCOUNT); mRemotePaths = intent.getStringArrayListExtra(EXTRA_REMOTE_PATHS); mLocalPaths = intent.getStringArrayListExtra(EXTRA_LOCAL_PATHS); - mStorageManager = new FileDataStorageManager(mAccount, getContentResolver()); + mStorageManager = new FileDataStorageManagerImpl(mAccount, this); mHandler = new Handler(); if (mCurrentDialog != null) { mCurrentDialog.dismiss(); @@ -150,8 +153,9 @@ public boolean isEnabled(int position) { /** * {@inheritDoc} */ - @Override - public View getView (int position, View convertView, @NonNull ViewGroup parent) { + @NotNull + @Override + public View getView (int position, View convertView, @NonNull ViewGroup parent) { View view = convertView; if (view == null) { LayoutInflater vi = (LayoutInflater) getSystemService( diff --git a/src/main/java/com/owncloud/android/ui/activity/FileDisplayActivity.java b/src/main/java/com/owncloud/android/ui/activity/FileDisplayActivity.java index 053926f197e8..ccb902312879 100644 --- a/src/main/java/com/owncloud/android/ui/activity/FileDisplayActivity.java +++ b/src/main/java/com/owncloud/android/ui/activity/FileDisplayActivity.java @@ -62,6 +62,7 @@ import com.owncloud.android.MainApp; import com.owncloud.android.R; import com.owncloud.android.datamodel.FileDataStorageManager; +import com.owncloud.android.datamodel.FileDataStorageManagerImpl; import com.owncloud.android.datamodel.OCFile; import com.owncloud.android.datamodel.VirtualFolderType; import com.owncloud.android.files.services.FileDownloader; @@ -2656,7 +2657,7 @@ private void handleOpenFileViaIntent(Intent intent) { FileDataStorageManager storageManager = getStorageManager(); if (storageManager == null) { - storageManager = new FileDataStorageManager(newAccount, getContentResolver()); + storageManager = new FileDataStorageManagerImpl(newAccount, this); } FetchRemoteFileTask fetchRemoteFileTask = new FetchRemoteFileTask(newAccount, diff --git a/src/main/java/com/owncloud/android/ui/activity/ShareActivity.java b/src/main/java/com/owncloud/android/ui/activity/ShareActivity.java index c23644ad36d3..9067e18a1ac8 100644 --- a/src/main/java/com/owncloud/android/ui/activity/ShareActivity.java +++ b/src/main/java/com/owncloud/android/ui/activity/ShareActivity.java @@ -29,6 +29,7 @@ import com.google.android.material.snackbar.Snackbar; import com.owncloud.android.R; +import com.owncloud.android.datamodel.FileDataStorageManagerImpl; import com.owncloud.android.datamodel.OCFile; import com.owncloud.android.lib.common.OwnCloudAccount; import com.owncloud.android.lib.common.accounts.AccountUtils; @@ -238,7 +239,7 @@ && getEditShareFragment() != null && getEditShareFragment().isAdded()) { } /** - * Updates the view, reading data from {@link com.owncloud.android.datamodel.FileDataStorageManager}. + * Updates the view, reading data from {@link FileDataStorageManagerImpl}. */ private void refreshSharesFromStorageManager() { diff --git a/src/main/java/com/owncloud/android/ui/activity/StorageMigration.java b/src/main/java/com/owncloud/android/ui/activity/StorageMigration.java index 1f58fc6329b8..8fbe6faf2e42 100644 --- a/src/main/java/com/owncloud/android/ui/activity/StorageMigration.java +++ b/src/main/java/com/owncloud/android/ui/activity/StorageMigration.java @@ -33,6 +33,7 @@ import com.owncloud.android.MainApp; import com.owncloud.android.R; import com.owncloud.android.datamodel.FileDataStorageManager; +import com.owncloud.android.datamodel.FileDataStorageManagerImpl; import com.owncloud.android.lib.common.utils.Log_OC; import com.owncloud.android.utils.FileStorageUtils; @@ -433,7 +434,7 @@ private void copyDirs(File src, File dst) throws MigrationException { } private void updateIndex(Context context) throws MigrationException { - FileDataStorageManager manager = new FileDataStorageManager(null, context.getContentResolver()); + FileDataStorageManager manager = new FileDataStorageManagerImpl(null, context); try { manager.migrateStoredFiles(mStorageSource, mStorageTarget); diff --git a/src/main/java/com/owncloud/android/ui/adapter/OCFileListAdapter.java b/src/main/java/com/owncloud/android/ui/adapter/OCFileListAdapter.java index 1486849306db..95bd799906d2 100644 --- a/src/main/java/com/owncloud/android/ui/adapter/OCFileListAdapter.java +++ b/src/main/java/com/owncloud/android/ui/adapter/OCFileListAdapter.java @@ -51,6 +51,7 @@ import com.nextcloud.client.preferences.AppPreferences; import com.owncloud.android.R; import com.owncloud.android.datamodel.FileDataStorageManager; +import com.owncloud.android.datamodel.FileDataStorageManagerImpl; import com.owncloud.android.datamodel.OCFile; import com.owncloud.android.datamodel.ThumbnailsCacheManager; import com.owncloud.android.datamodel.VirtualFolderType; @@ -797,7 +798,7 @@ public void setData(List objects, ExtendedListFragment.SearchType search } if (mStorageManager == null) { - mStorageManager = new FileDataStorageManager(user.toPlatformAccount(), activity.getContentResolver()); + mStorageManager = new FileDataStorageManagerImpl(user.toPlatformAccount(), activity.getContentResolver()); } if (clear) { @@ -863,7 +864,7 @@ private void parseShares(List objects) { if (result.isSuccess()) { OCFile file = FileStorageUtils.fillOCFile((RemoteFile) result.getData().get(0)); FileStorageUtils.searchForLocalFileInDefaultPath(file, user.toPlatformAccount()); - file = mStorageManager.saveFileWithParent(file, activity); + file = mStorageManager.saveFileWithParent(file); ShareType newShareType = ocShare.getShareType(); if (newShareType == ShareType.PUBLIC_LINK) { @@ -924,7 +925,7 @@ private void parseVirtuals(List objects, ExtendedListFragment.SearchType mStorageManager.saveFile(ocFile); } else { - ocFile = mStorageManager.saveFileWithParent(ocFile, activity); + ocFile = mStorageManager.saveFileWithParent(ocFile); // also sync folder content if (ocFile.isFolder()) { diff --git a/src/main/java/com/owncloud/android/ui/adapter/UploaderAdapter.java b/src/main/java/com/owncloud/android/ui/adapter/UploaderAdapter.java index 18b226468596..294b51603955 100644 --- a/src/main/java/com/owncloud/android/ui/adapter/UploaderAdapter.java +++ b/src/main/java/com/owncloud/android/ui/adapter/UploaderAdapter.java @@ -50,14 +50,16 @@ public class UploaderAdapter extends SimpleAdapter { private LayoutInflater inflater; public UploaderAdapter(Context context, - List> data, int resource, String[] from, - int[] to, FileDataStorageManager storageManager, Account account) { + List> data, + int resource, String[] from, + int[] to, + FileDataStorageManager storageManager, + Account account) { super(context, data, resource, from, to); mAccount = account; mStorageManager = storageManager; mContext = context; - inflater = (LayoutInflater) mContext - .getSystemService(Context.LAYOUT_INFLATER_SERVICE); + inflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE); } @Override diff --git a/src/main/java/com/owncloud/android/ui/adapter/UserListAdapter.java b/src/main/java/com/owncloud/android/ui/adapter/UserListAdapter.java index 3d8aaac2bfc2..6814ac935cc0 100644 --- a/src/main/java/com/owncloud/android/ui/adapter/UserListAdapter.java +++ b/src/main/java/com/owncloud/android/ui/adapter/UserListAdapter.java @@ -32,15 +32,9 @@ import android.widget.ImageView; import android.widget.PopupMenu; import android.widget.TextView; -import androidx.annotation.DrawableRes; -import androidx.annotation.NonNull; -import androidx.appcompat.widget.AppCompatCheckBox; -import androidx.fragment.app.FragmentManager; -import androidx.recyclerview.widget.RecyclerView; -import butterknife.BindView; -import butterknife.ButterKnife; + import com.owncloud.android.R; -import com.owncloud.android.datamodel.FileDataStorageManager; +import com.owncloud.android.datamodel.FileDataStorageManagerImpl; import com.owncloud.android.datamodel.OCFile; import com.owncloud.android.lib.resources.shares.OCShare; import com.owncloud.android.lib.resources.shares.ShareType; @@ -56,6 +50,14 @@ import java.security.NoSuchAlgorithmException; import java.util.List; +import androidx.annotation.DrawableRes; +import androidx.annotation.NonNull; +import androidx.appcompat.widget.AppCompatCheckBox; +import androidx.fragment.app.FragmentManager; +import androidx.recyclerview.widget.RecyclerView; +import butterknife.BindView; +import butterknife.ButterKnife; + /** * Adapter to show a user/group/email/remote in Sharing list in file details view. */ @@ -82,7 +84,7 @@ public UserListAdapter(FragmentManager fragmentManager, Context context, List - * Depends on the parent Activity provides a {@link com.owncloud.android.datamodel.FileDataStorageManager} + * Depends on the parent Activity provides a {@link FileDataStorageManagerImpl} * instance ready to use. If not ready, does nothing. */ public void refreshCapabilitiesFromDB() { @@ -418,7 +419,7 @@ public void onUpdateSharePermissionsFinished(RemoteOperationResult result) { /** * Get {@link OCShare} instance from DB and updates the UI. * - * Depends on the parent Activity provides a {@link com.owncloud.android.datamodel.FileDataStorageManager} + * Depends on the parent Activity provides a {@link FileDataStorageManagerImpl} * instance ready to use. If not ready, does nothing. */ public void refreshUiFromDB() { @@ -431,7 +432,7 @@ public void refreshUiFromDB() { /** * Get {@link OCShare} instance from DB and updates the UI. * - * Depends on the parent Activity provides a {@link com.owncloud.android.datamodel.FileDataStorageManager} + * Depends on the parent Activity provides a {@link FileDataStorageManagerImpl} * instance ready to use. If not ready, does nothing. * * @param editShareView Root view in the fragment. diff --git a/src/main/java/com/owncloud/android/ui/fragment/FileDetailActivitiesFragment.java b/src/main/java/com/owncloud/android/ui/fragment/FileDetailActivitiesFragment.java index 5d55620882e6..bcf6d33161e4 100644 --- a/src/main/java/com/owncloud/android/ui/fragment/FileDetailActivitiesFragment.java +++ b/src/main/java/com/owncloud/android/ui/fragment/FileDetailActivitiesFragment.java @@ -45,6 +45,7 @@ import com.nextcloud.common.NextcloudClient; import com.owncloud.android.R; import com.owncloud.android.datamodel.FileDataStorageManager; +import com.owncloud.android.datamodel.FileDataStorageManagerImpl; import com.owncloud.android.datamodel.OCFile; import com.owncloud.android.lib.common.OwnCloudClient; import com.owncloud.android.lib.common.operations.RemoteOperationResult; @@ -244,7 +245,7 @@ public void onDestroy() { } private void setupView() { - FileDataStorageManager storageManager = new FileDataStorageManager(account, requireActivity().getContentResolver()); + FileDataStorageManager storageManager = new FileDataStorageManagerImpl(account, requireActivity()); operationsHelper = ((ComponentsGetter) requireActivity()).getFileOperationsHelper(); OCCapability capability = storageManager.getCapability(account.name); diff --git a/src/main/java/com/owncloud/android/ui/fragment/FileDetailSharingFragment.java b/src/main/java/com/owncloud/android/ui/fragment/FileDetailSharingFragment.java index 3d3da6dba194..d6b1490de4ac 100644 --- a/src/main/java/com/owncloud/android/ui/fragment/FileDetailSharingFragment.java +++ b/src/main/java/com/owncloud/android/ui/fragment/FileDetailSharingFragment.java @@ -44,6 +44,7 @@ import com.nextcloud.client.di.Injectable; import com.owncloud.android.R; import com.owncloud.android.datamodel.FileDataStorageManager; +import com.owncloud.android.datamodel.FileDataStorageManagerImpl; import com.owncloud.android.datamodel.OCFile; import com.owncloud.android.lib.common.OwnCloudAccount; import com.owncloud.android.lib.common.operations.RemoteOperationResult; @@ -202,7 +203,7 @@ public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, unbinder = ButterKnife.bind(this, view); if (fileDataStorageManager == null) { - fileDataStorageManager = new FileDataStorageManager(account, fileDisplayActivity.getContentResolver()); + fileDataStorageManager = new FileDataStorageManagerImpl(account, fileDisplayActivity); } setupView(); diff --git a/src/main/java/com/owncloud/android/ui/fragment/SearchShareesFragment.java b/src/main/java/com/owncloud/android/ui/fragment/SearchShareesFragment.java index 96d773ef9390..535e8a4f9893 100644 --- a/src/main/java/com/owncloud/android/ui/fragment/SearchShareesFragment.java +++ b/src/main/java/com/owncloud/android/ui/fragment/SearchShareesFragment.java @@ -34,6 +34,7 @@ import android.widget.ListView; import com.owncloud.android.R; +import com.owncloud.android.datamodel.FileDataStorageManagerImpl; import com.owncloud.android.datamodel.OCFile; import com.owncloud.android.lib.common.utils.Log_OC; import com.owncloud.android.lib.resources.shares.OCShare; @@ -153,7 +154,7 @@ public void onActivityCreated(Bundle savedInstanceState) { /** * Get users and groups from the DB to fill in the "share with" list * - * Depends on the parent Activity provides a {@link com.owncloud.android.datamodel.FileDataStorageManager} + * Depends on the parent Activity provides a {@link FileDataStorageManagerImpl} * instance ready to use. If not ready, does nothing. */ public void refreshUsersOrGroupsListFromDB (){ diff --git a/src/main/java/com/owncloud/android/ui/fragment/ShareFileFragment.java b/src/main/java/com/owncloud/android/ui/fragment/ShareFileFragment.java index fe64df9cba04..1b9baa2827af 100644 --- a/src/main/java/com/owncloud/android/ui/fragment/ShareFileFragment.java +++ b/src/main/java/com/owncloud/android/ui/fragment/ShareFileFragment.java @@ -42,6 +42,7 @@ import com.google.android.material.button.MaterialButton; import com.google.android.material.snackbar.Snackbar; import com.owncloud.android.R; +import com.owncloud.android.datamodel.FileDataStorageManagerImpl; import com.owncloud.android.datamodel.OCFile; import com.owncloud.android.datamodel.ThumbnailsCacheManager; import com.owncloud.android.lib.common.utils.Log_OC; @@ -587,7 +588,7 @@ public void onDetach() { /** * Get known server capabilities from DB *

- * Depends on the parent Activity provides a {@link com.owncloud.android.datamodel.FileDataStorageManager} + * Depends on the parent Activity provides a {@link FileDataStorageManagerImpl} * instance ready to use. If not ready, does nothing. */ public void refreshCapabilitiesFromDB() { @@ -599,7 +600,7 @@ public void refreshCapabilitiesFromDB() { /** * Get users and groups from the DB to fill in the "share with" list. *

- * Depends on the parent Activity provides a {@link com.owncloud.android.datamodel.FileDataStorageManager} + * Depends on the parent Activity provides a {@link FileDataStorageManagerImpl} * instance ready to use. If not ready, does nothing. */ public void refreshUsersOrGroupsListFromDB() { @@ -662,7 +663,7 @@ public void editShare(OCShare share) { *

* Takes into account server capabilities before reading database. *

- * Depends on the parent Activity provides a {@link com.owncloud.android.datamodel.FileDataStorageManager} + * Depends on the parent Activity provides a {@link FileDataStorageManagerImpl} * instance ready to use. If not ready, does nothing. */ public void refreshPublicShareFromDB() { diff --git a/src/main/java/com/owncloud/android/ui/fragment/contactsbackup/ContactListFragment.java b/src/main/java/com/owncloud/android/ui/fragment/contactsbackup/ContactListFragment.java index a2c3acd7ea37..d954a029f63d 100644 --- a/src/main/java/com/owncloud/android/ui/fragment/contactsbackup/ContactListFragment.java +++ b/src/main/java/com/owncloud/android/ui/fragment/contactsbackup/ContactListFragment.java @@ -63,6 +63,7 @@ import com.nextcloud.client.network.ClientFactory; import com.owncloud.android.R; import com.owncloud.android.datamodel.FileDataStorageManager; +import com.owncloud.android.datamodel.FileDataStorageManagerImpl; import com.owncloud.android.datamodel.OCFile; import com.owncloud.android.files.services.FileDownloader; import com.owncloud.android.jobs.ContactsImportJob; @@ -515,8 +516,8 @@ public void onReceive(Context context, Intent intent) { if (FileDownloader.getDownloadFinishMessage().equalsIgnoreCase(intent.getAction())) { String downloadedRemotePath = intent.getStringExtra(FileDownloader.EXTRA_REMOTE_PATH); - FileDataStorageManager storageManager = new FileDataStorageManager(account, - context.getContentResolver()); + FileDataStorageManager storageManager = new FileDataStorageManagerImpl(account, + context); ocFile = storageManager.getFileByPath(downloadedRemotePath); loadContactsTask.execute(); } diff --git a/src/main/java/com/owncloud/android/ui/fragment/contactsbackup/ContactsBackupFragment.java b/src/main/java/com/owncloud/android/ui/fragment/contactsbackup/ContactsBackupFragment.java index 6b9cba657dd0..1305da9036d9 100644 --- a/src/main/java/com/owncloud/android/ui/fragment/contactsbackup/ContactsBackupFragment.java +++ b/src/main/java/com/owncloud/android/ui/fragment/contactsbackup/ContactsBackupFragment.java @@ -43,6 +43,7 @@ import com.owncloud.android.R; import com.owncloud.android.datamodel.ArbitraryDataProvider; import com.owncloud.android.datamodel.FileDataStorageManager; +import com.owncloud.android.datamodel.FileDataStorageManagerImpl; import com.owncloud.android.datamodel.OCFile; import com.owncloud.android.jobs.ContactsBackupJob; import com.owncloud.android.lib.common.operations.RemoteOperationResult; @@ -213,8 +214,8 @@ private void refreshBackupFolder(final String backupFolderPath, AsyncTask task = new AsyncTask() { @Override protected Boolean doInBackground(String... path) { - FileDataStorageManager storageManager = new FileDataStorageManager(account, - contactsPreferenceActivity.getContentResolver()); + FileDataStorageManager storageManager = new FileDataStorageManagerImpl(account, + contactsPreferenceActivity); OCFile folder = storageManager.getFileByPath(path[0]); diff --git a/src/main/java/com/owncloud/android/ui/helpers/FileOperationsHelper.java b/src/main/java/com/owncloud/android/ui/helpers/FileOperationsHelper.java index ef720682c05d..90021d95a628 100755 --- a/src/main/java/com/owncloud/android/ui/helpers/FileOperationsHelper.java +++ b/src/main/java/com/owncloud/android/ui/helpers/FileOperationsHelper.java @@ -51,6 +51,7 @@ import com.owncloud.android.MainApp; import com.owncloud.android.R; import com.owncloud.android.datamodel.FileDataStorageManager; +import com.owncloud.android.datamodel.FileDataStorageManagerImpl; import com.owncloud.android.datamodel.OCFile; import com.owncloud.android.files.StreamMediaFileOperation; import com.owncloud.android.files.services.FileDownloader.FileDownloaderBinder; @@ -196,8 +197,8 @@ private Intent createIntentFromFile(String storagePath) { public void startSyncForFileAndIntent(OCFile file, Intent intent) { new Thread(() -> { Account account = fileActivity.getAccount(); - FileDataStorageManager storageManager = new FileDataStorageManager(fileActivity.getAccount(), - fileActivity.getContentResolver()); + FileDataStorageManager storageManager = new FileDataStorageManagerImpl(fileActivity.getAccount(), + fileActivity); // check if file is in conflict (this is known due to latest folder refresh) if (file.isInConflict()) { @@ -296,7 +297,7 @@ public void openFile(OCFile file) { public void run() { User user = currentAccount.getUser(); FileDataStorageManager storageManager = - new FileDataStorageManager(user.toPlatformAccount(), fileActivity.getContentResolver()); + new FileDataStorageManagerImpl(user.toPlatformAccount(), fileActivity); // a fresh object is needed; many things could have occurred to the file // since it was registered to observe again, assuming that local files // are linked to a remote file AT MOST, SOMETHING TO BE DONE; diff --git a/src/main/java/com/owncloud/android/ui/preview/PreviewImageActivity.java b/src/main/java/com/owncloud/android/ui/preview/PreviewImageActivity.java index b14b35c95a83..912720f5ddd0 100644 --- a/src/main/java/com/owncloud/android/ui/preview/PreviewImageActivity.java +++ b/src/main/java/com/owncloud/android/ui/preview/PreviewImageActivity.java @@ -22,7 +22,6 @@ */ package com.owncloud.android.ui.preview; -import android.accounts.Account; import android.annotation.SuppressLint; import android.content.BroadcastReceiver; import android.content.ComponentName; @@ -37,7 +36,6 @@ import android.view.View; import com.google.android.material.snackbar.Snackbar; -import com.nextcloud.client.account.User; import com.nextcloud.client.di.Injectable; import com.nextcloud.client.preferences.AppPreferences; import com.owncloud.android.MainApp; diff --git a/src/main/java/com/owncloud/android/ui/preview/PreviewImagePagerAdapter.java b/src/main/java/com/owncloud/android/ui/preview/PreviewImagePagerAdapter.java index 6ec60b989cc0..108faea17f25 100644 --- a/src/main/java/com/owncloud/android/ui/preview/PreviewImagePagerAdapter.java +++ b/src/main/java/com/owncloud/android/ui/preview/PreviewImagePagerAdapter.java @@ -64,9 +64,12 @@ public class PreviewImagePagerAdapter extends FragmentStatePagerAdapter { * @param parentFolder Folder where images will be searched for. * @param storageManager Bridge to database. */ - public PreviewImagePagerAdapter(FragmentManager fragmentManager, OCFile parentFolder, - Account account, FileDataStorageManager storageManager, - boolean onlyOnDevice, AppPreferences preferences) { + public PreviewImagePagerAdapter(FragmentManager fragmentManager, + OCFile parentFolder, + Account account, + FileDataStorageManager storageManager, + boolean onlyOnDevice, + AppPreferences preferences) { super(fragmentManager); if (fragmentManager == null) { diff --git a/src/main/java/com/owncloud/android/utils/GetShareWithUsersAsyncTask.java b/src/main/java/com/owncloud/android/utils/GetShareWithUsersAsyncTask.java index 6513a6c119cb..5b59db0c1df1 100644 --- a/src/main/java/com/owncloud/android/utils/GetShareWithUsersAsyncTask.java +++ b/src/main/java/com/owncloud/android/utils/GetShareWithUsersAsyncTask.java @@ -25,6 +25,7 @@ import com.owncloud.android.MainApp; import com.owncloud.android.datamodel.FileDataStorageManager; +import com.owncloud.android.datamodel.FileDataStorageManagerImpl; import com.owncloud.android.datamodel.OCFile; import com.owncloud.android.lib.common.OwnCloudAccount; import com.owncloud.android.lib.common.OwnCloudClient; @@ -58,7 +59,7 @@ protected Pair doInBackground(Object... if (params != null && params.length == 3) { OCFile file = (OCFile) params[0]; Account account = (Account) params[1]; - FileDataStorageManager fileDataStorageManager = (FileDataStorageManager) params[2]; + FileDataStorageManager fileDataStorageManager = (FileDataStorageManagerImpl) params[2]; try { // Get shares request @@ -93,4 +94,4 @@ protected void onPostExecute(Pair result } } -} \ No newline at end of file +} diff --git a/src/main/java/com/owncloud/android/utils/ThemeUtils.java b/src/main/java/com/owncloud/android/utils/ThemeUtils.java index 3ee1df68cb76..2e4bf5889c46 100644 --- a/src/main/java/com/owncloud/android/utils/ThemeUtils.java +++ b/src/main/java/com/owncloud/android/utils/ThemeUtils.java @@ -51,6 +51,7 @@ import com.owncloud.android.MainApp; import com.owncloud.android.R; import com.owncloud.android.datamodel.FileDataStorageManager; +import com.owncloud.android.datamodel.FileDataStorageManagerImpl; import com.owncloud.android.lib.common.utils.Log_OC; import com.owncloud.android.lib.resources.status.OCCapability; import com.owncloud.android.ui.activity.ToolbarActivity; @@ -631,7 +632,7 @@ private static OCCapability getCapability(Account acc, Context context) { } if (account != null) { - FileDataStorageManager storageManager = new FileDataStorageManager(account, context.getContentResolver()); + FileDataStorageManager storageManager = new FileDataStorageManagerImpl(account, context); return storageManager.getCapability(account.name); } else { return new OCCapability(); diff --git a/src/test/java/com/owncloud/android/FileDataStorageManagerLocal.java b/src/test/java/com/owncloud/android/FileDataStorageManagerLocal.java new file mode 100644 index 000000000000..2b17a0e40647 --- /dev/null +++ b/src/test/java/com/owncloud/android/FileDataStorageManagerLocal.java @@ -0,0 +1,149 @@ +package com.owncloud.android; + +import android.accounts.Account; + +import com.owncloud.android.datamodel.FileDataStorageManager; +import com.owncloud.android.datamodel.OCFile; +import com.owncloud.android.lib.resources.shares.OCShare; +import com.owncloud.android.lib.resources.shares.ShareType; +import com.owncloud.android.lib.resources.status.OCCapability; + +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import androidx.annotation.Nullable; + +public class FileDataStorageManagerLocal implements FileDataStorageManager { + private Map pathToFile = new HashMap<>(); + private long currentMaxId = 0; + + public FileDataStorageManagerLocal() { + // always have root file + pathToFile.put("/", createOCFile("/")); + } + + @Override + public OCFile getFileByPath(String path) { + return pathToFile.get(path); + } + + @Override + public Account getAccount() { + throw new UnsupportedOperationException("to implement"); + } + + @Nullable + @Override + public OCFile getFileById(long id) { + for (Map.Entry entry : pathToFile.entrySet()) { + if (entry.getValue().getFileId() == id) { + return entry.getValue(); + } + } + + return null; + } + + @Override + public void saveConflict(OCFile file, String etagInConflict) { + throw new UnsupportedOperationException("to implement"); + } + + @Override + public void deleteFileInMediaScan(String path) { + throw new UnsupportedOperationException("to implement"); + } + + @Override + public boolean saveFile(OCFile file) { + pathToFile.put(file.getRemotePath(), file); + + return true; + } + + @Override + public boolean fileExists(long id) { + throw new UnsupportedOperationException("to implement"); + } + + @Override + public List getFolderContent(OCFile f, boolean onlyOnDevice) { + throw new UnsupportedOperationException("to implement"); + } + + @Override + public void saveFolder(OCFile folder, Collection updatedFiles, Collection filesToRemove) { + throw new UnsupportedOperationException("to implement"); + } + + @Override + public boolean removeFile(OCFile file, boolean removeDBData, boolean removeLocalCopy) { + throw new UnsupportedOperationException("to implement"); + } + + @Override + public boolean removeFolder(OCFile folder, boolean removeDBData, boolean removeLocalContent) { + throw new UnsupportedOperationException("to implement"); + } + + @Override + public void moveLocalFile(OCFile file, String targetPath, String targetParentPath) { + throw new UnsupportedOperationException("to implement"); + } + + @Override + public boolean saveShare(OCShare share) { + throw new UnsupportedOperationException("to implement"); + } + + @Override + public List getSharesWithForAFile(String filePath, String accountName) { + throw new UnsupportedOperationException("to implement"); + } + + @Override + public void removeShare(OCShare share) { + throw new UnsupportedOperationException("to implement"); + } + + @Override + public void copyLocalFile(OCFile file, String targetPath) { + throw new UnsupportedOperationException("to implement"); + } + + @Override + public OCShare getFirstShareByPathAndType(String path, ShareType type, String shareWith) { + throw new UnsupportedOperationException("to implement"); + } + + @Override + public OCCapability saveCapabilities(OCCapability capability) { + throw new UnsupportedOperationException("to implement"); + } + + @Override + public void saveSharesDB(List shares) { + throw new UnsupportedOperationException("to implement"); + } + + @Override + public void removeSharesForFile(String remotePath) { + throw new UnsupportedOperationException("to implement"); + } + + @Override + public OCShare getShareById(long id) { + throw new UnsupportedOperationException("to implement"); + } + + public OCFile createOCFile(String path) { + OCFile file = new OCFile(path); + + file.setFileId(currentMaxId); + currentMaxId++; + + return file; + } +} diff --git a/src/test/java/com/owncloud/android/operations/CreateFolderOperationTest.java b/src/test/java/com/owncloud/android/operations/CreateFolderOperationTest.java new file mode 100644 index 000000000000..c5786dfe1ec2 --- /dev/null +++ b/src/test/java/com/owncloud/android/operations/CreateFolderOperationTest.java @@ -0,0 +1,72 @@ +package com.owncloud.android.operations; + +import com.owncloud.android.FileDataStorageManagerLocal; +import com.owncloud.android.datamodel.FileDataStorageManager; +import com.owncloud.android.lib.common.OwnCloudClient; +import com.owncloud.android.lib.common.operations.RemoteOperationResult; +import com.owncloud.android.lib.resources.files.CreateFolderRemoteOperation; +import com.owncloud.android.lib.resources.files.ReadFolderRemoteOperation; +import com.owncloud.android.lib.resources.files.model.RemoteFile; + +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +import java.util.ArrayList; + +import static junit.framework.TestCase.assertTrue; +import static org.junit.Assert.assertNull; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.when; + +public class CreateFolderOperationTest { + private FileDataStorageManager fileDataStorageManager = new FileDataStorageManagerLocal(); + + @Mock OwnCloudClient client; + + @Mock CreateFolderRemoteOperation createFolderRemoteOperation; + @Mock ReadFolderRemoteOperation readFolderRemoteOperation; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + } + + @Test + public void testCreateFolder() { + // setup + String path = "/testFolder/"; + CreateFolderOperation sut = spy(new CreateFolderOperation(path, true)); + + when(createFolderRemoteOperation.execute(any())) + .thenReturn(new RemoteOperationResult(RemoteOperationResult.ResultCode.OK)); + + RemoteOperationResult result = new RemoteOperationResult(RemoteOperationResult.ResultCode.OK); + ArrayList list = new ArrayList<>(); + list.add(new RemoteFile("/testFolder")); + + result.setData(list); + + when(readFolderRemoteOperation.execute(any(OwnCloudClient.class))).thenReturn(result); + doReturn(createFolderRemoteOperation). + when(sut).createCreateFolderRemoteOperation(any(String.class), any(Boolean.class)); + doReturn(readFolderRemoteOperation) + .when(sut).createReadFolderRemoteOperation(any(String.class)); + + // tests + // folder does not exist yet + assertNull(fileDataStorageManager.getFileByPath(path)); + + // run + RemoteOperationResult syncResult = sut.execute(client, fileDataStorageManager); + + // verify + assertTrue(syncResult.isSuccess()); + + // folder exists + assertTrue(fileDataStorageManager.getFileByPath(path).isFolder()); + } +} From 6da3a0766b5007815daf695cdd7f2bb69d56a316 Mon Sep 17 00:00:00 2001 From: tobiasKaminsky Date: Fri, 13 Dec 2019 07:44:46 +0100 Subject: [PATCH 2/6] update tests Signed-off-by: tobiasKaminsky --- .../operations/CreateFolderOperation.java | 6 +- .../android/FileDataStorageManagerLocal.java | 93 +++++++++++++++++++ .../operations/CreateFolderOperationTest.java | 7 +- 3 files changed, 102 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/owncloud/android/operations/CreateFolderOperation.java b/src/main/java/com/owncloud/android/operations/CreateFolderOperation.java index 2e01c9415661..c87d69891f0c 100644 --- a/src/main/java/com/owncloud/android/operations/CreateFolderOperation.java +++ b/src/main/java/com/owncloud/android/operations/CreateFolderOperation.java @@ -71,7 +71,7 @@ public RemoteOperationResult run(OwnCloudClient client) { RemoteOperationResult result = createCreateFolderRemoteOperation(mRemotePath, mCreateFullPath).execute(client); if (result.isSuccess()) { - RemoteOperationResult remoteFolderOperationResult = new ReadFolderRemoteOperation(mRemotePath) + RemoteOperationResult remoteFolderOperationResult = createReadFolderRemoteOperation(mRemotePath) .execute(client); createdRemoteFolder = (RemoteFile) remoteFolderOperationResult.getData().get(0); @@ -83,11 +83,11 @@ public RemoteOperationResult run(OwnCloudClient client) { return result; } - public CreateFolderRemoteOperation createCreateFolderRemoteOperation(String remotePath, boolean createFullPath) { + CreateFolderRemoteOperation createCreateFolderRemoteOperation(String remotePath, boolean createFullPath) { return new CreateFolderRemoteOperation(remotePath, createFullPath); } - public ReadFolderRemoteOperation createReadFolderRemoteOperation(String remotePath) { + ReadFolderRemoteOperation createReadFolderRemoteOperation(String remotePath) { return new ReadFolderRemoteOperation(remotePath); } diff --git a/src/test/java/com/owncloud/android/FileDataStorageManagerLocal.java b/src/test/java/com/owncloud/android/FileDataStorageManagerLocal.java index 2b17a0e40647..d2136e026ccf 100644 --- a/src/test/java/com/owncloud/android/FileDataStorageManagerLocal.java +++ b/src/test/java/com/owncloud/android/FileDataStorageManagerLocal.java @@ -1,18 +1,24 @@ package com.owncloud.android; import android.accounts.Account; +import android.content.ContentValues; +import android.content.OperationApplicationException; +import android.os.RemoteException; import com.owncloud.android.datamodel.FileDataStorageManager; import com.owncloud.android.datamodel.OCFile; +import com.owncloud.android.datamodel.VirtualFolderType; import com.owncloud.android.lib.resources.shares.OCShare; import com.owncloud.android.lib.resources.shares.ShareType; import com.owncloud.android.lib.resources.status.OCCapability; +import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; +import androidx.annotation.NonNull; import androidx.annotation.Nullable; public class FileDataStorageManagerLocal implements FileDataStorageManager { @@ -68,6 +74,11 @@ public boolean fileExists(long id) { throw new UnsupportedOperationException("to implement"); } + @Override + public boolean fileExists(String path) { + throw new UnsupportedOperationException("to implement"); + } + @Override public List getFolderContent(OCFile f, boolean onlyOnDevice) { throw new UnsupportedOperationException("to implement"); @@ -123,6 +134,12 @@ public OCCapability saveCapabilities(OCCapability capability) { throw new UnsupportedOperationException("to implement"); } + @NonNull + @Override + public OCCapability getCapability(String accountName) { + throw new UnsupportedOperationException("to implement"); + } + @Override public void saveSharesDB(List shares) { throw new UnsupportedOperationException("to implement"); @@ -138,6 +155,82 @@ public OCShare getShareById(long id) { throw new UnsupportedOperationException("to implement"); } + @Override + public void triggerMediaScan(String path) { + throw new UnsupportedOperationException("to implement"); + } + + @Override + public OCFile getFileByLocalPath(String path) { + throw new UnsupportedOperationException("to implement"); + } + + @Nullable + @Override + public OCFile getFileByRemoteId(String remoteId) { + throw new UnsupportedOperationException("to implement"); + } + + @Override + public List getFolderImages(OCFile folder, boolean onlyOnDevice) { + throw new UnsupportedOperationException("to implement"); + } + + @Override + public OCFile saveFileWithParent(OCFile file) { + throw new UnsupportedOperationException("to implement"); + } + + @Override + public void saveNewFile(OCFile newFile) { + throw new UnsupportedOperationException("to implement"); + } + + @Override + public void migrateStoredFiles(String srcPath, String dstPath) throws RemoteException, OperationApplicationException { + throw new UnsupportedOperationException("to implement"); + } + + @Override + public void saveShares(Collection shares) { + throw new UnsupportedOperationException("to implement"); + } + + @Override + public void updateSharedFiles(Collection sharedFiles) { + throw new UnsupportedOperationException("to implement"); + } + + @Override + public void saveSharesInFolder(ArrayList shares, OCFile folder) { + throw new UnsupportedOperationException("to implement"); + } + + @Override + public void deleteVirtuals(VirtualFolderType type) { + throw new UnsupportedOperationException("to implement"); + } + + @Override + public void saveVirtuals(VirtualFolderType type, List values) { + throw new UnsupportedOperationException("to implement"); + } + + @Override + public void saveVirtual(VirtualFolderType type, OCFile file) { + throw new UnsupportedOperationException("to implement"); + } + + @Override + public List getVirtualFolderContent(VirtualFolderType type, boolean onlyImages) { + throw new UnsupportedOperationException("to implement"); + } + + @Override + public void deleteAllFiles() { + throw new UnsupportedOperationException("to implement"); + } + public OCFile createOCFile(String path) { OCFile file = new OCFile(path); diff --git a/src/test/java/com/owncloud/android/operations/CreateFolderOperationTest.java b/src/test/java/com/owncloud/android/operations/CreateFolderOperationTest.java index c5786dfe1ec2..ce984e850748 100644 --- a/src/test/java/com/owncloud/android/operations/CreateFolderOperationTest.java +++ b/src/test/java/com/owncloud/android/operations/CreateFolderOperationTest.java @@ -1,5 +1,6 @@ package com.owncloud.android.operations; +import com.nextcloud.client.logger.Logger; import com.owncloud.android.FileDataStorageManagerLocal; import com.owncloud.android.datamodel.FileDataStorageManager; import com.owncloud.android.lib.common.OwnCloudClient; @@ -30,6 +31,8 @@ public class CreateFolderOperationTest { @Mock CreateFolderRemoteOperation createFolderRemoteOperation; @Mock ReadFolderRemoteOperation readFolderRemoteOperation; + @Mock Logger logger; + @Before public void setUp() { MockitoAnnotations.initMocks(this); @@ -41,7 +44,9 @@ public void testCreateFolder() { String path = "/testFolder/"; CreateFolderOperation sut = spy(new CreateFolderOperation(path, true)); - when(createFolderRemoteOperation.execute(any())) + sut.logger = logger; + + when(createFolderRemoteOperation.execute(any(OwnCloudClient.class))) .thenReturn(new RemoteOperationResult(RemoteOperationResult.ResultCode.OK)); RemoteOperationResult result = new RemoteOperationResult(RemoteOperationResult.ResultCode.OK); From 1e2cbff1c81c7d2e494a34ac595fdfb6d7c75983 Mon Sep 17 00:00:00 2001 From: tobiasKaminsky Date: Fri, 13 Dec 2019 08:14:34 +0100 Subject: [PATCH 3/6] fix during CI Signed-off-by: tobiasKaminsky --- .../com/owncloud/android/datamodel/FileDataStorageManager.java | 3 +-- .../owncloud/android/datamodel/FileDataStorageManagerImpl.java | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/owncloud/android/datamodel/FileDataStorageManager.java b/src/main/java/com/owncloud/android/datamodel/FileDataStorageManager.java index 64c5e6a18868..fb4c8d74b50d 100644 --- a/src/main/java/com/owncloud/android/datamodel/FileDataStorageManager.java +++ b/src/main/java/com/owncloud/android/datamodel/FileDataStorageManager.java @@ -9,7 +9,6 @@ import com.owncloud.android.lib.resources.shares.ShareType; import com.owncloud.android.lib.resources.status.OCCapability; -import java.util.ArrayList; import java.util.Collection; import java.util.List; @@ -86,7 +85,7 @@ public interface FileDataStorageManager { void updateSharedFiles(Collection sharedFiles); - void saveSharesInFolder(ArrayList shares, OCFile folder); + void saveSharesInFolder(List shares, OCFile folder); void deleteVirtuals(VirtualFolderType type); diff --git a/src/main/java/com/owncloud/android/datamodel/FileDataStorageManagerImpl.java b/src/main/java/com/owncloud/android/datamodel/FileDataStorageManagerImpl.java index c2ea1f1928c7..718ea854025c 100644 --- a/src/main/java/com/owncloud/android/datamodel/FileDataStorageManagerImpl.java +++ b/src/main/java/com/owncloud/android/datamodel/FileDataStorageManagerImpl.java @@ -1573,7 +1573,7 @@ public void removeSharesForFile(String remotePath) { } - public void saveSharesInFolder(ArrayList shares, OCFile folder) { + public void saveSharesInFolder(List shares, OCFile folder) { resetShareFlagsInFolder(folder); ArrayList operations = new ArrayList<>(); operations = prepareRemoveSharesInFolder(folder, operations); From 688a44dd61f5bef573779d7f425852c3d2929f87 Mon Sep 17 00:00:00 2001 From: tobiasKaminsky Date: Fri, 13 Dec 2019 08:51:35 +0100 Subject: [PATCH 4/6] remove annotation Signed-off-by: tobiasKaminsky --- .../ui/activity/ErrorsWhileCopyingHandlerActivity.java | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/main/java/com/owncloud/android/ui/activity/ErrorsWhileCopyingHandlerActivity.java b/src/main/java/com/owncloud/android/ui/activity/ErrorsWhileCopyingHandlerActivity.java index e552eeff23d8..26649dea560c 100644 --- a/src/main/java/com/owncloud/android/ui/activity/ErrorsWhileCopyingHandlerActivity.java +++ b/src/main/java/com/owncloud/android/ui/activity/ErrorsWhileCopyingHandlerActivity.java @@ -45,8 +45,6 @@ import com.owncloud.android.utils.DisplayUtils; import com.owncloud.android.utils.FileStorageUtils; -import org.jetbrains.annotations.NotNull; - import java.io.File; import java.util.List; @@ -153,9 +151,8 @@ public boolean isEnabled(int position) { /** * {@inheritDoc} */ - @NotNull @Override - public View getView (int position, View convertView, @NonNull ViewGroup parent) { + public View getView(int position, View convertView, @NonNull ViewGroup parent) { View view = convertView; if (view == null) { LayoutInflater vi = (LayoutInflater) getSystemService( From aaba0a8a5389d3b96776f2bbec9302e10be1d414 Mon Sep 17 00:00:00 2001 From: tobiasKaminsky Date: Thu, 19 Dec 2019 08:27:36 +0100 Subject: [PATCH 5/6] Fix unittests Signed-off-by: tobiasKaminsky --- .../java/com/owncloud/android/FileDataStorageManagerLocal.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/test/java/com/owncloud/android/FileDataStorageManagerLocal.java b/src/test/java/com/owncloud/android/FileDataStorageManagerLocal.java index d2136e026ccf..217796236265 100644 --- a/src/test/java/com/owncloud/android/FileDataStorageManagerLocal.java +++ b/src/test/java/com/owncloud/android/FileDataStorageManagerLocal.java @@ -12,7 +12,6 @@ import com.owncloud.android.lib.resources.shares.ShareType; import com.owncloud.android.lib.resources.status.OCCapability; -import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.List; @@ -202,7 +201,7 @@ public void updateSharedFiles(Collection sharedFiles) { } @Override - public void saveSharesInFolder(ArrayList shares, OCFile folder) { + public void saveSharesInFolder(List shares, OCFile folder) { throw new UnsupportedOperationException("to implement"); } From fb969cc6a8f7143eee388dd83195c316ad6193d8 Mon Sep 17 00:00:00 2001 From: tobiasKaminsky Date: Fri, 10 Jan 2020 20:19:58 +0100 Subject: [PATCH 6/6] wip Signed-off-by: tobiasKaminsky --- .../com/owncloud/android/ui/adapter/OCFileListAdapter.java | 2 +- .../ui/dialog/ChooseRichDocumentsTemplateDialogFragment.java | 5 +++-- .../android/ui/dialog/ChooseTemplateDialogFragment.java | 5 +++-- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/owncloud/android/ui/adapter/OCFileListAdapter.java b/src/main/java/com/owncloud/android/ui/adapter/OCFileListAdapter.java index 95bd799906d2..3832ba3f07e4 100644 --- a/src/main/java/com/owncloud/android/ui/adapter/OCFileListAdapter.java +++ b/src/main/java/com/owncloud/android/ui/adapter/OCFileListAdapter.java @@ -798,7 +798,7 @@ public void setData(List objects, ExtendedListFragment.SearchType search } if (mStorageManager == null) { - mStorageManager = new FileDataStorageManagerImpl(user.toPlatformAccount(), activity.getContentResolver()); + mStorageManager = new FileDataStorageManagerImpl(user.toPlatformAccount(), activity); } if (clear) { diff --git a/src/main/java/com/owncloud/android/ui/dialog/ChooseRichDocumentsTemplateDialogFragment.java b/src/main/java/com/owncloud/android/ui/dialog/ChooseRichDocumentsTemplateDialogFragment.java index f75d371d039d..564f174c1318 100644 --- a/src/main/java/com/owncloud/android/ui/dialog/ChooseRichDocumentsTemplateDialogFragment.java +++ b/src/main/java/com/owncloud/android/ui/dialog/ChooseRichDocumentsTemplateDialogFragment.java @@ -44,6 +44,7 @@ import com.owncloud.android.MainApp; import com.owncloud.android.R; import com.owncloud.android.datamodel.FileDataStorageManager; +import com.owncloud.android.datamodel.FileDataStorageManagerImpl; import com.owncloud.android.datamodel.OCFile; import com.owncloud.android.datamodel.Template; import com.owncloud.android.files.CreateFileFromTemplateOperation; @@ -249,9 +250,9 @@ protected String doInBackground(Void... voids) { OCFile temp = FileStorageUtils.fillOCFile((RemoteFile) newFileResult.getData().get(0)); if (chooseTemplateDialogFragmentWeakReference.get() != null) { - FileDataStorageManager storageManager = new FileDataStorageManager( + FileDataStorageManager storageManager = new FileDataStorageManagerImpl( user.toPlatformAccount(), - chooseTemplateDialogFragmentWeakReference.get().requireContext().getContentResolver()); + chooseTemplateDialogFragmentWeakReference.get().requireContext()); storageManager.saveFile(temp); file = storageManager.getFileByPath(path); diff --git a/src/main/java/com/owncloud/android/ui/dialog/ChooseTemplateDialogFragment.java b/src/main/java/com/owncloud/android/ui/dialog/ChooseTemplateDialogFragment.java index 4be10da5cf11..764caea5af9f 100644 --- a/src/main/java/com/owncloud/android/ui/dialog/ChooseTemplateDialogFragment.java +++ b/src/main/java/com/owncloud/android/ui/dialog/ChooseTemplateDialogFragment.java @@ -47,6 +47,7 @@ import com.owncloud.android.MainApp; import com.owncloud.android.R; import com.owncloud.android.datamodel.FileDataStorageManager; +import com.owncloud.android.datamodel.FileDataStorageManagerImpl; import com.owncloud.android.datamodel.OCFile; import com.owncloud.android.lib.common.Creator; import com.owncloud.android.lib.common.OwnCloudClient; @@ -253,9 +254,9 @@ protected String doInBackground(Void... voids) { OCFile temp = FileStorageUtils.fillOCFile((RemoteFile) newFileResult.getData().get(0)); if (chooseTemplateDialogFragmentWeakReference.get() != null) { - FileDataStorageManager storageManager = new FileDataStorageManager( + FileDataStorageManager storageManager = new FileDataStorageManagerImpl( user.toPlatformAccount(), - chooseTemplateDialogFragmentWeakReference.get().requireContext().getContentResolver()); + chooseTemplateDialogFragmentWeakReference.get().requireContext()); storageManager.saveFile(temp); file = storageManager.getFileByPath(path);