From d73180ab67b1deed77add0a7078d362d1cbf3256 Mon Sep 17 00:00:00 2001 From: Jorge Antonio Diaz-Benito Soriano Date: Fri, 19 Sep 2014 11:53:21 +0200 Subject: [PATCH 01/27] Added build.gradle --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 9119948a..f9a7cef7 100644 --- a/build.gradle +++ b/build.gradle @@ -49,4 +49,4 @@ android { abortOnError false } } -} +} \ No newline at end of file From 39b3f376e218d577ba7f85204774063a28865130 Mon Sep 17 00:00:00 2001 From: Jorge Antonio Diaz-Benito Soriano Date: Fri, 19 Sep 2014 12:07:17 +0200 Subject: [PATCH 02/27] Added gradle folder to .gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index dd7c979e..984d59e0 100644 --- a/.gitignore +++ b/.gitignore @@ -11,6 +11,7 @@ # generated files bin/ build/ +gradle/ gen/ target/ *.iml From 7fd0028cc993e44581f5a0d42d9b91a65fb35912 Mon Sep 17 00:00:00 2001 From: Jorge Antonio Diaz-Benito Soriano Date: Fri, 19 Sep 2014 12:20:14 +0200 Subject: [PATCH 03/27] Added sample_client build.gradle --- sample_client/build.gradle | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sample_client/build.gradle b/sample_client/build.gradle index 3518d29e..be251c14 100644 --- a/sample_client/build.gradle +++ b/sample_client/build.gradle @@ -5,6 +5,7 @@ repositories { } dependencies { + compile fileTree(dir: 'libs', include: '*.jar') compile project(':') } @@ -35,7 +36,7 @@ android { debug.setRoot('build-types/debug') release.setRoot('build-types/release') } - + lintOptions { abortOnError false } From 4a76d429abadf7ad40cafa762fb590f49e9e914f Mon Sep 17 00:00:00 2001 From: Jorge Antonio Diaz-Benito Soriano Date: Fri, 19 Sep 2014 12:37:30 +0200 Subject: [PATCH 04/27] Updated build.gradle to allow Android Studio to properly identify test_client as a module --- sample_client/build.gradle | 2 +- test_client/build.gradle | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/sample_client/build.gradle b/sample_client/build.gradle index be251c14..ea875afd 100644 --- a/sample_client/build.gradle +++ b/sample_client/build.gradle @@ -36,7 +36,7 @@ android { debug.setRoot('build-types/debug') release.setRoot('build-types/release') } - + lintOptions { abortOnError false } diff --git a/test_client/build.gradle b/test_client/build.gradle index d9d8f39d..98a93568 100644 --- a/test_client/build.gradle +++ b/test_client/build.gradle @@ -7,7 +7,6 @@ repositories { dependencies { compile 'commons-httpclient:commons-httpclient:3.1' compile 'com.android.support:support-v4:20.0.0' - compile project(':') } android { From c3478eb8d4d8544f321cbff7c250ca5ed5fd0d40 Mon Sep 17 00:00:00 2001 From: Jorge Antonio Diaz-Benito Soriano Date: Fri, 19 Sep 2014 13:38:04 +0200 Subject: [PATCH 05/27] Disabled abort-build-on-lint-error check (all modules have errors). --- build.gradle | 2 +- sample_client/build.gradle | 5 +++++ test_client/build.gradle | 5 +++++ 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index f9a7cef7..9119948a 100644 --- a/build.gradle +++ b/build.gradle @@ -49,4 +49,4 @@ android { abortOnError false } } -} \ No newline at end of file +} diff --git a/sample_client/build.gradle b/sample_client/build.gradle index ea875afd..31503a37 100644 --- a/sample_client/build.gradle +++ b/sample_client/build.gradle @@ -44,4 +44,9 @@ android { packagingOptions { exclude 'META-INF/LICENSE.txt' } + android { + lintOptions { + abortOnError false + } + } } diff --git a/test_client/build.gradle b/test_client/build.gradle index 98a93568..05d527b8 100644 --- a/test_client/build.gradle +++ b/test_client/build.gradle @@ -44,4 +44,9 @@ android { packagingOptions { exclude 'META-INF/LICENSE.txt' } + android { + lintOptions { + abortOnError false + } + } } From 5f66b204bb49daedc362b1592ea97ae1f6898ca5 Mon Sep 17 00:00:00 2001 From: Jorge Antonio Diaz-Benito Soriano Date: Fri, 19 Sep 2014 13:49:46 +0200 Subject: [PATCH 06/27] Updated .gitignore --- .gitignore | 1 - 1 file changed, 1 deletion(-) diff --git a/.gitignore b/.gitignore index 984d59e0..dd7c979e 100644 --- a/.gitignore +++ b/.gitignore @@ -11,7 +11,6 @@ # generated files bin/ build/ -gradle/ gen/ target/ *.iml From 0842c4c4072815ae889cfd23910fd794c5bfb427 Mon Sep 17 00:00:00 2001 From: Jorge Antonio Diaz-Benito Soriano Date: Thu, 23 Oct 2014 22:46:49 +0200 Subject: [PATCH 07/27] Added some neccesities for the copy operation --- .../operations/RemoteOperationResult.java | 129 ++++++----- .../files/CopyRemoteFileOperation.java | 215 ++++++++++++++++++ 2 files changed, 283 insertions(+), 61 deletions(-) create mode 100644 src/com/owncloud/android/lib/resources/files/CopyRemoteFileOperation.java diff --git a/src/com/owncloud/android/lib/common/operations/RemoteOperationResult.java b/src/com/owncloud/android/lib/common/operations/RemoteOperationResult.java index 8075d1ef..e4295311 100644 --- a/src/com/owncloud/android/lib/common/operations/RemoteOperationResult.java +++ b/src/com/owncloud/android/lib/common/operations/RemoteOperationResult.java @@ -33,8 +33,12 @@ import java.net.SocketException; import java.net.SocketTimeoutException; import java.net.UnknownHostException; import java.util.ArrayList; +import android.accounts.Account; +import android.accounts.AccountsException; -import javax.net.ssl.SSLException; +import com.owncloud.android.lib.common.accounts.AccountUtils.AccountNotFoundException; +import com.owncloud.android.lib.common.network.CertificateCombinedException; +import com.owncloud.android.lib.common.utils.Log_OC; import org.apache.commons.httpclient.ConnectTimeoutException; import org.apache.commons.httpclient.Header; @@ -43,24 +47,27 @@ import org.apache.commons.httpclient.HttpStatus; import org.apache.jackrabbit.webdav.DavException; import org.json.JSONException; -import android.accounts.Account; -import android.accounts.AccountsException; +import java.io.IOException; +import java.io.Serializable; +import java.net.MalformedURLException; +import java.net.SocketException; +import java.net.SocketTimeoutException; +import java.net.UnknownHostException; +import java.util.ArrayList; -import com.owncloud.android.lib.common.accounts.AccountUtils.AccountNotFoundException; -import com.owncloud.android.lib.common.network.CertificateCombinedException; -import com.owncloud.android.lib.common.utils.Log_OC; +import javax.net.ssl.SSLException; /** * The result of a remote operation required to an ownCloud server. - * + *

