mirror of
https://github.com/owncloud/android-library.git
synced 2025-06-07 16:06:08 +00:00
Merge pull request #83 from owncloud/sync_full_folder
Minor changes to support synchronization of full folders in OC app
This commit is contained in:
commit
f02dffb1d3
@ -129,7 +129,7 @@ public class WebdavEntry {
|
||||
prop = propSet.get(DavPropertyName.GETETAG);
|
||||
if (prop != null) {
|
||||
mEtag = (String) prop.getValue();
|
||||
mEtag = mEtag.substring(1, mEtag.length()-1);
|
||||
mEtag = WebdavUtils.parseEtag(mEtag);
|
||||
}
|
||||
|
||||
// {DAV:}quota-used-bytes
|
||||
|
@ -32,6 +32,8 @@ import java.util.Locale;
|
||||
|
||||
import android.net.Uri;
|
||||
|
||||
import org.apache.commons.httpclient.Header;
|
||||
import org.apache.commons.httpclient.HttpMethod;
|
||||
import org.apache.jackrabbit.webdav.property.DavPropertyName;
|
||||
import org.apache.jackrabbit.webdav.property.DavPropertyNameSet;
|
||||
import org.apache.jackrabbit.webdav.xml.Namespace;
|
||||
@ -131,4 +133,47 @@ public class WebdavUtils {
|
||||
|
||||
return propSet;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param rawEtag
|
||||
* @return
|
||||
*/
|
||||
public static String parseEtag(String rawEtag) {
|
||||
if (rawEtag == null || rawEtag.length() == 0) {
|
||||
return "";
|
||||
}
|
||||
if (rawEtag.endsWith("-gzip")) {
|
||||
rawEtag = rawEtag.substring(0, rawEtag.length() - 5);
|
||||
}
|
||||
if (rawEtag.length() >= 2 && rawEtag.startsWith("\"") && rawEtag.endsWith("\"")) {
|
||||
rawEtag = rawEtag.substring(1, rawEtag.length() - 1);
|
||||
}
|
||||
return rawEtag;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @param method
|
||||
* @return
|
||||
*/
|
||||
public static String getEtagFromResponse(HttpMethod method) {
|
||||
Header eTag = method.getResponseHeader("OC-ETag");
|
||||
if (eTag == null) {
|
||||
eTag = method.getResponseHeader("oc-etag");
|
||||
}
|
||||
if (eTag == null) {
|
||||
eTag = method.getResponseHeader("ETag");
|
||||
}
|
||||
if (eTag == null) {
|
||||
eTag = method.getResponseHeader("etag");
|
||||
}
|
||||
String result = "";
|
||||
if (eTag != null) {
|
||||
result = parseEtag(eTag.getValue());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -390,11 +390,16 @@ public class RemoteOperationResult implements Serializable {
|
||||
|
||||
} else if (mCode == ResultCode.ACCOUNT_NOT_THE_SAME) {
|
||||
return "Authenticated with a different account than the one updating";
|
||||
|
||||
} else if (mCode == ResultCode.INVALID_CHARACTER_IN_NAME) {
|
||||
return "The file name contains an forbidden character";
|
||||
|
||||
} else if (mCode == ResultCode.FILE_NOT_FOUND) {
|
||||
return "Local file does not exist";
|
||||
}
|
||||
return "Local file does not exist";
|
||||
|
||||
} else if (mCode == ResultCode.SYNC_CONFLICT) {
|
||||
return "Synchronization conflict";
|
||||
}
|
||||
|
||||
return "Operation finished with HTTP status code " + mHttpCode + " (" +
|
||||
(isSuccess() ? "success" : "fail") + ")";
|
||||
|
@ -32,8 +32,7 @@ public class Log_OC {
|
||||
}
|
||||
|
||||
public static void i(String TAG, String message){
|
||||
|
||||
// Write the log message to the file
|
||||
Log.i(TAG, message);
|
||||
appendLog(TAG+" : "+ message);
|
||||
}
|
||||
|
||||
|
@ -32,7 +32,6 @@ import java.io.RandomAccessFile;
|
||||
import java.nio.channels.FileChannel;
|
||||
import java.util.Random;
|
||||
|
||||
import org.apache.commons.httpclient.HttpException;
|
||||
import org.apache.commons.httpclient.methods.PutMethod;
|
||||
|
||||
import com.owncloud.android.lib.common.OwnCloudClient;
|
||||
@ -47,14 +46,21 @@ public class ChunkedUploadRemoteFileOperation extends UploadRemoteFileOperation
|
||||
|
||||
public static final long CHUNK_SIZE = 1024000;
|
||||
private static final String OC_CHUNKED_HEADER = "OC-Chunked";
|
||||
private static final String OC_CHUNK_SIZE_HEADER = "OC-Chunk-Size";
|
||||
private static final String TAG = ChunkedUploadRemoteFileOperation.class.getSimpleName();
|
||||
|
||||
public ChunkedUploadRemoteFileOperation(String storagePath, String remotePath, String mimeType){
|
||||
super(storagePath, remotePath, mimeType);
|
||||
super(storagePath, remotePath, mimeType);
|
||||
}
|
||||
|
||||
public ChunkedUploadRemoteFileOperation(
|
||||
String storagePath, String remotePath, String mimeType, String requiredEtag
|
||||
){
|
||||
super(storagePath, remotePath, mimeType, requiredEtag);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int uploadFile(OwnCloudClient client) throws HttpException, IOException {
|
||||
protected int uploadFile(OwnCloudClient client) throws IOException {
|
||||
int status = -1;
|
||||
|
||||
FileChannel channel = null;
|
||||
@ -64,8 +70,6 @@ public class ChunkedUploadRemoteFileOperation extends UploadRemoteFileOperation
|
||||
raf = new RandomAccessFile(file, "r");
|
||||
channel = raf.getChannel();
|
||||
mEntity = new ChunkFromFileChannelRequestEntity(channel, mMimeType, CHUNK_SIZE, file);
|
||||
//((ProgressiveDataTransferer)mEntity).
|
||||
// addDatatransferProgressListeners(getDataTransferListeners());
|
||||
synchronized (mDataTransferListeners) {
|
||||
((ProgressiveDataTransferer)mEntity)
|
||||
.addDatatransferProgressListeners(mDataTransferListeners);
|
||||
@ -74,17 +78,31 @@ public class ChunkedUploadRemoteFileOperation extends UploadRemoteFileOperation
|
||||
long offset = 0;
|
||||
String uriPrefix = client.getWebdavUri() + WebdavUtils.encodePath(mRemotePath) +
|
||||
"-chunking-" + Math.abs((new Random()).nextInt(9000)+1000) + "-" ;
|
||||
long chunkCount = (long) Math.ceil((double)file.length() / CHUNK_SIZE);
|
||||
long totalLength = file.length();
|
||||
long chunkCount = (long) Math.ceil((double)totalLength / CHUNK_SIZE);
|
||||
String chunkSizeStr = String.valueOf(CHUNK_SIZE);
|
||||
String totalLengthStr = String.valueOf(file.length());
|
||||
for (int chunkIndex = 0; chunkIndex < chunkCount ; chunkIndex++, offset += CHUNK_SIZE) {
|
||||
if (chunkIndex == chunkCount - 1) {
|
||||
chunkSizeStr = String.valueOf(CHUNK_SIZE * chunkCount - totalLength);
|
||||
}
|
||||
if (mPutMethod != null) {
|
||||
mPutMethod.releaseConnection(); // let the connection available
|
||||
// for other methods
|
||||
}
|
||||
mPutMethod = new PutMethod(uriPrefix + chunkCount + "-" + chunkIndex);
|
||||
if (mRequiredEtag != null && mRequiredEtag.length() > 0) {
|
||||
mPutMethod.addRequestHeader(IF_MATCH_HEADER, "\"" + mRequiredEtag + "\"");
|
||||
}
|
||||
mPutMethod.addRequestHeader(OC_CHUNKED_HEADER, OC_CHUNKED_HEADER);
|
||||
mPutMethod.addRequestHeader(OC_TOTAL_LENGTH_HEADER, String.valueOf(file.length()));
|
||||
mPutMethod.addRequestHeader(OC_CHUNK_SIZE_HEADER, chunkSizeStr);
|
||||
mPutMethod.addRequestHeader(OC_TOTAL_LENGTH_HEADER, totalLengthStr);
|
||||
((ChunkFromFileChannelRequestEntity) mEntity).setOffset(offset);
|
||||
mPutMethod.setRequestEntity(mEntity);
|
||||
if (mCancellationRequested.get()) {
|
||||
mPutMethod.abort();
|
||||
// next method will throw an exception
|
||||
}
|
||||
status = client.executeMethod(mPutMethod);
|
||||
|
||||
if (status == 400) {
|
||||
|
@ -61,6 +61,7 @@ public class DownloadRemoteFileOperation extends RemoteOperation {
|
||||
private Set<OnDatatransferProgressListener> mDataTransferListeners = new HashSet<OnDatatransferProgressListener>();
|
||||
private final AtomicBoolean mCancellationRequested = new AtomicBoolean(false);
|
||||
private long mModificationTimestamp = 0;
|
||||
private String mEtag = "";
|
||||
private GetMethod mGet;
|
||||
|
||||
private String mRemotePath;
|
||||
@ -140,12 +141,24 @@ public class DownloadRemoteFileOperation extends RemoteOperation {
|
||||
if (transferred == totalToTransfer) { // Check if the file is completed
|
||||
savedFile = true;
|
||||
Header modificationTime = mGet.getResponseHeader("Last-Modified");
|
||||
if (modificationTime == null) {
|
||||
modificationTime = mGet.getResponseHeader("last-modified");
|
||||
}
|
||||
if (modificationTime != null) {
|
||||
Date d = WebdavUtils.parseResponseDate((String) modificationTime.getValue());
|
||||
mModificationTimestamp = (d != null) ? d.getTime() : 0;
|
||||
}
|
||||
} else {
|
||||
Log_OC.e(TAG, "Could not read modification time from response downloading " + mRemotePath);
|
||||
}
|
||||
|
||||
mEtag = WebdavUtils.getEtagFromResponse(mGet);
|
||||
if (mEtag.length() == 0) {
|
||||
Log_OC.e(TAG, "Could not read eTag from response downloading " + mRemotePath);
|
||||
}
|
||||
|
||||
} else {
|
||||
client.exhaustResponse(mGet.getResponseBodyAsStream());
|
||||
// TODO some kind of error control!
|
||||
}
|
||||
|
||||
} else {
|
||||
@ -190,4 +203,7 @@ public class DownloadRemoteFileOperation extends RemoteOperation {
|
||||
return mModificationTimestamp;
|
||||
}
|
||||
|
||||
public String getEtag() {
|
||||
return mEtag;
|
||||
}
|
||||
}
|
||||
|
@ -32,7 +32,6 @@ import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import org.apache.commons.httpclient.HttpException;
|
||||
import org.apache.commons.httpclient.methods.PutMethod;
|
||||
import org.apache.commons.httpclient.methods.RequestEntity;
|
||||
import org.apache.http.HttpStatus;
|
||||
@ -60,14 +59,16 @@ public class UploadRemoteFileOperation extends RemoteOperation {
|
||||
private static final String TAG = UploadRemoteFileOperation.class.getSimpleName();
|
||||
|
||||
protected static final String OC_TOTAL_LENGTH_HEADER = "OC-Total-Length";
|
||||
protected static final String IF_MATCH_HEADER = "If-Match";
|
||||
|
||||
protected String mLocalPath;
|
||||
protected String mRemotePath;
|
||||
protected String mMimeType;
|
||||
protected PutMethod mPutMethod = null;
|
||||
protected boolean mForbiddenCharsInServer = false;
|
||||
protected String mRequiredEtag = null;
|
||||
|
||||
private final AtomicBoolean mCancellationRequested = new AtomicBoolean(false);
|
||||
protected final AtomicBoolean mCancellationRequested = new AtomicBoolean(false);
|
||||
protected Set<OnDatatransferProgressListener> mDataTransferListeners = new HashSet<OnDatatransferProgressListener>();
|
||||
|
||||
protected RequestEntity mEntity = null;
|
||||
@ -78,33 +79,38 @@ public class UploadRemoteFileOperation extends RemoteOperation {
|
||||
mMimeType = mimeType;
|
||||
}
|
||||
|
||||
public UploadRemoteFileOperation(String localPath, String remotePath, String mimeType, String requiredEtag) {
|
||||
this(localPath, remotePath, mimeType);
|
||||
mRequiredEtag = requiredEtag;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected RemoteOperationResult run(OwnCloudClient client) {
|
||||
RemoteOperationResult result = null;
|
||||
|
||||
try {
|
||||
// / perform the upload
|
||||
synchronized (mCancellationRequested) {
|
||||
if (mCancellationRequested.get()) {
|
||||
throw new OperationCancelledException();
|
||||
mPutMethod = new PutMethod(client.getWebdavUri() + WebdavUtils.encodePath(mRemotePath));
|
||||
|
||||
if (mCancellationRequested.get()) {
|
||||
// the operation was cancelled before getting it's turn to be executed in the queue of uploads
|
||||
result = new RemoteOperationResult(new OperationCancelledException());
|
||||
|
||||
} else {
|
||||
// perform the upload
|
||||
int status = uploadFile(client);
|
||||
if (mForbiddenCharsInServer){
|
||||
result = new RemoteOperationResult(
|
||||
RemoteOperationResult.ResultCode.INVALID_CHARACTER_DETECT_IN_SERVER);
|
||||
} else {
|
||||
mPutMethod = new PutMethod(client.getWebdavUri() +
|
||||
WebdavUtils.encodePath(mRemotePath));
|
||||
result = new RemoteOperationResult(isSuccess(status), status,
|
||||
(mPutMethod != null ? mPutMethod.getResponseHeaders() : null));
|
||||
}
|
||||
}
|
||||
|
||||
int status = uploadFile(client);
|
||||
if (mForbiddenCharsInServer){
|
||||
result = new RemoteOperationResult(
|
||||
RemoteOperationResult.ResultCode.INVALID_CHARACTER_DETECT_IN_SERVER);
|
||||
} else {
|
||||
result = new RemoteOperationResult(isSuccess(status), status,
|
||||
(mPutMethod != null ? mPutMethod.getResponseHeaders() : null));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// TODO something cleaner with cancellations
|
||||
if (mCancellationRequested.get()) {
|
||||
if (mPutMethod != null && mPutMethod.isAborted()) {
|
||||
result = new RemoteOperationResult(new OperationCancelledException());
|
||||
|
||||
} else {
|
||||
result = new RemoteOperationResult(e);
|
||||
}
|
||||
@ -117,8 +123,7 @@ public class UploadRemoteFileOperation extends RemoteOperation {
|
||||
status == HttpStatus.SC_NO_CONTENT));
|
||||
}
|
||||
|
||||
protected int uploadFile(OwnCloudClient client) throws HttpException, IOException,
|
||||
OperationCancelledException {
|
||||
protected int uploadFile(OwnCloudClient client) throws IOException {
|
||||
int status = -1;
|
||||
try {
|
||||
File f = new File(mLocalPath);
|
||||
@ -127,6 +132,9 @@ public class UploadRemoteFileOperation extends RemoteOperation {
|
||||
((ProgressiveDataTransferer)mEntity)
|
||||
.addDatatransferProgressListeners(mDataTransferListeners);
|
||||
}
|
||||
if (mRequiredEtag != null && mRequiredEtag.length() > 0) {
|
||||
mPutMethod.addRequestHeader(IF_MATCH_HEADER, "\"" + mRequiredEtag + "\"");
|
||||
}
|
||||
mPutMethod.addRequestHeader(OC_TOTAL_LENGTH_HEADER, String.valueOf(f.length()));
|
||||
mPutMethod.setRequestEntity(mEntity);
|
||||
status = client.executeMethod(mPutMethod);
|
||||
|
Loading…
x
Reference in New Issue
Block a user