123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366 |
- /**
- * Nextcloud Android client application
- *
- * Copyright (C) 2016 Andy Scherzinger
- * Copyright (C) 2016 Nextcloud.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or any later version.
- *
- * 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 AFFERO GENERAL PUBLIC LICENSE for more details.
- *
- * You should have received a copy of the GNU Affero General Public
- * License along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
- package com.owncloud.android.datamodel;
- import android.accounts.Account;
- import android.content.ContentResolver;
- import android.content.ContentValues;
- import android.content.Context;
- import android.database.Cursor;
- import android.net.Uri;
- import android.support.annotation.NonNull;
- import com.owncloud.android.MainApp;
- import com.owncloud.android.db.PreferenceManager;
- import com.owncloud.android.db.ProviderMeta;
- import com.owncloud.android.lib.common.utils.Log_OC;
- import java.io.File;
- import java.util.ArrayList;
- import java.util.List;
- import java.util.Observable;
- /**
- * Database provider for handling the persistence aspects of {@link SyncedFolder}s.
- */
- public class SyncedFolderProvider extends Observable {
- static private final String TAG = SyncedFolderProvider.class.getSimpleName();
- private ContentResolver mContentResolver;
- /**
- * constructor.
- *
- * @param contentResolver the ContentResolver to work with.
- */
- public SyncedFolderProvider(ContentResolver contentResolver) {
- if (contentResolver == null) {
- throw new IllegalArgumentException("Cannot create an instance with a NULL contentResolver");
- }
- mContentResolver = contentResolver;
- }
- /**
- * Stores an media folder sync object in database.
- *
- * @param syncedFolder synced folder to store
- * @return synced folder id, -1 if the insert process fails.
- */
- public long storeFolderSync(SyncedFolder syncedFolder) {
- Log_OC.v(TAG, "Inserting " + syncedFolder.getLocalPath() + " with enabled=" + syncedFolder.isEnabled());
- ContentValues cv = createContentValuesFromSyncedFolder(syncedFolder);
- Uri result = mContentResolver.insert(ProviderMeta.ProviderTableMeta.CONTENT_URI_SYNCED_FOLDERS, cv);
- if (result != null) {
- notifyFolderSyncObservers(syncedFolder);
- return Long.parseLong(result.getPathSegments().get(1));
- } else {
- Log_OC.e(TAG, "Failed to insert item " + syncedFolder.getLocalPath() + " into folder sync db.");
- return -1;
- }
- }
- /**
- * get all synced folder entries.
- *
- * @return all synced folder entries, empty if none have been found
- */
- public List<SyncedFolder> getSyncedFolders() {
- Cursor cursor = mContentResolver.query(
- ProviderMeta.ProviderTableMeta.CONTENT_URI_SYNCED_FOLDERS,
- null,
- "1=1",
- null,
- null
- );
- if (cursor != null) {
- List<SyncedFolder> list = new ArrayList<>(cursor.getCount());
- if (cursor.moveToFirst()) {
- do {
- SyncedFolder syncedFolder = createSyncedFolderFromCursor(cursor);
- if (syncedFolder == null) {
- Log_OC.e(TAG, "SyncedFolder could not be created from cursor");
- } else {
- list.add(cursor.getPosition(), syncedFolder);
- }
- } while (cursor.moveToNext());
- }
- cursor.close();
- return list;
- } else {
- Log_OC.e(TAG, "DB error creating read all cursor for synced folders.");
- }
- return new ArrayList<>(0);
- }
- /**
- * Update upload status of file uniquely referenced by id.
- *
- * @param id folder sync id.
- * @param enabled new status.
- * @return the number of rows updated.
- */
- public int updateFolderSyncEnabled(long id, Boolean enabled) {
- Log_OC.v(TAG, "Storing sync folder id" + id + " with enabled=" + enabled);
- int result = 0;
- Cursor cursor = mContentResolver.query(
- ProviderMeta.ProviderTableMeta.CONTENT_URI_SYNCED_FOLDERS,
- null,
- ProviderMeta.ProviderTableMeta._ID + "=?",
- new String[]{String.valueOf(id)},
- null
- );
- if (cursor != null && cursor.getCount() == 1) {
- while (cursor.moveToNext()) {
- // read sync folder object and update
- SyncedFolder syncedFolder = createSyncedFolderFromCursor(cursor);
- syncedFolder.setEnabled(enabled);
- // update sync folder object in db
- result = updateSyncFolder(syncedFolder);
- cursor.close();
- }
- } else {
- if (cursor == null) {
- Log_OC.e(TAG, "Sync folder db cursor for ID=" + id + " in NULL.");
- } else {
- Log_OC.e(TAG, cursor.getCount() + " items for id=" + id + " available in sync folder database. " +
- "Expected 1. Failed to update sync folder db.");
- }
- }
- return result;
- }
- /**
- * find a synced folder by local path.
- *
- * @param localPath the local path of the local folder
- * @return the synced folder if found, else null
- */
- public SyncedFolder findByLocalPath(String localPath) {
- SyncedFolder result = null;
- Cursor cursor = mContentResolver.query(
- ProviderMeta.ProviderTableMeta.CONTENT_URI_SYNCED_FOLDERS,
- null,
- ProviderMeta.ProviderTableMeta.SYNCED_FOLDER_LOCAL_PATH + "== \"" + localPath + "\"",
- null,
- null
- );
- if (cursor != null && cursor.getCount() == 1) {
- result = createSyncedFolderFromCursor(cursor);
- cursor.close();
- } else {
- if (cursor == null) {
- Log_OC.e(TAG, "Sync folder db cursor for local path=" + localPath + " in NULL.");
- } else {
- Log_OC.e(TAG, cursor.getCount() + " items for local path=" + localPath
- + " available in sync folder db. Expected 1. Failed to update sync folder db.");
- }
- }
- return result;
- }
- /**
- * Delete all synced folders for an account
- *
- * @param account whose synced folders should be deleted
- */
- public int deleteSyncFoldersForAccount(Account account) {
- int result = mContentResolver.delete(
- ProviderMeta.ProviderTableMeta.CONTENT_URI_SYNCED_FOLDERS,
- ProviderMeta.ProviderTableMeta.SYNCED_FOLDER_ACCOUNT + " = ?",
- new String[]{String.valueOf(account.name)}
- );
- return result;
- }
- /**
- * Delete a synced folder from the db
- *
- * @param id for the synced folder.
- */
- private int deleteSyncFolderWithId(long id) {
- int result = mContentResolver.delete(
- ProviderMeta.ProviderTableMeta.CONTENT_URI_SYNCED_FOLDERS,
- ProviderMeta.ProviderTableMeta._ID + " = ?",
- new String[]{String.valueOf(id)}
- );
- return result;
- }
- /**
- * Try to figure out if a path exists for synced folder, and if not, go one folder back
- * Otherwise, delete the entry
- *
- * @param context the context.
- */
- public void updateAutoUploadPaths(Context context) {
- List<SyncedFolder> syncedFolders = getSyncedFolders();
- for (int i = 0; i < syncedFolders.size(); i++) {
- SyncedFolder syncedFolder = syncedFolders.get(i);
- if (!new File(syncedFolder.getLocalPath()).exists()) {
- String localPath = syncedFolder.getLocalPath();
- if (localPath.endsWith("/")) {
- localPath = localPath.substring(0, localPath.lastIndexOf("/"));
- }
- localPath = localPath.substring(0, localPath.lastIndexOf("/"));
- if (new File(localPath).exists()) {
- syncedFolders.get(i).setLocalPath(localPath);
- updateSyncFolder(syncedFolder);
- } else {
- deleteSyncFolderWithId(syncedFolder.getId());
- }
- }
- }
- if (context != null) {
- PreferenceManager.setAutoUploadPathsUpdate(context, true);
- }
- }
- /**
- * delete any records of synchronized folders that are not within the given list of ids.
- *
- * @param context the context.
- * @param ids the list of ids to be excluded from deletion.
- * @return number of deleted records.
- */
- public int deleteSyncedFoldersNotInList(Context context, ArrayList<Long> ids) {
- int result = mContentResolver.delete(
- ProviderMeta.ProviderTableMeta.CONTENT_URI_SYNCED_FOLDERS,
- ProviderMeta.ProviderTableMeta._ID + " NOT IN (?)",
- new String[]{String.valueOf(ids)}
- );
- if (result > 0 && context != null) {
- PreferenceManager.setLegacyClean(context, true);
- }
- return result;
- }
- /**
- * update given synced folder.
- *
- * @param syncedFolder the synced folder to be updated.
- * @return the number of rows updated.
- */
- public int updateSyncFolder(SyncedFolder syncedFolder) {
- Log_OC.v(TAG, "Updating " + syncedFolder.getLocalPath() + " with enabled=" + syncedFolder.isEnabled());
- ContentValues cv = createContentValuesFromSyncedFolder(syncedFolder);
- int result = mContentResolver.update(
- ProviderMeta.ProviderTableMeta.CONTENT_URI_SYNCED_FOLDERS,
- cv,
- ProviderMeta.ProviderTableMeta._ID + "=?",
- new String[]{String.valueOf(syncedFolder.getId())}
- );
- if (result > 0) {
- notifyFolderSyncObservers(syncedFolder);
- }
- return result;
- }
- /**
- * maps a cursor into a SyncedFolder object.
- *
- * @param cursor the db cursor
- * @return the mapped SyncedFolder, null if cursor is null
- */
- private SyncedFolder createSyncedFolderFromCursor(Cursor cursor) {
- SyncedFolder syncedFolder = null;
- if (cursor != null) {
- long id = cursor.getLong(cursor.getColumnIndex(ProviderMeta.ProviderTableMeta._ID));
- String localPath = cursor.getString(cursor.getColumnIndex(
- ProviderMeta.ProviderTableMeta.SYNCED_FOLDER_LOCAL_PATH));
- String remotePath = cursor.getString(cursor.getColumnIndex(
- ProviderMeta.ProviderTableMeta.SYNCED_FOLDER_REMOTE_PATH));
- Boolean wifiOnly = cursor.getInt(cursor.getColumnIndex(
- ProviderMeta.ProviderTableMeta.SYNCED_FOLDER_WIFI_ONLY)) == 1;
- Boolean chargingOnly = cursor.getInt(cursor.getColumnIndex(
- ProviderMeta.ProviderTableMeta.SYNCED_FOLDER_CHARGING_ONLY)) == 1;
- Boolean subfolderByDate = cursor.getInt(cursor.getColumnIndex(
- ProviderMeta.ProviderTableMeta.SYNCED_FOLDER_SUBFOLDER_BY_DATE)) == 1;
- String accountName = cursor.getString(cursor.getColumnIndex(
- ProviderMeta.ProviderTableMeta.SYNCED_FOLDER_ACCOUNT));
- Integer uploadAction = cursor.getInt(cursor.getColumnIndex(
- ProviderMeta.ProviderTableMeta.SYNCED_FOLDER_UPLOAD_ACTION));
- Boolean enabled = cursor.getInt(cursor.getColumnIndex(
- ProviderMeta.ProviderTableMeta.SYNCED_FOLDER_ENABLED)) == 1;
- syncedFolder = new SyncedFolder(id, localPath, remotePath, wifiOnly, chargingOnly, subfolderByDate,
- accountName, uploadAction, enabled);
- }
- return syncedFolder;
- }
- /**
- * create ContentValues object based on given SyncedFolder.
- *
- * @param syncedFolder the synced folder
- * @return the corresponding ContentValues object
- */
- @NonNull
- private ContentValues createContentValuesFromSyncedFolder(SyncedFolder syncedFolder) {
- ContentValues cv = new ContentValues();
- cv.put(ProviderMeta.ProviderTableMeta.SYNCED_FOLDER_LOCAL_PATH, syncedFolder.getLocalPath());
- cv.put(ProviderMeta.ProviderTableMeta.SYNCED_FOLDER_REMOTE_PATH, syncedFolder.getRemotePath());
- cv.put(ProviderMeta.ProviderTableMeta.SYNCED_FOLDER_WIFI_ONLY, syncedFolder.getWifiOnly());
- cv.put(ProviderMeta.ProviderTableMeta.SYNCED_FOLDER_CHARGING_ONLY, syncedFolder.getChargingOnly());
- cv.put(ProviderMeta.ProviderTableMeta.SYNCED_FOLDER_ENABLED, syncedFolder.isEnabled());
- cv.put(ProviderMeta.ProviderTableMeta.SYNCED_FOLDER_SUBFOLDER_BY_DATE, syncedFolder.getSubfolderByDate());
- cv.put(ProviderMeta.ProviderTableMeta.SYNCED_FOLDER_ACCOUNT, syncedFolder.getAccount());
- cv.put(ProviderMeta.ProviderTableMeta.SYNCED_FOLDER_UPLOAD_ACTION, syncedFolder.getUploadAction());
- return cv;
- }
- /**
- * Inform all observers about data change.
- *
- * @param syncedFolder changed, synchronized folder
- */
- private void notifyFolderSyncObservers(SyncedFolder syncedFolder) {
- if (syncedFolder != null) {
- MainApp.getSyncedFolderObserverService().restartObserver(syncedFolder);
- Log_OC.d(TAG, "notifying folder sync data observers for changed/added: " + syncedFolder.getLocalPath());
- }
- }
- }
|