From: David A. Velasco Date: Tue, 13 Nov 2012 14:59:05 +0000 (+0100) Subject: Granted update of modificationTimestamp with the end of downloads and uploads X-Git-Tag: oc-android-1.4.3~108 X-Git-Url: http://git.linex4red.de/pub/Android/ownCloud.git/commitdiff_plain/925a0554e53ac4a35fe17cbed2bf61670a8191f0 Granted update of modificationTimestamp with the end of downloads and uploads --- diff --git a/src/com/owncloud/android/files/services/FileDownloader.java b/src/com/owncloud/android/files/services/FileDownloader.java index a07b0823..0ca42484 100644 --- a/src/com/owncloud/android/files/services/FileDownloader.java +++ b/src/com/owncloud/android/files/services/FileDownloader.java @@ -25,8 +25,8 @@ import java.util.Vector; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; +import com.owncloud.android.datamodel.FileDataStorageManager; import com.owncloud.android.datamodel.OCFile; -import com.owncloud.android.db.ProviderMeta.ProviderTableMeta; import eu.alefzero.webdav.OnDatatransferProgressListener; import com.owncloud.android.network.OwnCloudClientUtils; @@ -40,7 +40,6 @@ import android.app.Notification; import android.app.NotificationManager; import android.app.PendingIntent; import android.app.Service; -import android.content.ContentValues; import android.content.Intent; import android.os.Binder; import android.os.Handler; @@ -73,6 +72,7 @@ public class FileDownloader extends Service implements OnDatatransferProgressLis private IBinder mBinder; private WebdavClient mDownloadClient = null; private Account mLastAccount = null; + private FileDataStorageManager mStorageManager; private ConcurrentMap mPendingDownloads = new ConcurrentHashMap(); private DownloadFileOperation mCurrentDownload = null; @@ -250,6 +250,7 @@ public class FileDownloader extends Service implements OnDatatransferProgressLis /// prepare client object to send the request to the ownCloud server if (mDownloadClient == null || !mLastAccount.equals(mCurrentDownload.getAccount())) { mLastAccount = mCurrentDownload.getAccount(); + mStorageManager = new FileDataStorageManager(mLastAccount, getContentResolver()); mDownloadClient = OwnCloudClientUtils.createOwnCloudClient(mLastAccount, getApplicationContext()); } @@ -258,16 +259,7 @@ public class FileDownloader extends Service implements OnDatatransferProgressLis try { downloadResult = mCurrentDownload.execute(mDownloadClient); if (downloadResult.isSuccess()) { - ContentValues cv = new ContentValues(); - cv.put(ProviderTableMeta.FILE_STORAGE_PATH, mCurrentDownload.getSavePath()); - getContentResolver().update( - ProviderTableMeta.CONTENT_URI, - cv, - ProviderTableMeta.FILE_NAME + "=? AND " - + ProviderTableMeta.FILE_ACCOUNT_OWNER + "=?", - new String[] { - mCurrentDownload.getSavePath().substring(mCurrentDownload.getSavePath().lastIndexOf('/') + 1), - mLastAccount.name }); + saveDownloadedFile(); } } finally { @@ -284,7 +276,22 @@ public class FileDownloader extends Service implements OnDatatransferProgressLis } } - + + /** + * Updates the OC File after a successful download. + */ + private void saveDownloadedFile() { + OCFile file = mCurrentDownload.getFile(); + file.setLastSyncDate(System.currentTimeMillis()); + file.setModificationTimestamp(mCurrentDownload.getModificationTimestamp()); + // file.setEtag(mCurrentDownload.getEtag()); // TODO Etag, where available + file.setMimetype(mCurrentDownload.getMimeType()); + file.setStoragePath(mCurrentDownload.getSavePath()); + file.setFileLength((new File(mCurrentDownload.getSavePath()).length())); + mStorageManager.saveFile(file); + } + + /** * Creates a status notification to show the download progress * diff --git a/src/com/owncloud/android/files/services/FileUploader.java b/src/com/owncloud/android/files/services/FileUploader.java index b466d596..c8916ef2 100644 --- a/src/com/owncloud/android/files/services/FileUploader.java +++ b/src/com/owncloud/android/files/services/FileUploader.java @@ -25,6 +25,10 @@ import java.util.Vector; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; +import org.apache.http.HttpStatus; +import org.apache.jackrabbit.webdav.MultiStatus; +import org.apache.jackrabbit.webdav.client.methods.PropFindMethod; + import com.owncloud.android.authenticator.AccountAuthenticator; import com.owncloud.android.datamodel.FileDataStorageManager; import com.owncloud.android.datamodel.OCFile; @@ -37,6 +41,8 @@ import com.owncloud.android.ui.fragment.FileDetailFragment; import com.owncloud.android.utils.OwnCloudVersion; import eu.alefzero.webdav.OnDatatransferProgressListener; +import eu.alefzero.webdav.WebdavEntry; +import eu.alefzero.webdav.WebdavUtils; import com.owncloud.android.network.OwnCloudClientUtils; @@ -360,7 +366,7 @@ public class FileUploader extends Service implements OnDatatransferProgressListe try { uploadResult = mCurrentUpload.execute(mUploadClient); if (uploadResult.isSuccess()) { - saveUploadedFile(mCurrentUpload.getFile(), mStorageManager); + saveUploadedFile(); } } finally { @@ -379,15 +385,76 @@ public class FileUploader extends Service implements OnDatatransferProgressListe } /** - * Saves a new OC File after a successful upload. + * Saves a OC File after a successful upload. + * + * A PROPFIND is necessary to keep the props in the local database synchronized with the server, + * specially the modification time and Etag (where available) * - * @param file OCFile describing the uploaded file - * @param storageManager Interface to the database where the new OCFile has to be stored. - * @param parentDirId Id of the parent OCFile. + * TODO refactor this ugly thing */ - private void saveUploadedFile(OCFile file, FileDataStorageManager storageManager) { - file.setModificationTimestamp(System.currentTimeMillis()); - storageManager.saveFile(file); + private void saveUploadedFile() { + OCFile file = mCurrentUpload.getFile(); + + PropFindMethod propfind = null; + RemoteOperationResult result = null; + try { + propfind = new PropFindMethod(mUploadClient.getBaseUri() + WebdavUtils.encodePath(mCurrentUpload.getRemotePath())); + int status = mUploadClient.executeMethod(propfind); + boolean isMultiStatus = status == HttpStatus.SC_MULTI_STATUS; + if (isMultiStatus) { + MultiStatus resp = propfind.getResponseBodyAsMultiStatus(); + WebdavEntry we = new WebdavEntry(resp.getResponses()[0], + mUploadClient.getBaseUri().getPath()); + OCFile newFile = fillOCFile(we); + newFile.setStoragePath(file.getStoragePath()); + newFile.setKeepInSync(file.keepInSync()); + file = newFile; + + } else { + // this would be a problem + mUploadClient.exhaustResponse(propfind.getResponseBodyAsStream()); + } + + result = new RemoteOperationResult(isMultiStatus, status); + Log.i(TAG, "Update: synchronizing properties for uploaded " + mCurrentUpload.getRemotePath() + ": " + result.getLogMessage()); + + } catch (Exception e) { + result = new RemoteOperationResult(e); + Log.i(TAG, "Update: synchronizing properties for uploaded " + mCurrentUpload.getRemotePath() + ": " + result.getLogMessage(), e); + + } finally { + if (propfind != null) + propfind.releaseConnection(); + } + + if (!result.isSuccess()) { + // file was successfully uploaded, but the new time stamp and Etag in the server could not be read; + // just keeping old values :( + if (!mCurrentUpload.getRemotePath().equals(file.getRemotePath())) { + // true when the file was automatically renamed to avoid an overwrite + OCFile newFile = new OCFile(mCurrentUpload.getRemotePath()); + newFile.setCreationTimestamp(file.getCreationTimestamp()); + newFile.setFileLength(file.getFileLength()); + newFile.setMimetype(file.getMimetype()); + newFile.setModificationTimestamp(file.getModificationTimestamp()); // this is specially BAD + // newFile.setEtag(file.getEtag()) // TODO and this is still worse + file = newFile; + } + } + + file.setLastSyncDate(System.currentTimeMillis()); + mStorageManager.saveFile(file); + } + + + 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.setEtag(mCurrentDownload.getEtag()); // TODO Etag, where available + return file; } diff --git a/src/com/owncloud/android/operations/DownloadFileOperation.java b/src/com/owncloud/android/operations/DownloadFileOperation.java index 2704654d..59343d15 100644 --- a/src/com/owncloud/android/operations/DownloadFileOperation.java +++ b/src/com/owncloud/android/operations/DownloadFileOperation.java @@ -22,11 +22,13 @@ import java.io.BufferedInputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; +import java.util.Date; import java.util.HashSet; import java.util.Iterator; import java.util.Set; import java.util.concurrent.atomic.AtomicBoolean; +import org.apache.commons.httpclient.Header; import org.apache.commons.httpclient.HttpException; import org.apache.commons.httpclient.methods.GetMethod; import org.apache.http.HttpStatus; @@ -56,6 +58,7 @@ public class DownloadFileOperation extends RemoteOperation { private OCFile mFile; private Set mDataTransferListeners = new HashSet(); private final AtomicBoolean mCancellationRequested = new AtomicBoolean(false); + private long mModificationTimestamp = 0; public DownloadFileOperation(Account account, OCFile file) { @@ -94,7 +97,7 @@ public class DownloadFileOperation extends RemoteOperation { } public String getMimeType() { - String mimeType = mFile.getMimetype(); // TODO fix the mime types in OCFiles FOREVER + String mimeType = mFile.getMimetype(); if (mimeType == null || mimeType.length() <= 0) { try { mimeType = MimeTypeMap.getSingleton() @@ -114,6 +117,10 @@ public class DownloadFileOperation extends RemoteOperation { return mFile.getFileLength(); } + public long getModificationTimestamp() { + return (mModificationTimestamp > 0) ? mModificationTimestamp : mFile.getModificationTimestamp(); + } + public void addDatatransferProgressListener (OnDatatransferProgressListener listener) { mDataTransferListeners.add(listener); @@ -189,6 +196,11 @@ public class DownloadFileOperation extends RemoteOperation { } } savedFile = true; + Header modificationTime = get.getResponseHeader("Last-Modified"); + if (modificationTime != null) { + Date d = WebdavUtils.parseResponseDate((String) modificationTime.getValue()); + mModificationTimestamp = (d != null) ? d.getTime() : 0; + } } else { client.exhaustResponse(get.getResponseBodyAsStream());