Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 033eaceb authored by Vincent Bourgmayer's avatar Vincent Bourgmayer
Browse files

Ignore hidden remote files & refactor ListFileRemoteOperation

parent 3894a8b9
Loading
Loading
Loading
Loading
+88 −57
Original line number Diff line number Diff line
@@ -28,19 +28,20 @@ import foundation.e.drive.utils.CommonUtils;
/**
 * /!\ Doesn't require NextcloudClient yet
 * @author Vincent Bourgmayer
 * Created on 04/05/2018.
 */
public class ListFileRemoteOperation extends RemoteOperation<ArrayList<RemoteFile>> {
    private final String TAG = ListFileRemoteOperation.class.getSimpleName();

    private final List<SyncedFolder> mSyncedFolders;
    private final Context mContext;
    private final List<SyncedFolder> syncedFolders;
    private final Context context;
    private final int initialFolderNumber;
    private final ArrayList<RemoteFile> remoteFiles;

    public ListFileRemoteOperation(List<SyncedFolder> syncedFolders, Context context, int initialFolderNumber) {
        this.mSyncedFolders = syncedFolders;
        this.mContext = context;
        this.syncedFolders = syncedFolders;
        this.context = context;
        this.initialFolderNumber = initialFolderNumber;
        remoteFiles = new ArrayList<>();
    }

