X-Git-Url: http://git.linex4red.de/pub/Android/ownCloud.git/blobdiff_plain/68d4c74fdaba1dcbf135b4b84adfd7def15f2730..d6267698e85f19f9d32e1459738a6fb3500446e5:/src/com/owncloud/android/operations/SynchronizeFolderOperation.java diff --git a/src/com/owncloud/android/operations/SynchronizeFolderOperation.java b/src/com/owncloud/android/operations/SynchronizeFolderOperation.java index 67c7389e..68d539c8 100644 --- a/src/com/owncloud/android/operations/SynchronizeFolderOperation.java +++ b/src/com/owncloud/android/operations/SynchronizeFolderOperation.java @@ -23,6 +23,7 @@ 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; @@ -35,7 +36,6 @@ import org.apache.jackrabbit.webdav.client.methods.PropFindMethod; import android.accounts.Account; import android.content.Context; - import com.owncloud.android.Log_OC; import com.owncloud.android.datamodel.DataStorageManager; import com.owncloud.android.datamodel.OCFile; @@ -64,7 +64,7 @@ public class SynchronizeFolderOperation extends RemoteOperation { /** Id of the folder to synchronize in the local database */ private long mParentId; - + /** Access to the local database */ private DataStorageManager mStorageManager; @@ -121,87 +121,116 @@ public class SynchronizeFolderOperation extends RemoteOperation { return mChildren; } - + public String getRemotePath() { + return mRemotePath; + } + + public long getParentId() { + return mParentId; + } + @Override protected RemoteOperationResult run(WebdavClient client) { RemoteOperationResult result = null; mFailsInFavouritesFound = 0; mConflictsFound = 0; mForgottenLocalFiles.clear(); - + boolean fileChanged = false; + // code before in FileSyncAdapter.fetchData PropFindMethod query = null; try { Log_OC.d(TAG, "Synchronizing " + mAccount.name + ", fetching files in " + mRemotePath); - + // remote request query = new PropFindMethod(client.getBaseUri() + WebdavUtils.encodePath(mRemotePath)); int status = client.executeMethod(query); - + // check and process response - /// TODO take into account all the possible status per child-resource if (isMultiStatus(status)) { MultiStatus resp = query.getResponseBodyAsMultiStatus(); - + // synchronize properties of the parent folder, if necessary if (mParentId == DataStorageManager.ROOT_PARENT_ID) { WebdavEntry we = new WebdavEntry(resp.getResponses()[0], client.getBaseUri().getPath()); + + // Properties of server folder OCFile parent = fillOCFile(we); - mStorageManager.saveFile(parent); - mParentId = parent.getFileId(); + // Properties of local folder + OCFile localParent = mStorageManager.getFileById(1); + if (parent.getEtag() != localParent.getEtag()) { + mStorageManager.saveFile(parent); + mParentId = parent.getFileId(); + } } - + + // read contents in folder + List filesOnServer = new ArrayList (); // Contains the lists of files on server List updatedFiles = new Vector(resp.getResponses().length - 1); List filesToSyncContents = new Vector(); for (int i = 1; i < resp.getResponses().length; ++i) { /// new OCFile instance with the data from the server WebdavEntry we = new WebdavEntry(resp.getResponses()[i], client.getBaseUri().getPath()); OCFile file = fillOCFile(we); - + + filesOnServer.add(file.getRemotePath()); // Registry the file in the list + /// set data about local state, keeping unchanged former data if existing file.setLastSyncDateForProperties(mCurrentSyncTime); OCFile oldFile = mStorageManager.getFileByPath(file.getRemotePath()); + + // Check if it is needed to synchronize the folder + fileChanged = false; if (oldFile != null) { - file.setKeepInSync(oldFile.keepInSync()); - file.setLastSyncDateForData(oldFile.getLastSyncDateForData()); - file.setModificationTimestampAtLastSyncForData(oldFile.getModificationTimestampAtLastSyncForData()); // must be kept unchanged when the file contents are not updated - checkAndFixForeignStoragePath(oldFile); - file.setStoragePath(oldFile.getStoragePath()); - } + if (!file.getEtag().equalsIgnoreCase(oldFile.getEtag())) { + fileChanged = true; + } + } else + fileChanged= true; - /// scan default location if local copy of file is not linked in OCFile instance - if (file.getStoragePath() == null && !file.isDirectory()) { - File f = new File(FileStorageUtils.getDefaultSavePathFor(mAccount.name, file)); - if (f.exists()) { - file.setStoragePath(f.getAbsolutePath()); - file.setLastSyncDateForData(f.lastModified()); + if (fileChanged){ + if (oldFile != null) { + file.setKeepInSync(oldFile.keepInSync()); + file.setLastSyncDateForData(oldFile.getLastSyncDateForData()); + file.setModificationTimestampAtLastSyncForData(oldFile.getModificationTimestampAtLastSyncForData()); // must be kept unchanged when the file contents are not updated + checkAndFixForeignStoragePath(oldFile); + file.setStoragePath(oldFile.getStoragePath()); } + /// scan default location if local copy of file is not linked in OCFile instance + if (file.getStoragePath() == null && !file.isDirectory()) { + File f = new File(FileStorageUtils.getDefaultSavePathFor(mAccount.name, file)); + if (f.exists()) { + file.setStoragePath(f.getAbsolutePath()); + file.setLastSyncDateForData(f.lastModified()); + } + } + + /// prepare content synchronization for kept-in-sync files + if (file.keepInSync()) { + SynchronizeFileOperation operation = new SynchronizeFileOperation( oldFile, + file, + mStorageManager, + mAccount, + true, + false, + mContext + ); + filesToSyncContents.add(operation); + } + + updatedFiles.add(file); } - - /// prepare content synchronization for kept-in-sync files - if (file.keepInSync()) { - SynchronizeFileOperation operation = new SynchronizeFileOperation( oldFile, - file, - mStorageManager, - mAccount, - true, - false, - mContext - ); - filesToSyncContents.add(operation); - } - - updatedFiles.add(file); } - + // save updated contents in local database; all at once, trying to get a best performance in database update (not a big deal, indeed) mStorageManager.saveFiles(updatedFiles); - + // request for the synchronization of files AFTER saving last properties - SynchronizeFileOperation op = null; + //SynchronizeFileOperation op = null; RemoteOperationResult contentsResult = null; - for (int i=0; i < filesToSyncContents.size(); i++) { - op = filesToSyncContents.get(i); + for (SynchronizeFileOperation op: filesToSyncContents) {//int i=0; i < filesToSyncContents.size(); i++) { + //op = filesToSyncContents.get(i); contentsResult = op.execute(client); // returns without waiting for upload or download finishes if (!contentsResult.isSuccess()) { if (contentsResult.getCode() == ResultCode.SYNC_CONFLICT) { @@ -217,40 +246,46 @@ public class SynchronizeFolderOperation extends RemoteOperation { } // won't let these fails break the synchronization process } - + // removal of obsolete files mChildren = mStorageManager.getDirectoryContent(mStorageManager.getFileById(mParentId)); - OCFile file; + //OCFile file; String currentSavePath = FileStorageUtils.getSavePath(mAccount.name); - for (int i=0; i < mChildren.size(); ) { - file = mChildren.get(i); - if (file.getLastSyncDateForProperties() != mCurrentSyncTime) { - Log_OC.d(TAG, "removing file: " + file); - mStorageManager.removeFile(file, (file.isDown() && file.getStoragePath().startsWith(currentSavePath))); - mChildren.remove(i); - } else { - i++; + for (OCFile fileChild: mChildren) { + //file = mChildren.get(i); + //if (file.getLastSyncDateForProperties() != mCurrentSyncTime) { + if (!filesOnServer.contains(fileChild.getRemotePath())) { + Log_OC.d(TAG, "removing file: " + fileChild.getFileName()); + mStorageManager.removeFile(fileChild, (fileChild.isDown() && fileChild.getStoragePath().startsWith(currentSavePath))); + mChildren.remove(fileChild); //.remove(i); } + // } else { + // i++; + // } } - + // } + //} + } else { client.exhaustResponse(query.getResponseBodyAsStream()); } - + // prepare result object - if (isMultiStatus(status)) { + if (!fileChanged) { + result = new RemoteOperationResult(ResultCode.OK_NO_CHANGES_ON_DIR); + + } else if (isMultiStatus(status)) { 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(false, status, query.getResponseHeaders()); } - - - + Log_OC.i(TAG, "Synchronizing " + mAccount.name + ", folder " + mRemotePath + ": " + result.getLogMessage()); + } catch (Exception e) { result = new RemoteOperationResult(e); @@ -268,10 +303,10 @@ public class SynchronizeFolderOperation extends RemoteOperation { } } } - + return result; } - + public boolean isMultiStatus(int status) { return (status == HttpStatus.SC_MULTI_STATUS); @@ -291,6 +326,7 @@ public class SynchronizeFolderOperation extends RemoteOperation { file.setMimetype(we.contentType()); file.setModificationTimestamp(we.modifiedTimestamp()); file.setParentId(mParentId); + file.setEtag(we.etag()); return file; } @@ -301,7 +337,7 @@ public class SynchronizeFolderOperation extends RemoteOperation { * * If the copy fails, the link to the local file is nullified. The account of forgotten files is kept in * {@link #mForgottenLocalFiles} - * + *) * @param file File to check and fix. */ private void checkAndFixForeignStoragePath(OCFile file) {