mirror of
				https://github.com/owncloud/android-library.git
				synced 2025-10-31 10:27:45 +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); |             prop = propSet.get(DavPropertyName.GETETAG); | ||||||
|             if (prop != null) { |             if (prop != null) { | ||||||
|                 mEtag = (String) prop.getValue(); |                 mEtag = (String) prop.getValue(); | ||||||
|                 mEtag = mEtag.substring(1, mEtag.length()-1); |                 mEtag = WebdavUtils.parseEtag(mEtag); | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             // {DAV:}quota-used-bytes |             // {DAV:}quota-used-bytes | ||||||
|  | |||||||
| @ -32,6 +32,8 @@ import java.util.Locale; | |||||||
| 
 | 
 | ||||||
| import android.net.Uri; | 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.DavPropertyName; | ||||||
| import org.apache.jackrabbit.webdav.property.DavPropertyNameSet; | import org.apache.jackrabbit.webdav.property.DavPropertyNameSet; | ||||||
| import org.apache.jackrabbit.webdav.xml.Namespace; | import org.apache.jackrabbit.webdav.xml.Namespace; | ||||||
| @ -131,4 +133,47 @@ public class WebdavUtils { | |||||||
| 
 | 
 | ||||||
|         return propSet; |         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) { |         } else if (mCode == ResultCode.ACCOUNT_NOT_THE_SAME) { | ||||||
|             return "Authenticated with a different account than the one updating"; |             return "Authenticated with a different account than the one updating"; | ||||||
|  | 
 | ||||||
|         } else if (mCode == ResultCode.INVALID_CHARACTER_IN_NAME) { |         } else if (mCode == ResultCode.INVALID_CHARACTER_IN_NAME) { | ||||||
|                 return "The file name contains an forbidden character"; |                 return "The file name contains an forbidden character"; | ||||||
|  | 
 | ||||||
|         } else if (mCode == ResultCode.FILE_NOT_FOUND) { |         } 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 + " (" + |         return "Operation finished with HTTP status code " + mHttpCode + " (" + | ||||||
|                 (isSuccess() ? "success" : "fail") + ")"; |                 (isSuccess() ? "success" : "fail") + ")"; | ||||||
|  | |||||||
| @ -32,8 +32,7 @@ public class Log_OC { | |||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     public static void i(String TAG, String message){ |     public static void i(String TAG, String message){ | ||||||
| 
 |         Log.i(TAG, message); | ||||||
|         // Write the log message to the file |  | ||||||
|         appendLog(TAG+" : "+ message); |         appendLog(TAG+" : "+ message); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -32,7 +32,6 @@ import java.io.RandomAccessFile; | |||||||
| import java.nio.channels.FileChannel; | import java.nio.channels.FileChannel; | ||||||
| import java.util.Random; | import java.util.Random; | ||||||
| 
 | 
 | ||||||
| import org.apache.commons.httpclient.HttpException; |  | ||||||
| import org.apache.commons.httpclient.methods.PutMethod; | import org.apache.commons.httpclient.methods.PutMethod; | ||||||
| 
 | 
 | ||||||
| import com.owncloud.android.lib.common.OwnCloudClient; | import com.owncloud.android.lib.common.OwnCloudClient; | ||||||
| @ -47,14 +46,21 @@ public class ChunkedUploadRemoteFileOperation extends UploadRemoteFileOperation | |||||||
|      |      | ||||||
|     public static final long CHUNK_SIZE = 1024000; |     public static final long CHUNK_SIZE = 1024000; | ||||||
|     private static final String OC_CHUNKED_HEADER = "OC-Chunked"; |     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(); |     private static final String TAG = ChunkedUploadRemoteFileOperation.class.getSimpleName(); | ||||||
| 
 | 
 | ||||||
|     public ChunkedUploadRemoteFileOperation(String storagePath, String remotePath, String mimeType){ |     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 |     @Override | ||||||
|     protected int uploadFile(OwnCloudClient client) throws HttpException, IOException { |     protected int uploadFile(OwnCloudClient client) throws IOException { | ||||||
|         int status = -1; |         int status = -1; | ||||||
| 
 | 
 | ||||||
|         FileChannel channel = null; |         FileChannel channel = null; | ||||||
| @ -64,8 +70,6 @@ public class ChunkedUploadRemoteFileOperation extends UploadRemoteFileOperation | |||||||
|             raf = new RandomAccessFile(file, "r"); |             raf = new RandomAccessFile(file, "r"); | ||||||
|             channel = raf.getChannel(); |             channel = raf.getChannel(); | ||||||
|             mEntity = new ChunkFromFileChannelRequestEntity(channel, mMimeType, CHUNK_SIZE, file); |             mEntity = new ChunkFromFileChannelRequestEntity(channel, mMimeType, CHUNK_SIZE, file); | ||||||
|             //((ProgressiveDataTransferer)mEntity). |  | ||||||
|             // addDatatransferProgressListeners(getDataTransferListeners()); |  | ||||||
|             synchronized (mDataTransferListeners) { |             synchronized (mDataTransferListeners) { | ||||||
| 				((ProgressiveDataTransferer)mEntity) | 				((ProgressiveDataTransferer)mEntity) | ||||||
|                         .addDatatransferProgressListeners(mDataTransferListeners); |                         .addDatatransferProgressListeners(mDataTransferListeners); | ||||||
| @ -74,17 +78,31 @@ public class ChunkedUploadRemoteFileOperation extends UploadRemoteFileOperation | |||||||
|             long offset = 0; |             long offset = 0; | ||||||
|             String uriPrefix = client.getWebdavUri() + WebdavUtils.encodePath(mRemotePath) + |             String uriPrefix = client.getWebdavUri() + WebdavUtils.encodePath(mRemotePath) + | ||||||
|                     "-chunking-" + Math.abs((new Random()).nextInt(9000)+1000) + "-" ; |                     "-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) { |             for (int chunkIndex = 0; chunkIndex < chunkCount ; chunkIndex++, offset += CHUNK_SIZE) { | ||||||
|  |                 if (chunkIndex == chunkCount - 1) { | ||||||
|  |                     chunkSizeStr = String.valueOf(CHUNK_SIZE * chunkCount - totalLength); | ||||||
|  |                 } | ||||||
|                 if (mPutMethod != null) { |                 if (mPutMethod != null) { | ||||||
|                     mPutMethod.releaseConnection();     // let the connection available |                     mPutMethod.releaseConnection();     // let the connection available | ||||||
|                                                         // for other methods |                                                         // for other methods | ||||||
|                 } |                 } | ||||||
|                 mPutMethod = new PutMethod(uriPrefix + chunkCount + "-" + chunkIndex); |                 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_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); |                 ((ChunkFromFileChannelRequestEntity) mEntity).setOffset(offset); | ||||||
|                 mPutMethod.setRequestEntity(mEntity); |                 mPutMethod.setRequestEntity(mEntity); | ||||||
|  |                 if (mCancellationRequested.get()) { | ||||||
|  |                     mPutMethod.abort(); | ||||||
|  |                     // next method will throw an exception | ||||||
|  |                 } | ||||||
|                 status = client.executeMethod(mPutMethod); |                 status = client.executeMethod(mPutMethod); | ||||||
| 
 | 
 | ||||||
|                 if (status == 400) { |                 if (status == 400) { | ||||||
|  | |||||||
| @ -61,6 +61,7 @@ public class DownloadRemoteFileOperation extends RemoteOperation { | |||||||
| 	private Set<OnDatatransferProgressListener> mDataTransferListeners = new HashSet<OnDatatransferProgressListener>(); | 	private Set<OnDatatransferProgressListener> mDataTransferListeners = new HashSet<OnDatatransferProgressListener>(); | ||||||
|     private final AtomicBoolean mCancellationRequested = new AtomicBoolean(false); |     private final AtomicBoolean mCancellationRequested = new AtomicBoolean(false); | ||||||
|     private long mModificationTimestamp = 0; |     private long mModificationTimestamp = 0; | ||||||
|  |     private String mEtag = ""; | ||||||
|     private GetMethod mGet; |     private GetMethod mGet; | ||||||
|      |      | ||||||
|     private String mRemotePath; |     private String mRemotePath; | ||||||
| @ -140,12 +141,24 @@ public class DownloadRemoteFileOperation extends RemoteOperation { | |||||||
|                 if (transferred == totalToTransfer) {  // Check if the file is completed |                 if (transferred == totalToTransfer) {  // Check if the file is completed | ||||||
|                 	savedFile = true; |                 	savedFile = true; | ||||||
|                 	Header modificationTime = mGet.getResponseHeader("Last-Modified"); |                 	Header modificationTime = mGet.getResponseHeader("Last-Modified"); | ||||||
|  |                     if (modificationTime == null) { | ||||||
|  |                         modificationTime = mGet.getResponseHeader("last-modified"); | ||||||
|  |                     } | ||||||
|                 	if (modificationTime != null) { |                 	if (modificationTime != null) { | ||||||
|                 		Date d = WebdavUtils.parseResponseDate((String) modificationTime.getValue()); |                 		Date d = WebdavUtils.parseResponseDate((String) modificationTime.getValue()); | ||||||
|                 		mModificationTimestamp = (d != null) ? d.getTime() : 0; |                 		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 { |                 } else { | ||||||
|                 	client.exhaustResponse(mGet.getResponseBodyAsStream()); |                 	client.exhaustResponse(mGet.getResponseBodyAsStream()); | ||||||
|  |                     // TODO some kind of error control! | ||||||
|                 } |                 } | ||||||
|                  |                  | ||||||
|             } else { |             } else { | ||||||
| @ -190,4 +203,7 @@ public class DownloadRemoteFileOperation extends RemoteOperation { | |||||||
| 		return mModificationTimestamp; | 		return mModificationTimestamp; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  |     public String getEtag() { | ||||||
|  |         return mEtag; | ||||||
|  |     } | ||||||
| } | } | ||||||
|  | |||||||
| @ -32,7 +32,6 @@ import java.util.HashSet; | |||||||
| import java.util.Set; | import java.util.Set; | ||||||
| import java.util.concurrent.atomic.AtomicBoolean; | 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.PutMethod; | ||||||
| import org.apache.commons.httpclient.methods.RequestEntity; | import org.apache.commons.httpclient.methods.RequestEntity; | ||||||
| import org.apache.http.HttpStatus; | import org.apache.http.HttpStatus; | ||||||
| @ -60,14 +59,16 @@ public class UploadRemoteFileOperation extends RemoteOperation { | |||||||
| 	private static final String TAG = UploadRemoteFileOperation.class.getSimpleName(); | 	private static final String TAG = UploadRemoteFileOperation.class.getSimpleName(); | ||||||
| 
 | 
 | ||||||
| 	protected static final String OC_TOTAL_LENGTH_HEADER = "OC-Total-Length"; | 	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 mLocalPath; | ||||||
| 	protected String mRemotePath; | 	protected String mRemotePath; | ||||||
| 	protected String mMimeType; | 	protected String mMimeType; | ||||||
| 	protected PutMethod mPutMethod = null; | 	protected PutMethod mPutMethod = null; | ||||||
| 	protected boolean mForbiddenCharsInServer = false; | 	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 Set<OnDatatransferProgressListener> mDataTransferListeners = new HashSet<OnDatatransferProgressListener>(); | ||||||
| 
 | 
 | ||||||
| 	protected RequestEntity mEntity = null; | 	protected RequestEntity mEntity = null; | ||||||
| @ -78,33 +79,38 @@ public class UploadRemoteFileOperation extends RemoteOperation { | |||||||
| 		mMimeType = mimeType; | 		mMimeType = mimeType; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	public UploadRemoteFileOperation(String localPath, String remotePath, String mimeType, String requiredEtag) { | ||||||
|  | 		this(localPath, remotePath, mimeType); | ||||||
|  | 		mRequiredEtag = requiredEtag; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	@Override | 	@Override | ||||||
| 	protected RemoteOperationResult run(OwnCloudClient client) { | 	protected RemoteOperationResult run(OwnCloudClient client) { | ||||||
| 		RemoteOperationResult result = null; | 		RemoteOperationResult result = null; | ||||||
| 
 | 
 | ||||||
| 		try { | 		try { | ||||||
| 			// / perform the upload | 			mPutMethod = new PutMethod(client.getWebdavUri() + WebdavUtils.encodePath(mRemotePath)); | ||||||
| 			synchronized (mCancellationRequested) { | 
 | ||||||
| 				if (mCancellationRequested.get()) { | 			if (mCancellationRequested.get()) { | ||||||
| 					throw new OperationCancelledException(); | 				// 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 { | 				} else { | ||||||
| 					mPutMethod = new PutMethod(client.getWebdavUri() + | 					result = new RemoteOperationResult(isSuccess(status), status, | ||||||
|                             WebdavUtils.encodePath(mRemotePath)); | 							(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) { | 		} catch (Exception e) { | ||||||
| 			// TODO something cleaner with cancellations | 			if (mPutMethod != null && mPutMethod.isAborted()) { | ||||||
| 			if (mCancellationRequested.get()) { |  | ||||||
| 				result = new RemoteOperationResult(new OperationCancelledException()); | 				result = new RemoteOperationResult(new OperationCancelledException()); | ||||||
|  | 
 | ||||||
| 			} else { | 			} else { | ||||||
| 				result = new RemoteOperationResult(e); | 				result = new RemoteOperationResult(e); | ||||||
| 			} | 			} | ||||||
| @ -117,8 +123,7 @@ public class UploadRemoteFileOperation extends RemoteOperation { | |||||||
|                 status == HttpStatus.SC_NO_CONTENT)); |                 status == HttpStatus.SC_NO_CONTENT)); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	protected int uploadFile(OwnCloudClient client) throws HttpException, IOException, | 	protected int uploadFile(OwnCloudClient client) throws IOException { | ||||||
|             OperationCancelledException { |  | ||||||
| 		int status = -1; | 		int status = -1; | ||||||
| 		try { | 		try { | ||||||
| 			File f = new File(mLocalPath); | 			File f = new File(mLocalPath); | ||||||
| @ -127,6 +132,9 @@ public class UploadRemoteFileOperation extends RemoteOperation { | |||||||
| 				((ProgressiveDataTransferer)mEntity) | 				((ProgressiveDataTransferer)mEntity) | ||||||
|                         .addDatatransferProgressListeners(mDataTransferListeners); |                         .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.addRequestHeader(OC_TOTAL_LENGTH_HEADER, String.valueOf(f.length())); | ||||||
| 			mPutMethod.setRequestEntity(mEntity); | 			mPutMethod.setRequestEntity(mEntity); | ||||||
| 			status = client.executeMethod(mPutMethod); | 			status = client.executeMethod(mPutMethod); | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user