    /**
@@ -50,12 +51,10 @@ public class ListFileRemoteOperation extends RemoteOperation<ArrayList<RemoteFil
     */
    @Override
    protected RemoteOperationResult<ArrayList<RemoteFile>> run(OwnCloudClient ownCloudClient) {
        Log.i(TAG, "run()");
        final ArrayList<RemoteFile> mRemoteFiles = new ArrayList<>();
        RemoteOperationResult finalResult;

        boolean atLeastOneDirAsChanged = false;
        final ListIterator<SyncedFolder> mSyncedFolderIterator = mSyncedFolders.listIterator();
        final ListIterator<SyncedFolder> mSyncedFolderIterator = syncedFolders.listIterator();

        while (mSyncedFolderIterator.hasNext()) {
            try {
@@ -71,73 +70,106 @@ public class ListFileRemoteOperation extends RemoteOperation<ArrayList<RemoteFil
            }

            if (syncedFolder.getId() == -1) {
                final int syncedFolderId = (int) DbHelper.insertSyncedFolder(syncedFolder, mContext);
                if (syncedFolderId > 0) {
                    syncedFolder.setId(syncedFolderId);
                } else {
                final int syncedFolderId = (int) DbHelper.insertSyncedFolder(syncedFolder, context);
                if (syncedFolderId <= 0) {
                    mSyncedFolderIterator.remove();
                    Log.w(TAG, "syncedFolder " + syncedFolder.getRemoteFolder() + " doesn't have a valid ID");
                    continue;
                }
                syncedFolder.setId(syncedFolderId);
            }

            final ReadFolderRemoteOperation operation = new ReadFolderRemoteOperation(syncedFolder.getRemoteFolder());
            final RemoteOperationResult result = operation.execute(ownCloudClient);

            if (result.isSuccess()) {
                atLeastOneDirAsChanged = onListFileSuccess(mSyncedFolderIterator, syncedFolder, result);
            } else { //Result isn't a success
                if (result.getHttpCode() == 404) { //dir has not been found
                    atLeastOneDirAsChanged = true;
                    onHttp404Received(mSyncedFolderIterator, syncedFolder);
                }
                Log.w(TAG, "ReadFolderRemoteOperation failed : http " + result.getHttpCode() + ", " + result.getLogMessage() + " => Ignored");
            }
        }
        finalResult = new RemoteOperationResult<>(RemoteOperationResult.ResultCode.OK);
        if (atLeastOneDirAsChanged) {
            DbHelper.updateSyncedFolders(this.syncedFolders, this.context);
            finalResult.setResultData(remoteFiles);
        }
        return finalResult;
    }


    /**
     * Analyze list of remote files for a given Directory
     * @param iterator ListIterator<SyncedFolder> contains list of syncedFolder to check
     * @param syncedFolder the SyncedFolder for the given Directory
     * @param result Result of ListRemoteFile operation
     * @return true if some directory has changed or its content
     */
    private boolean onListFileSuccess(final ListIterator<SyncedFolder> iterator, SyncedFolder syncedFolder, RemoteOperationResult result) {
        final int dataSize = result.getData().size();
        final RemoteFile directory = (RemoteFile) result.getData().get(0);

        if (directory.getEtag().equals(syncedFolder.getLastEtag())) {
                    continue;
            return false;
        }
        syncedFolder.setLastEtag(directory.getEtag()).setToSync(true);
                atLeastOneDirAsChanged = true;

                if (dataSize > 1) {
                    final List<Object> remoteFiles = result.getData().subList(1, dataSize); //get list of subfiles
        final List<Object> subFiles = result.getData().subList(1, dataSize);

                    //loop through subelements
                    for (int i = -1, remoteFilesSize = remoteFiles.size(); ++i < remoteFilesSize; ) {
                        final RemoteFile remoteFile = (RemoteFile) remoteFiles.get(i);
        for (int i = -1, subFilesSize = subFiles.size(); ++i < subFilesSize;) {
            final RemoteFile remoteFile = (RemoteFile) subFiles.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);
                iterator.add(subSyncedFolder);
                iterator.previous();
            } else if (!isHiddenFile(remoteFile)) {
                this.remoteFiles.add(remoteFile);
            }
        }
        return true;
    }
            }else { //Result isn't a success
                if (result.getHttpCode() == 404) { //File not found
                    atLeastOneDirAsChanged = true;

    /**
     * Handle a case where the checked directory is missing on cloud
     * @param iterator ListIterator<SyncedFolder> list of syncedFolder to scan
     * @param syncedFolder Missing syncedFolder on cloud
     */
    private void onHttp404Received(final ListIterator<SyncedFolder> iterator, SyncedFolder syncedFolder) {
        syncedFolder.setToSync(true);

        final File localFolder = new File(syncedFolder.getLocalFolder());
                    if (!localFolder.exists()) {
                        if (syncedFolder.getId() > this.initialFolderNumber) {
                            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) {
        if (localFolder.listFiles().length == 0) {
            localFolder.delete();
        }

        if (!localFolder.exists()) {
            if (syncedFolder.getId() > this.initialFolderNumber) { //Do not remove initial syncedFolder
                DbHelper.deleteSyncedFolder(syncedFolder.getId(), context);
            }
                Log.w(TAG, "ReadFolderRemoteOperation failed : http " + result.getHttpCode() + ", " + result.getLogMessage() + " => Ignored");
            }
            iterator.remove();
        }
        finalResult = new RemoteOperationResult<>(RemoteOperationResult.ResultCode.OK);
        if (atLeastOneDirAsChanged) {
            DbHelper.updateSyncedFolders(this.mSyncedFolders, this.mContext);
            finalResult.setResultData(mRemoteFiles);
    }
        return finalResult;


    /**
     * Indicate if remote file is an hidden file
     * @param file Remote file
     * @return true if it's an hidden file
     */
    private boolean isHiddenFile(RemoteFile file) {
        final String fileName = CommonUtils.getFileNameFromPath(file.getRemotePath());
        return fileName.startsWith(".");
    }

    /**
     * Indicate if we should skip SyncedFolder
     * @param syncedFolder
     * @return
     */
    private boolean shouldSkipSyncedFolder(SyncedFolder syncedFolder) {
        return (syncedFolder.isMediaType()
                && CommonUtils.getFileNameFromPath(syncedFolder.getRemoteFolder()).startsWith("."))
@@ -145,10 +177,9 @@ public class ListFileRemoteOperation extends RemoteOperation<ArrayList<RemoteFil
    }

    /**
     * 
     * @return list of syncedFolder
     */  
   public List<SyncedFolder> getSyncedFolderList(){
        return this.mSyncedFolders;
        return this.syncedFolders;
    }
}