From ebc3d5527960b42f934e014522ad1472db1e4960 Mon Sep 17 00:00:00 2001 From: vincent Bourgmayer Date: Mon, 9 May 2022 17:00:22 +0200 Subject: [PATCH 01/10] update build.gradle - add repositories entry to load jitpack.io to get access to NC android library - Replace NC library's subproject by calling latest from internet --- app/build.gradle | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 6f4aaa57..8df786c1 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -62,10 +62,13 @@ android { } } - +repositories { + maven { url "https://jitpack.io" } +} dependencies { - api project(':NextcloudLib') + implementation 'com.github.nextcloud:android-library:2.10.1+' + implementation fileTree(include: ['*.jar'], dir: 'libs') api 'androidx.annotation:annotation:1.3.0' implementation 'androidx.core:core:1.6.0' -- GitLab From e7f3436fb334c54bd53f469833303b1a8e0b3211 Mon Sep 17 00:00:00 2001 From: vincent Bourgmayer Date: Mon, 9 May 2022 17:14:29 +0200 Subject: [PATCH 02/10] Update UploadFileOperation to use official NC lib & add missing library - Replace GetRemoteUserInfoOperation by GetUserInfoRemoteOperation (used to get available quota) - Remove call to "askResultEtag(true)" from buildUploadOperation(...) as not available in official lib. - Update code to get eTag from UploadFileRemoteOperation as result in case of success - Update checkAvailableSpace(...) to fit with official NC lib: * Set RemoteOperationResult as result type * replace deprecated setSingleData(...) by setResultData() * load value with getResultData() * Remove returned data from Upload Operation (in UploadFileOperaton & SynchronizationService) - Add Apache Commons Http library to fix GetAliasOperation Changes not directly related to new NC lib: - Remove 'targetPath' from parameter list of buildUploadOperation(...) method cause it was useless. - Remove useless comments - update some comments - Update some Log's content - set few variables 'final' - Add a new getSyncedState() method to be able to load syncedFileState's id in the result instead of passing it into Result's data. --- app/build.gradle | 2 +- .../drive/operations/UploadFileOperation.java | 93 +++++++------------ .../services/SynchronizationService.java | 21 +---- 3 files changed, 41 insertions(+), 75 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 8df786c1..dcb6fffb 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -68,7 +68,7 @@ repositories { dependencies { implementation 'com.github.nextcloud:android-library:2.10.1+' - + implementation "commons-httpclient:commons-httpclient:3.1@jar" implementation fileTree(include: ['*.jar'], dir: 'libs') api 'androidx.annotation:annotation:1.3.0' implementation 'androidx.core:core:1.6.0' diff --git a/app/src/main/java/foundation/e/drive/operations/UploadFileOperation.java b/app/src/main/java/foundation/e/drive/operations/UploadFileOperation.java index 5b4c24ae..28e359d3 100644 --- a/app/src/main/java/foundation/e/drive/operations/UploadFileOperation.java +++ b/app/src/main/java/foundation/e/drive/operations/UploadFileOperation.java @@ -10,7 +10,6 @@ package foundation.e.drive.operations; import android.content.Context; import android.util.Log; - import androidx.annotation.VisibleForTesting; import com.owncloud.android.lib.common.OwnCloudClient; @@ -20,10 +19,10 @@ import com.owncloud.android.lib.common.operations.RemoteOperationResult; import com.owncloud.android.lib.resources.files.CreateFolderRemoteOperation; import com.owncloud.android.lib.resources.files.FileUtils; import com.owncloud.android.lib.resources.files.UploadFileRemoteOperation; -import com.owncloud.android.lib.resources.users.GetRemoteUserInfoOperation; import com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode; +import com.owncloud.android.lib.resources.users.GetUserInfoRemoteOperation; + import java.io.File; -import java.util.ArrayList; import foundation.e.drive.database.DbHelper; import foundation.e.drive.models.SyncedFileState; import foundation.e.drive.utils.CommonUtils; @@ -38,6 +37,7 @@ public class UploadFileOperation extends RemoteOperation { private int restartCounter =0; private long previousLastModified; //get to restore real value if all trials fails private Context context; + private SyncedFileState syncedState; private long availableQuota = -1; @@ -64,34 +64,27 @@ public class UploadFileOperation extends RemoteOperation { */ @Override protected RemoteOperationResult run(OwnCloudClient client ) { - //as operation isn't executed immediatly, file might have been deleted since creation of operation - if (syncedState == null ) { - Log.e(TAG, "run(client): no syncedFileState or target path, can't perform upload operation"); - return new RemoteOperationResult(ResultCode.FORBIDDEN); - } - - File file = new File(syncedState.getLocalPath()); - if (file == null || !file.exists()) { + // file might have been deleted since creation of operation + final File file = new File(syncedState.getLocalPath()); + if (!file.exists()) { Log.w(TAG, "Can't get the file. It might have been deleted"); return new RemoteOperationResult(ResultCode.FORBIDDEN); } final String targetPath = syncedState.getRemotePath(); - //If an Etag is already Stored and LastModified from DB is the same as real file + //If file already up-to-date & synced if (syncedState.isLastEtagStored() && syncedState.getLocalLastModified() == file.lastModified()) { Log.d(TAG, "syncedState last modified: "+ syncedState.getLocalLastModified()+" <=> file last modified: "+file.lastModified() +": So return sync_conflict"); return new RemoteOperationResult(ResultCode.SYNC_CONFLICT); } - Float relativeQuotaBeforeFileUpload = 0.0f; - if (this.availableQuota == -1) { - RemoteOperationResult checkQuotaResult = checkAvailableSpace(client, file.length()); + if (this.availableQuota == -1) { //if upload is retried because of failure (mustRestart = true) this test avoid rechecking quota + final RemoteOperationResult checkQuotaResult = checkAvailableSpace(client, file.length()); if (checkQuotaResult.getCode() != ResultCode.OK) { + Log.e(TAG, "Impossible to check quota. Upload of " + syncedState.getLocalPath() + "cancelled"); return new RemoteOperationResult(checkQuotaResult.getCode()); - } else { - relativeQuotaBeforeFileUpload = ((Double) checkQuotaResult.getSingleData()).floatValue(); } } @@ -99,18 +92,17 @@ public class UploadFileOperation extends RemoteOperation { return new RemoteOperationResult(ResultCode.UNKNOWN_ERROR); } - final UploadFileRemoteOperation uploadOperation = buildUploadOperation(file, targetPath); + final UploadFileRemoteOperation uploadOperation = buildUploadOperation(file); - // Execute UploadFileOperation - RemoteOperationResult uploadResult = uploadOperation.execute(client ); - ResultCode resultCode; + final RemoteOperationResult uploadResult = uploadOperation.execute(client ); + final ResultCode resultCode; boolean mustRestart = true; //if upload is a success if (uploadResult.isSuccess()) { - Object data = uploadResult.getSingleData(); - if (data != null) { - syncedState.setLastETAG((String) data); + String etag = uploadResult.getResultData(); + if (etag != null) { + syncedState.setLastETAG(etag); } syncedState.setLocalLastModified(file.lastModified()); resultCode = uploadResult.getCode(); @@ -124,7 +116,6 @@ public class UploadFileOperation extends RemoteOperation { resultCode = ResultCode.QUOTA_EXCEEDED; mustRestart = false; } else { - //Upload failed Log.e(TAG, "UploadFileRemoteOperation for : " + file.getName() + " failed => code: " + uploadResult.getCode()); resultCode = ResultCode.UNKNOWN_ERROR; mustRestart = false; @@ -134,37 +125,28 @@ public class UploadFileOperation extends RemoteOperation { if (mustRestart) { if (this.restartCounter < 1) { this.restartCounter += 1; - //if we encounter more than one time same error, stop trying to upload. return this.run(client); } else { syncedState.setLocalLastModified(this.previousLastModified); //Revert syncFileState to its previous state } } - // updated syncedFile in DB DbHelper.manageSyncedFileStateDB(syncedState, "UPDATE", context); - ArrayList datas = new ArrayList<>(); - datas.add(syncedState.getSyncedFolderId()); - datas.add(relativeQuotaBeforeFileUpload); - final RemoteOperationResult finalResult = new RemoteOperationResult(resultCode); - finalResult.setData(datas); - return finalResult; + return new RemoteOperationResult(resultCode); } /** * Build the operation to put the file on server * @return the operation to execute */ - private UploadFileRemoteOperation buildUploadOperation(File file, String targetPath) { - String timeStamp = ((Long) (file.lastModified() / 1000) ).toString() ; + private UploadFileRemoteOperation buildUploadOperation(File file) { + final String timeStamp = ((Long) (file.lastModified() / 1000) ).toString() ; - //create UploadFileOperation - UploadFileRemoteOperation uploadRemoteFileOperation = new UploadFileRemoteOperation(syncedState.getLocalPath(), - (targetPath != null ) ? targetPath : syncedState.getRemotePath(), + final UploadFileRemoteOperation uploadRemoteFileOperation = new UploadFileRemoteOperation(syncedState.getLocalPath(), + syncedState.getRemotePath(), CommonUtils.getMimeType(file ), (!this.syncedState.isMediaType() || syncedState.getLastETAG().isEmpty() )? null : syncedState.getLastETAG(), //If not null, This can cause error 412; that means remote file has change timeStamp ); - uploadRemoteFileOperation.askResultEtag(true); return uploadRemoteFileOperation; } @@ -175,27 +157,20 @@ public class UploadFileOperation extends RemoteOperation { */ @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) public RemoteOperationResult checkAvailableSpace(OwnCloudClient client, long fileSize) { - GetRemoteUserInfoOperation getRemoteUserInfoOperation = new GetRemoteUserInfoOperation(); - RemoteOperationResult ocsResult = getRemoteUserInfoOperation.execute(client); - if (ocsResult.isSuccess() && ocsResult.getData() != null) { - UserInfo userInfo = (UserInfo) ocsResult.getData().get(0); - this.availableQuota = userInfo.getQuota().getFree(); - if (((UserInfo) ocsResult.getData().get(0)).getQuota().getFree() < fileSize ) { - Log.w(TAG, "quota exceeded!"); - return new RemoteOperationResult(ResultCode.QUOTA_EXCEEDED); - } else { - Log.d(TAG, "Quota Okay"); - RemoteOperationResult result = new RemoteOperationResult(ResultCode.OK); - result.setSingleData((Double) userInfo.getQuota().getRelative()); - return result; - } - } else { - Log.w(TAG, "getRemoteUserInfoOperation failed: "+ocsResult.getHttpCode() ); - return new RemoteOperationResult(ocsResult.getCode()); + final GetUserInfoRemoteOperation getRemoteUserInfoOperation = new GetUserInfoRemoteOperation(); + final RemoteOperationResult ocsResult = getRemoteUserInfoOperation.execute(client); + final UserInfo userInfo = ocsResult.getResultData(); + + final RemoteOperationResult result; + if(ocsResult.isSuccess() && userInfo.getQuota().getFree() < fileSize) { + Log.w(TAG, "Not enough quota to upload the file"); + result = new RemoteOperationResult(ResultCode.QUOTA_EXCEEDED); + } else { + result = new RemoteOperationResult(ocsResult.getCode()); } + return result; } - /** * Create remote parent folder of the file if missing * @param targetPath @@ -216,4 +191,8 @@ public class UploadFileOperation extends RemoteOperation { } return false; } + + public SyncedFileState getSyncedState() { + return syncedState; + } } diff --git a/app/src/main/java/foundation/e/drive/services/SynchronizationService.java b/app/src/main/java/foundation/e/drive/services/SynchronizationService.java index 72cee50c..d77c69c3 100644 --- a/app/src/main/java/foundation/e/drive/services/SynchronizationService.java +++ b/app/src/main/java/foundation/e/drive/services/SynchronizationService.java @@ -154,11 +154,6 @@ public class SynchronizationService extends Service implements OnRemoteOperation } } else { String operationClassName = callerOperation.getClass().getSimpleName(); - final ArrayList callerOperationResultData = result.getData(); - if (callerOperation instanceof UploadFileOperation && callerOperationResultData != null - && callerOperationResultData.size() > 1) { - final Float relativeQuota = (Float) result.getData().get(1); - } switch (result.getCode()) { case OK: Log.d(TAG, operationClassName + " Succeed"); @@ -172,24 +167,16 @@ public class SynchronizationService extends Service implements OnRemoteOperation break; case UNKNOWN_ERROR: if (callerOperation instanceof UploadFileOperation) { - if (callerOperationResultData != null && callerOperationResultData.size() > 0) { - int rowAffected = DbHelper.forceFoldertoBeRescan(((Long) callerOperationResultData.get(0)).intValue(), getApplicationContext()); - Log.e(TAG, " Upload failed for unknown reason.\n Force folder to be rescan next time (row affected) :" + rowAffected); - } else { - Log.w(TAG, "result.getData() for UploadFileOperation returned null"); - } + final int rowAffected = DbHelper.forceFoldertoBeRescan(((UploadFileOperation) callerOperation).getSyncedState().getId(), getApplicationContext()); + Log.e(TAG, " Upload failed for unknown reason.\n Force folder to be rescan next time (row affected) :" + rowAffected); } else if (callerOperation instanceof DownloadFileOperation) { Log.e(TAG, " Download: Unknown_error : failed"); } break; case FORBIDDEN: if (callerOperation instanceof UploadFileOperation) { - if (callerOperationResultData != null && callerOperationResultData.size() > 0) { - int rowAffected = DbHelper.forceFoldertoBeRescan(((Long) callerOperationResultData.get(0)).intValue(), getApplicationContext()); - Log.e(TAG, " Upload: Forbidden : Can't get syncedFileState, no remote path defined. Force folder to be rescan next time (row affected) :" + rowAffected); - } else { - Log.w(TAG, "result.getData() for UploadFileOperation returned null"); - } + final int rowAffected = DbHelper.forceFoldertoBeRescan(((UploadFileOperation) callerOperation).getSyncedState().getId(), getApplicationContext()); + Log.e(TAG, " Upload: Forbidden : Can't get syncedFileState, no remote path defined. Force folder to be rescan next time (row affected) :" + rowAffected); } else if (callerOperation instanceof DownloadFileOperation) { Log.e(TAG, "Download : Forbidden: Can't get syncedFileState, no local path defined"); } -- GitLab From 1bb1dfeca7773950c0de37f2c1b41c32c5eeda5b Mon Sep 17 00:00:00 2001 From: vincent Bourgmayer Date: Tue, 10 May 2022 09:32:39 +0200 Subject: [PATCH 03/10] Update AccountUserInfoWorker & GetAliasOperation to fit with new NC lib - rewrite AccountUserInfoWorker.fetchUserInfo(...): * Replace GetRemoteUserInfoOperation from old fork by GetUserInfoRemoteOperation from latest version * Remove usage of alternateDisplayName as not needed anymore * Use RemoteOperationResult as type for checking userInfo from serveur. It allows to avoid parsing result. * use Getter to access userInfo property due to latest version of UserInfo - rewrite GetAliasOperation to provide RemoteOperationResult> instead of Arraylist - rewrite AccoutnUserInfoWorker.fetchAliases(...): * Replace RemoteOperationResult by RemoteOperationResult> to avoid parsing * remove some variables * make some variables final * reduce use of if/else statement * Add a 'return false' if request isn't a success. - remove useless comments - set few variables final --- .../e/drive/operations/GetAliasOperation.java | 20 +++---- .../e/drive/work/AccountUserInfoWorker.java | 60 +++++++++---------- 2 files changed, 37 insertions(+), 43 deletions(-) diff --git a/app/src/main/java/foundation/e/drive/operations/GetAliasOperation.java b/app/src/main/java/foundation/e/drive/operations/GetAliasOperation.java index 4f67f76f..7df0b64f 100644 --- a/app/src/main/java/foundation/e/drive/operations/GetAliasOperation.java +++ b/app/src/main/java/foundation/e/drive/operations/GetAliasOperation.java @@ -24,7 +24,6 @@ import java.util.ArrayList; /** * @author TheScarastic */ - public class GetAliasOperation extends RemoteOperation { private static final String TAG = GetAliasOperation.class.getSimpleName(); @@ -35,14 +34,13 @@ public class GetAliasOperation extends RemoteOperation { private static final String NODE_DATA = "data"; private static final String NODE_ALIASES = "aliases"; - private boolean isSuccess(int status) { return (status == HttpStatus.SC_OK); } @Override - protected RemoteOperationResult run(OwnCloudClient client) { - RemoteOperationResult result; + protected RemoteOperationResult> run(OwnCloudClient client) { + RemoteOperationResult> result; GetMethod get = null; final String uri = client.getBaseUri() + ALIAS_PATH + client.getCredentials().getUsername(); @@ -52,25 +50,25 @@ public class GetAliasOperation extends RemoteOperation { get.setQueryString(new NameValuePair[]{new NameValuePair("format", "json")}); if (isSuccess(client.executeMethod(get))) { - String response = get.getResponseBodyAsString(); + final String response = get.getResponseBodyAsString(); // parse final JSONArray aliases = new JSONObject(response).getJSONObject(NODE_OCS) .getJSONObject(NODE_DATA).getJSONArray(NODE_ALIASES); - final ArrayList resultAliases = new ArrayList<>(); + final ArrayList resultAliases = new ArrayList<>(); for (int i = 0; i < aliases.length(); i++) { - resultAliases.add(aliases.get(i)); + resultAliases.add(aliases.get(i).toString()); } - result = new RemoteOperationResult(true, get); - result.setData(resultAliases); + result = new RemoteOperationResult<>(true, get); + result.setResultData(resultAliases); } else { - result = new RemoteOperationResult(false, get); + result = new RemoteOperationResult<>(false, get); } } catch (Exception e) { e.printStackTrace(); - result = new RemoteOperationResult(e); + result = new RemoteOperationResult<>(e); Log_OC.e(TAG, "Fetching aliases failed"); } finally { if (get != null) diff --git a/app/src/main/java/foundation/e/drive/work/AccountUserInfoWorker.java b/app/src/main/java/foundation/e/drive/work/AccountUserInfoWorker.java index b2532894..c42fb578 100644 --- a/app/src/main/java/foundation/e/drive/work/AccountUserInfoWorker.java +++ b/app/src/main/java/foundation/e/drive/work/AccountUserInfoWorker.java @@ -30,9 +30,10 @@ import androidx.work.WorkerParameters; import com.bumptech.glide.Glide; import com.bumptech.glide.load.engine.DiskCacheStrategy; import com.owncloud.android.lib.common.OwnCloudClient; +import com.owncloud.android.lib.common.Quota; import com.owncloud.android.lib.common.UserInfo; import com.owncloud.android.lib.common.operations.RemoteOperationResult; -import com.owncloud.android.lib.resources.users.GetRemoteUserInfoOperation; +import com.owncloud.android.lib.resources.users.GetUserInfoRemoteOperation; import java.util.ArrayList; @@ -49,9 +50,9 @@ import foundation.e.drive.widgets.EDriveWidget; */ public class AccountUserInfoWorker extends Worker { public static final String UNIQUE_WORK_NAME = "AccountUserInfoWorker"; - final AccountManager accountManager; - final GetRemoteUserInfoOperation getRemoteUserInfoOperation = new GetRemoteUserInfoOperation(); - final GetAliasOperation getAliasOperation = new GetAliasOperation(); + private final AccountManager accountManager; + private final GetUserInfoRemoteOperation getRemoteUserInfoOperation = new GetUserInfoRemoteOperation(); + private final GetAliasOperation getAliasOperation = new GetAliasOperation(); private final Context mContext; private Account account; @@ -66,7 +67,7 @@ public class AccountUserInfoWorker extends Worker { public Result doWork() { account = CommonUtils.getAccount(mContext.getString(R.string.eelo_account_type), accountManager); - OwnCloudClient client = CommonUtils.getOwnCloudClient(account, mContext); + final OwnCloudClient client = CommonUtils.getOwnCloudClient(account, mContext); if (account != null && client != null) { if (fetchUserInfo(client) && fetchAliases(client)) { @@ -85,32 +86,26 @@ public class AccountUserInfoWorker extends Worker { } private boolean fetchUserInfo(final OwnCloudClient client) { - final RemoteOperationResult ocsResult = getRemoteUserInfoOperation.execute(client); + final RemoteOperationResult ocsResult = getRemoteUserInfoOperation.execute(client); - if (ocsResult.isSuccess() && ocsResult.getData() != null && !ocsResult.getData().isEmpty()) { - final UserInfo userInfo = (UserInfo) ocsResult.getData().get(0); + if (ocsResult.isSuccess()) { + final UserInfo userInfo = ocsResult.getResultData(); - final String name; - if (userInfo.displayName == null || userInfo.displayName.isEmpty()) { - name = userInfo.alternateDisplayName; - } else { - name = userInfo.displayName; - } - final double relativeQuota = userInfo.getQuota().relative; - long totalQuota = userInfo.getQuota().total; + final Quota userQuota = userInfo.getQuota(); + final double relativeQuota = userQuota.getRelative(); + long totalQuota = userQuota.getTotal(); if (totalQuota <= 0) { totalQuota = 0; } - final long usedQuota = userInfo.getQuota().used; - final String groups = String.join(",", userInfo.groups); - final String email = userInfo.id; - accountManager.setUserData(account, ACCOUNT_DATA_NAME, name); - accountManager.setUserData(account, ACCOUNT_DATA_EMAIL, email); + final String groups = String.join(",", userInfo.getGroups()); + + accountManager.setUserData(account, ACCOUNT_DATA_NAME, userInfo.getDisplayName()); + accountManager.setUserData(account, ACCOUNT_DATA_EMAIL, userInfo.getEmail()); accountManager.setUserData(account, ACCOUNT_DATA_GROUPS, groups); accountManager.setUserData(account, ACCOUNT_DATA_TOTAL_QUOTA_KEY, "" + totalQuota); accountManager.setUserData(account, ACCOUNT_DATA_RELATIVE_QUOTA_KEY, "" + relativeQuota); - accountManager.setUserData(account, ACCOUNT_DATA_USED_QUOTA_KEY, "" + usedQuota); + accountManager.setUserData(account, ACCOUNT_DATA_USED_QUOTA_KEY, "" + userQuota.getUsed()); addNotifAboutQuota(relativeQuota); return true; @@ -139,7 +134,7 @@ public class AccountUserInfoWorker extends Worker { * - make message & title to be a parameter of the method, so we could reuse the function somewhere * - else with different notification. File conflict for example. **/ - private void addNotification(NotificationManager manager, String title, String text, boolean isOnGoing) { + private void addNotification(final NotificationManager manager, final String title, final String text, final boolean isOnGoing) { final NotificationCompat.Builder builder = new NotificationCompat.Builder(getApplicationContext(), AppConstants.notificationChannelID) .setSmallIcon(android.R.drawable.stat_sys_warning) @@ -147,19 +142,20 @@ public class AccountUserInfoWorker extends Worker { .setContentText(text) .setOngoing(isOnGoing) .setStyle(new NotificationCompat.BigTextStyle().bigText(text)); - // Add as notification manager.notify(0, builder.build()); } private boolean fetchAliases(final OwnCloudClient client) { - final RemoteOperationResult ocsResult = getAliasOperation.execute(client); - String aliases = ""; - if (ocsResult.isSuccess() && ocsResult.getData() != null && !ocsResult.getData().isEmpty()) { - ArrayList alias = new ArrayList<>(ocsResult.getData().size()); - for (Object object : ocsResult.getData()) { - alias.add(object.toString()); - } - aliases = String.join(",", alias); + final RemoteOperationResult> ocsResult = getAliasOperation.execute(client); + if (!ocsResult.isSuccess()) { + return false; + } + final ArrayList aliasList = ocsResult.getResultData(); + final String aliases; + if (!aliasList.isEmpty()) { + aliases = String.join(",", aliasList); + } else { + aliases = ""; } accountManager.setUserData(account, ACCOUNT_DATA_ALIAS_KEY, aliases); return true; -- GitLab From f13f354812542ea27055c8392e5085f7e26bbdaa Mon Sep 17 00:00:00 2001 From: vincent Bourgmayer Date: Tue, 10 May 2022 10:12:56 +0200 Subject: [PATCH 04/10] fix CreateRemoteFolderWork.java --- .../e/drive/work/CreateRemoteFolderWorker.java | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/foundation/e/drive/work/CreateRemoteFolderWorker.java b/app/src/main/java/foundation/e/drive/work/CreateRemoteFolderWorker.java index 38ec32f0..1a8ea515 100644 --- a/app/src/main/java/foundation/e/drive/work/CreateRemoteFolderWorker.java +++ b/app/src/main/java/foundation/e/drive/work/CreateRemoteFolderWorker.java @@ -56,6 +56,7 @@ public class CreateRemoteFolderWorker extends Worker { public Result doWork() { final Context context = getApplicationContext(); final Account account = getAccount(); + if (account == null) { Log.e(TAG, "Can't get valid account: stop everything"); return Result.failure(); @@ -85,7 +86,7 @@ public class CreateRemoteFolderWorker extends Worker { new CreateFolderRemoteOperation(syncedFolder.getRemoteFolder(), true); try { - final RemoteOperationResult result = mkcolRequest.execute(client, true); + final RemoteOperationResult result = mkcolRequest.execute(client); if (result.isSuccess() || result.getCode() == RemoteOperationResult.ResultCode.FOLDER_ALREADY_EXISTS) { if(DbHelper.insertSyncedFolder(syncedFolder, context) >= 0 ) { Log.d(TAG, "Insertion in DB succeed"); @@ -99,8 +100,8 @@ public class CreateRemoteFolderWorker extends Worker { } private SyncedFolder getSyncedFolderFromData() { - Data data = getInputData(); - SyncedFolder result = new SyncedFolder( + final Data data = getInputData(); + final SyncedFolder result = new SyncedFolder( data.getString(DATA_KEY_LIBELLE), data.getString(DATA_KEY_LOCAL_PATH), data.getString(DATA_KEY_REMOTE_PATH), @@ -118,7 +119,7 @@ public class CreateRemoteFolderWorker extends Worker { private Account getAccount() { - SharedPreferences prefs = getApplicationContext().getSharedPreferences(AppConstants.SHARED_PREFERENCE_NAME, Context.MODE_PRIVATE); + final SharedPreferences prefs = getApplicationContext().getSharedPreferences(AppConstants.SHARED_PREFERENCE_NAME, Context.MODE_PRIVATE); final String accountName = prefs.getString(AccountManager.KEY_ACCOUNT_NAME, ""); final String accountType = prefs.getString(AccountManager.KEY_ACCOUNT_TYPE, ""); -- GitLab From 732f87e0503f27b68dbe0a38954e7efa4c1cbc6b Mon Sep 17 00:00:00 2001 From: vincent Bourgmayer Date: Tue, 10 May 2022 11:34:43 +0200 Subject: [PATCH 05/10] Fix DownloadFileOperation - Make DownloadFileOperation's property final when possible - Import DownloadFileRemoteOperation from latest NC lib - Remove old duplicate DownloadFileRemoteOperation from NC lib - Remove code to check if parent of file exist, because file existence is checked before - Remove useless if statement at the beginning of "execute(...)" method - update some comments - update code which handlefailure of move of temporary file to expected destination --- .../operations/DownloadFileOperation.java | 49 ++--- .../DownloadFileRemoteOperation.java | 180 ------------------ 2 files changed, 17 insertions(+), 212 deletions(-) delete mode 100644 app/src/main/java/foundation/e/drive/operations/DownloadFileRemoteOperation.java diff --git a/app/src/main/java/foundation/e/drive/operations/DownloadFileOperation.java b/app/src/main/java/foundation/e/drive/operations/DownloadFileOperation.java index 4445239c..0142dcdf 100644 --- a/app/src/main/java/foundation/e/drive/operations/DownloadFileOperation.java +++ b/app/src/main/java/foundation/e/drive/operations/DownloadFileOperation.java @@ -13,6 +13,7 @@ import android.util.Log; import com.owncloud.android.lib.common.OwnCloudClient; import com.owncloud.android.lib.common.operations.RemoteOperation; import com.owncloud.android.lib.common.operations.RemoteOperationResult; +import com.owncloud.android.lib.resources.files.DownloadFileRemoteOperation; import com.owncloud.android.lib.resources.files.FileUtils; import com.owncloud.android.lib.resources.files.model.RemoteFile; import java.io.File; @@ -28,11 +29,11 @@ public class DownloadFileOperation extends RemoteOperation { private final static String TAG = DownloadFileOperation.class.getSimpleName(); private final RemoteFile remoteFile; - private Context context; - private String targetPath; + private final Context context; + private final String targetPath; private int restartCounter =0; - private SyncedFileState syncedFileState; - private String previousEtag; + private final SyncedFileState syncedFileState; + private final String previousEtag; /** * COnstructor of download operation where syncedFileState is already known @@ -50,26 +51,22 @@ public class DownloadFileOperation extends RemoteOperation { @Override protected RemoteOperationResult run(OwnCloudClient ownCloudClient) { Log.i(TAG, "run(ownCloudClient)"); - - //get or build synced file equivalent of this.mFile - if (syncedFileState == null || targetPath == null || targetPath.isEmpty()) { - Log.e(TAG, "syncedFileState or targetPath is empty or null. Can't Download in those conditions"); - return new RemoteOperationResult(RemoteOperationResult.ResultCode.FORBIDDEN); - } else if (syncedFileState.getId() == -1) { + if (syncedFileState.getId() == -1) { this.syncedFileState.setId(DbHelper.manageSyncedFileStateDB(this.syncedFileState, "INSERT", context)); } - if (syncedFileState.getLastETAG().equals(remoteFile.getEtag()) && syncedFileState.getLocalLastModified() > 0L) { - //Same etag and localLastModified not null mean the file is up to date + if (syncedFileState.getLastETAG().equals(remoteFile.getEtag()) + && syncedFileState.getLocalLastModified() > 0L) { //file is up to date Log.w(TAG, "File already up-to-date"); return new RemoteOperationResult(RemoteOperationResult.ResultCode.ETAG_UNCHANGED); } final String tmpTargetPath = context.getExternalCacheDir()+ FileUtils.PATH_SEPARATOR+ syncedFileState.getName(); + final DownloadFileRemoteOperation downloadOperation = new DownloadFileRemoteOperation(remoteFile.getRemotePath(), tmpTargetPath); - final RemoteOperationResult downloadResult = downloadOperation.execute(ownCloudClient); + RemoteOperationResult.ResultCode resultCode; boolean mustRestart = true; @@ -78,32 +75,20 @@ public class DownloadFileOperation extends RemoteOperation { if (!tmpLocalFile.exists()) { Log.e(TAG, "Downloaded file doesn't exist or is null"); resultCode = RemoteOperationResult.ResultCode.FILE_NOT_FOUND; - } else if (tmpLocalFile.length() != remoteFile.getLength()) { - Log.e(TAG, "Local and remote file doesn't have the same size."); resultCode = RemoteOperationResult.ResultCode.INVALID_OVERWRITE; tmpLocalFile.delete(); + } else { //file has been correctly download - } else { - //file has been correctly download. final File localFile = new File(targetPath); - if (localFile.exists()) { - localFile.delete(); - } - //Check parentFolder existence and create if needed - final String parentFoldersPath = localFile.getParent(); - final File localParentFile = new File(parentFoldersPath); - if (!localParentFile.exists()) { - if (localParentFile.mkdirs()) - Log.d(TAG, "Created folders: "+parentFoldersPath); - else - Log.d(TAG, "Can't create folders: "+parentFoldersPath); + if (localFile.exists()) { localFile.delete(); } + + if (!tmpLocalFile.renameTo(localFile)) { + Log.d(TAG, "Can't move " + tmpTargetPath + " to " + targetPath); + return new RemoteOperationResult(RemoteOperationResult.ResultCode.FORBIDDEN); } - boolean renameResult = tmpLocalFile.renameTo(localFile); - if (!renameResult) - Log.d(TAG, "File hasn't been successfully moved at its place"); syncedFileState.setLocalLastModified(localFile.lastModified()) .setLastETAG(remoteFile.getEtag()); mustRestart = false; @@ -118,7 +103,7 @@ public class DownloadFileOperation extends RemoteOperation { } if (mustRestart) { - Log.w(TAG, restartCounter+" unsuccessfull trial.s of downloading file " + Log.w(TAG, restartCounter+" unsuccessfull trial.s of downloading " + remoteFile.getRemotePath()); syncedFileState.setLastETAG(this.previousEtag); if (this.restartCounter < 3) { diff --git a/app/src/main/java/foundation/e/drive/operations/DownloadFileRemoteOperation.java b/app/src/main/java/foundation/e/drive/operations/DownloadFileRemoteOperation.java deleted file mode 100644 index dce9dff6..00000000 --- a/app/src/main/java/foundation/e/drive/operations/DownloadFileRemoteOperation.java +++ /dev/null @@ -1,180 +0,0 @@ - -/* ownCloud Android Library is available under MIT license - * Copyright (C) 2015 ownCloud Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - */ -package foundation.e.drive.operations; - -import com.owncloud.android.lib.common.OwnCloudClient; -import com.owncloud.android.lib.common.network.WebdavUtils; -import com.owncloud.android.lib.common.operations.OperationCancelledException; -import com.owncloud.android.lib.common.operations.RemoteOperation; -import com.owncloud.android.lib.common.operations.RemoteOperationResult; -import com.owncloud.android.lib.common.utils.Log_OC; -import org.apache.commons.httpclient.Header; -import org.apache.commons.httpclient.HttpStatus; -import org.apache.commons.httpclient.methods.GetMethod; -import java.io.BufferedInputStream; -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.util.Date; -import java.util.concurrent.atomic.AtomicBoolean; - -/** - * Remote operation performing the download of a remote file in the ownCloud server. - * - * @author David A. Velasco - * @author masensio - * @author Vincent Bourgmayer - */ -class DownloadFileRemoteOperation extends RemoteOperation { - private static final String TAG = DownloadFileRemoteOperation.class.getSimpleName(); - - private final AtomicBoolean mCancellationRequested = new AtomicBoolean(false); - private long mModificationTimestamp = 0; - private String mEtag = ""; - private GetMethod mGet; - private final String mRemotePath; - private final String mLocalFolderPath; - - /** - * Constructor - * @param remotePath Path of file on the server - * @param localFolderPath Path of file on the device - */ - public DownloadFileRemoteOperation(String remotePath, String localFolderPath) { - mRemotePath = remotePath; - mLocalFolderPath = localFolderPath; - } - - @Override - protected RemoteOperationResult run(OwnCloudClient client) { - RemoteOperationResult result = null; - /// download will be performed to a temporal file, then moved to the final location - File tmpFile = new File(getTmpPath()); - /// perform the download - try { - tmpFile.getParentFile().mkdirs(); - int status = downloadFile(client, tmpFile); - result = new RemoteOperationResult(isSuccess(status), mGet); - Log_OC.i(TAG, "Download of " + mRemotePath + " to " + getTmpPath() + ": " + - result.getLogMessage()); - - } catch (Exception e) { - result = new RemoteOperationResult(e); - Log_OC.e(TAG, "Download of " + mRemotePath + " to " + getTmpPath() + ": " + - result.getLogMessage(), e); - } - - return result; - } - - private int downloadFile(OwnCloudClient client, File targetFile) throws IOException, OperationCancelledException { - int status = -1; - boolean savedFile = false; - mGet = new GetMethod(client.getWebdavUri() + WebdavUtils.encodePath(mRemotePath)); - - FileOutputStream fos = null; - try { - status = client.executeMethod(mGet); - if (isSuccess(status)) { - targetFile.createNewFile(); - BufferedInputStream bis = new BufferedInputStream(mGet.getResponseBodyAsStream()); - fos = new FileOutputStream(targetFile); - long transferred = 0; - - Header contentLength = mGet.getResponseHeader("Content-Length"); - long totalToTransfer = (contentLength != null && - contentLength.getValue().length() > 0) ? - Long.parseLong(contentLength.getValue()) : 0; - - byte[] bytes = new byte[4096]; - int readResult = 0; - while ((readResult = bis.read(bytes)) != -1) { - synchronized (mCancellationRequested) { - if (mCancellationRequested.get()) { - mGet.abort(); - throw new OperationCancelledException(); - } - } - fos.write(bytes, 0, readResult); - transferred += readResult; - } - // Check if the file is completed - // if transfer-encoding: chunked we cannot check if the file is complete - Header transferEncodingHeader = mGet.getResponseHeader("Transfer-Encoding"); - boolean transferEncoding = false; - - if (transferEncodingHeader != null) { - transferEncoding = transferEncodingHeader.getValue().equals("chunked"); - } - - if (transferred == totalToTransfer || transferEncoding) { - savedFile = true; - Header modificationTime = mGet.getResponseHeader("Last-Modified"); - if (modificationTime == null) { - modificationTime = mGet.getResponseHeader("last-modified"); - } - if (modificationTime != null) { - Date d = WebdavUtils.parseResponseDate(modificationTime.getValue()); - mModificationTimestamp = (d != null) ? d.getTime() : 0; - } else { - Log_OC.e(TAG, "Could not read modification time from response downloading " + mRemotePath); - } - - mEtag = WebdavUtils.getEtagFromResponse(mGet); - if (mEtag.length() == 0) { - Log_OC.e(TAG, "Could not read eTag from response downloading " + mRemotePath); - } - - } else { - client.exhaustResponse(mGet.getResponseBodyAsStream()); - // TODO some kind of error control! - } - } else { - client.exhaustResponse(mGet.getResponseBodyAsStream()); - } - } catch (Exception e) { - Log_OC.e(TAG, e.getMessage()); - } finally { - if (fos != null) fos.close(); - if (!savedFile && targetFile.exists()) { - targetFile.delete(); - } - mGet.releaseConnection(); // let the connection available for other methods - } - return status; - } - - private boolean isSuccess(int status) { - return (status == HttpStatus.SC_OK); - } - - /** - * IMPLEMENTATION DIFFER FROM NC IMPLEMENTATION - * @return - */ - private String getTmpPath() { - return mLocalFolderPath; - } -} -- GitLab From b15b75a97e594416238368bfc9b39a6f501da293 Mon Sep 17 00:00:00 2001 From: vincent Bourgmayer Date: Tue, 10 May 2022 12:47:07 +0200 Subject: [PATCH 06/10] Fix ListFileRemoteOperation.java to work with latest nc lib. - Replace LightReadFolderRemoteOperation from ou fork by ReadFolderRemoteOperation from NC lib - clean code style for if/else, {}, + & () - remove duplicated variable when scanning result - make some variables final - add new method "shouldSkipSyncedFolder(SyncedFolder syncedfolder)" to get more readibility - remove duplicated codes - rewrite nested if/else statement for better readability - move block to add small delay beetween ReadFolderRemoteOperation call --- .../operations/ListFileRemoteOperation.java | 155 ++++++++---------- 1 file changed, 66 insertions(+), 89 deletions(-) diff --git a/app/src/main/java/foundation/e/drive/operations/ListFileRemoteOperation.java b/app/src/main/java/foundation/e/drive/operations/ListFileRemoteOperation.java index ffde62e8..fea2f6c7 100644 --- a/app/src/main/java/foundation/e/drive/operations/ListFileRemoteOperation.java +++ b/app/src/main/java/foundation/e/drive/operations/ListFileRemoteOperation.java @@ -13,8 +13,8 @@ import android.util.Log; import com.owncloud.android.lib.common.OwnCloudClient; import com.owncloud.android.lib.common.operations.RemoteOperation; import com.owncloud.android.lib.common.operations.RemoteOperationResult; +import com.owncloud.android.lib.resources.files.ReadFolderRemoteOperation; import com.owncloud.android.lib.resources.files.model.RemoteFile; -import com.owncloud.android.lib.resources.files.LightReadFolderRemoteOperation; import java.io.File; import java.util.ArrayList; import java.util.List; @@ -23,12 +23,10 @@ import foundation.e.drive.database.DbHelper; import foundation.e.drive.models.SyncedFolder; import foundation.e.drive.utils.CommonUtils; -import static org.apache.jackrabbit.webdav.DavConstants.DEPTH_1; - /** * * @author Vincent Bourgmayer - * Created by Vincent on 04/05/2018. + * Created on 04/05/2018. */ public class ListFileRemoteOperation extends RemoteOperation { private final String TAG = ListFileRemoteOperation.class.getSimpleName(); @@ -37,8 +35,7 @@ public class ListFileRemoteOperation extends RemoteOperation { private final Context mContext; private final int initialFolderNumber; - public ListFileRemoteOperation(List syncedFolders, Context context, int initialFolderNumber){ - Log.i(TAG, "Constructor of ListFileRemoteOperation"); + public ListFileRemoteOperation(List syncedFolders, Context context, int initialFolderNumber) { this.mSyncedFolders = syncedFolders; this.mContext = context; this.initialFolderNumber = initialFolderNumber; @@ -50,124 +47,98 @@ public class ListFileRemoteOperation extends RemoteOperation { * @return List containing remoteFolder followed by remote files */ @Override - protected RemoteOperationResult run(OwnCloudClient ownCloudClient){ + protected RemoteOperationResult run(OwnCloudClient ownCloudClient) { Log.i(TAG, "run()"); - ArrayList mRemoteFiles = new ArrayList<>(); + final ArrayList mRemoteFiles = new ArrayList<>(); RemoteOperationResult finalResult; boolean atLeastOneDirAsChanged = false; - ListIterator mSyncedFolderIterator = mSyncedFolders.listIterator(); - - //Loop through list of SyncedFolder - while (mSyncedFolderIterator.hasNext() ){ + final ListIterator mSyncedFolderIterator = mSyncedFolders.listIterator(); - //Get CurrentSyncedFolder - SyncedFolder syncedFolder = mSyncedFolderIterator.next(); + while (mSyncedFolderIterator.hasNext()) { - //if folder is media type() && is an hidden folder then ignore it - if(syncedFolder.isMediaType() - && CommonUtils.getFileNameFromPath(syncedFolder.getRemoteFolder()).startsWith(".")){ - mSyncedFolderIterator.remove(); - continue; + try{ + Thread.sleep(150); + }catch(InterruptedException e) { + Log.w(TAG, "listFileRemoteOperation's sleep had been interrupted"); } - //If folder isn't to be scan remotly, ignore it - if(!syncedFolder.isScanRemote()) { + final SyncedFolder syncedFolder = mSyncedFolderIterator.next(); + if (shouldSkipSyncedFolder(syncedFolder)) { mSyncedFolderIterator.remove(); continue; } - if(syncedFolder.getId() == -1) { - //persist new syncedFolder + if (syncedFolder.getId() == -1) { int syncedFolderId = (int) DbHelper.insertSyncedFolder(syncedFolder, mContext); if (syncedFolderId > 0) { syncedFolder.setId(syncedFolderId); - }else{ + } else { mSyncedFolderIterator.remove(); - Log.w(TAG, "syncedFolder "+syncedFolder.getRemoteFolder()+" doesn't have a valid ID"); + Log.w(TAG, "ignore syncedFolder :" +syncedFolder.getRemoteFolder()+ " can't be saved in DB"); continue; } } //Create ReadRemoteOperation - LightReadFolderRemoteOperation operation = new LightReadFolderRemoteOperation(syncedFolder.getRemoteFolder(), DEPTH_1, false); - RemoteOperationResult result = operation.execute(ownCloudClient); - - if(result.isSuccess() ){ - //is success then data can't be null - int dataSize = result.getData().size(); - if(dataSize > 1){ //There is at least one subfiles - RemoteFile directory = (RemoteFile) result.getData().get(0); - if(!directory.getEtag().equals(syncedFolder.getLastEtag() )){ //if etag differs - List remoteFiles = result.getData().subList( 1, dataSize ); //get list of subfiles - - //loop through subelements - for (int i = -1, remoteFilesSize = remoteFiles.size(); ++i < remoteFilesSize; ){ - RemoteFile remoteFile = (RemoteFile) remoteFiles.get(i); - - //if remoteFile is in a "media" folder and its name start with "." - // then ignore it - if(syncedFolder.isMediaType() - && CommonUtils.getFileNameFromPath( remoteFile.getRemotePath() ).startsWith(".") ){ - continue; - } - if( remoteFile.getMimeType().equals("DIR") ) { - String suffixPath = remoteFile.getRemotePath().substring( syncedFolder.getRemoteFolder().length() ); - - //but is it already known as SyncedFolder? - SyncedFolder subSyncedFolder = new SyncedFolder(syncedFolder, suffixPath, 0L, "" ); //need to set empty etag to allow it to be scan - mSyncedFolderIterator.add(subSyncedFolder); - mSyncedFolderIterator.previous(); - - }else { - //If it's a file just add it to mRemoteFiles. - mRemoteFiles.add(remoteFile); - } + final ReadFolderRemoteOperation operation = new ReadFolderRemoteOperation(syncedFolder.getRemoteFolder()); + final RemoteOperationResult result = operation.execute(ownCloudClient); + + if (result.isSuccess()) { + final int dataSize = result.getData().size(); + final RemoteFile directory = (RemoteFile) result.getData().get(0); + if (directory.getEtag().equals(syncedFolder.getLastEtag())) { + continue; + } else { + syncedFolder.setLastEtag(directory.getEtag()).setToSync(true); + atLeastOneDirAsChanged = true; + } + + if (dataSize > 1) { + final List remoteFiles = result.getData().subList(1, dataSize); //get list of subfiles + + for (int i = -1, remoteFilesSize = remoteFiles.size(); ++i < remoteFilesSize;) { + final RemoteFile remoteFile = (RemoteFile) remoteFiles.get(i); + + if (remoteFile.getMimeType().equals("DIR")) { + final String suffixPath = remoteFile.getRemotePath().substring(syncedFolder.getRemoteFolder().length()); + + final SyncedFolder subSyncedFolder = new SyncedFolder(syncedFolder, suffixPath, 0L, ""); //need to set empty etag to allow it to be scan + mSyncedFolderIterator.add(subSyncedFolder); + mSyncedFolderIterator.previous(); + + } else { + mRemoteFiles.add(remoteFile); } - syncedFolder.setLastEtag(directory.getEtag() ).setToSync(true); - atLeastOneDirAsChanged = true; - } - }else if(dataSize == 1){ //Empty folder - RemoteFile directory = (RemoteFile) result.getData().get(0); - if(!directory.getEtag().equals(syncedFolder.getLastEtag())) { - syncedFolder.setLastEtag(directory.getEtag()).setToSync(true); - atLeastOneDirAsChanged = true; } - }//Last else correspond to error 404 at LightReadFolderRemoteOperation (see below) - }else{ //Result isn't a success - if(result.getHttpCode() == 404){ //File not found + } + } else { //Result isn't a success + if (result.getHttpCode() == 404) { //File not found atLeastOneDirAsChanged = true; syncedFolder.setToSync(true); //If there is no remote file, then try to delete local one if empty. Finally remove Synced Folder from DB. - File localFolder = new File(syncedFolder.getLocalFolder()); - if(localFolder.exists() && localFolder.listFiles().length == 0){ - localFolder.delete(); - } - if( !localFolder.exists() ) { + final File localFolder = new File(syncedFolder.getLocalFolder()); + + if (!localFolder.exists()) { if (syncedFolder.getId() > this.initialFolderNumber/*-1*/) { //does the synced folder has been persisted? - //remove it from DB - int deleteResult = DbHelper.deleteSyncedFolder(syncedFolder.getId(), mContext); - Log.d(TAG, "syncedFolder Id: "+syncedFolder.getId() + " deletion from db return " + deleteResult + " row affected"); + //remove it from DB. @Todo: do not remove, just disable + final int deleteResult = DbHelper.deleteSyncedFolder(syncedFolder.getId(), mContext); + Log.d(TAG, "syncedFolder Id: " +syncedFolder.getId() + " deletion from db return " + deleteResult + " row affected"); } mSyncedFolderIterator.remove(); + } else if (localFolder.listFiles().length == 0) { + localFolder.delete(); } } - Log.w(TAG, "LightReadFolderRemoteOperation failed : http " + result.getHttpCode() + ", " + result.getLogMessage()+" => Ignored"); - } - - - try{ - Thread.sleep(150); - }catch(InterruptedException e){ - Log.w(TAG, "listFileRemoteOperation's sleep had been interrupted"); + Log.w(TAG, "LightReadFolderRemoteOperation failed : http " + result.getHttpCode() + ", " + result.getLogMessage()+ " => Ignored"); } } //End of loop finalResult = new RemoteOperationResult(RemoteOperationResult.ResultCode.OK); - if( atLeastOneDirAsChanged ) { + if (atLeastOneDirAsChanged) { DbHelper.updateSyncedFolders(this.mSyncedFolders, this.mContext); - finalResult.setData(new ArrayList(mRemoteFiles) ); + finalResult.setData(new ArrayList(mRemoteFiles)); } Log.v(TAG, "end of run()"); @@ -178,7 +149,13 @@ public class ListFileRemoteOperation extends RemoteOperation { * * @return list of syncedFolder */ - public List getSyncedFolderList(){ + public List getSyncedFolderList() { return this.mSyncedFolders; - } + } + + private boolean shouldSkipSyncedFolder(SyncedFolder syncedFolder) { + return (syncedFolder.isMediaType() + && CommonUtils.getFileNameFromPath(syncedFolder.getRemoteFolder()).startsWith(".")) + || !syncedFolder.isScanRemote(); + } } -- GitLab From 6adf7d7fb78afd6f78eb6669418e2bd649f4115b Mon Sep 17 00:00:00 2001 From: vincent Bourgmayer Date: Tue, 10 May 2022 13:23:28 +0200 Subject: [PATCH 07/10] remove nextcloud lib's submodule --- .gitmodules | 1 - nextcloud-android-lib | 1 - 2 files changed, 2 deletions(-) delete mode 160000 nextcloud-android-lib diff --git a/.gitmodules b/.gitmodules index 34e74166..e274f81c 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,2 @@ [submodule "nextcloud-android-lib"] - path = nextcloud-android-lib url = ../nextcloud-android-lib.git \ No newline at end of file diff --git a/nextcloud-android-lib b/nextcloud-android-lib deleted file mode 160000 index b043a510..00000000 --- a/nextcloud-android-lib +++ /dev/null @@ -1 +0,0 @@ -Subproject commit b043a5104962a841daf4ca3e59383216eebf7ef0 -- GitLab From 574d85785a9436b9650769ed7279146c1cf80e26 Mon Sep 17 00:00:00 2001 From: vincent Bourgmayer Date: Tue, 10 May 2022 13:23:28 +0200 Subject: [PATCH 08/10] remove nextcloud lib's submodule --- .gitmodules | 1 - .idea/vcs.xml | 1 - app/build.gradle | 2 +- nextcloud-android-lib | 1 - settings.gradle | 3 +-- 5 files changed, 2 insertions(+), 6 deletions(-) delete mode 160000 nextcloud-android-lib diff --git a/.gitmodules b/.gitmodules index 34e74166..e274f81c 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,2 @@ [submodule "nextcloud-android-lib"] - path = nextcloud-android-lib url = ../nextcloud-android-lib.git \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml index 0bda0242..35eb1ddf 100644 --- a/.idea/vcs.xml +++ b/.idea/vcs.xml @@ -2,6 +2,5 @@ - \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index dcb6fffb..3e5bd13f 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -67,7 +67,7 @@ repositories { } dependencies { - implementation 'com.github.nextcloud:android-library:2.10.1+' + implementation 'com.github.nextcloud:android-library:2.10.1' implementation "commons-httpclient:commons-httpclient:3.1@jar" implementation fileTree(include: ['*.jar'], dir: 'libs') api 'androidx.annotation:annotation:1.3.0' diff --git a/nextcloud-android-lib b/nextcloud-android-lib deleted file mode 160000 index b043a510..00000000 --- a/nextcloud-android-lib +++ /dev/null @@ -1 +0,0 @@ -Subproject commit b043a5104962a841daf4ca3e59383216eebf7ef0 diff --git a/settings.gradle b/settings.gradle index 19a2fc3d..e7b4def4 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,2 +1 @@ -include ':app', ':NextcloudLib' -project(':NextcloudLib').projectDir = new File('nextcloud-android-lib') \ No newline at end of file +include ':app' -- GitLab From ea5289e9e98617b121cef9b17b58ad6b74c31e43 Mon Sep 17 00:00:00 2001 From: vincent Bourgmayer Date: Tue, 10 May 2022 13:39:39 +0200 Subject: [PATCH 09/10] update dependencies --- app/build.gradle | 3 --- build.gradle | 4 ++-- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 3e5bd13f..30c8f6ee 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -62,9 +62,6 @@ android { } } -repositories { - maven { url "https://jitpack.io" } -} dependencies { implementation 'com.github.nextcloud:android-library:2.10.1' diff --git a/build.gradle b/build.gradle index 3378f0cd..a967b912 100644 --- a/build.gradle +++ b/build.gradle @@ -4,12 +4,12 @@ buildscript { repositories { google() - jcenter() + mavenCentral() + maven { url "https://jitpack.io" } } dependencies { classpath 'com.android.tools.build:gradle:4.1.3' - // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files } -- GitLab From 5fd8a50e3dc663d70c9f1015a2ce01f9f5226d3e Mon Sep 17 00:00:00 2001 From: vincent Bourgmayer Date: Tue, 10 May 2022 16:57:54 +0200 Subject: [PATCH 10/10] fix build.gradle --- .gitmodules | 2 -- build.gradle | 4 ++-- 2 files changed, 2 insertions(+), 4 deletions(-) delete mode 100644 .gitmodules diff --git a/.gitmodules b/.gitmodules deleted file mode 100644 index e274f81c..00000000 --- a/.gitmodules +++ /dev/null @@ -1,2 +0,0 @@ -[submodule "nextcloud-android-lib"] - url = ../nextcloud-android-lib.git \ No newline at end of file diff --git a/build.gradle b/build.gradle index a967b912..c8fef1e0 100644 --- a/build.gradle +++ b/build.gradle @@ -5,7 +5,6 @@ buildscript { repositories { google() mavenCentral() - maven { url "https://jitpack.io" } } dependencies { classpath 'com.android.tools.build:gradle:4.1.3' @@ -18,7 +17,8 @@ buildscript { allprojects { repositories { google() - jcenter() + mavenCentral() + maven { url "https://jitpack.io" } } } -- GitLab