Loading app/src/main/java/foundation/e/drive/contentScanner/AbstractContentScanner.java +6 −9 Original line number Diff line number Diff line Loading @@ -7,7 +7,6 @@ */ package foundation.e.drive.contentScanner; import android.accounts.Account; import android.content.Context; import com.owncloud.android.lib.resources.files.FileUtils; Loading @@ -27,18 +26,16 @@ import foundation.e.drive.models.SyncedFolder; */ public abstract class AbstractContentScanner<T> { protected final Context context; protected final Account account; protected final HashMap<Integer, SyncRequest> syncRequests; protected final List<SyncedFolder> syncedFolders; /** * @param context Context used to access Database, etc. * @param account Account used to checked if user has change some synchronization's settings * @param syncedFolders List of SyncedFolders */ protected AbstractContentScanner(Context context, Account account, List<SyncedFolder> syncedFolders) { protected AbstractContentScanner(Context context, List<SyncedFolder> syncedFolders) { syncRequests = new HashMap<>(); this.context = context; this.account = account; this.syncedFolders = syncedFolders; } Loading Loading @@ -67,7 +64,7 @@ public abstract class AbstractContentScanner<T> { } for (SyncedFileState remainingFileState : fileStates) { onMissingRemoteFile(remainingFileState); onMissingFile(remainingFileState); } return syncRequests; }; Loading @@ -93,7 +90,7 @@ public abstract class AbstractContentScanner<T> { * When a file doesn't exist anymore we remove it from device/cloud (depending of implementation) & from Database * @param fileState SyncedFileState for which we lack remote file */ protected abstract void onMissingRemoteFile(SyncedFileState fileState); protected abstract void onMissingFile(SyncedFileState fileState); /** * A new file has been found Loading app/src/main/java/foundation/e/drive/contentScanner/LocalContentScanner.java +7 −9 Original line number Diff line number Diff line /* * Copyright © ECORP SAS 2022. * Copyright © MURENA SAS 2022. * All rights reserved. This program and the accompanying materials * are made available under the terms of the GNU Public License v3.0 * which accompanies this distribution, and is available at Loading @@ -7,7 +7,6 @@ */ package foundation.e.drive.contentScanner; import android.accounts.Account; import android.content.Context; import java.io.File; Loading @@ -24,16 +23,17 @@ import timber.log.Timber; /** * Class to encapsulate function about scanning local file and * create syncRequest when needed * @author vincent Bourgmayer */ public class LocalContentScanner extends AbstractContentScanner<File>{ public LocalContentScanner(Context context, Account account, List<SyncedFolder> syncedFolders) { super(context, account, syncedFolders); public LocalContentScanner(Context context, List<SyncedFolder> syncedFolders) { super(context, syncedFolders); Timber.tag(LocalContentScanner.class.getSimpleName()); } @Override protected void onMissingRemoteFile(SyncedFileState fileState) { protected void onMissingFile(SyncedFileState fileState) { if (!fileState.hasBeenSynchronizedOnce()) { return; } Loading Loading @@ -61,11 +61,9 @@ public class LocalContentScanner extends AbstractContentScanner<File>{ if (parentDir.isScanLocal()) scannableValue += 2; } //create the syncedFile State final SyncedFileState newSyncedFileState = new SyncedFileState(-1, file.getName(), filePath, parentDir.getRemoteFolder() + file.getName(), "", 0, parentDir.getId(), parentDir.isMediaType(),scannableValue); //Store it in DB int storedId = DbHelper.manageSyncedFileStateDB(newSyncedFileState, "INSERT", context); final int storedId = DbHelper.manageSyncedFileStateDB(newSyncedFileState, "INSERT", context); if (storedId > 0) { newSyncedFileState.setId( storedId ); Timber.d("Add upload SyncRequest for new file %s", filePath); Loading app/src/main/java/foundation/e/drive/contentScanner/RemoteContentScanner.java +7 −35 Original line number Diff line number Diff line /* * Copyright © ECORP SAS 2022. * Copyright © MURENA SAS 2022. * All rights reserved. This program and the accompanying materials * are made available under the terms of the GNU Public License v3.0 * which accompanies this distribution, and is available at Loading @@ -7,19 +7,18 @@ */ package foundation.e.drive.contentScanner; import static foundation.e.drive.models.SyncRequest.Type.LOCAL_DELETE; import static foundation.e.drive.utils.FileDiffUtils.getActionForFileDiff; import android.accounts.Account; import android.content.Context; import android.provider.MediaStore; import com.owncloud.android.lib.resources.files.model.RemoteFile; import java.io.File; import java.util.List; import foundation.e.drive.database.DbHelper; import foundation.e.drive.models.DownloadRequest; import foundation.e.drive.models.SyncRequest; import foundation.e.drive.models.SyncedFileState; import foundation.e.drive.models.SyncedFolder; import foundation.e.drive.utils.CommonUtils; Loading @@ -34,10 +33,9 @@ public class RemoteContentScanner extends AbstractContentScanner<RemoteFile> { /** * @param context Context used to access Database, etc. * @param account Account used to checked if user has change some synchronization's settings */ public RemoteContentScanner(Context context, Account account, List<SyncedFolder> syncedFolders) { super(context, account, syncedFolders); public RemoteContentScanner(Context context, List<SyncedFolder> syncedFolders) { super(context, syncedFolders); Timber.tag(RemoteContentScanner.class.getSimpleName()); } Loading Loading @@ -74,7 +72,6 @@ public class RemoteContentScanner extends AbstractContentScanner<RemoteFile> { final SyncedFileState newFileState = new SyncedFileState(-1, fileName, parentDir.getLocalFolder() + fileName, remoteFilePath, file.getEtag(), 0, parentDir.getId(), parentDir.isMediaType(), scannableValue); //Store it in DB final int storedId = DbHelper.manageSyncedFileStateDB(newFileState, "INSERT", context); if (storedId > 0) { newFileState.setId(storedId); Loading @@ -84,33 +81,8 @@ public class RemoteContentScanner extends AbstractContentScanner<RemoteFile> { } @Override protected void onMissingRemoteFile(SyncedFileState fileState) { if (!CommonUtils.isThisSyncAllowed(account, fileState.isMediaType())) { Timber.d("Sync of current file: %s isn't allowed", fileState.getName()); return; } if (!fileState.hasBeenSynchronizedOnce()) { return; } final File file = new File(fileState.getLocalPath()); if (!file.exists()) { return; } context.getContentResolver().delete(MediaStore.Files.getContentUri("external"), MediaStore.Files.FileColumns.DATA + "=?", new String[]{CommonUtils.getLocalPath(file)}); if (!file.delete()) { //May throw SecurityException or IOException Timber.d("local file ( %s ) removal failed",file.getName()); return; } if (DbHelper.manageSyncedFileStateDB(fileState, "DELETE", context) <= 0) { Timber.e("Failed to remove %s from DB", file.getName()); } protected void onMissingFile(SyncedFileState fileState) { this.syncRequests.put(fileState.getId(), new SyncRequest(fileState, LOCAL_DELETE)); } @Override Loading app/src/main/java/foundation/e/drive/database/SyncedFileStateDAO.java +18 −6 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ import android.database.sqlite.SQLiteDoneException; import android.database.sqlite.SQLiteStatement; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import foundation.e.drive.models.SyncedFileState; Loading Loading @@ -195,15 +196,26 @@ import static foundation.e.drive.database.SyncedFileStateContract.SYNCEDFOLDER_I /* package */ List<SyncedFileState> getBySyncedFolderIds(List<Long> syncedFolderIds) { final List<SyncedFileState> result = new ArrayList<>(); if (syncedFolderIds == null || syncedFolderIds.isEmpty()) { Timber.d("getBySyncedFolderIds(): SyncedFOlderIds is empty or null"); return result; } final String whereClause = SYNCEDFOLDER_ID + " IN (?)"; final String[] whereValue = new String[] { syncedFolderIds.toString() final List<String> matcherList = new ArrayList<>(); //list of "?" to be replaced by value by SQliteDatabase.query() call final String[] whereValue = new String[syncedFolderIds.size()]; for (int i = 0; i < syncedFolderIds.size(); i++) { matcherList.add("?"); whereValue[i] = syncedFolderIds.get(i).toString(); } final StringBuilder whereClause = new StringBuilder(); whereClause.append(SYNCEDFOLDER_ID) .append(" IN ") .append(matcherList.toString() .replace("[", "(") .replace("]", ")") }; .replace("]", ")")); final Cursor cursor = mDB.query(TABLE_NAME, allColumns, whereClause, whereValue, null, null, null); final Cursor cursor = mDB.query(TABLE_NAME, allColumns, whereClause.toString(), whereValue, null, null, null); cursor.moveToFirst(); while(!cursor.isAfterLast() ) { result.add( cursorToSyncedFileState(cursor) ); Loading app/src/main/java/foundation/e/drive/models/SyncRequest.java +1 −1 Original line number Diff line number Diff line Loading @@ -10,7 +10,7 @@ package foundation.e.drive.models; import androidx.annotation.Nullable; public class SyncRequest { public enum Type { UPLOAD, DOWNLOAD, REMOTE_DELETE}; public enum Type { UPLOAD, DOWNLOAD, REMOTE_DELETE, LOCAL_DELETE}; private final SyncedFileState syncedFileState; Loading Loading
app/src/main/java/foundation/e/drive/contentScanner/AbstractContentScanner.java +6 −9 Original line number Diff line number Diff line Loading @@ -7,7 +7,6 @@ */ package foundation.e.drive.contentScanner; import android.accounts.Account; import android.content.Context; import com.owncloud.android.lib.resources.files.FileUtils; Loading @@ -27,18 +26,16 @@ import foundation.e.drive.models.SyncedFolder; */ public abstract class AbstractContentScanner<T> { protected final Context context; protected final Account account; protected final HashMap<Integer, SyncRequest> syncRequests; protected final List<SyncedFolder> syncedFolders; /** * @param context Context used to access Database, etc. * @param account Account used to checked if user has change some synchronization's settings * @param syncedFolders List of SyncedFolders */ protected AbstractContentScanner(Context context, Account account, List<SyncedFolder> syncedFolders) { protected AbstractContentScanner(Context context, List<SyncedFolder> syncedFolders) { syncRequests = new HashMap<>(); this.context = context; this.account = account; this.syncedFolders = syncedFolders; } Loading Loading @@ -67,7 +64,7 @@ public abstract class AbstractContentScanner<T> { } for (SyncedFileState remainingFileState : fileStates) { onMissingRemoteFile(remainingFileState); onMissingFile(remainingFileState); } return syncRequests; }; Loading @@ -93,7 +90,7 @@ public abstract class AbstractContentScanner<T> { * When a file doesn't exist anymore we remove it from device/cloud (depending of implementation) & from Database * @param fileState SyncedFileState for which we lack remote file */ protected abstract void onMissingRemoteFile(SyncedFileState fileState); protected abstract void onMissingFile(SyncedFileState fileState); /** * A new file has been found Loading
app/src/main/java/foundation/e/drive/contentScanner/LocalContentScanner.java +7 −9 Original line number Diff line number Diff line /* * Copyright © ECORP SAS 2022. * Copyright © MURENA SAS 2022. * All rights reserved. This program and the accompanying materials * are made available under the terms of the GNU Public License v3.0 * which accompanies this distribution, and is available at Loading @@ -7,7 +7,6 @@ */ package foundation.e.drive.contentScanner; import android.accounts.Account; import android.content.Context; import java.io.File; Loading @@ -24,16 +23,17 @@ import timber.log.Timber; /** * Class to encapsulate function about scanning local file and * create syncRequest when needed * @author vincent Bourgmayer */ public class LocalContentScanner extends AbstractContentScanner<File>{ public LocalContentScanner(Context context, Account account, List<SyncedFolder> syncedFolders) { super(context, account, syncedFolders); public LocalContentScanner(Context context, List<SyncedFolder> syncedFolders) { super(context, syncedFolders); Timber.tag(LocalContentScanner.class.getSimpleName()); } @Override protected void onMissingRemoteFile(SyncedFileState fileState) { protected void onMissingFile(SyncedFileState fileState) { if (!fileState.hasBeenSynchronizedOnce()) { return; } Loading Loading @@ -61,11 +61,9 @@ public class LocalContentScanner extends AbstractContentScanner<File>{ if (parentDir.isScanLocal()) scannableValue += 2; } //create the syncedFile State final SyncedFileState newSyncedFileState = new SyncedFileState(-1, file.getName(), filePath, parentDir.getRemoteFolder() + file.getName(), "", 0, parentDir.getId(), parentDir.isMediaType(),scannableValue); //Store it in DB int storedId = DbHelper.manageSyncedFileStateDB(newSyncedFileState, "INSERT", context); final int storedId = DbHelper.manageSyncedFileStateDB(newSyncedFileState, "INSERT", context); if (storedId > 0) { newSyncedFileState.setId( storedId ); Timber.d("Add upload SyncRequest for new file %s", filePath); Loading
app/src/main/java/foundation/e/drive/contentScanner/RemoteContentScanner.java +7 −35 Original line number Diff line number Diff line /* * Copyright © ECORP SAS 2022. * Copyright © MURENA SAS 2022. * All rights reserved. This program and the accompanying materials * are made available under the terms of the GNU Public License v3.0 * which accompanies this distribution, and is available at Loading @@ -7,19 +7,18 @@ */ package foundation.e.drive.contentScanner; import static foundation.e.drive.models.SyncRequest.Type.LOCAL_DELETE; import static foundation.e.drive.utils.FileDiffUtils.getActionForFileDiff; import android.accounts.Account; import android.content.Context; import android.provider.MediaStore; import com.owncloud.android.lib.resources.files.model.RemoteFile; import java.io.File; import java.util.List; import foundation.e.drive.database.DbHelper; import foundation.e.drive.models.DownloadRequest; import foundation.e.drive.models.SyncRequest; import foundation.e.drive.models.SyncedFileState; import foundation.e.drive.models.SyncedFolder; import foundation.e.drive.utils.CommonUtils; Loading @@ -34,10 +33,9 @@ public class RemoteContentScanner extends AbstractContentScanner<RemoteFile> { /** * @param context Context used to access Database, etc. * @param account Account used to checked if user has change some synchronization's settings */ public RemoteContentScanner(Context context, Account account, List<SyncedFolder> syncedFolders) { super(context, account, syncedFolders); public RemoteContentScanner(Context context, List<SyncedFolder> syncedFolders) { super(context, syncedFolders); Timber.tag(RemoteContentScanner.class.getSimpleName()); } Loading Loading @@ -74,7 +72,6 @@ public class RemoteContentScanner extends AbstractContentScanner<RemoteFile> { final SyncedFileState newFileState = new SyncedFileState(-1, fileName, parentDir.getLocalFolder() + fileName, remoteFilePath, file.getEtag(), 0, parentDir.getId(), parentDir.isMediaType(), scannableValue); //Store it in DB final int storedId = DbHelper.manageSyncedFileStateDB(newFileState, "INSERT", context); if (storedId > 0) { newFileState.setId(storedId); Loading @@ -84,33 +81,8 @@ public class RemoteContentScanner extends AbstractContentScanner<RemoteFile> { } @Override protected void onMissingRemoteFile(SyncedFileState fileState) { if (!CommonUtils.isThisSyncAllowed(account, fileState.isMediaType())) { Timber.d("Sync of current file: %s isn't allowed", fileState.getName()); return; } if (!fileState.hasBeenSynchronizedOnce()) { return; } final File file = new File(fileState.getLocalPath()); if (!file.exists()) { return; } context.getContentResolver().delete(MediaStore.Files.getContentUri("external"), MediaStore.Files.FileColumns.DATA + "=?", new String[]{CommonUtils.getLocalPath(file)}); if (!file.delete()) { //May throw SecurityException or IOException Timber.d("local file ( %s ) removal failed",file.getName()); return; } if (DbHelper.manageSyncedFileStateDB(fileState, "DELETE", context) <= 0) { Timber.e("Failed to remove %s from DB", file.getName()); } protected void onMissingFile(SyncedFileState fileState) { this.syncRequests.put(fileState.getId(), new SyncRequest(fileState, LOCAL_DELETE)); } @Override Loading
app/src/main/java/foundation/e/drive/database/SyncedFileStateDAO.java +18 −6 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ import android.database.sqlite.SQLiteDoneException; import android.database.sqlite.SQLiteStatement; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import foundation.e.drive.models.SyncedFileState; Loading Loading @@ -195,15 +196,26 @@ import static foundation.e.drive.database.SyncedFileStateContract.SYNCEDFOLDER_I /* package */ List<SyncedFileState> getBySyncedFolderIds(List<Long> syncedFolderIds) { final List<SyncedFileState> result = new ArrayList<>(); if (syncedFolderIds == null || syncedFolderIds.isEmpty()) { Timber.d("getBySyncedFolderIds(): SyncedFOlderIds is empty or null"); return result; } final String whereClause = SYNCEDFOLDER_ID + " IN (?)"; final String[] whereValue = new String[] { syncedFolderIds.toString() final List<String> matcherList = new ArrayList<>(); //list of "?" to be replaced by value by SQliteDatabase.query() call final String[] whereValue = new String[syncedFolderIds.size()]; for (int i = 0; i < syncedFolderIds.size(); i++) { matcherList.add("?"); whereValue[i] = syncedFolderIds.get(i).toString(); } final StringBuilder whereClause = new StringBuilder(); whereClause.append(SYNCEDFOLDER_ID) .append(" IN ") .append(matcherList.toString() .replace("[", "(") .replace("]", ")") }; .replace("]", ")")); final Cursor cursor = mDB.query(TABLE_NAME, allColumns, whereClause, whereValue, null, null, null); final Cursor cursor = mDB.query(TABLE_NAME, allColumns, whereClause.toString(), whereValue, null, null, null); cursor.moveToFirst(); while(!cursor.isAfterLast() ) { result.add( cursorToSyncedFileState(cursor) ); Loading
app/src/main/java/foundation/e/drive/models/SyncRequest.java +1 −1 Original line number Diff line number Diff line Loading @@ -10,7 +10,7 @@ package foundation.e.drive.models; import androidx.annotation.Nullable; public class SyncRequest { public enum Type { UPLOAD, DOWNLOAD, REMOTE_DELETE}; public enum Type { UPLOAD, DOWNLOAD, REMOTE_DELETE, LOCAL_DELETE}; private final SyncedFileState syncedFileState; Loading