X-Git-Url: http://git.linex4red.de/pub/Android/ownCloud.git/blobdiff_plain/34433e924df7c368c2a4012854c76591be64b5c2..1e847c4ac89943fdb5516470dae6829adcd7cd14:/src/com/owncloud/android/operations/RefreshFolderOperation.java
diff --git a/src/com/owncloud/android/operations/RefreshFolderOperation.java b/src/com/owncloud/android/operations/RefreshFolderOperation.java
new file mode 100644
index 00000000..53717893
--- /dev/null
+++ b/src/com/owncloud/android/operations/RefreshFolderOperation.java
@@ -0,0 +1,610 @@
+/* ownCloud Android client application
+ * Copyright (C) 2012-2014 ownCloud Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2,
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ */
+
+package com.owncloud.android.operations;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Vector;
+
+import org.apache.http.HttpStatus;
+import android.accounts.Account;
+import android.content.Context;
+import android.content.Intent;
+import android.util.Log;
+//import android.support.v4.content.LocalBroadcastManager;
+
+import com.owncloud.android.datamodel.FileDataStorageManager;
+import com.owncloud.android.datamodel.OCFile;
+
+import com.owncloud.android.lib.common.OwnCloudClient;
+import com.owncloud.android.lib.resources.shares.OCShare;
+import com.owncloud.android.lib.common.operations.RemoteOperation;
+import com.owncloud.android.lib.common.operations.RemoteOperationResult;
+import com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode;
+import com.owncloud.android.lib.common.utils.Log_OC;
+import com.owncloud.android.lib.resources.shares.GetRemoteSharesForFileOperation;
+import com.owncloud.android.lib.resources.files.FileUtils;
+import com.owncloud.android.lib.resources.files.ReadRemoteFileOperation;
+import com.owncloud.android.lib.resources.files.ReadRemoteFolderOperation;
+import com.owncloud.android.lib.resources.files.RemoteFile;
+
+import com.owncloud.android.syncadapter.FileSyncAdapter;
+import com.owncloud.android.utils.FileStorageUtils;
+
+
+
+/**
+ * Remote operation performing the synchronization of the list of files contained
+ * in a folder identified with its remote path.
+ *
+ * Fetches the list and properties of the files contained in the given folder, including their
+ * properties, and updates the local database with them.
+ *
+ * Does NOT enter in the child folders to synchronize their contents also.
+ *
+ * @author David A. Velasco
+ */
+public class RefreshFolderOperation extends RemoteOperation {
+
+ private static final String TAG = RefreshFolderOperation.class.getSimpleName();
+
+ public static final String EVENT_SINGLE_FOLDER_CONTENTS_SYNCED =
+ RefreshFolderOperation.class.getName() + ".EVENT_SINGLE_FOLDER_CONTENTS_SYNCED";
+ public static final String EVENT_SINGLE_FOLDER_SHARES_SYNCED =
+ RefreshFolderOperation.class.getName() + ".EVENT_SINGLE_FOLDER_SHARES_SYNCED";
+
+ /** Time stamp for the synchronization process in progress */
+ private long mCurrentSyncTime;
+
+ /** Remote folder to synchronize */
+ private OCFile mLocalFolder;
+
+ /** Access to the local database */
+ private FileDataStorageManager mStorageManager;
+
+ /** Account where the file to synchronize belongs */
+ private Account mAccount;
+
+ /** Android context; necessary to send requests to the download service */
+ private Context mContext;
+
+ /** Files and folders contained in the synchronized folder after a successful operation */
+ private List mChildren;
+
+ /** Counter of conflicts found between local and remote files */
+ private int mConflictsFound;
+
+ /** Counter of failed operations in synchronization of kept-in-sync files */
+ private int mFailsInFavouritesFound;
+
+ /**
+ * Map of remote and local paths to files that where locally stored in a location
+ * out of the ownCloud folder and couldn't be copied automatically into it
+ **/
+ private Map mForgottenLocalFiles;
+
+ /** 'True' means that this operation is part of a full account synchronization */
+ private boolean mSyncFullAccount;
+
+ /** 'True' means that Share resources bound to the files into should be refreshed also */
+ private boolean mIsShareSupported;
+
+ /** 'True' means that the remote folder changed and should be fetched */
+ private boolean mRemoteFolderChanged;
+
+ /** 'True' means that Etag will be ignored */
+ private boolean mIgnoreETag;
+
+
+ /**
+ * Creates a new instance of {@link RefreshFolderOperation}.
+ *
+ * @param folder Folder to synchronize.
+ * @param currentSyncTime Time stamp for the synchronization process in progress.
+ * @param syncFullAccount 'True' means that this operation is part of a full account
+ * synchronization.
+ * @param isShareSupported 'True' means that the server supports the sharing API.
+ * @param ignoreEtag 'True' means that the content of the remote folder should
+ * be fetched and updated even though the 'eTag' did not
+ * change.
+ * @param dataStorageManager Interface with the local database.
+ * @param account ownCloud account where the folder is located.
+ * @param context Application context.
+ */
+ public RefreshFolderOperation(OCFile folder,
+ long currentSyncTime,
+ boolean syncFullAccount,
+ boolean isShareSupported,
+ boolean ignoreETag,
+ FileDataStorageManager dataStorageManager,
+ Account account,
+ Context context) {
+ mLocalFolder = folder;
+ mCurrentSyncTime = currentSyncTime;
+ mSyncFullAccount = syncFullAccount;
+ mIsShareSupported = isShareSupported;
+ mStorageManager = dataStorageManager;
+ mAccount = account;
+ mContext = context;
+ mForgottenLocalFiles = new HashMap();
+ mRemoteFolderChanged = false;
+ mIgnoreETag = ignoreETag;
+ }
+
+
+ public int getConflictsFound() {
+ return mConflictsFound;
+ }
+
+ public int getFailsInFavouritesFound() {
+ return mFailsInFavouritesFound;
+ }
+
+ public Map getForgottenLocalFiles() {
+ return mForgottenLocalFiles;
+ }
+
+ /**
+ * Returns the list of files and folders contained in the synchronized folder,
+ * if called after synchronization is complete.
+ *
+ * @return List of files and folders contained in the synchronized folder.
+ */
+ public List getChildren() {
+ return mChildren;
+ }
+
+ /**
+ * Performs the synchronization.
+ *
+ * {@inheritDoc}
+ */
+ @Override
+ protected RemoteOperationResult run(OwnCloudClient client) {
+ RemoteOperationResult result = null;
+ mFailsInFavouritesFound = 0;
+ mConflictsFound = 0;
+ mForgottenLocalFiles.clear();
+
+ if (FileUtils.PATH_SEPARATOR.equals(mLocalFolder.getRemotePath()) && !mSyncFullAccount) {
+ updateOCVersion(client);
+ }
+
+ result = checkForChanges(client);
+
+ if (result.isSuccess()) {
+ if (mRemoteFolderChanged) {
+ result = fetchAndSyncRemoteFolder(client);
+ } else {
+ mChildren = mStorageManager.getFolderContent(mLocalFolder);
+ }
+ }
+
+ if (!mSyncFullAccount) {
+ sendLocalBroadcast(
+ EVENT_SINGLE_FOLDER_CONTENTS_SYNCED, mLocalFolder.getRemotePath(), result
+ );
+ }
+
+ if (result.isSuccess() && mIsShareSupported && !mSyncFullAccount) {
+ refreshSharesForFolder(client); // share result is ignored
+ }
+
+ if (!mSyncFullAccount) {
+ sendLocalBroadcast(
+ EVENT_SINGLE_FOLDER_SHARES_SYNCED, mLocalFolder.getRemotePath(), result
+ );
+ }
+
+ return result;
+
+ }
+
+
+ private void updateOCVersion(OwnCloudClient client) {
+ UpdateOCVersionOperation update = new UpdateOCVersionOperation(mAccount, mContext);
+ RemoteOperationResult result = update.execute(client);
+ if (result.isSuccess()) {
+ mIsShareSupported = update.getOCVersion().isSharedSupported();
+ }
+ }
+
+
+ private RemoteOperationResult checkForChanges(OwnCloudClient client) {
+ mRemoteFolderChanged = true;
+ RemoteOperationResult result = null;
+ String remotePath = null;
+
+ remotePath = mLocalFolder.getRemotePath();
+ Log_OC.d(TAG, "Checking changes in " + mAccount.name + remotePath);
+
+ // remote request
+ ReadRemoteFileOperation operation = new ReadRemoteFileOperation(remotePath);
+ result = operation.execute(client);
+ if (result.isSuccess()){
+ OCFile remoteFolder = FileStorageUtils.fillOCFile((RemoteFile) result.getData().get(0));
+
+ if (!mIgnoreETag) {
+ // check if remote and local folder are different
+ mRemoteFolderChanged =
+ !(remoteFolder.getEtag().equalsIgnoreCase(mLocalFolder.getEtag()));
+ }
+
+ result = new RemoteOperationResult(ResultCode.OK);
+
+ Log_OC.i(TAG, "Checked " + mAccount.name + remotePath + " : " +
+ (mRemoteFolderChanged ? "changed" : "not changed"));
+
+ } else {
+ // check failed
+ if (result.getCode() == ResultCode.FILE_NOT_FOUND) {
+ removeLocalFolder();
+ }
+ if (result.isException()) {
+ Log_OC.e(TAG, "Checked " + mAccount.name + remotePath + " : " +
+ result.getLogMessage(), result.getException());
+ } else {
+ Log_OC.e(TAG, "Checked " + mAccount.name + remotePath + " : " +
+ result.getLogMessage());
+ }
+ }
+
+ return result;
+ }
+
+
+ private RemoteOperationResult fetchAndSyncRemoteFolder(OwnCloudClient client) {
+ String remotePath = mLocalFolder.getRemotePath();
+ ReadRemoteFolderOperation operation = new ReadRemoteFolderOperation(remotePath);
+ RemoteOperationResult result = operation.execute(client);
+ Log_OC.d(TAG, "Synchronizing " + mAccount.name + remotePath);
+
+ if (result.isSuccess()) {
+ synchronizeData(result.getData(), client);
+ if (mConflictsFound > 0 || mFailsInFavouritesFound > 0) {
+ result = new RemoteOperationResult(ResultCode.SYNC_CONFLICT);
+ // should be a different result code, but will do the job
+ }
+ } else {
+ if (result.getCode() == ResultCode.FILE_NOT_FOUND)
+ removeLocalFolder();
+ }
+
+ return result;
+ }
+
+
+ private void removeLocalFolder() {
+ if (mStorageManager.fileExists(mLocalFolder.getFileId())) {
+ String currentSavePath = FileStorageUtils.getSavePath(mAccount.name);
+ mStorageManager.removeFolder(
+ mLocalFolder,
+ true,
+ ( mLocalFolder.isDown() &&
+ mLocalFolder.getStoragePath().startsWith(currentSavePath)
+ )
+ );
+ }
+ }
+
+
+ /**
+ * Synchronizes the data retrieved from the server about the contents of the target folder
+ * with the current data in the local database.
+ *
+ * Grants that mChildren is updated with fresh data after execution.
+ *
+ * @param folderAndFiles Remote folder and children files in Folder
+ *
+ * @param client Client instance to the remote server where the data were
+ * retrieved.
+ * @return 'True' when any change was made in the local data, 'false' otherwise
+ */
+ private void synchronizeData(ArrayList