From: David A. Velasco Date: Mon, 22 Oct 2012 13:11:59 +0000 (+0200) Subject: Updating synchronization for providing SSL warning when necessary; step 1: refactorin... X-Git-Tag: oc-android-1.4.3~137 X-Git-Url: http://git.linex4red.de/pub/Android/ownCloud.git/commitdiff_plain/67eb921007efb1c9204e4b69fb85110fc23bf51f?hp=-c Updating synchronization for providing SSL warning when necessary; step 1: refactoring based in RemoteOperation (in progress) --- 67eb921007efb1c9204e4b69fb85110fc23bf51f diff --git a/src/com/owncloud/android/network/CertificateCombinedException.java b/src/com/owncloud/android/network/CertificateCombinedException.java index fad7a6f2..27427dd4 100644 --- a/src/com/owncloud/android/network/CertificateCombinedException.java +++ b/src/com/owncloud/android/network/CertificateCombinedException.java @@ -45,7 +45,7 @@ import javax.net.ssl.SSLPeerUnverifiedException; */ public class CertificateCombinedException extends RuntimeException { - /** Generated */ + /** Generated - to refresh every time the class changes */ private static final long serialVersionUID = -8875782030758554999L; private X509Certificate mServerCert = null; diff --git a/src/com/owncloud/android/operations/RemoteOperationResult.java b/src/com/owncloud/android/operations/RemoteOperationResult.java index 0618b86d..1415228f 100644 --- a/src/com/owncloud/android/operations/RemoteOperationResult.java +++ b/src/com/owncloud/android/operations/RemoteOperationResult.java @@ -19,6 +19,7 @@ package com.owncloud.android.operations; import java.io.IOException; +import java.io.Serializable; import java.net.MalformedURLException; import java.net.SocketException; import java.net.SocketTimeoutException; @@ -40,13 +41,18 @@ import com.owncloud.android.network.CertificateCombinedException; * * @author David A. Velasco */ -public class RemoteOperationResult { +public class RemoteOperationResult implements Serializable { + + /** Generated - to refresh every time the class changes */ + private static final long serialVersionUID = -7805531062432602444L; + public enum ResultCode { OK, OK_SSL, OK_NO_SSL, UNHANDLED_HTTP_CODE, + UNAUTHORIZED, FILE_NOT_FOUND, INSTANCE_NOT_CONFIGURED, UNKNOWN_ERROR, @@ -81,6 +87,9 @@ public class RemoteOperationResult { } else if (httpCode > 0) { switch (httpCode) { + case HttpStatus.SC_UNAUTHORIZED: + mCode = ResultCode.UNAUTHORIZED; + break; case HttpStatus.SC_NOT_FOUND: mCode = ResultCode.FILE_NOT_FOUND; break; diff --git a/src/com/owncloud/android/operations/SynchronizeFolderOperation.java b/src/com/owncloud/android/operations/SynchronizeFolderOperation.java new file mode 100644 index 00000000..36b9b229 --- /dev/null +++ b/src/com/owncloud/android/operations/SynchronizeFolderOperation.java @@ -0,0 +1,193 @@ +/* ownCloud Android client application + * Copyright (C) 2012 Bartek Przybylski + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * 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.IOException; +import java.util.List; +import java.util.Vector; + +import org.apache.http.HttpStatus; +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.MultiStatus; +import org.apache.jackrabbit.webdav.client.methods.PropFindMethod; + +import android.accounts.Account; +import android.content.Intent; +import android.util.Log; + +import com.owncloud.android.datamodel.FileDataStorageManager; +import com.owncloud.android.datamodel.OCFile; +import com.owncloud.android.files.services.FileDownloader; + +import eu.alefzero.webdav.WebdavClient; +import eu.alefzero.webdav.WebdavEntry; +import eu.alefzero.webdav.WebdavUtils; + + +/** + * Remote operation performing the synchronization a the contents of a remote folder with the local database + * + * @author David A. Velasco + */ +public class SynchronizeFolderOperation extends RemoteOperation { + + private static final String TAG = SynchronizeFolderOperation.class.getCanonicalName(); + + /** Remote folder to synchronize */ + private String mRemotePath; + + /** Timestamp for the synchronization in progress */ + private long mCurrentSyncTime; + + /** Id of the folder to synchronize in the local database */ + private long mParentId; + + /** Access to the local database */ + private FileDataStorageManager mStorageManager; + + /** Account where the file to synchronize belongs */ + private Account mAccount; + + + SynchronizeFolderOperation(String remotePath, long currentSyncTime, long parentId, FileDataStorageManager storageManager, Account account) { + mRemotePath = remotePath; + mCurrentSyncTime = currentSyncTime; + mParentId = parentId; + mStorageManager = storageManager; + mAccount = account; + } + + + @Override + protected RemoteOperationResult run(WebdavClient client) { + RemoteOperationResult result = null; + + // code before in FileSyncAdapter.fetchData + PropFindMethod query = null; + Vector children = null; + try { + Log.d(TAG, "Fetching files in " + mRemotePath); + + // remote request + query = new PropFindMethod(client.getBaseUri() + WebdavUtils.encodePath(mRemotePath)); + int status = client.executeMethod(query); + + if (isSuccess(status)) { + + MultiStatus resp = query.getResponseBodyAsMultiStatus(); + + // reading files + List updatedFiles = new Vector(resp.getResponses().length - 1); + for (int i = 1; i < resp.getResponses().length; ++i) { + WebdavEntry we = new WebdavEntry(resp.getResponses()[i], client.getBaseUri().getPath()); + OCFile file = fillOCFile(we); + file.setParentId(mParentId); + OCFile oldFile = mStorageManager.getFileByPath(file.getRemotePath()); + if (oldFile != null) { + if (oldFile.keepInSync() && file.getModificationTimestamp() > oldFile.getModificationTimestamp()) { + requestContentDownload(); + } + file.setKeepInSync(oldFile.keepInSync()); + } + + updatedFiles.add(file); + } + + + // save updated files in local database; all at once, trying to get a best performance in database update (not a big deal, indeed) + mStorageManager.saveFiles(updatedFiles); + + + // removal of obsolete files + children = mStorageManager.getDirectoryContent(mStorageManager.getFileById(mParentId)); + OCFile file; + String currentSavePath = FileDownloader.getSavePath(mAccount.name); + for (int i=0; i < children.size(); ) { + file = children.get(i); + if (file.getLastSyncDate() != mCurrentSyncTime) { + Log.d(TAG, "removing file: " + file); + mStorageManager.removeFile(file, (file.isDown() && file.getStoragePath().startsWith(currentSavePath))); + children.remove(i); + } else { + i++; + } + } + + } else if (status == HttpStatus.SC_UNAUTHORIZED) { + syncResult.stats.numAuthExceptions++; + + } else { + // TODO something smart with syncResult? OR NOT + } + + result = new RemoteOperationResult(isSuccess(status), status); + Log.i(TAG, "Synchronization of " + mRemotePath + ": " + result.getLogMessage()); + + + } catch (IOException e) { + syncResult.stats.numIoExceptions++; + logException(e, uri); + + } catch (DavException e) { + syncResult.stats.numParseExceptions++; + logException(e, uri); + + } catch (Exception e) { + // TODO something smart with syncresult + mRightSync = false; + logException(e, uri); + + } finally { + if (query != null) + query.releaseConnection(); // let the connection available for other methods + + // synchronized folder -> notice to UI + sendStickyBroadcast(true, getStorageManager().getFileById(parentId).getRemotePath()); + } + + + return result; + } + + + public boolean isSuccess(int status) { + return (status == HttpStatus.SC_MULTI_STATUS); // TODO check other possible OK codes; doc doesn't help + } + + + private void requestContentDownload() { + Intent intent = new Intent(this.getContext(), FileDownloader.class); + intent.putExtra(FileDownloader.EXTRA_ACCOUNT, getAccount()); + intent.putExtra(FileDownloader.EXTRA_FILE, file); + file.setKeepInSync(true); + getContext().startService(intent); + } + + + private OCFile fillOCFile(WebdavEntry we) { + OCFile file = new OCFile(we.decodedPath()); + file.setCreationTimestamp(we.createTimestamp()); + file.setFileLength(we.contentLength()); + file.setMimetype(we.contentType()); + file.setModificationTimestamp(we.modifiedTimesamp()); + file.setLastSyncDate(mCurrentSyncTime); + return file; + } + +} diff --git a/src/com/owncloud/android/syncadapter/FileSyncAdapter.java b/src/com/owncloud/android/syncadapter/FileSyncAdapter.java index 5b398c01..db9d87db 100644 --- a/src/com/owncloud/android/syncadapter/FileSyncAdapter.java +++ b/src/com/owncloud/android/syncadapter/FileSyncAdapter.java @@ -34,6 +34,7 @@ import com.owncloud.android.authenticator.AccountAuthenticator; import com.owncloud.android.datamodel.FileDataStorageManager; import com.owncloud.android.datamodel.OCFile; import com.owncloud.android.files.services.FileDownloader; +import com.owncloud.android.operations.RemoteOperationResult; import com.owncloud.android.utils.OwnCloudVersion; import android.accounts.Account; @@ -97,7 +98,7 @@ public class FileSyncAdapter extends AbstractOwnCloudSyncAdapter { Log.d(TAG, "syncing owncloud account " + account.name); - sendStickyBroadcast(true, null); // message to signal the start to the UI + sendStickyBroadcast(true, null, null); // message to signal the start to the UI updateOCVersion(); @@ -315,13 +316,16 @@ public class FileSyncAdapter extends AbstractOwnCloudSyncAdapter { } - private void sendStickyBroadcast(boolean inProgress, String dirRemotePath) { + private void sendStickyBroadcast(boolean inProgress, String dirRemotePath, RemoteOperationResult result) { Intent i = new Intent(FileSyncService.SYNC_MESSAGE); i.putExtra(FileSyncService.IN_PROGRESS, inProgress); i.putExtra(FileSyncService.ACCOUNT_NAME, getAccount().name); if (dirRemotePath != null) { i.putExtra(FileSyncService.SYNC_FOLDER_REMOTE_PATH, dirRemotePath); } + if (result != null) { + i.putExtra(FileSyncService.SYNC_RESULT, result); + } getContext().sendStickyBroadcast(i); } diff --git a/src/com/owncloud/android/syncadapter/FileSyncService.java b/src/com/owncloud/android/syncadapter/FileSyncService.java index 74c7fa67..cb2f7200 100644 --- a/src/com/owncloud/android/syncadapter/FileSyncService.java +++ b/src/com/owncloud/android/syncadapter/FileSyncService.java @@ -32,6 +32,7 @@ public class FileSyncService extends Service { public static final String SYNC_FOLDER_REMOTE_PATH = "SYNC_FOLDER_REMOTE_PATH"; public static final String IN_PROGRESS = "SYNC_IN_PROGRESS"; public static final String ACCOUNT_NAME = "ACCOUNT_NAME"; + public static final String SYNC_RESULT = "SYNC_RESULT"; /* * {@inheritDoc}