|
@@ -23,7 +23,6 @@ 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;
|
|
@@ -50,25 +49,29 @@ import eu.alefzero.webdav.WebdavUtils;
|
|
|
|
|
|
|
|
|
/**
|
|
|
- * Remote operation performing the synchronization a the contents of a remote folder with the local database
|
|
|
+ * 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
|
|
|
+ * @author David A. Velasco
|
|
|
*/
|
|
|
public class SynchronizeFolderOperation extends RemoteOperation {
|
|
|
|
|
|
private static final String TAG = SynchronizeFolderOperation.class.getSimpleName();
|
|
|
|
|
|
- /** Remote folder to synchronize */
|
|
|
- private String mRemotePath;
|
|
|
|
|
|
- /** Timestamp for the synchronization in progress */
|
|
|
+ /** Time stamp for the synchronization process in progress */
|
|
|
private long mCurrentSyncTime;
|
|
|
|
|
|
- /** Id of the folder to synchronize in the local database */
|
|
|
- private long mParentId;
|
|
|
+ /** Remote folder to synchronize */
|
|
|
+ private OCFile mLocalFolder;
|
|
|
|
|
|
- /** Boolean to indicate if is mandatory to update the folder */
|
|
|
- private boolean mEnforceMetadataUpdate;
|
|
|
+ /** '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;
|
|
@@ -76,33 +79,47 @@ public class SynchronizeFolderOperation extends RemoteOperation {
|
|
|
/** Account where the file to synchronize belongs */
|
|
|
private Account mAccount;
|
|
|
|
|
|
- /** Android context; necessary to send requests to the download service; maybe something to refactor */
|
|
|
+ /** Android context; necessary to send requests to the download service */
|
|
|
private Context mContext;
|
|
|
|
|
|
- /** Files and folders contained in the synchronized folder */
|
|
|
+ /** Files and folders contained in the synchronized folder after a successful operation */
|
|
|
private List<OCFile> 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<String, String> mForgottenLocalFiles;
|
|
|
-
|
|
|
+
|
|
|
+ /** 'True' means that this operation is part of a full account synchronization */
|
|
|
private boolean mSyncFullAccount;
|
|
|
|
|
|
|
|
|
- public SynchronizeFolderOperation( String remotePath,
|
|
|
+ /**
|
|
|
+ * Creates a new instance of {@link SynchronizeFolderOperation}.
|
|
|
+ *
|
|
|
+ * @param remoteFolderPath Remote folder to synchronize.
|
|
|
+ * @param currentSyncTime Time stamp for the synchronization process in progress.
|
|
|
+ * @param localFolderId Identifier in the local database of the folder to synchronize.
|
|
|
+ * @param updateFolderProperties 'True' means that the properties of the folder should be updated also, not just its content.
|
|
|
+ * @param syncFullAccount 'True' means that this operation is part of a full account synchronization.
|
|
|
+ * @param dataStorageManager Interface with the local database.
|
|
|
+ * @param account ownCloud account where the folder is located.
|
|
|
+ * @param context Application context.
|
|
|
+ */
|
|
|
+ public SynchronizeFolderOperation( OCFile folder,
|
|
|
long currentSyncTime,
|
|
|
- long parentId,
|
|
|
- boolean enforceMetadataUpdate,
|
|
|
+ boolean updateFolderProperties,
|
|
|
boolean syncFullAccount,
|
|
|
DataStorageManager dataStorageManager,
|
|
|
Account account,
|
|
|
Context context ) {
|
|
|
- mRemotePath = remotePath;
|
|
|
+ mLocalFolder = folder;
|
|
|
mCurrentSyncTime = currentSyncTime;
|
|
|
- mParentId = parentId;
|
|
|
- mEnforceMetadataUpdate = enforceMetadataUpdate;
|
|
|
+ mUpdateFolderProperties = updateFolderProperties;
|
|
|
mSyncFullAccount = syncFullAccount;
|
|
|
mStorageManager = dataStorageManager;
|
|
|
mAccount = account;
|
|
@@ -126,178 +143,53 @@ public class SynchronizeFolderOperation extends RemoteOperation {
|
|
|
/**
|
|
|
* 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.
|
|
|
+ * @return List of files and folders contained in the synchronized folder.
|
|
|
*/
|
|
|
public List<OCFile> getChildren() {
|
|
|
return mChildren;
|
|
|
}
|
|
|
|
|
|
- public String getRemotePath() {
|
|
|
- return mRemotePath;
|
|
|
- }
|
|
|
-
|
|
|
- public long getParentId() {
|
|
|
- return mParentId;
|
|
|
- }
|
|
|
-
|
|
|
+ /**
|
|
|
+ * Performs the synchronization.
|
|
|
+ *
|
|
|
+ * {@inheritDoc}
|
|
|
+ */
|
|
|
@Override
|
|
|
protected RemoteOperationResult run(WebdavClient client) {
|
|
|
RemoteOperationResult result = null;
|
|
|
mFailsInFavouritesFound = 0;
|
|
|
mConflictsFound = 0;
|
|
|
mForgottenLocalFiles.clear();
|
|
|
- boolean dirChanged = false;
|
|
|
-
|
|
|
- // code before in FileSyncAdapter.fetchData
|
|
|
+ String remotePath = null;
|
|
|
PropFindMethod query = null;
|
|
|
try {
|
|
|
- Log_OC.d(TAG, "Synchronizing " + mAccount.name + ", fetching files in " + mRemotePath);
|
|
|
+ remotePath = mLocalFolder.getRemotePath();
|
|
|
+ Log_OC.d(TAG, "Synchronizing " + mAccount.name + remotePath);
|
|
|
|
|
|
// remote request
|
|
|
- query = new PropFindMethod(client.getBaseUri() + WebdavUtils.encodePath(mRemotePath));
|
|
|
+ query = new PropFindMethod(client.getBaseUri() + WebdavUtils.encodePath(remotePath));
|
|
|
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
|
|
|
- WebdavEntry we = new WebdavEntry(resp.getResponses()[0], client.getBaseUri().getPath());
|
|
|
-
|
|
|
- // Properties of server folder
|
|
|
- OCFile parent = fillOCFile(we);
|
|
|
- // Properties of local folder
|
|
|
- OCFile localParent = mStorageManager.getFileByPath(mRemotePath);
|
|
|
- if (localParent == null || !(parent.getEtag().equalsIgnoreCase(localParent.getEtag())) || mEnforceMetadataUpdate) {
|
|
|
- if (localParent != null) {
|
|
|
- parent.setParentId(localParent.getParentId());
|
|
|
- }
|
|
|
- mStorageManager.saveFile(parent);
|
|
|
- if (mParentId == DataStorageManager.ROOT_PARENT_ID)
|
|
|
- mParentId = parent.getFileId();
|
|
|
- dirChanged = true;
|
|
|
- }
|
|
|
-
|
|
|
- if (dirChanged) {
|
|
|
- // read contents in folder
|
|
|
- List<String> filesOnServer = new ArrayList<String> (); // Contains the lists of files on server
|
|
|
- List<OCFile> updatedFiles = new Vector<OCFile>(resp.getResponses().length - 1);
|
|
|
- List<SynchronizeFileOperation> filesToSyncContents = new Vector<SynchronizeFileOperation>();
|
|
|
- for (int i = 1; i < resp.getResponses().length; ++i) {
|
|
|
- /// new OCFile instance with the data from the server
|
|
|
- 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
|
|
|
- if (oldFile != null) {
|
|
|
- if (!file.getEtag().equalsIgnoreCase(oldFile.getEtag())) {
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- 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.isDirectory())
|
|
|
- file.setEtag(oldFile.getEtag());
|
|
|
- } else
|
|
|
- if (file.isDirectory())
|
|
|
- file.setEtag("");
|
|
|
-
|
|
|
- /// 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);
|
|
|
- }
|
|
|
-
|
|
|
- // 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
|
|
|
- RemoteOperationResult contentsResult = null;
|
|
|
- for (SynchronizeFileOperation op: filesToSyncContents) {
|
|
|
- contentsResult = op.execute(client); // returns without waiting for upload or download finishes
|
|
|
- if (!contentsResult.isSuccess()) {
|
|
|
- if (contentsResult.getCode() == ResultCode.SYNC_CONFLICT) {
|
|
|
- mConflictsFound++;
|
|
|
- } else {
|
|
|
- mFailsInFavouritesFound++;
|
|
|
- if (contentsResult.getException() != null) {
|
|
|
- Log_OC.e(TAG, "Error while synchronizing favourites : " + contentsResult.getLogMessage(), contentsResult.getException());
|
|
|
- } else {
|
|
|
- Log_OC.e(TAG, "Error while synchronizing favourites : " + contentsResult.getLogMessage());
|
|
|
- }
|
|
|
- }
|
|
|
- } // won't let these fails break the synchronization process
|
|
|
- }
|
|
|
-
|
|
|
- // removal of obsolete files
|
|
|
- mChildren = mStorageManager.getDirectoryContent(mStorageManager.getFileById(mParentId));
|
|
|
- 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++;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- } else {
|
|
|
- client.exhaustResponse(query.getResponseBodyAsStream());
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- // prepare result object
|
|
|
- if (!dirChanged) {
|
|
|
- result = new RemoteOperationResult(ResultCode.OK_NO_CHANGES_ON_DIR);
|
|
|
- mChildren = mStorageManager.getDirectoryContent(mStorageManager.getFileById(mParentId));
|
|
|
-
|
|
|
- } else {
|
|
|
+ // 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);
|
|
|
}
|
|
|
|
|
|
} else {
|
|
|
+ // synchronization failed
|
|
|
+ client.exhaustResponse(query.getResponseBodyAsStream());
|
|
|
if (status == HttpStatus.SC_NOT_FOUND) {
|
|
|
- OCFile dir = mStorageManager.getFileByPath(mRemotePath);
|
|
|
- if (dir != null) {
|
|
|
+ if (mStorageManager.fileExists(mLocalFolder.getFileId())) {
|
|
|
String currentSavePath = FileStorageUtils.getSavePath(mAccount.name);
|
|
|
- mStorageManager.removeDirectory(dir, true, (dir.isDown() && dir.getStoragePath().startsWith(currentSavePath)));
|
|
|
+ mStorageManager.removeDirectory(mLocalFolder, true, (mLocalFolder.isDown() && mLocalFolder.getStoragePath().startsWith(currentSavePath)));
|
|
|
}
|
|
|
}
|
|
|
result = new RemoteOperationResult(false, status, query.getResponseHeaders());
|
|
@@ -311,17 +203,17 @@ public class SynchronizeFolderOperation extends RemoteOperation {
|
|
|
if (query != null)
|
|
|
query.releaseConnection(); // let the connection available for other methods
|
|
|
if (result.isSuccess()) {
|
|
|
- Log_OC.i(TAG, "Synchroned " + mAccount.name + ", folder " + mRemotePath + ": " + result.getLogMessage());
|
|
|
+ Log_OC.i(TAG, "Synchronized " + mAccount.name + remotePath + ": " + result.getLogMessage());
|
|
|
} else {
|
|
|
if (result.isException()) {
|
|
|
- Log_OC.e(TAG, "Synchroned " + mAccount.name + ", folder " + mRemotePath + ": " + result.getLogMessage(), result.getException());
|
|
|
+ Log_OC.e(TAG, "Synchroned " + mAccount.name + remotePath + ": " + result.getLogMessage(), result.getException());
|
|
|
} else {
|
|
|
- Log_OC.e(TAG, "Synchroned " + mAccount.name + ", folder " + mRemotePath + ": " + result.getLogMessage());
|
|
|
+ Log_OC.e(TAG, "Synchroned " + mAccount.name + remotePath + ": " + result.getLogMessage());
|
|
|
}
|
|
|
}
|
|
|
|
|
|
if (!mSyncFullAccount) {
|
|
|
- sendStickyBroadcast(false, mRemotePath, result);
|
|
|
+ sendStickyBroadcast(false, remotePath, result);
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -329,6 +221,155 @@ public class SynchronizeFolderOperation extends RemoteOperation {
|
|
|
}
|
|
|
|
|
|
|
|
|
+ /**
|
|
|
+ * 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 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) {
|
|
|
+ // get 'fresh data' from the database
|
|
|
+ mLocalFolder = mStorageManager.getFileById(mLocalFolder.getFileId());
|
|
|
+
|
|
|
+ // parse data from remote folder
|
|
|
+ WebdavEntry we = new WebdavEntry(dataInServer.getResponses()[0], client.getBaseUri().getPath());
|
|
|
+ OCFile remoteFolder = fillOCFile(we);
|
|
|
+ remoteFolder.setParentId(mLocalFolder.getParentId());
|
|
|
+ remoteFolder.setFileId(mLocalFolder.getFileId());
|
|
|
+
|
|
|
+ // check if remote and local folder are different
|
|
|
+ boolean folderChanged = !(remoteFolder.getEtag().equalsIgnoreCase(mLocalFolder.getEtag()));
|
|
|
+
|
|
|
+ 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<OCFile> updatedFiles = new Vector<OCFile>(dataInServer.getResponses().length - 1);
|
|
|
+ List<SynchronizeFileOperation> filesToSyncContents = new Vector<SynchronizeFileOperation>();
|
|
|
+
|
|
|
+ // loop to update every child
|
|
|
+ OCFile remoteFile = null, localFile = null;
|
|
|
+ for (int i = 1; i < dataInServer.getResponses().length; ++i) {
|
|
|
+ /// new OCFile instance with the data from the server
|
|
|
+ we = new WebdavEntry(dataInServer.getResponses()[i], client.getBaseUri().getPath());
|
|
|
+ remoteFile = fillOCFile(we);
|
|
|
+ remoteFile.setParentId(mLocalFolder.getFileId());
|
|
|
+
|
|
|
+ /// retrieve local data for the read file
|
|
|
+ localFile = mStorageManager.getFileByPath(remoteFile.getRemotePath());
|
|
|
+
|
|
|
+ /// add to the remoteFile (the new one) data about LOCAL STATE (not existing in the server side)
|
|
|
+ remoteFile.setLastSyncDateForProperties(mCurrentSyncTime);
|
|
|
+ if (localFile != null) {
|
|
|
+ // properties of local state are kept unmodified
|
|
|
+ remoteFile.setKeepInSync(localFile.keepInSync());
|
|
|
+ remoteFile.setLastSyncDateForData(localFile.getLastSyncDateForData());
|
|
|
+ remoteFile.setModificationTimestampAtLastSyncForData(localFile.getModificationTimestampAtLastSyncForData());
|
|
|
+ remoteFile.setStoragePath(localFile.getStoragePath());
|
|
|
+ remoteFile.setEtag(localFile.getEtag()); // eTag will not be updated unless contents are synchronized (Synchronize[File|Folder]Operation with remoteFile as parameter)
|
|
|
+ } else {
|
|
|
+ remoteFile.setEtag(""); // remote eTag will not be updated unless contents are synchronized (Synchronize[File|Folder]Operation with remoteFile as parameter)
|
|
|
+ }
|
|
|
+
|
|
|
+ /// check and fix, if need, local storage path
|
|
|
+ checkAndFixForeignStoragePath(remoteFile); // fixing old policy - now local files must be copied into the ownCloud local folder
|
|
|
+ searchForLocalFileInDefaultPath(remoteFile); // legacy
|
|
|
+
|
|
|
+ /// prepare content synchronization for kept-in-sync files
|
|
|
+ if (remoteFile.keepInSync()) {
|
|
|
+ SynchronizeFileOperation operation = new SynchronizeFileOperation( localFile,
|
|
|
+ remoteFile,
|
|
|
+ mStorageManager,
|
|
|
+ mAccount,
|
|
|
+ true,
|
|
|
+ false,
|
|
|
+ mContext
|
|
|
+ );
|
|
|
+ filesToSyncContents.add(operation);
|
|
|
+ }
|
|
|
+
|
|
|
+ updatedFiles.add(remoteFile);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 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 file contents AFTER saving current remote properties
|
|
|
+ startContentSynchronizations(filesToSyncContents, client);
|
|
|
+
|
|
|
+ // removal of obsolete files
|
|
|
+ removeObsoleteFiles();
|
|
|
+
|
|
|
+ // must be done AFTER saving all the children information, so that eTag is not updated in the database in case of unexpected exceptions
|
|
|
+ mStorageManager.saveFile(remoteFolder);
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ return folderChanged;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Removes obsolete children in the folder after saving all the new data.
|
|
|
+ */
|
|
|
+ private void removeObsoleteFiles() {
|
|
|
+ mChildren = mStorageManager.getDirectoryContent(mLocalFolder);
|
|
|
+ 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++;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Performs a list of synchronization operations, determining if a download or upload is needed or
|
|
|
+ * if exists conflict due to changes both in local and remote contents of the each file.
|
|
|
+ *
|
|
|
+ * If download or upload is needed, request the operation to the corresponding service and goes on.
|
|
|
+ *
|
|
|
+ * @param filesToSyncContents Synchronization operations to execute.
|
|
|
+ * @param client Interface to the remote ownCloud server.
|
|
|
+ */
|
|
|
+ private void startContentSynchronizations(List<SynchronizeFileOperation> filesToSyncContents, WebdavClient client) {
|
|
|
+ RemoteOperationResult contentsResult = null;
|
|
|
+ for (SynchronizeFileOperation op: filesToSyncContents) {
|
|
|
+ contentsResult = op.execute(client); // returns without waiting for upload or download finishes
|
|
|
+ if (!contentsResult.isSuccess()) {
|
|
|
+ if (contentsResult.getCode() == ResultCode.SYNC_CONFLICT) {
|
|
|
+ mConflictsFound++;
|
|
|
+ } else {
|
|
|
+ mFailsInFavouritesFound++;
|
|
|
+ if (contentsResult.getException() != null) {
|
|
|
+ Log_OC.e(TAG, "Error while synchronizing favourites : " + contentsResult.getLogMessage(), contentsResult.getException());
|
|
|
+ } else {
|
|
|
+ Log_OC.e(TAG, "Error while synchronizing favourites : " + contentsResult.getLogMessage());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } // won't let these fails break the synchronization process
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
public boolean isMultiStatus(int status) {
|
|
|
return (status == HttpStatus.SC_MULTI_STATUS);
|
|
|
}
|
|
@@ -346,7 +387,6 @@ public class SynchronizeFolderOperation extends RemoteOperation {
|
|
|
file.setFileLength(we.contentLength());
|
|
|
file.setMimetype(we.contentType());
|
|
|
file.setModificationTimestamp(we.modifiedTimestamp());
|
|
|
- file.setParentId(mParentId);
|
|
|
file.setEtag(we.etag());
|
|
|
return file;
|
|
|
}
|
|
@@ -415,6 +455,25 @@ public class SynchronizeFolderOperation extends RemoteOperation {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Scans the default location for saving local copies of files searching for
|
|
|
+ * a 'lost' file with the same full name as the {@link OCFile} received as
|
|
|
+ * parameter.
|
|
|
+ *
|
|
|
+ * @param file File to associate a possible 'lost' local file.
|
|
|
+ */
|
|
|
+ private void searchForLocalFileInDefaultPath(OCFile file) {
|
|
|
+ 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());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
/**
|
|
|
* Sends a message to any application component interested in the progress of the synchronization.
|
|
|
*
|