* Provides a common classification of remote operation results for all the * application. - * + * * @author David A. Velasco */ public class RemoteOperationResult implements Serializable { - + /** Generated - should be refreshed every time the class changes!! */; private static final long serialVersionUID = -1909603208238358633L; @@ -71,32 +78,32 @@ public class RemoteOperationResult implements Serializable { OK_SSL, OK_NO_SSL, UNHANDLED_HTTP_CODE, - UNAUTHORIZED, - FILE_NOT_FOUND, - INSTANCE_NOT_CONFIGURED, - UNKNOWN_ERROR, - WRONG_CONNECTION, - TIMEOUT, - INCORRECT_ADDRESS, - HOST_NOT_AVAILABLE, - NO_NETWORK_CONNECTION, + UNAUTHORIZED, + FILE_NOT_FOUND, + INSTANCE_NOT_CONFIGURED, + UNKNOWN_ERROR, + WRONG_CONNECTION, + TIMEOUT, + INCORRECT_ADDRESS, + HOST_NOT_AVAILABLE, + NO_NETWORK_CONNECTION, SSL_ERROR, SSL_RECOVERABLE_PEER_UNVERIFIED, BAD_OC_VERSION, - CANCELLED, - INVALID_LOCAL_FILE_NAME, + CANCELLED, + INVALID_LOCAL_FILE_NAME, INVALID_OVERWRITE, - CONFLICT, + CONFLICT, OAUTH2_ERROR, SYNC_CONFLICT, - LOCAL_STORAGE_FULL, - LOCAL_STORAGE_NOT_MOVED, - LOCAL_STORAGE_NOT_COPIED, + LOCAL_STORAGE_FULL, + LOCAL_STORAGE_NOT_MOVED, + LOCAL_STORAGE_NOT_COPIED, OAUTH2_ERROR_ACCESS_DENIED, - QUOTA_EXCEEDED, - ACCOUNT_NOT_FOUND, - ACCOUNT_EXCEPTION, - ACCOUNT_NOT_NEW, + QUOTA_EXCEEDED, + ACCOUNT_NOT_FOUND, + ACCOUNT_EXCEPTION, + ACCOUNT_NOT_NEW, ACCOUNT_NOT_THE_SAME, INVALID_CHARACTER_IN_NAME, SHARE_NOT_FOUND, @@ -106,6 +113,7 @@ public class RemoteOperationResult implements Serializable { OK_REDIRECT_TO_NON_SECURE_CONNECTION, INVALID_MOVE_INTO_DESCENDANT, PARTIAL_MOVE_DONE, + PARTIAL_COPY_DONE, INVALID_CHARACTER_DETECT_IN_SERVER } @@ -161,20 +169,20 @@ public class RemoteOperationResult implements Serializable { } } } - + public RemoteOperationResult(boolean success, int httpCode, Header[] headers) { this(success, httpCode); if (headers != null) { Header current; - for (int i=0; i files){ - mData = files; + public void setData(ArrayList files) { + mData = files; } - - public ArrayList getData(){ - return mData; - } - + + public ArrayList getData() { + return mData; + } + public boolean isSuccess() { return mSuccess; } @@ -291,9 +299,9 @@ public class RemoteOperationResult implements Serializable { return mCode == ResultCode.SSL_RECOVERABLE_PEER_UNVERIFIED; } - public boolean isRedirectToNonSecureConnection() { - return mCode == ResultCode.OK_REDIRECT_TO_NON_SECURE_CONNECTION; - } + public boolean isRedirectToNonSecureConnection() { + return mCode == ResultCode.OK_REDIRECT_TO_NON_SECURE_CONNECTION; + } private CertificateCombinedException getCertificateCombinedException(Exception e) { CertificateCombinedException result = null; @@ -360,10 +368,10 @@ public class RemoteOperationResult implements Serializable { } else if (mException instanceof AccountsException) { return "Exception while using account"; - + } else if (mException instanceof JSONException) { - return "JSON exception"; - + return "JSON exception"; + } else { return "Unexpected exception"; } @@ -415,25 +423,24 @@ public class RemoteOperationResult implements Serializable { public String getRedirectedLocation() { return mRedirectedLocation; } - + public boolean isIdPRedirection() { return (mRedirectedLocation != null && - (mRedirectedLocation.toUpperCase().contains("SAML") || - mRedirectedLocation.toLowerCase().contains("wayf"))); + (mRedirectedLocation.toUpperCase().contains("SAML") || + mRedirectedLocation.toLowerCase().contains("wayf"))); + } + + /** + * Checks if is a non https connection + * + * @return boolean true/false + */ + public boolean isNonSecureRedirection() { + return (mRedirectedLocation != null && !(mRedirectedLocation.toLowerCase().startsWith("https://"))); } - - /** - * Checks if is a non https connection - * - * @return boolean true/false - */ - public boolean isNonSecureRedirection() { - return (mRedirectedLocation != null && - !(mRedirectedLocation.toLowerCase().startsWith("https://"))); - } public String getAuthenticateHeader() { - return mAuthenticate; + return mAuthenticate; } public String getLastPermanentLocation() { diff --git a/src/com/owncloud/android/lib/resources/files/CopyRemoteFileOperation.java b/src/com/owncloud/android/lib/resources/files/CopyRemoteFileOperation.java new file mode 100644 index 00000000..56e7eeb9 --- /dev/null +++ b/src/com/owncloud/android/lib/resources/files/CopyRemoteFileOperation.java @@ -0,0 +1,215 @@ +/* ownCloud Android Library is available under MIT license + * Copyright (C) 2014 ownCloud Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + +package com.owncloud.android.lib.resources.files; + +import android.util.Log; + +import com.owncloud.android.lib.common.OwnCloudClient; +import com.owncloud.android.lib.common.network.WebdavUtils; +import com.owncloud.android.lib.common.operations.RemoteOperation; +import com.owncloud.android.lib.common.operations.RemoteOperationResult; +import com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode; +import com.owncloud.android.lib.resources.status.OwnCloudVersion; + +import org.apache.commons.httpclient.HttpStatus; +import org.apache.jackrabbit.webdav.DavException; +import org.apache.jackrabbit.webdav.MultiStatusResponse; +import org.apache.jackrabbit.webdav.Status; +import org.apache.jackrabbit.webdav.client.methods.CopyMethod; + +import java.io.IOException; + + +/** + * Remote operation moving a remote file or folder in the ownCloud server to a different folder + * in the same account. + *

+ * Allows renaming the moving file/folder at the same time. + * + * @author David A. Velasco + */ +public class CopyRemoteFileOperation extends RemoteOperation { + + private static final String TAG = CopyRemoteFileOperation.class.getSimpleName(); + + private static final int COPY_READ_TIMEOUT = 600000; + private static final int COPY_CONNECTION_TIMEOUT = 5000; + + private String mSrcRemotePath; + private String mTargetRemotePath; + + private boolean mOverwrite; + + + /** + * Constructor. + *

+ * TODO Paths should finish in "/" in the case of folders. ? + * + * @param srcRemotePath Remote path of the file/folder to move. + * @param targetRemotePath Remove path desired for the file/folder after moving it. + */ + public CopyRemoteFileOperation( + String srcRemotePath, String targetRemotePath, boolean overwrite + ) { + + mSrcRemotePath = srcRemotePath; + mTargetRemotePath = targetRemotePath; + mOverwrite = overwrite; + } + + + /** + * Performs the rename operation. + * + * @param client Client object to communicate with the remote ownCloud server. + */ + @Override + protected RemoteOperationResult run(OwnCloudClient client) { + + OwnCloudVersion version = client.getOwnCloudVersion(); + boolean versionWithForbiddenChars = + (version != null && version.isVersionWithForbiddenCharacters()); + + /// check parameters + if (!FileUtils.isValidPath(mTargetRemotePath, versionWithForbiddenChars)) { + return new RemoteOperationResult(ResultCode.INVALID_CHARACTER_IN_NAME); + } + + if (mTargetRemotePath.equals(mSrcRemotePath)) { + // nothing to do! + return new RemoteOperationResult(ResultCode.OK); + } + + if (mTargetRemotePath.startsWith(mSrcRemotePath)) { + return new RemoteOperationResult(ResultCode.INVALID_MOVE_INTO_DESCENDANT); + } + + + /// perform remote operation + CopyMethod copyMethod = null; + RemoteOperationResult result = null; + try { + copyMethod = new CopyMethod( + client.getWebdavUri() + WebdavUtils.encodePath(mSrcRemotePath), + client.getWebdavUri() + WebdavUtils.encodePath(mTargetRemotePath), + mOverwrite + ); + int status = client.executeMethod(copyMethod, COPY_READ_TIMEOUT, COPY_CONNECTION_TIMEOUT); + + /// process response + if (status == HttpStatus.SC_MULTI_STATUS) { + result = processPartialError(copyMethod); + + } else if (status == HttpStatus.SC_PRECONDITION_FAILED && !mOverwrite) { + + result = new RemoteOperationResult(ResultCode.INVALID_OVERWRITE); + client.exhaustResponse(copyMethod.getResponseBodyAsStream()); + + + /// for other errors that could be explicitly handled, check first: + /// http://www.webdav.org/specs/rfc4918.html#rfc.section.9.9.4 + + } else { + result = new RemoteOperationResult( + isSuccess(status), // copy.succeeded()? trustful? + status, + copyMethod.getResponseHeaders() + ); + client.exhaustResponse(copyMethod.getResponseBodyAsStream()); + } + + Log.i(TAG, "Copy " + mSrcRemotePath + " to " + mTargetRemotePath + ": " + + result.getLogMessage()); + + } catch (Exception e) { + result = new RemoteOperationResult(e); + Log.e(TAG, "Copy " + mSrcRemotePath + " to " + mTargetRemotePath + ": " + + result.getLogMessage(), e); + + } finally { + if (copyMethod != null) + copyMethod.releaseConnection(); + } + + return result; + } + + + /** + * Analyzes a multistatus response from the OC server to generate an appropriate result. + *

+ * In WebDAV, a COPY request on collections (folders) can be PARTIALLY successful: some + * children are copied, some other aren't. + *

+ * According to the WebDAV specification, a multistatus response SHOULD NOT include partial + * successes (201, 204) nor for descendants of already failed children (424) in the response + * entity. But SHOULD NOT != MUST NOT, so take carefully. + * + * @param copyMethod Copy operation just finished with a multistatus response + * @return A result for the {@link com.owncloud.android.lib.resources.files.CopyRemoteFileOperation} caller + * @throws java.io.IOException If the response body could not be parsed + * @throws org.apache.jackrabbit.webdav.DavException If the status code is other than MultiStatus or if obtaining + * the response XML document fails + */ + private RemoteOperationResult processPartialError(CopyMethod copyMethod) + throws IOException, DavException { + // Adding a list of failed descendants to the result could be interesting; or maybe not. + // For the moment, let's take the easy way. + + /// check that some error really occurred + MultiStatusResponse[] responses = copyMethod.getResponseBodyAsMultiStatus().getResponses(); + Status[] status; + boolean failFound = false; + for (int i = 0; i < responses.length && !failFound; i++) { + status = responses[i].getStatus(); + failFound = ( + status != null && + status.length > 0 && + status[0].getStatusCode() > 299 + ); + } + + RemoteOperationResult result; + if (failFound) { + result = new RemoteOperationResult(ResultCode.PARTIAL_COPY_DONE); + } else { + result = new RemoteOperationResult( + true, + HttpStatus.SC_MULTI_STATUS, + copyMethod.getResponseHeaders() + ); + } + + return result; + + } + + + protected boolean isSuccess(int status) { + return status == HttpStatus.SC_CREATED || status == HttpStatus.SC_NO_CONTENT; + } + +} From 43e82df560507b46036f4ea89d4d320251c469c3 Mon Sep 17 00:00:00 2001 From: Jorge Antonio Diaz-Benito Soriano Date: Thu, 23 Oct 2014 23:04:54 +0200 Subject: [PATCH 08/27] New Travis-CI conf test --- .travis.yml | 20 ++++++-------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/.travis.yml b/.travis.yml index d663a0c8..2a46a99f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,21 +3,13 @@ android: components: - build-tools-22.0.1 - android-19 - - android-17 - - android-14 - - extra-android-support - licenses: - - 'android-sdk-license-5be876d5' - - 'android-sdk-license-598b93a6' -jdk: oraclejdk7 before_install: -- echo no | android create avd --force -n test -t $ANDROID_TARGET --abi $ANDROID_ABI -c 20M -- emulator -avd test -no-skin -no-audio -no-window & -- rm pom.xml -- android update project -p . -before_script: -- chmod +x ./wait_for_emulator.sh -- ./wait_for_emulator.sh + - echo no | android create avd --force -n test -t $ANDROID_TARGET --abi $ANDROID_ABI -c 20M + - emulator -avd test -no-skin -no-audio -no-window & + - rm pom.xml + - android update project -p . + - chmod +x ./wait_for_emulator.sh + - ./wait_for_emulator.sh script: - ant clean - ant debug From 3e28768d8f5b19e329cce20f6d46bfcfdfb49549 Mon Sep 17 00:00:00 2001 From: Jorge Antonio Diaz-Benito Soriano Date: Mon, 27 Oct 2014 23:43:16 +0100 Subject: [PATCH 09/27] Updated some dependencies --- test_client/build.gradle | 1 + 1 file changed, 1 insertion(+) diff --git a/test_client/build.gradle b/test_client/build.gradle index 05d527b8..e815f1f3 100644 --- a/test_client/build.gradle +++ b/test_client/build.gradle @@ -7,6 +7,7 @@ repositories { dependencies { compile 'commons-httpclient:commons-httpclient:3.1' compile 'com.android.support:support-v4:20.0.0' + compile project(':') } android { From 542e596bf5c74c38ccb34f54412c70a59bfc663f Mon Sep 17 00:00:00 2001 From: Jorge Antonio Diaz-Benito Soriano Date: Tue, 28 Oct 2014 12:17:27 +0100 Subject: [PATCH 10/27] Removed unnecessary command --- .../lib/test_project/test/CopyFileTest.java | 459 ++++++++++++++++++ 1 file changed, 459 insertions(+) create mode 100644 test_client/tests/src/com/owncloud/android/lib/test_project/test/CopyFileTest.java diff --git a/test_client/tests/src/com/owncloud/android/lib/test_project/test/CopyFileTest.java b/test_client/tests/src/com/owncloud/android/lib/test_project/test/CopyFileTest.java new file mode 100644 index 00000000..5f846691 --- /dev/null +++ b/test_client/tests/src/com/owncloud/android/lib/test_project/test/CopyFileTest.java @@ -0,0 +1,459 @@ +/* ownCloud Android Library is available under MIT license + * Copyright (C) 2014 ownCloud Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + */ + +package com.owncloud.android.lib.test_project.test; + +import android.content.Context; +import android.net.Uri; +import android.test.ActivityInstrumentationTestCase2; +import android.util.Log; + +import com.owncloud.android.lib.common.OwnCloudClient; +import com.owncloud.android.lib.common.OwnCloudClientFactory; +import com.owncloud.android.lib.common.OwnCloudCredentialsFactory; +import com.owncloud.android.lib.common.network.NetworkUtils; +import com.owncloud.android.lib.common.operations.RemoteOperationResult; +import com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode; +import com.owncloud.android.lib.resources.files.CopyRemoteFileOperation; +import com.owncloud.android.lib.test_project.R; +import com.owncloud.android.lib.test_project.SelfSignedConfidentSslSocketFactory; +import com.owncloud.android.lib.test_project.TestActivity; + +import junit.framework.AssertionFailedError; + +import org.apache.commons.httpclient.HttpStatus; +import org.apache.commons.httpclient.protocol.Protocol; +import org.apache.commons.httpclient.protocol.ProtocolSocketFactory; + +import java.io.File; +import java.security.GeneralSecurityException; + +//import android.test.AndroidTestCase; + +/** + * Class to test CopyRemoteFileOperation + *

+ * With this TestCase we are experimenting a bit to improve the test suite design, in two aspects: + *

+ * - Reduce the dependency from the set of test cases on the "test project" needed to + * have an instrumented APK to install in the device, as required by the testing framework + * provided by Android. To get there, this class avoids calling TestActivity methods in the test + * method. + *

+ * - Reduce the impact of creating a remote fixture over the Internet, while the structure of the + * TestCase is kept easy to maintain. To get this, all the tests are done in a single test method, + * granting this way that setUp and tearDown are run only once. + * + * @author David A. Velasco + */ + +//public class CopyFileTest extends AndroidTestCase { +public class CopyFileTest extends ActivityInstrumentationTestCase2 { + + private static final String LOG_TAG = CopyFileTest.class.getCanonicalName(); + + + /// Paths to files and folders in fixture + + private static final String SRC_BASE_FOLDER = "/src/"; + private static final String TARGET_BASE_FOLDER = "/target/"; + private static final String NO_FILE = "nofile.txt"; + private static final String FILE1 = "file1.txt"; + private static final String FILE2 = "file2.txt"; + private static final String FILE3 = "file3.txt"; + private static final String FILE4 = "file4.txt"; + private static final String FILE5 = "file5.txt"; + private static final String FILE6 = "file6.txt"; + private static final String FILE7 = "file7.txt"; + private static final String EMPTY = "empty/"; + private static final String NO_FOLDER = "nofolder/"; + private static final String FOLDER1 = "folder1/"; + private static final String FOLDER2 = "folder2/"; + private static final String FOLDER3 = "folder3/"; + private static final String FOLDER4 = "folder4/"; + + private static final String SRC_PATH_TO_FILE_1 = SRC_BASE_FOLDER + FILE1; + private static final String TARGET_PATH_TO_FILE_1 = TARGET_BASE_FOLDER + FILE1; + + private static final String SRC_PATH_TO_FILE_2 = SRC_BASE_FOLDER + FILE2; + private static final String TARGET_PATH_TO_FILE_2_RENAMED = + TARGET_BASE_FOLDER + "renamed_" + FILE2; + + private static final String SRC_PATH_TO_FILE_3 = SRC_BASE_FOLDER + FILE3; + private static final String SRC_PATH_TO_FILE_3_RENAMED = SRC_BASE_FOLDER + "renamed_" + FILE3; + + private static final String SRC_PATH_TO_FILE_4 = SRC_BASE_FOLDER + FILE4; + + private static final String SRC_PATH_TO_FILE_5 = SRC_BASE_FOLDER + FILE5; + + private static final String SRC_PATH_TO_FILE_6 = SRC_BASE_FOLDER + FILE6; + + private static final String SRC_PATH_TO_FILE_7 = SRC_BASE_FOLDER + FILE7; + + private static final String SRC_PATH_TO_NON_EXISTENT_FILE = SRC_BASE_FOLDER + NO_FILE; + + private static final String SRC_PATH_TO_EMPTY_FOLDER = SRC_BASE_FOLDER + EMPTY; + private static final String TARGET_PATH_TO_EMPTY_FOLDER = TARGET_BASE_FOLDER + EMPTY; + + private static final String SRC_PATH_TO_FULL_FOLDER_1 = SRC_BASE_FOLDER + FOLDER1; + private static final String TARGET_PATH_TO_FULL_FOLDER_1 = TARGET_BASE_FOLDER + FOLDER1; + + private static final String SRC_PATH_TO_FULL_FOLDER_2 = SRC_BASE_FOLDER + FOLDER2; + + private static final String TARGET_PATH_TO_FULL_FOLDER_2_RENAMED = + TARGET_BASE_FOLDER + "renamed_" + FOLDER2; + + private static final String SRC_PATH_TO_FULL_FOLDER_3 = SRC_BASE_FOLDER + FOLDER3; + private static final String SRC_PATH_TO_FULL_FOLDER_4 = SRC_BASE_FOLDER + FOLDER4; + + private static final String SRC_PATH_TO_FULL_FOLDER_3_RENAMED = + SRC_BASE_FOLDER + "renamed_" + FOLDER3; + + private static final String TARGET_PATH_RENAMED_WITH_INVALID_CHARS = + SRC_BASE_FOLDER + "renamed:??_" + FILE6; + + private static final String TARGET_PATH_TO_ALREADY_EXISTENT_EMPTY_FOLDER_4 = TARGET_BASE_FOLDER + + FOLDER4; + + private static final String TARGET_PATH_TO_NON_EXISTENT_FILE = TARGET_BASE_FOLDER + NO_FILE; + + private static final String TARGET_PATH_TO_FILE_5_INTO_NON_EXISTENT_FOLDER = + TARGET_BASE_FOLDER + NO_FOLDER + FILE5; + + private static final String TARGET_PATH_TO_ALREADY_EXISTENT_FILE_7 = TARGET_BASE_FOLDER + FILE7; + + private static final String[] FOLDERS_IN_FIXTURE = { + SRC_PATH_TO_EMPTY_FOLDER, + + SRC_PATH_TO_FULL_FOLDER_1, + SRC_PATH_TO_FULL_FOLDER_1 + FOLDER1, + SRC_PATH_TO_FULL_FOLDER_1 + FOLDER2, + SRC_PATH_TO_FULL_FOLDER_1 + FOLDER2 + FOLDER1, + SRC_PATH_TO_FULL_FOLDER_1 + FOLDER2 + FOLDER2, + + SRC_PATH_TO_FULL_FOLDER_2, + SRC_PATH_TO_FULL_FOLDER_2 + FOLDER1, + SRC_PATH_TO_FULL_FOLDER_2 + FOLDER2, + SRC_PATH_TO_FULL_FOLDER_2 + FOLDER2 + FOLDER1, + SRC_PATH_TO_FULL_FOLDER_2 + FOLDER2 + FOLDER2, + + SRC_PATH_TO_FULL_FOLDER_3, + SRC_PATH_TO_FULL_FOLDER_3 + FOLDER1, + SRC_PATH_TO_FULL_FOLDER_3 + FOLDER2, + SRC_PATH_TO_FULL_FOLDER_3 + FOLDER2 + FOLDER1, + SRC_PATH_TO_FULL_FOLDER_3 + FOLDER2 + FOLDER2, + + SRC_PATH_TO_FULL_FOLDER_4, + SRC_PATH_TO_FULL_FOLDER_4 + FOLDER1, + SRC_PATH_TO_FULL_FOLDER_4 + FOLDER2, + SRC_PATH_TO_FULL_FOLDER_4 + FOLDER2 + FOLDER1, + SRC_PATH_TO_FULL_FOLDER_4 + FOLDER2 + FOLDER2, + + TARGET_BASE_FOLDER, + TARGET_PATH_TO_ALREADY_EXISTENT_EMPTY_FOLDER_4 + }; + + private static final String[] FILES_IN_FIXTURE = { + SRC_PATH_TO_FILE_1, + SRC_PATH_TO_FILE_2, + SRC_PATH_TO_FILE_3, + SRC_PATH_TO_FILE_4, + SRC_PATH_TO_FILE_5, + + SRC_PATH_TO_FULL_FOLDER_1 + FILE1, + SRC_PATH_TO_FULL_FOLDER_1 + FOLDER2 + FILE1, + SRC_PATH_TO_FULL_FOLDER_1 + FOLDER2 + FILE2, + SRC_PATH_TO_FULL_FOLDER_1 + FOLDER2 + FOLDER2 + FILE2, + + SRC_PATH_TO_FULL_FOLDER_2 + FILE1, + SRC_PATH_TO_FULL_FOLDER_2 + FOLDER2 + FILE1, + SRC_PATH_TO_FULL_FOLDER_2 + FOLDER2 + FILE2, + SRC_PATH_TO_FULL_FOLDER_2 + FOLDER2 + FOLDER2 + FILE2, + + SRC_PATH_TO_FULL_FOLDER_3 + FILE1, + SRC_PATH_TO_FULL_FOLDER_3 + FOLDER2 + FILE1, + SRC_PATH_TO_FULL_FOLDER_3 + FOLDER2 + FILE2, + SRC_PATH_TO_FULL_FOLDER_3 + FOLDER2 + FOLDER2 + FILE2, + + SRC_PATH_TO_FULL_FOLDER_4 + FILE1, + SRC_PATH_TO_FULL_FOLDER_4 + FOLDER2 + FILE1, + SRC_PATH_TO_FULL_FOLDER_4 + FOLDER2 + FILE2, + SRC_PATH_TO_FULL_FOLDER_4 + FOLDER2 + FOLDER2 + FILE2, + + TARGET_PATH_TO_ALREADY_EXISTENT_FILE_7 + }; + + + String mServerUri, mUser, mPass; + OwnCloudClient mClient = null; + + public CopyFileTest() { + super(TestActivity.class); + + Protocol pr = Protocol.getProtocol("https"); + if (pr == null || !(pr.getSocketFactory() instanceof SelfSignedConfidentSslSocketFactory)) { + try { + ProtocolSocketFactory psf = new SelfSignedConfidentSslSocketFactory(); + Protocol.registerProtocol( + "https", + new Protocol("https", psf, 443)); + + } catch (GeneralSecurityException e) { + throw new AssertionFailedError( + "Self-signed confident SSL context could not be loaded"); + } + } + + } + + + protected Context getContext() { + return getActivity(); + } + + @Override + protected void setUp() throws Exception { + super.setUp(); + + // Next initialization cannot be done in the constructor because getContext() is not + // ready yet, returns NULL. + initAccessToServer(getContext()); + + Log.v(LOG_TAG, "Setting up the remote fixture..."); + + RemoteOperationResult result = null; + for (String folderPath : FOLDERS_IN_FIXTURE) { + result = TestActivity.createFolder(folderPath, true, mClient); + if (!result.isSuccess()) { + Utils.logAndThrow(LOG_TAG, result); + } + } + + File txtFile = TestActivity.extractAsset( + TestActivity.ASSETS__TEXT_FILE_NAME, getContext() + ); + for (String filePath : FILES_IN_FIXTURE) { + result = TestActivity.uploadFile( + txtFile.getAbsolutePath(), filePath, "txt/plain", mClient + ); + if (!result.isSuccess()) { + Utils.logAndThrow(LOG_TAG, result); + } + } + + Log.v(LOG_TAG, "Remote fixture created."); + + } + + + /** + * Test copy folder + */ + public void testCopyRemoteFileOperation() { + Log.v(LOG_TAG, "testCopyFolder in"); + + /// successful cases + + // copy file + CopyRemoteFileOperation copyOperation = new CopyRemoteFileOperation( + SRC_PATH_TO_FILE_1, + TARGET_PATH_TO_FILE_1, + false + ); + RemoteOperationResult result = copyOperation.execute(mClient); + assertTrue(result.isSuccess()); + + // copy & rename file, different location + copyOperation = new CopyRemoteFileOperation( + SRC_PATH_TO_FILE_2, + TARGET_PATH_TO_FILE_2_RENAMED, + false + ); + result = copyOperation.execute(mClient); + assertTrue(result.isSuccess()); + + // copy & rename file, same location (rename file) + copyOperation = new CopyRemoteFileOperation( + SRC_PATH_TO_FILE_3, + SRC_PATH_TO_FILE_3_RENAMED, + false + ); + result = copyOperation.execute(mClient); + assertTrue(result.isSuccess()); + + // copy empty folder + copyOperation = new CopyRemoteFileOperation( + SRC_PATH_TO_EMPTY_FOLDER, + TARGET_PATH_TO_EMPTY_FOLDER, + false + ); + result = copyOperation.execute(mClient); + assertTrue(result.isSuccess()); + + // copy non-empty folder + copyOperation = new CopyRemoteFileOperation( + SRC_PATH_TO_FULL_FOLDER_1, + TARGET_PATH_TO_FULL_FOLDER_1, + false + ); + result = copyOperation.execute(mClient); + assertTrue(result.isSuccess()); + + // copy & rename folder, different location + copyOperation = new CopyRemoteFileOperation( + SRC_PATH_TO_FULL_FOLDER_2, + TARGET_PATH_TO_FULL_FOLDER_2_RENAMED, + false + ); + result = copyOperation.execute(mClient); + assertTrue(result.isSuccess()); + + // copy & rename folder, same location (rename folder) + copyOperation = new CopyRemoteFileOperation( + SRC_PATH_TO_FULL_FOLDER_3, + SRC_PATH_TO_FULL_FOLDER_3_RENAMED, + false + ); + result = copyOperation.execute(mClient); + assertTrue(result.isSuccess()); + + // copy for nothing (success, but no interaction with network) + copyOperation = new CopyRemoteFileOperation( + SRC_PATH_TO_FILE_4, + SRC_PATH_TO_FILE_4, + false + ); + result = copyOperation.execute(mClient); + assertTrue(result.isSuccess()); + + // copy overwriting + copyOperation = new CopyRemoteFileOperation( + SRC_PATH_TO_FULL_FOLDER_4, + TARGET_PATH_TO_ALREADY_EXISTENT_EMPTY_FOLDER_4, + true + ); + result = copyOperation.execute(mClient); + assertTrue(result.isSuccess()); + + + /// Failed cases + + // file to copy does not exist + copyOperation = new CopyRemoteFileOperation( + SRC_PATH_TO_NON_EXISTENT_FILE, + TARGET_PATH_TO_NON_EXISTENT_FILE, + false + ); + result = copyOperation.execute(mClient); + assertTrue(result.getCode() == ResultCode.FILE_NOT_FOUND); + + // folder to copy into does no exist + copyOperation = new CopyRemoteFileOperation( + SRC_PATH_TO_FILE_5, + TARGET_PATH_TO_FILE_5_INTO_NON_EXISTENT_FOLDER, + false + ); + result = copyOperation.execute(mClient); + assertTrue(result.getHttpCode() == HttpStatus.SC_CONFLICT); + + // target location (renaming) has invalid characters + copyOperation = new CopyRemoteFileOperation( + SRC_PATH_TO_FILE_6, + TARGET_PATH_RENAMED_WITH_INVALID_CHARS, + false + ); + result = copyOperation.execute(mClient); + assertTrue(result.getCode() == ResultCode.INVALID_CHARACTER_IN_NAME); + + // name collision + copyOperation = new CopyRemoteFileOperation( + SRC_PATH_TO_FILE_7, + TARGET_PATH_TO_ALREADY_EXISTENT_FILE_7, + false + ); + result = copyOperation.execute(mClient); + assertTrue(result.getCode() == ResultCode.INVALID_OVERWRITE); + + // copy a folder into a descendant + copyOperation = new CopyRemoteFileOperation( + SRC_BASE_FOLDER, + SRC_PATH_TO_EMPTY_FOLDER, + false + ); + result = copyOperation.execute(mClient); + assertTrue(result.getCode() == ResultCode.INVALID_COPY_INTO_DESCENDANT); + + } + + @Override + protected void tearDown() throws Exception { + Log.v(LOG_TAG, "Deleting remote fixture..."); + + String[] mPathsToCleanUp = { + SRC_BASE_FOLDER, + TARGET_BASE_FOLDER + }; + + for (String path : mPathsToCleanUp) { + RemoteOperationResult removeResult = + TestActivity.removeFile(path, mClient); + if (!removeResult.isSuccess() && removeResult.getCode() != ResultCode.TIMEOUT) { + Utils.logAndThrow(LOG_TAG, removeResult); + } + } + + super.tearDown(); + + Log.v(LOG_TAG, "Remote fixture delete."); + } + + + private void initAccessToServer(Context context) { + Log.v(LOG_TAG, "Setting up client instance to access OC server..."); + + mServerUri = context.getString(R.string.server_base_url); + mUser = context.getString(R.string.username); + mPass = context.getString(R.string.password); + + mClient = new OwnCloudClient( + Uri.parse(mServerUri), + NetworkUtils.getMultiThreadedConnManager() + ); + mClient.setDefaultTimeouts( + OwnCloudClientFactory.DEFAULT_DATA_TIMEOUT, + OwnCloudClientFactory.DEFAULT_CONNECTION_TIMEOUT); + mClient.setFollowRedirects(true); + mClient.setCredentials( + OwnCloudCredentialsFactory.newBasicCredentials( + mUser, + mPass + ) + ); + + Log.v(LOG_TAG, "Client instance set up."); + + } + + +} From f753b1bde825396c46360979c13d41cff478237f Mon Sep 17 00:00:00 2001 From: Jorge Antonio Diaz-Benito Soriano Date: Tue, 28 Oct 2014 12:46:44 +0100 Subject: [PATCH 11/27] Added INVALID_COPY_INTO_DESCENDANT code --- .../common/operations/RemoteOperationResult.java | 13 +++---------- .../resources/files/CopyRemoteFileOperation.java | 2 +- 2 files changed, 4 insertions(+), 11 deletions(-) diff --git a/src/com/owncloud/android/lib/common/operations/RemoteOperationResult.java b/src/com/owncloud/android/lib/common/operations/RemoteOperationResult.java index e4295311..f8eb8cc1 100644 --- a/src/com/owncloud/android/lib/common/operations/RemoteOperationResult.java +++ b/src/com/owncloud/android/lib/common/operations/RemoteOperationResult.java @@ -47,14 +47,6 @@ import org.apache.commons.httpclient.HttpStatus; import org.apache.jackrabbit.webdav.DavException; import org.json.JSONException; -import java.io.IOException; -import java.io.Serializable; -import java.net.MalformedURLException; -import java.net.SocketException; -import java.net.SocketTimeoutException; -import java.net.UnknownHostException; -import java.util.ArrayList; - import javax.net.ssl.SSLException; @@ -69,7 +61,7 @@ import javax.net.ssl.SSLException; public class RemoteOperationResult implements Serializable { /** Generated - should be refreshed every time the class changes!! */; - private static final long serialVersionUID = -1909603208238358633L; + private static final long serialVersionUID = 1129130415603799707L; private static final String TAG = RemoteOperationResult.class.getSimpleName(); @@ -111,7 +103,8 @@ public class RemoteOperationResult implements Serializable { FORBIDDEN, SHARE_FORBIDDEN, OK_REDIRECT_TO_NON_SECURE_CONNECTION, - INVALID_MOVE_INTO_DESCENDANT, + INVALID_MOVE_INTO_DESCENDANT, + INVALID_COPY_INTO_DESCENDANT, PARTIAL_MOVE_DONE, PARTIAL_COPY_DONE, INVALID_CHARACTER_DETECT_IN_SERVER diff --git a/src/com/owncloud/android/lib/resources/files/CopyRemoteFileOperation.java b/src/com/owncloud/android/lib/resources/files/CopyRemoteFileOperation.java index 56e7eeb9..f8708761 100644 --- a/src/com/owncloud/android/lib/resources/files/CopyRemoteFileOperation.java +++ b/src/com/owncloud/android/lib/resources/files/CopyRemoteFileOperation.java @@ -104,7 +104,7 @@ public class CopyRemoteFileOperation extends RemoteOperation { } if (mTargetRemotePath.startsWith(mSrcRemotePath)) { - return new RemoteOperationResult(ResultCode.INVALID_MOVE_INTO_DESCENDANT); + return new RemoteOperationResult(ResultCode.INVALID_COPY_INTO_DESCENDANT); } From 8e0739aed00fafc3b311b1426dd1f2aa357070e9 Mon Sep 17 00:00:00 2001 From: Jorge Antonio Diaz-Benito Soriano Date: Fri, 19 Sep 2014 12:07:17 +0200 Subject: [PATCH 12/27] Added gradle folder to .gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index dd7c979e..984d59e0 100644 --- a/.gitignore +++ b/.gitignore @@ -11,6 +11,7 @@ # generated files bin/ build/ +gradle/ gen/ target/ *.iml From 775fb5b1f25517e0f152ef68b5f21571b3d002a2 Mon Sep 17 00:00:00 2001 From: Jorge Antonio Diaz-Benito Soriano Date: Fri, 19 Sep 2014 12:37:30 +0200 Subject: [PATCH 13/27] Updated build.gradle to allow Android Studio to properly identify test_client as a module --- test_client/build.gradle | 1 + 1 file changed, 1 insertion(+) diff --git a/test_client/build.gradle b/test_client/build.gradle index e815f1f3..7a89bad0 100644 --- a/test_client/build.gradle +++ b/test_client/build.gradle @@ -1,3 +1,4 @@ + apply plugin: 'com.android.application' repositories { From 25ec49acfb2ab5fbadb40b2cec13694530c38703 Mon Sep 17 00:00:00 2001 From: Jorge Antonio Diaz-Benito Soriano Date: Fri, 19 Sep 2014 13:29:33 +0200 Subject: [PATCH 14/27] Replaced obsolete Android plugins and updated Gradle plugin version to 0.13 --- build.gradle | 1 + 1 file changed, 1 insertion(+) diff --git a/build.gradle b/build.gradle index 9119948a..2fc53f41 100644 --- a/build.gradle +++ b/build.gradle @@ -6,6 +6,7 @@ buildscript { classpath 'com.android.tools.build:gradle:1.2.3' } } + apply plugin: 'com.android.library' repositories { From b8830e0faf9e9223026ecafa9522b968ad700de0 Mon Sep 17 00:00:00 2001 From: Jorge Antonio Diaz-Benito Soriano Date: Fri, 19 Sep 2014 13:38:04 +0200 Subject: [PATCH 15/27] Disabled abort-build-on-lint-error check (all modules have errors). --- test_client/build.gradle | 1 - 1 file changed, 1 deletion(-) diff --git a/test_client/build.gradle b/test_client/build.gradle index 7a89bad0..e815f1f3 100644 --- a/test_client/build.gradle +++ b/test_client/build.gradle @@ -1,4 +1,3 @@ - apply plugin: 'com.android.application' repositories { From 97b133b36af56b7de08f5e73cd95b813a5088f78 Mon Sep 17 00:00:00 2001 From: Jorge Antonio Diaz-Benito Soriano Date: Fri, 19 Sep 2014 13:49:46 +0200 Subject: [PATCH 16/27] Updated .gitignore --- .gitignore | 1 - 1 file changed, 1 deletion(-) diff --git a/.gitignore b/.gitignore index 984d59e0..dd7c979e 100644 --- a/.gitignore +++ b/.gitignore @@ -11,7 +11,6 @@ # generated files bin/ build/ -gradle/ gen/ target/ *.iml From b53c8ccf9dc2e2413f77c1d0709b08972baa6fc3 Mon Sep 17 00:00:00 2001 From: Jorge Antonio Diaz-Benito Soriano Date: Mon, 27 Oct 2014 23:43:16 +0100 Subject: [PATCH 17/27] Updated some dependencies --- sample_client/build.gradle | 1 - 1 file changed, 1 deletion(-) diff --git a/sample_client/build.gradle b/sample_client/build.gradle index 31503a37..5e4ae3c9 100644 --- a/sample_client/build.gradle +++ b/sample_client/build.gradle @@ -5,7 +5,6 @@ repositories { } dependencies { - compile fileTree(dir: 'libs', include: '*.jar') compile project(':') } From 8633efbb493d657ce1ab292d27ecb74e50b7d7b4 Mon Sep 17 00:00:00 2001 From: Jorge Antonio Diaz-Benito Soriano Date: Thu, 23 Oct 2014 22:46:49 +0200 Subject: [PATCH 18/27] Added some neccesities for the copy operation --- .../android/lib/resources/files/CopyRemoteFileOperation.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/com/owncloud/android/lib/resources/files/CopyRemoteFileOperation.java b/src/com/owncloud/android/lib/resources/files/CopyRemoteFileOperation.java index f8708761..934c69be 100644 --- a/src/com/owncloud/android/lib/resources/files/CopyRemoteFileOperation.java +++ b/src/com/owncloud/android/lib/resources/files/CopyRemoteFileOperation.java @@ -107,7 +107,6 @@ public class CopyRemoteFileOperation extends RemoteOperation { return new RemoteOperationResult(ResultCode.INVALID_COPY_INTO_DESCENDANT); } - /// perform remote operation CopyMethod copyMethod = null; RemoteOperationResult result = null; From 2970b54e7c3557a8a61fd2fcfb329676676c3234 Mon Sep 17 00:00:00 2001 From: Jorge Antonio Diaz-Benito Soriano Date: Tue, 4 Nov 2014 15:56:30 +0100 Subject: [PATCH 19/27] Updated CopyRemoteFileOperation and verified with the unit tests --- .../files/CopyRemoteFileOperation.java | 11 +++-- .../lib/test_project/test/CopyFileTest.java | 42 ++++++++----------- 2 files changed, 25 insertions(+), 28 deletions(-) diff --git a/src/com/owncloud/android/lib/resources/files/CopyRemoteFileOperation.java b/src/com/owncloud/android/lib/resources/files/CopyRemoteFileOperation.java index 934c69be..bd7f118e 100644 --- a/src/com/owncloud/android/lib/resources/files/CopyRemoteFileOperation.java +++ b/src/com/owncloud/android/lib/resources/files/CopyRemoteFileOperation.java @@ -24,6 +24,7 @@ package com.owncloud.android.lib.resources.files; +import android.content.Context; import android.util.Log; import com.owncloud.android.lib.common.OwnCloudClient; @@ -61,6 +62,7 @@ public class CopyRemoteFileOperation extends RemoteOperation { private String mTargetRemotePath; private boolean mOverwrite; + private Context mContext; /** @@ -71,10 +73,9 @@ public class CopyRemoteFileOperation extends RemoteOperation { * @param srcRemotePath Remote path of the file/folder to move. * @param targetRemotePath Remove path desired for the file/folder after moving it. */ - public CopyRemoteFileOperation( - String srcRemotePath, String targetRemotePath, boolean overwrite + public CopyRemoteFileOperation(Context context, String srcRemotePath, String targetRemotePath, boolean overwrite ) { - + mContext = context; mSrcRemotePath = srcRemotePath; mTargetRemotePath = targetRemotePath; mOverwrite = overwrite; @@ -107,6 +108,10 @@ public class CopyRemoteFileOperation extends RemoteOperation { return new RemoteOperationResult(ResultCode.INVALID_COPY_INTO_DESCENDANT); } + if (!new ExistenceCheckRemoteOperation(mSrcRemotePath, mContext, Boolean.FALSE).run(getClient()).isSuccess()) { + return new RemoteOperationResult(ResultCode.FILE_NOT_FOUND); + } + /// perform remote operation CopyMethod copyMethod = null; RemoteOperationResult result = null; diff --git a/test_client/tests/src/com/owncloud/android/lib/test_project/test/CopyFileTest.java b/test_client/tests/src/com/owncloud/android/lib/test_project/test/CopyFileTest.java index 5f846691..7b9bbbf2 100644 --- a/test_client/tests/src/com/owncloud/android/lib/test_project/test/CopyFileTest.java +++ b/test_client/tests/src/com/owncloud/android/lib/test_project/test/CopyFileTest.java @@ -36,18 +36,11 @@ import com.owncloud.android.lib.common.network.NetworkUtils; import com.owncloud.android.lib.common.operations.RemoteOperationResult; import com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode; import com.owncloud.android.lib.resources.files.CopyRemoteFileOperation; -import com.owncloud.android.lib.test_project.R; -import com.owncloud.android.lib.test_project.SelfSignedConfidentSslSocketFactory; import com.owncloud.android.lib.test_project.TestActivity; -import junit.framework.AssertionFailedError; - import org.apache.commons.httpclient.HttpStatus; -import org.apache.commons.httpclient.protocol.Protocol; -import org.apache.commons.httpclient.protocol.ProtocolSocketFactory; import java.io.File; -import java.security.GeneralSecurityException; //import android.test.AndroidTestCase; @@ -210,21 +203,6 @@ public class CopyFileTest extends ActivityInstrumentationTestCase2 public CopyFileTest() { super(TestActivity.class); - - Protocol pr = Protocol.getProtocol("https"); - if (pr == null || !(pr.getSocketFactory() instanceof SelfSignedConfidentSslSocketFactory)) { - try { - ProtocolSocketFactory psf = new SelfSignedConfidentSslSocketFactory(); - Protocol.registerProtocol( - "https", - new Protocol("https", psf, 443)); - - } catch (GeneralSecurityException e) { - throw new AssertionFailedError( - "Self-signed confident SSL context could not be loaded"); - } - } - } @@ -277,6 +255,7 @@ public class CopyFileTest extends ActivityInstrumentationTestCase2 // copy file CopyRemoteFileOperation copyOperation = new CopyRemoteFileOperation( + getContext(), SRC_PATH_TO_FILE_1, TARGET_PATH_TO_FILE_1, false @@ -286,6 +265,7 @@ public class CopyFileTest extends ActivityInstrumentationTestCase2 // copy & rename file, different location copyOperation = new CopyRemoteFileOperation( + getContext(), SRC_PATH_TO_FILE_2, TARGET_PATH_TO_FILE_2_RENAMED, false @@ -295,6 +275,7 @@ public class CopyFileTest extends ActivityInstrumentationTestCase2 // copy & rename file, same location (rename file) copyOperation = new CopyRemoteFileOperation( + getContext(), SRC_PATH_TO_FILE_3, SRC_PATH_TO_FILE_3_RENAMED, false @@ -304,6 +285,7 @@ public class CopyFileTest extends ActivityInstrumentationTestCase2 // copy empty folder copyOperation = new CopyRemoteFileOperation( + getContext(), SRC_PATH_TO_EMPTY_FOLDER, TARGET_PATH_TO_EMPTY_FOLDER, false @@ -313,6 +295,7 @@ public class CopyFileTest extends ActivityInstrumentationTestCase2 // copy non-empty folder copyOperation = new CopyRemoteFileOperation( + getContext(), SRC_PATH_TO_FULL_FOLDER_1, TARGET_PATH_TO_FULL_FOLDER_1, false @@ -322,6 +305,7 @@ public class CopyFileTest extends ActivityInstrumentationTestCase2 // copy & rename folder, different location copyOperation = new CopyRemoteFileOperation( + getContext(), SRC_PATH_TO_FULL_FOLDER_2, TARGET_PATH_TO_FULL_FOLDER_2_RENAMED, false @@ -331,6 +315,7 @@ public class CopyFileTest extends ActivityInstrumentationTestCase2 // copy & rename folder, same location (rename folder) copyOperation = new CopyRemoteFileOperation( + getContext(), SRC_PATH_TO_FULL_FOLDER_3, SRC_PATH_TO_FULL_FOLDER_3_RENAMED, false @@ -340,6 +325,7 @@ public class CopyFileTest extends ActivityInstrumentationTestCase2 // copy for nothing (success, but no interaction with network) copyOperation = new CopyRemoteFileOperation( + getContext(), SRC_PATH_TO_FILE_4, SRC_PATH_TO_FILE_4, false @@ -349,6 +335,7 @@ public class CopyFileTest extends ActivityInstrumentationTestCase2 // copy overwriting copyOperation = new CopyRemoteFileOperation( + getContext(), SRC_PATH_TO_FULL_FOLDER_4, TARGET_PATH_TO_ALREADY_EXISTENT_EMPTY_FOLDER_4, true @@ -361,6 +348,7 @@ public class CopyFileTest extends ActivityInstrumentationTestCase2 // file to copy does not exist copyOperation = new CopyRemoteFileOperation( + getContext(), SRC_PATH_TO_NON_EXISTENT_FILE, TARGET_PATH_TO_NON_EXISTENT_FILE, false @@ -370,6 +358,7 @@ public class CopyFileTest extends ActivityInstrumentationTestCase2 // folder to copy into does no exist copyOperation = new CopyRemoteFileOperation( + getContext(), SRC_PATH_TO_FILE_5, TARGET_PATH_TO_FILE_5_INTO_NON_EXISTENT_FOLDER, false @@ -379,6 +368,7 @@ public class CopyFileTest extends ActivityInstrumentationTestCase2 // target location (renaming) has invalid characters copyOperation = new CopyRemoteFileOperation( + getContext(), SRC_PATH_TO_FILE_6, TARGET_PATH_RENAMED_WITH_INVALID_CHARS, false @@ -388,7 +378,8 @@ public class CopyFileTest extends ActivityInstrumentationTestCase2 // name collision copyOperation = new CopyRemoteFileOperation( - SRC_PATH_TO_FILE_7, + getContext(), + SRC_PATH_TO_FILE_1, TARGET_PATH_TO_ALREADY_EXISTENT_FILE_7, false ); @@ -397,13 +388,13 @@ public class CopyFileTest extends ActivityInstrumentationTestCase2 // copy a folder into a descendant copyOperation = new CopyRemoteFileOperation( + getContext(), SRC_BASE_FOLDER, SRC_PATH_TO_EMPTY_FOLDER, false ); result = copyOperation.execute(mClient); assertTrue(result.getCode() == ResultCode.INVALID_COPY_INTO_DESCENDANT); - } @Override @@ -437,12 +428,13 @@ public class CopyFileTest extends ActivityInstrumentationTestCase2 mPass = context.getString(R.string.password); mClient = new OwnCloudClient( - Uri.parse(mServerUri), + Uri.parse("http://" + mServerUri), NetworkUtils.getMultiThreadedConnManager() ); mClient.setDefaultTimeouts( OwnCloudClientFactory.DEFAULT_DATA_TIMEOUT, OwnCloudClientFactory.DEFAULT_CONNECTION_TIMEOUT); + mClient.setBaseUri(Uri.parse("http://" + mServerUri)); mClient.setFollowRedirects(true); mClient.setCredentials( OwnCloudCredentialsFactory.newBasicCredentials( From ed720d0a65a3625cfb21d30645c6fb3d68c822e1 Mon Sep 17 00:00:00 2001 From: Jorge Antonio Diaz-Benito Soriano Date: Tue, 4 Nov 2014 16:08:24 +0100 Subject: [PATCH 20/27] Cleanup --- .../lib/test_project/test/CopyFileTest.java | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/test_client/tests/src/com/owncloud/android/lib/test_project/test/CopyFileTest.java b/test_client/tests/src/com/owncloud/android/lib/test_project/test/CopyFileTest.java index 7b9bbbf2..1218eeb4 100644 --- a/test_client/tests/src/com/owncloud/android/lib/test_project/test/CopyFileTest.java +++ b/test_client/tests/src/com/owncloud/android/lib/test_project/test/CopyFileTest.java @@ -203,6 +203,21 @@ public class CopyFileTest extends ActivityInstrumentationTestCase2 public CopyFileTest() { super(TestActivity.class); + + Protocol pr = Protocol.getProtocol("https"); + if (pr == null || !(pr.getSocketFactory() instanceof SelfSignedConfidentSslSocketFactory)) { + try { + ProtocolSocketFactory psf = new SelfSignedConfidentSslSocketFactory(); + Protocol.registerProtocol( + "https", + new Protocol("https", psf, 443)); + + } catch (GeneralSecurityException e) { + throw new AssertionFailedError( + "Self-signed confident SSL context could not be loaded"); + } + } + } @@ -428,13 +443,12 @@ public class CopyFileTest extends ActivityInstrumentationTestCase2 mPass = context.getString(R.string.password); mClient = new OwnCloudClient( - Uri.parse("http://" + mServerUri), + Uri.parse(mServerUri), NetworkUtils.getMultiThreadedConnManager() ); mClient.setDefaultTimeouts( OwnCloudClientFactory.DEFAULT_DATA_TIMEOUT, OwnCloudClientFactory.DEFAULT_CONNECTION_TIMEOUT); - mClient.setBaseUri(Uri.parse("http://" + mServerUri)); mClient.setFollowRedirects(true); mClient.setCredentials( OwnCloudCredentialsFactory.newBasicCredentials( From 6f1232493087fc70dfe24e97a92cfe88c731107e Mon Sep 17 00:00:00 2001 From: Jorge Antonio Diaz-Benito Soriano Date: Tue, 4 Nov 2014 16:31:12 +0100 Subject: [PATCH 21/27] Added some missing imports --- .../android/lib/test_project/test/CopyFileTest.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/test_client/tests/src/com/owncloud/android/lib/test_project/test/CopyFileTest.java b/test_client/tests/src/com/owncloud/android/lib/test_project/test/CopyFileTest.java index 1218eeb4..2b36ddbd 100644 --- a/test_client/tests/src/com/owncloud/android/lib/test_project/test/CopyFileTest.java +++ b/test_client/tests/src/com/owncloud/android/lib/test_project/test/CopyFileTest.java @@ -36,11 +36,18 @@ import com.owncloud.android.lib.common.network.NetworkUtils; import com.owncloud.android.lib.common.operations.RemoteOperationResult; import com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode; import com.owncloud.android.lib.resources.files.CopyRemoteFileOperation; +import com.owncloud.android.lib.test_project.R; +import com.owncloud.android.lib.test_project.SelfSignedConfidentSslSocketFactory; import com.owncloud.android.lib.test_project.TestActivity; +import junit.framework.AssertionFailedError; + import org.apache.commons.httpclient.HttpStatus; +import org.apache.commons.httpclient.protocol.Protocol; +import org.apache.commons.httpclient.protocol.ProtocolSocketFactory; import java.io.File; +import java.security.GeneralSecurityException; //import android.test.AndroidTestCase; From b281585c93a7eec52e467f51850811f8b0a92955 Mon Sep 17 00:00:00 2001 From: "David A. Velasco" Date: Tue, 18 Aug 2015 13:27:44 +0200 Subject: [PATCH 22/27] Updated CopyRemoteFileOperation constructor --- .../resources/files/CopyRemoteFileOperation.java | 12 ++++-------- .../resources/files/MoveRemoteFileOperation.java | 2 -- .../lib/test_project/test/CopyFileTest.java | 14 -------------- 3 files changed, 4 insertions(+), 24 deletions(-) diff --git a/src/com/owncloud/android/lib/resources/files/CopyRemoteFileOperation.java b/src/com/owncloud/android/lib/resources/files/CopyRemoteFileOperation.java index bd7f118e..f9f9d346 100644 --- a/src/com/owncloud/android/lib/resources/files/CopyRemoteFileOperation.java +++ b/src/com/owncloud/android/lib/resources/files/CopyRemoteFileOperation.java @@ -24,7 +24,6 @@ package com.owncloud.android.lib.resources.files; -import android.content.Context; import android.util.Log; import com.owncloud.android.lib.common.OwnCloudClient; @@ -62,7 +61,6 @@ public class CopyRemoteFileOperation extends RemoteOperation { private String mTargetRemotePath; private boolean mOverwrite; - private Context mContext; /** @@ -73,9 +71,8 @@ public class CopyRemoteFileOperation extends RemoteOperation { * @param srcRemotePath Remote path of the file/folder to move. * @param targetRemotePath Remove path desired for the file/folder after moving it. */ - public CopyRemoteFileOperation(Context context, String srcRemotePath, String targetRemotePath, boolean overwrite + public CopyRemoteFileOperation(String srcRemotePath, String targetRemotePath, boolean overwrite ) { - mContext = context; mSrcRemotePath = srcRemotePath; mTargetRemotePath = targetRemotePath; mOverwrite = overwrite; @@ -108,10 +105,6 @@ public class CopyRemoteFileOperation extends RemoteOperation { return new RemoteOperationResult(ResultCode.INVALID_COPY_INTO_DESCENDANT); } - if (!new ExistenceCheckRemoteOperation(mSrcRemotePath, mContext, Boolean.FALSE).run(getClient()).isSuccess()) { - return new RemoteOperationResult(ResultCode.FILE_NOT_FOUND); - } - /// perform remote operation CopyMethod copyMethod = null; RemoteOperationResult result = null; @@ -136,6 +129,9 @@ public class CopyRemoteFileOperation extends RemoteOperation { /// for other errors that could be explicitly handled, check first: /// http://www.webdav.org/specs/rfc4918.html#rfc.section.9.9.4 + } else if (status == 400) { + result = new RemoteOperationResult(copyMethod.succeeded(), + copyMethod.getResponseBodyAsString(), status); } else { result = new RemoteOperationResult( isSuccess(status), // copy.succeeded()? trustful? diff --git a/src/com/owncloud/android/lib/resources/files/MoveRemoteFileOperation.java b/src/com/owncloud/android/lib/resources/files/MoveRemoteFileOperation.java index ed68535d..919b7926 100644 --- a/src/com/owncloud/android/lib/resources/files/MoveRemoteFileOperation.java +++ b/src/com/owncloud/android/lib/resources/files/MoveRemoteFileOperation.java @@ -39,7 +39,6 @@ import com.owncloud.android.lib.common.network.WebdavUtils; import com.owncloud.android.lib.common.operations.RemoteOperation; import com.owncloud.android.lib.common.operations.RemoteOperationResult; import com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode; -import com.owncloud.android.lib.common.utils.Log_OC; import com.owncloud.android.lib.resources.status.OwnCloudVersion; @@ -137,7 +136,6 @@ public class MoveRemoteFileOperation extends RemoteOperation { } else if (status == 400) { result = new RemoteOperationResult(move.succeeded(), move.getResponseBodyAsString(), status); - Log_OC.d(TAG, move.getResponseBodyAsString()); } else { result = new RemoteOperationResult( isSuccess(status), // move.succeeded()? trustful? diff --git a/test_client/tests/src/com/owncloud/android/lib/test_project/test/CopyFileTest.java b/test_client/tests/src/com/owncloud/android/lib/test_project/test/CopyFileTest.java index 2b36ddbd..468d2de1 100644 --- a/test_client/tests/src/com/owncloud/android/lib/test_project/test/CopyFileTest.java +++ b/test_client/tests/src/com/owncloud/android/lib/test_project/test/CopyFileTest.java @@ -277,7 +277,6 @@ public class CopyFileTest extends ActivityInstrumentationTestCase2 // copy file CopyRemoteFileOperation copyOperation = new CopyRemoteFileOperation( - getContext(), SRC_PATH_TO_FILE_1, TARGET_PATH_TO_FILE_1, false @@ -287,7 +286,6 @@ public class CopyFileTest extends ActivityInstrumentationTestCase2 // copy & rename file, different location copyOperation = new CopyRemoteFileOperation( - getContext(), SRC_PATH_TO_FILE_2, TARGET_PATH_TO_FILE_2_RENAMED, false @@ -297,7 +295,6 @@ public class CopyFileTest extends ActivityInstrumentationTestCase2 // copy & rename file, same location (rename file) copyOperation = new CopyRemoteFileOperation( - getContext(), SRC_PATH_TO_FILE_3, SRC_PATH_TO_FILE_3_RENAMED, false @@ -307,7 +304,6 @@ public class CopyFileTest extends ActivityInstrumentationTestCase2 // copy empty folder copyOperation = new CopyRemoteFileOperation( - getContext(), SRC_PATH_TO_EMPTY_FOLDER, TARGET_PATH_TO_EMPTY_FOLDER, false @@ -317,7 +313,6 @@ public class CopyFileTest extends ActivityInstrumentationTestCase2 // copy non-empty folder copyOperation = new CopyRemoteFileOperation( - getContext(), SRC_PATH_TO_FULL_FOLDER_1, TARGET_PATH_TO_FULL_FOLDER_1, false @@ -327,7 +322,6 @@ public class CopyFileTest extends ActivityInstrumentationTestCase2 // copy & rename folder, different location copyOperation = new CopyRemoteFileOperation( - getContext(), SRC_PATH_TO_FULL_FOLDER_2, TARGET_PATH_TO_FULL_FOLDER_2_RENAMED, false @@ -337,7 +331,6 @@ public class CopyFileTest extends ActivityInstrumentationTestCase2 // copy & rename folder, same location (rename folder) copyOperation = new CopyRemoteFileOperation( - getContext(), SRC_PATH_TO_FULL_FOLDER_3, SRC_PATH_TO_FULL_FOLDER_3_RENAMED, false @@ -347,7 +340,6 @@ public class CopyFileTest extends ActivityInstrumentationTestCase2 // copy for nothing (success, but no interaction with network) copyOperation = new CopyRemoteFileOperation( - getContext(), SRC_PATH_TO_FILE_4, SRC_PATH_TO_FILE_4, false @@ -357,7 +349,6 @@ public class CopyFileTest extends ActivityInstrumentationTestCase2 // copy overwriting copyOperation = new CopyRemoteFileOperation( - getContext(), SRC_PATH_TO_FULL_FOLDER_4, TARGET_PATH_TO_ALREADY_EXISTENT_EMPTY_FOLDER_4, true @@ -370,7 +361,6 @@ public class CopyFileTest extends ActivityInstrumentationTestCase2 // file to copy does not exist copyOperation = new CopyRemoteFileOperation( - getContext(), SRC_PATH_TO_NON_EXISTENT_FILE, TARGET_PATH_TO_NON_EXISTENT_FILE, false @@ -380,7 +370,6 @@ public class CopyFileTest extends ActivityInstrumentationTestCase2 // folder to copy into does no exist copyOperation = new CopyRemoteFileOperation( - getContext(), SRC_PATH_TO_FILE_5, TARGET_PATH_TO_FILE_5_INTO_NON_EXISTENT_FOLDER, false @@ -390,7 +379,6 @@ public class CopyFileTest extends ActivityInstrumentationTestCase2 // target location (renaming) has invalid characters copyOperation = new CopyRemoteFileOperation( - getContext(), SRC_PATH_TO_FILE_6, TARGET_PATH_RENAMED_WITH_INVALID_CHARS, false @@ -400,7 +388,6 @@ public class CopyFileTest extends ActivityInstrumentationTestCase2 // name collision copyOperation = new CopyRemoteFileOperation( - getContext(), SRC_PATH_TO_FILE_1, TARGET_PATH_TO_ALREADY_EXISTENT_FILE_7, false @@ -410,7 +397,6 @@ public class CopyFileTest extends ActivityInstrumentationTestCase2 // copy a folder into a descendant copyOperation = new CopyRemoteFileOperation( - getContext(), SRC_BASE_FOLDER, SRC_PATH_TO_EMPTY_FOLDER, false From 819b4653853ed26f3e427118437af39c9b42d651 Mon Sep 17 00:00:00 2001 From: "David A. Velasco" Date: Tue, 18 Aug 2015 14:07:59 +0200 Subject: [PATCH 23/27] Recovered error when file to copy doesn't exist but still keeping dependency on Context out --- .../files/CopyRemoteFileOperation.java | 4 +++ .../files/ExistenceCheckRemoteOperation.java | 36 +++++++++---------- .../lib/test_project/test/CopyFileTest.java | 1 + 3 files changed, 22 insertions(+), 19 deletions(-) diff --git a/src/com/owncloud/android/lib/resources/files/CopyRemoteFileOperation.java b/src/com/owncloud/android/lib/resources/files/CopyRemoteFileOperation.java index f9f9d346..38bdcf5a 100644 --- a/src/com/owncloud/android/lib/resources/files/CopyRemoteFileOperation.java +++ b/src/com/owncloud/android/lib/resources/files/CopyRemoteFileOperation.java @@ -105,6 +105,10 @@ public class CopyRemoteFileOperation extends RemoteOperation { return new RemoteOperationResult(ResultCode.INVALID_COPY_INTO_DESCENDANT); } + if (!new ExistenceCheckRemoteOperation(mSrcRemotePath, Boolean.FALSE).run(getClient()).isSuccess()) { + return new RemoteOperationResult(ResultCode.FILE_NOT_FOUND); + } + /// perform remote operation CopyMethod copyMethod = null; RemoteOperationResult result = null; diff --git a/src/com/owncloud/android/lib/resources/files/ExistenceCheckRemoteOperation.java b/src/com/owncloud/android/lib/resources/files/ExistenceCheckRemoteOperation.java index 71a2e46f..e6a4b73c 100644 --- a/src/com/owncloud/android/lib/resources/files/ExistenceCheckRemoteOperation.java +++ b/src/com/owncloud/android/lib/resources/files/ExistenceCheckRemoteOperation.java @@ -28,7 +28,6 @@ import org.apache.commons.httpclient.HttpStatus; import org.apache.commons.httpclient.methods.HeadMethod; import android.content.Context; -import android.net.ConnectivityManager; import com.owncloud.android.lib.common.OwnCloudClient; import com.owncloud.android.lib.common.network.RedirectionPath; @@ -50,7 +49,6 @@ public class ExistenceCheckRemoteOperation extends RemoteOperation { private static final String TAG = ExistenceCheckRemoteOperation.class.getSimpleName(); private String mPath; - private Context mContext; private boolean mSuccessIfAbsent; /** Sequence of redirections followed. Available only after executing the operation */ @@ -59,24 +57,31 @@ public class ExistenceCheckRemoteOperation extends RemoteOperation { /** * Full constructor. Success of the operation will depend upon the value of successIfAbsent. - * - * @param remotePath Path to append to the URL owned by the client instance. - * @param context Android application context. + * + * @param remotePath Path to append to the URL owned by the client instance. * @param successIfAbsent When 'true', the operation finishes in success if the path does * NOT exist in the remote server (HTTP 404). */ - public ExistenceCheckRemoteOperation(String remotePath, Context context, boolean successIfAbsent) { + public ExistenceCheckRemoteOperation(String remotePath, boolean successIfAbsent) { mPath = (remotePath != null) ? remotePath : ""; - mContext = context; mSuccessIfAbsent = successIfAbsent; } - - @Override + /** + * Full constructor. Success of the operation will depend upon the value of successIfAbsent. + * + * @param remotePath Path to append to the URL owned by the client instance. + * @param context Android application context. + * @param successIfAbsent When 'true', the operation finishes in success if the path does + * NOT exist in the remote server (HTTP 404). + * @deprecated + */ + public ExistenceCheckRemoteOperation(String remotePath, Context context, boolean successIfAbsent) { + this(remotePath, successIfAbsent); + } + + @Override protected RemoteOperationResult run(OwnCloudClient client) { - if (!isOnline()) { - return new RemoteOperationResult(RemoteOperationResult.ResultCode.NO_NETWORK_CONNECTION); - } RemoteOperationResult result = null; HeadMethod head = null; boolean previousFollowRedirects = client.getFollowRedirects(); @@ -112,13 +117,6 @@ public class ExistenceCheckRemoteOperation extends RemoteOperation { return result; } - private boolean isOnline() { - ConnectivityManager cm = (ConnectivityManager) mContext - .getSystemService(Context.CONNECTIVITY_SERVICE); - return cm != null && cm.getActiveNetworkInfo() != null - && cm.getActiveNetworkInfo().isConnectedOrConnecting(); - } - /** * Gets the sequence of redirections followed during the execution of the operation. diff --git a/test_client/tests/src/com/owncloud/android/lib/test_project/test/CopyFileTest.java b/test_client/tests/src/com/owncloud/android/lib/test_project/test/CopyFileTest.java index 468d2de1..e7f84003 100644 --- a/test_client/tests/src/com/owncloud/android/lib/test_project/test/CopyFileTest.java +++ b/test_client/tests/src/com/owncloud/android/lib/test_project/test/CopyFileTest.java @@ -397,6 +397,7 @@ public class CopyFileTest extends ActivityInstrumentationTestCase2 // copy a folder into a descendant copyOperation = new CopyRemoteFileOperation( + getContext(), SRC_BASE_FOLDER, SRC_PATH_TO_EMPTY_FOLDER, false From b15fb19399270dab59251b4abb36037d2c435366 Mon Sep 17 00:00:00 2001 From: "David A. Velasco" Date: Tue, 18 Aug 2015 14:18:37 +0200 Subject: [PATCH 24/27] Fixed broken copy test --- .../com/owncloud/android/lib/test_project/test/CopyFileTest.java | 1 - 1 file changed, 1 deletion(-) diff --git a/test_client/tests/src/com/owncloud/android/lib/test_project/test/CopyFileTest.java b/test_client/tests/src/com/owncloud/android/lib/test_project/test/CopyFileTest.java index e7f84003..468d2de1 100644 --- a/test_client/tests/src/com/owncloud/android/lib/test_project/test/CopyFileTest.java +++ b/test_client/tests/src/com/owncloud/android/lib/test_project/test/CopyFileTest.java @@ -397,7 +397,6 @@ public class CopyFileTest extends ActivityInstrumentationTestCase2 // copy a folder into a descendant copyOperation = new CopyRemoteFileOperation( - getContext(), SRC_BASE_FOLDER, SRC_PATH_TO_EMPTY_FOLDER, false From 5ac5c808099e90b43c1c3343135e77bf07030e90 Mon Sep 17 00:00:00 2001 From: "David A. Velasco" Date: Tue, 18 Aug 2015 18:06:06 +0200 Subject: [PATCH 25/27] Return FILE_NOT_FOUND error only if the file is not found in the server, not in case of any other error checking its existence --- .../android/lib/resources/files/CopyRemoteFileOperation.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/com/owncloud/android/lib/resources/files/CopyRemoteFileOperation.java b/src/com/owncloud/android/lib/resources/files/CopyRemoteFileOperation.java index 38bdcf5a..dca36494 100644 --- a/src/com/owncloud/android/lib/resources/files/CopyRemoteFileOperation.java +++ b/src/com/owncloud/android/lib/resources/files/CopyRemoteFileOperation.java @@ -105,7 +105,7 @@ public class CopyRemoteFileOperation extends RemoteOperation { return new RemoteOperationResult(ResultCode.INVALID_COPY_INTO_DESCENDANT); } - if (!new ExistenceCheckRemoteOperation(mSrcRemotePath, Boolean.FALSE).run(getClient()).isSuccess()) { + if (new ExistenceCheckRemoteOperation(mSrcRemotePath, true).run(getClient()).isSuccess()) { return new RemoteOperationResult(ResultCode.FILE_NOT_FOUND); } From 27b0308e06184225d6cb7d8c0f8f8acdf51c20ff Mon Sep 17 00:00:00 2001 From: "David A. Velasco" Date: Tue, 1 Sep 2015 16:01:41 +0200 Subject: [PATCH 26/27] //This extra check is unnecessary after https://github.com/owncloud/core/pull/14505 --- .../android/lib/resources/files/CopyRemoteFileOperation.java | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/com/owncloud/android/lib/resources/files/CopyRemoteFileOperation.java b/src/com/owncloud/android/lib/resources/files/CopyRemoteFileOperation.java index dca36494..f9f9d346 100644 --- a/src/com/owncloud/android/lib/resources/files/CopyRemoteFileOperation.java +++ b/src/com/owncloud/android/lib/resources/files/CopyRemoteFileOperation.java @@ -105,10 +105,6 @@ public class CopyRemoteFileOperation extends RemoteOperation { return new RemoteOperationResult(ResultCode.INVALID_COPY_INTO_DESCENDANT); } - if (new ExistenceCheckRemoteOperation(mSrcRemotePath, true).run(getClient()).isSuccess()) { - return new RemoteOperationResult(ResultCode.FILE_NOT_FOUND); - } - /// perform remote operation CopyMethod copyMethod = null; RemoteOperationResult result = null; From ef07416c6a97d9f87c3952875b44f4d33c528253 Mon Sep 17 00:00:00 2001 From: root Date: Tue, 1 Sep 2015 15:29:50 +0000 Subject: [PATCH 27/27] Updated target server for automatic tests --- .travis.yml | 37 +++++++++++++++++++------------------ 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/.travis.yml b/.travis.yml index 2a46a99f..8ccad6c8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,26 +1,27 @@ language: android android: components: - - build-tools-22.0.1 - - android-19 + - build-tools-22.0.1 + - android-19 before_install: - - echo no | android create avd --force -n test -t $ANDROID_TARGET --abi $ANDROID_ABI -c 20M - - emulator -avd test -no-skin -no-audio -no-window & - - rm pom.xml - - android update project -p . - - chmod +x ./wait_for_emulator.sh - - ./wait_for_emulator.sh +- echo no | android create avd --force -n test -t $ANDROID_TARGET --abi $ANDROID_ABI + -c 20M +- emulator -avd test -no-skin -no-audio -no-window & +- rm pom.xml +- android update project -p . +- chmod +x ./wait_for_emulator.sh +- ./wait_for_emulator.sh script: - - ant clean - - ant debug - - cd test_client/tests - - ant acceptance-test - - cd ../.. - - ./gradlew clean build +- ant clean +- ant debug +- cd test_client/tests +- ant acceptance-test +- cd ../.. +- ./gradlew clean build env: global: - - secure: f4Kms/mzkYRG4Kp8k6hsvG3Y0ztbJnA2J79OBw3VdqJOKVTzwsxMd1Yh325YDYO7I4HeHxGXy0H4p3rAPzIWr/nrOJ4wmcDwQYDQtVjF7S1ARWsX51FrCEV6A9ec2LAqNCQ8ZC0SoGb+HsmpFCE3uKAxRQt+B5MzOZvKNcvYpMA= - - secure: aF4U20Xlu/rfrbxCmoJAiGh1doYTAZ10UEDmajuinT+ZGSJLivuqD7DDY/00sI6IXWg+J1vL+7jJm4JSYusHPg38UHZ4q92k6RmZycW2ATUzZnGT54O5FRnY67MfVwgVpIMK9UOL/6NEciBHEjlIOL0wbKQiJB++1YtBZOQLGL4= - - secure: N+ECSwNg8v2GsAFJ2y/tCiffauHDpN76zuFI2pDqf0fjmCtJZHu4BH5ArXBHjyHKmgn20a/8eZXcwJaH1HsJ80bo7vDJ2miShjGIQ90hPcdmUiB2XVJcew4f04CtvMDH5o7DRt4ykWArlbPL2rhVag0jotlSidolHBwRFnbDhDY= + - secure: HxHoqnC8mauCKi87zlo7pQcSsSw0W5MtW+iUcB8T11quwTBgUPWIOmycXv2FcmwpST0E43Ct+dhE+mttm+6P+5PSB33HQNLq00hfTVIJ4ttcb/5eWW8MnP7L+kPK8d0EtfDG6GQto7QktaybeG4+sNKKD336ZlFfM7xgPtPv+tg= + - secure: WQMw0ciloe8i2ApGhePhuTmmH8UgAV1Ri10C1qhUH9hVOJAr+/1X5A93VPYGrgJ2EH5MdiL6f2XMDCYAgb9efuvZIUKNE0J92xh8m/yRa8nAVWNBE0PBdS4+OycoHpIQfMcUghooERXjP4GUYd/ZwICvWA+sXdOYWDdKjODUgl4= + - secure: QPxKT8vC7sm1b/hYJcfkQkLgpwNRBvVKk8S8S0t43mmqPJfs94FJTQHH4kZaGSwOeuDkRQbGuKzYtXOnGOKX2hhUBqKJd1idpJnUID8id8Kqo6VutjG017+XxZQp0hPHmfmDxYkDvlaLeoZpP2NkpwZ1p4TL2MSCr2Ibl6uTWvc= matrix: - - ANDROID_TARGET=android-19 ANDROID_ABI=armeabi-v7a + - ANDROID_TARGET=android-19 ANDROID_ABI=armeabi-v7a