X-Git-Url: http://git.linex4red.de/pub/Android/ownCloud.git/blobdiff_plain/0aef684087c266b5e79a2693592748a53cc87a56..bcc972d63d3ed1d76b51a8a03a27e809983dc756:/src/com/owncloud/android/operations/SynchronizeFolderOperation.java?ds=sidebyside diff --git a/src/com/owncloud/android/operations/SynchronizeFolderOperation.java b/src/com/owncloud/android/operations/SynchronizeFolderOperation.java index 4935a616..e93736c4 100644 --- a/src/com/owncloud/android/operations/SynchronizeFolderOperation.java +++ b/src/com/owncloud/android/operations/SynchronizeFolderOperation.java @@ -23,29 +23,34 @@ 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 org.apache.jackrabbit.webdav.MultiStatus; +import org.apache.jackrabbit.webdav.DavConstants; import org.apache.jackrabbit.webdav.client.methods.PropFindMethod; import android.accounts.Account; import android.content.Context; import android.content.Intent; -import com.owncloud.android.Log_OC; -import com.owncloud.android.datamodel.DataStorageManager; +import com.owncloud.android.datamodel.FileDataStorageManager; import com.owncloud.android.datamodel.OCFile; -import com.owncloud.android.operations.RemoteOperationResult.ResultCode; +import com.owncloud.android.oc_framework.network.webdav.WebdavClient; +import com.owncloud.android.oc_framework.network.webdav.WebdavEntry; +import com.owncloud.android.oc_framework.network.webdav.WebdavUtils; +import com.owncloud.android.oc_framework.operations.RemoteOperation; +import com.owncloud.android.oc_framework.operations.RemoteOperationResult; +import com.owncloud.android.oc_framework.operations.RemoteOperationResult.ResultCode; +import com.owncloud.android.oc_framework.operations.remote.ReadRemoteFolderOperation; +import com.owncloud.android.oc_framework.operations.RemoteFile; import com.owncloud.android.syncadapter.FileSyncService; import com.owncloud.android.utils.FileStorageUtils; +import com.owncloud.android.utils.Log_OC; -import eu.alefzero.webdav.WebdavClient; -import eu.alefzero.webdav.WebdavEntry; -import eu.alefzero.webdav.WebdavUtils; /** @@ -70,11 +75,8 @@ public class SynchronizeFolderOperation extends RemoteOperation { /** Remote folder to synchronize */ private OCFile mLocalFolder; - /** 'True' means that the properties of the folder should be updated also, not just its content */ - private boolean mUpdateFolderProperties; - /** Access to the local database */ - private DataStorageManager mStorageManager; + private FileDataStorageManager mStorageManager; /** Account where the file to synchronize belongs */ private Account mAccount; @@ -96,6 +98,9 @@ public class SynchronizeFolderOperation extends RemoteOperation { /** 'True' means that this operation is part of a full account synchronization */ private boolean mSyncFullAccount; + + /** 'True' means that the remote folder changed from last synchronization and should be fetched */ + private boolean mRemoteFolderChanged; /** @@ -112,19 +117,18 @@ public class SynchronizeFolderOperation extends RemoteOperation { */ public SynchronizeFolderOperation( OCFile folder, long currentSyncTime, - boolean updateFolderProperties, boolean syncFullAccount, - DataStorageManager dataStorageManager, + FileDataStorageManager dataStorageManager, Account account, Context context ) { mLocalFolder = folder; mCurrentSyncTime = currentSyncTime; - mUpdateFolderProperties = updateFolderProperties; mSyncFullAccount = syncFullAccount; mStorageManager = dataStorageManager; mAccount = account; mContext = context; mForgottenLocalFiles = new HashMap(); + mRemoteFolderChanged = false; } @@ -160,37 +164,58 @@ public class SynchronizeFolderOperation extends RemoteOperation { mFailsInFavouritesFound = 0; mConflictsFound = 0; mForgottenLocalFiles.clear(); + + result = checkForChanges(client); + + if (result.isSuccess()) { + if (mRemoteFolderChanged) { + result = fetchAndSyncRemoteFolder(client); + } else { + mChildren = mStorageManager.getFolderContent(mLocalFolder); + } + } + + if (!mSyncFullAccount) { + sendStickyBroadcast(false, mLocalFolder.getRemotePath(), result); + } + + return result; + + } + + + private RemoteOperationResult checkForChanges(WebdavClient client) { + mRemoteFolderChanged = false; + RemoteOperationResult result = null; String remotePath = null; PropFindMethod query = null; + try { remotePath = mLocalFolder.getRemotePath(); - Log_OC.d(TAG, "Synchronizing " + mAccount.name + remotePath); + Log_OC.d(TAG, "Checking changes in " + mAccount.name + remotePath); // remote request - query = new PropFindMethod(client.getBaseUri() + WebdavUtils.encodePath(remotePath)); + query = new PropFindMethod(client.getBaseUri() + WebdavUtils.encodePath(remotePath), + DavConstants.PROPFIND_ALL_PROP, + DavConstants.DEPTH_0); int status = client.executeMethod(query); // check and process response if (isMultiStatus(status)) { - boolean folderChanged = synchronizeData(query.getResponseBodyAsMultiStatus(), client); - if (folderChanged) { - if (mConflictsFound > 0 || mFailsInFavouritesFound > 0) { - result = new RemoteOperationResult(ResultCode.SYNC_CONFLICT); // should be different result, but will do the job - } else { - result = new RemoteOperationResult(true, status, query.getResponseHeaders()); - } - } else { - result = new RemoteOperationResult(ResultCode.OK_NO_CHANGES_ON_DIR); - } + // parse data from remote folder + WebdavEntry we = new WebdavEntry(query.getResponseBodyAsMultiStatus().getResponses()[0], client.getBaseUri().getPath()); + OCFile remoteFolder = fillOCFile(we); + + // check if remote and local folder are different + mRemoteFolderChanged = !(remoteFolder.getEtag().equalsIgnoreCase(mLocalFolder.getEtag())); + + result = new RemoteOperationResult(ResultCode.OK); } else { - // synchronization failed + // check failed client.exhaustResponse(query.getResponseBodyAsStream()); if (status == HttpStatus.SC_NOT_FOUND) { - if (mStorageManager.fileExists(mLocalFolder.getFileId())) { - String currentSavePath = FileStorageUtils.getSavePath(mAccount.name); - mStorageManager.removeDirectory(mLocalFolder, true, (mLocalFolder.isDown() && mLocalFolder.getStoragePath().startsWith(currentSavePath))); - } + removeLocalFolder(); } result = new RemoteOperationResult(false, status, query.getResponseHeaders()); } @@ -203,143 +228,142 @@ public class SynchronizeFolderOperation extends RemoteOperation { if (query != null) query.releaseConnection(); // let the connection available for other methods if (result.isSuccess()) { - Log_OC.i(TAG, "Synchronized " + mAccount.name + remotePath + ": " + result.getLogMessage()); + Log_OC.i(TAG, "Checked " + mAccount.name + remotePath + " : " + (mRemoteFolderChanged ? "changed" : "not changed")); } else { if (result.isException()) { - Log_OC.e(TAG, "Synchronized " + mAccount.name + remotePath + ": " + result.getLogMessage(), result.getException()); + Log_OC.e(TAG, "Checked " + mAccount.name + remotePath + " : " + result.getLogMessage(), result.getException()); } else { - Log_OC.e(TAG, "Synchronized " + mAccount.name + remotePath + ": " + result.getLogMessage()); + Log_OC.e(TAG, "Checked " + mAccount.name + remotePath + " : " + result.getLogMessage()); } } - if (!mSyncFullAccount) { - sendStickyBroadcast(false, remotePath, result); - } } + return result; + } + + private RemoteOperationResult fetchAndSyncRemoteFolder(WebdavClient 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 different result, 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 dataInServer Full response got from the server with the data of the target - * folder and its direct children. + * + * @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 boolean synchronizeData(MultiStatus dataInServer, WebdavClient client) { + private void synchronizeData(ArrayList folderAndFiles, WebdavClient client) { // get 'fresh data' from the database - mLocalFolder = mStorageManager.getFileById(mLocalFolder.getFileId()); + mLocalFolder = mStorageManager.getFileByPath(mLocalFolder.getRemotePath()); // parse data from remote folder - WebdavEntry we = new WebdavEntry(dataInServer.getResponses()[0], client.getBaseUri().getPath()); - OCFile remoteFolder = fillOCFile(we); + OCFile remoteFolder = fillOCFile(folderAndFiles.get(0)); remoteFolder.setParentId(mLocalFolder.getParentId()); remoteFolder.setFileId(mLocalFolder.getFileId()); - // check if remote and local folder are different - boolean folderChanged = !(remoteFolder.getEtag().equalsIgnoreCase(mLocalFolder.getEtag())); + Log_OC.d(TAG, "Remote folder " + mLocalFolder.getRemotePath() + " changed - starting update of local data "); - if (!folderChanged) { - if (mUpdateFolderProperties) { // TODO check if this is really necessary - mStorageManager.saveFile(remoteFolder); - } - - mChildren = mStorageManager.getDirectoryContent(mLocalFolder); - - } else { - // read info of folder contents - List updatedFiles = new Vector(dataInServer.getResponses().length - 1); - List filesToSyncContents = new Vector(); + List updatedFiles = new Vector(folderAndFiles.size() - 1); + List filesToSyncContents = new Vector(); + + // get current data about local contents of the folder to synchronize + List localFiles = mStorageManager.getFolderContent(mLocalFolder); + Map localFilesMap = new HashMap(localFiles.size()); + for (OCFile file : localFiles) { + localFilesMap.put(file.getRemotePath(), file); + } + + // loop to update every child + OCFile remoteFile = null, localFile = null; + for (int i=1; i