1
0
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:
Maria Asensio 2015-10-30 14:06:48 +01:00
commit f02dffb1d3
7 changed files with 125 additions and 34 deletions

View File

@ -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

View File

@ -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;
}
}

View File

@ -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") + ")";

View File

@ -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);
}

View File

@ -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) {

View File

@ -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;
}
}

View File

@ -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;
@ -75,7 +76,12 @@ public class UploadRemoteFileOperation extends RemoteOperation {
public UploadRemoteFileOperation(String localPath, String remotePath, String mimeType) {
mLocalPath = localPath;
mRemotePath = remotePath;
mMimeType = mimeType;
mMimeType = mimeType;
}
public UploadRemoteFileOperation(String localPath, String remotePath, String mimeType, String requiredEtag) {
this(localPath, remotePath, mimeType);
mRequiredEtag = requiredEtag;
}
@Override
@ -83,28 +89,28 @@ public class UploadRemoteFileOperation extends RemoteOperation {
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);