import java.util.concurrent.ConcurrentHashMap;\r
import java.util.concurrent.ConcurrentMap;\r
\r
+import com.owncloud.android.datamodel.FileDataStorageManager;\r
import com.owncloud.android.datamodel.OCFile;\r
-import com.owncloud.android.db.ProviderMeta.ProviderTableMeta;\r
import eu.alefzero.webdav.OnDatatransferProgressListener;\r
\r
import com.owncloud.android.network.OwnCloudClientUtils;\r
import android.app.NotificationManager;\r
import android.app.PendingIntent;\r
import android.app.Service;\r
-import android.content.ContentValues;\r
import android.content.Intent;\r
import android.os.Binder;\r
import android.os.Handler;\r
private IBinder mBinder;\r
private WebdavClient mDownloadClient = null;\r
private Account mLastAccount = null;\r
+ private FileDataStorageManager mStorageManager;\r
\r
private ConcurrentMap<String, DownloadFileOperation> mPendingDownloads = new ConcurrentHashMap<String, DownloadFileOperation>();\r
private DownloadFileOperation mCurrentDownload = null;\r
/// prepare client object to send the request to the ownCloud server\r
if (mDownloadClient == null || !mLastAccount.equals(mCurrentDownload.getAccount())) {\r
mLastAccount = mCurrentDownload.getAccount();\r
+ mStorageManager = new FileDataStorageManager(mLastAccount, getContentResolver());\r
mDownloadClient = OwnCloudClientUtils.createOwnCloudClient(mLastAccount, getApplicationContext());\r
}\r
\r
try {\r
downloadResult = mCurrentDownload.execute(mDownloadClient);\r
if (downloadResult.isSuccess()) {\r
- ContentValues cv = new ContentValues();\r
- cv.put(ProviderTableMeta.FILE_STORAGE_PATH, mCurrentDownload.getSavePath());\r
- getContentResolver().update(\r
- ProviderTableMeta.CONTENT_URI,\r
- cv,\r
- ProviderTableMeta.FILE_NAME + "=? AND "\r
- + ProviderTableMeta.FILE_ACCOUNT_OWNER + "=?",\r
- new String[] {\r
- mCurrentDownload.getSavePath().substring(mCurrentDownload.getSavePath().lastIndexOf('/') + 1),\r
- mLastAccount.name });\r
+ saveDownloadedFile();\r
}\r
\r
} finally {\r
}\r
}\r
\r
- \r
+\r
+ /**\r
+ * Updates the OC File after a successful download.\r
+ */\r
+ private void saveDownloadedFile() {\r
+ OCFile file = mCurrentDownload.getFile();\r
+ file.setLastSyncDate(System.currentTimeMillis());\r
+ file.setModificationTimestamp(mCurrentDownload.getModificationTimestamp());\r
+ // file.setEtag(mCurrentDownload.getEtag()); // TODO Etag, where available\r
+ file.setMimetype(mCurrentDownload.getMimeType());\r
+ file.setStoragePath(mCurrentDownload.getSavePath());\r
+ file.setFileLength((new File(mCurrentDownload.getSavePath()).length()));\r
+ mStorageManager.saveFile(file);\r
+ }\r
+\r
+\r
/**\r
* Creates a status notification to show the download progress\r
* \r
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;
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;
try {
uploadResult = mCurrentUpload.execute(mUploadClient);
if (uploadResult.isSuccess()) {
- saveUploadedFile(mCurrentUpload.getFile(), mStorageManager);
+ saveUploadedFile();
}
} finally {
}
/**
- * 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;
}
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;
private OCFile mFile;
private Set<OnDatatransferProgressListener> mDataTransferListeners = new HashSet<OnDatatransferProgressListener>();
private final AtomicBoolean mCancellationRequested = new AtomicBoolean(false);
+ private long mModificationTimestamp = 0;
public DownloadFileOperation(Account account, OCFile file) {
}
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()
return mFile.getFileLength();
}
+ public long getModificationTimestamp() {
+ return (mModificationTimestamp > 0) ? mModificationTimestamp : mFile.getModificationTimestamp();
+ }
+
public void addDatatransferProgressListener (OnDatatransferProgressListener listener) {
mDataTransferListeners.add(listener);
}
}
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());