From eb7cac064f2747e18eb8f03ef8c62c8a5c5c316b Mon Sep 17 00:00:00 2001 From: davigonz Date: Tue, 28 Aug 2018 17:41:49 +0200 Subject: [PATCH] Prepare wrapper to handle response bodies after exceptions --- .../android/lib/common/OwnCloudClient.java | 10 ++-- .../lib/common/http/HttpConstants.java | 2 + .../common/http/methods/HttpBaseMethod.java | 43 +++++++++------ .../http/methods/webdav/CopyMethod.java | 47 +++++++++++----- .../common/http/methods/webdav/DavMethod.java | 36 +++++++++++-- .../http/methods/webdav/MkColMethod.java | 46 +++++++++++----- .../http/methods/webdav/MoveMethod.java | 54 +++++++++++++------ .../http/methods/webdav/PropfindMethod.java | 42 +++++++-------- .../common/http/methods/webdav/PutMethod.java | 29 ++++------ .../operations/RemoteOperationResult.java | 2 +- .../files/ExistenceCheckRemoteOperation.java | 4 +- 11 files changed, 202 insertions(+), 113 deletions(-) diff --git a/src/com/owncloud/android/lib/common/OwnCloudClient.java b/src/com/owncloud/android/lib/common/OwnCloudClient.java index 40a6daea..be4c808d 100644 --- a/src/com/owncloud/android/lib/common/OwnCloudClient.java +++ b/src/com/owncloud/android/lib/common/OwnCloudClient.java @@ -148,7 +148,7 @@ public class OwnCloudClient extends HttpClient { } private void checkFirstRedirection(HttpBaseMethod method) { - final String location = method.getResponseHeader("location"); + final String location = method.getResponseHeader(HttpConstants.LOCATION_HEADER_LOWER); if(location != null && !location.isEmpty()) { mRedirectedLocation = location; } @@ -182,9 +182,9 @@ public class OwnCloudClient extends HttpClient { status == HttpConstants.HTTP_TEMPORARY_REDIRECT) ) { - final String location = method.getResponseHeader("Location") != null - ? method.getResponseHeader("Location") - : method.getResponseHeader("location"); + final String location = method.getResponseHeader(HttpConstants.LOCATION_HEADER) != null + ? method.getResponseHeader(HttpConstants.LOCATION_HEADER) + : method.getResponseHeader(HttpConstants.LOCATION_HEADER_LOWER); if (location != null) { Log_OC.d(TAG + " #" + mInstanceNumber, @@ -458,7 +458,7 @@ public class OwnCloudClient extends HttpClient { mRedirectedLocation.toLowerCase().contains("wayf"))); } - public boolean isFollowRedirects() { + public boolean followRedirects() { return mFollowRedirects; } diff --git a/src/com/owncloud/android/lib/common/http/HttpConstants.java b/src/com/owncloud/android/lib/common/http/HttpConstants.java index 5ac09eea..3f3cbc3f 100644 --- a/src/com/owncloud/android/lib/common/http/HttpConstants.java +++ b/src/com/owncloud/android/lib/common/http/HttpConstants.java @@ -44,6 +44,8 @@ public class HttpConstants { public static final String OC_X_OC_MTIME_HEADER = "X-OC-Mtime"; public static final String PARAM_SINGLE_COOKIE_HEADER = "http.protocol.single-cookie-header"; public static final String OC_X_REQUEST_ID = "X-Request-ID"; + public static final String LOCATION_HEADER = "Location"; + public static final String LOCATION_HEADER_LOWER = "location"; /*********************************************************************************************************** ************************************************ STATUS CODES ********************************************* diff --git a/src/com/owncloud/android/lib/common/http/methods/HttpBaseMethod.java b/src/com/owncloud/android/lib/common/http/methods/HttpBaseMethod.java index 39c3d14e..08ee472b 100644 --- a/src/com/owncloud/android/lib/common/http/methods/HttpBaseMethod.java +++ b/src/com/owncloud/android/lib/common/http/methods/HttpBaseMethod.java @@ -41,8 +41,8 @@ import okhttp3.Response; /** * Wrapper to perform http calls transparently by using: - * - OkHttp for non webdav methods - * - Dav4Android for webdav methods + * - OkHttp for non webdav methods + * - Dav4Android for webdav methods * * @author David González Verdugo */ @@ -54,7 +54,7 @@ public abstract class HttpBaseMethod { protected Call mCall; protected URL mUrl; - protected HttpBaseMethod (URL url) { + protected HttpBaseMethod(URL url) { mOkHttpClient = HttpClient.getOkHttpClient(); mUrl = url; mRequest = new Request.Builder() @@ -84,7 +84,22 @@ public abstract class HttpBaseMethod { // Getter ////////////////////////////// + // Request + + public Headers getRequestHeaders() { + return mRequest.headers(); + } + + public String getRequestHeader(String name) { + return mRequest.header(name); + } + + public HttpUrl getUrl() { + return mRequest.url(); + } + // Response + public int getStatusCode() { return mResponse.code(); } @@ -109,28 +124,16 @@ public abstract class HttpBaseMethod { return mResponse.header(headerName); } - public HttpUrl getUrl() { - return mRequest.url(); - } - public boolean getRetryOnConnectionFailure() { return mOkHttpClient.retryOnConnectionFailure(); } - // Request - public String getRequestHeader(String name) { - return mRequest.header(name); - } - - public Headers getRequestHeaders() { - return mRequest.headers(); - } - ////////////////////////////// // Setter ////////////////////////////// // Connection parameters + public void setReadTimeout(long readTimeout, TimeUnit timeUnit) { mOkHttpClient = mOkHttpClient.newBuilder() .readTimeout(readTimeout, timeUnit) @@ -155,12 +158,20 @@ public abstract class HttpBaseMethod { .build(); } + // Request + public void addRequestHeader(String name, String value) { mRequest = mRequest.newBuilder() .addHeader(name, value) .build(); } + /** + * Sets a header and replace it if already exists with that name + * + * @param name header name + * @param value header value + */ public void setRequestHeader(String name, String value) { mRequest = mRequest.newBuilder() .header(name, value) diff --git a/src/com/owncloud/android/lib/common/http/methods/webdav/CopyMethod.java b/src/com/owncloud/android/lib/common/http/methods/webdav/CopyMethod.java index ea79deaf..6350ff82 100644 --- a/src/com/owncloud/android/lib/common/http/methods/webdav/CopyMethod.java +++ b/src/com/owncloud/android/lib/common/http/methods/webdav/CopyMethod.java @@ -1,13 +1,38 @@ +/* ownCloud Android Library is available under MIT license + * Copyright (C) 2018 ownCloud GmbH. + * + * 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.common.http.methods.webdav; import java.net.URL; -import at.bitfire.dav4android.exception.UnauthorizedException; import kotlin.Unit; -import kotlin.jvm.functions.Function1; -import okhttp3.HttpUrl; -import okhttp3.Response; +/** + * Copy calls wrapper + * @author Christian Schabesberger + * @author David González Verdugo + */ public class CopyMethod extends DavMethod { final String destinationUrl; @@ -21,15 +46,11 @@ public class CopyMethod extends DavMethod { @Override public int onExecute() throws Exception { - try { - mDavResource.copy(destinationUrl, forceOverride, response -> { - mResponse = response; - return Unit.INSTANCE; - }); + mDavResource.copy(destinationUrl, forceOverride, response -> { + mResponse = response; + return Unit.INSTANCE; + }); - } catch (UnauthorizedException davException) { - // Do nothing, we will use the 401 code to handle the situation - } return super.getStatusCode(); } -} +} \ No newline at end of file diff --git a/src/com/owncloud/android/lib/common/http/methods/webdav/DavMethod.java b/src/com/owncloud/android/lib/common/http/methods/webdav/DavMethod.java index 43b94d96..d9797bf6 100644 --- a/src/com/owncloud/android/lib/common/http/methods/webdav/DavMethod.java +++ b/src/com/owncloud/android/lib/common/http/methods/webdav/DavMethod.java @@ -24,6 +24,7 @@ package com.owncloud.android.lib.common.http.methods.webdav; +import com.owncloud.android.lib.common.http.HttpConstants; import com.owncloud.android.lib.common.http.methods.HttpBaseMethod; import java.net.URL; @@ -31,8 +32,12 @@ import java.util.concurrent.TimeUnit; import at.bitfire.dav4android.Constants; import at.bitfire.dav4android.DavOCResource; +import at.bitfire.dav4android.exception.HttpException; import at.bitfire.dav4android.exception.RedirectException; import okhttp3.HttpUrl; +import okhttp3.Protocol; +import okhttp3.Response; +import okhttp3.ResponseBody; /** * Wrapper to perform WebDAV (dav4android) calls @@ -59,13 +64,36 @@ public abstract class DavMethod extends HttpBaseMethod { public int execute() throws Exception { try { return onExecute(); - } catch (RedirectException e) { - return getStatusCode(); + } catch (HttpException httpException) { + // Modify responses with information gathered from exceptions + if (httpException instanceof RedirectException) { + mResponse = new Response.Builder() + .header( + HttpConstants.LOCATION_HEADER, ((RedirectException) httpException).getRedirectLocation() + ) + .code(httpException.getCode()) + .request(mRequest) + .message(httpException.getMessage()) + .protocol(Protocol.HTTP_1_1) + .build(); + + } else if (mResponse != null) { + ResponseBody responseBody = ResponseBody.create( + mResponse.body().contentType(), + httpException.getResponseBody() + ); + + mResponse = mResponse.newBuilder() + .body(responseBody) + .build(); + } + + return httpException.getCode(); } } ////////////////////////////// - // setter + // Setter ////////////////////////////// // Connection parameters @@ -106,7 +134,7 @@ public abstract class DavMethod extends HttpBaseMethod { } ////////////////////////////// - // getter + // Getter ////////////////////////////// @Override diff --git a/src/com/owncloud/android/lib/common/http/methods/webdav/MkColMethod.java b/src/com/owncloud/android/lib/common/http/methods/webdav/MkColMethod.java index 54a51763..4bafc0aa 100644 --- a/src/com/owncloud/android/lib/common/http/methods/webdav/MkColMethod.java +++ b/src/com/owncloud/android/lib/common/http/methods/webdav/MkColMethod.java @@ -1,12 +1,38 @@ +/* ownCloud Android Library is available under MIT license + * Copyright (C) 2018 ownCloud GmbH. + * + * 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.common.http.methods.webdav; import java.net.URL; -import at.bitfire.dav4android.exception.UnauthorizedException; import kotlin.Unit; -import kotlin.jvm.functions.Function1; -import okhttp3.Response; +/** + * MkCol calls wrapper + * @author Christian Schabesberger + * @author David González Verdugo + */ public class MkColMethod extends DavMethod { public MkColMethod(URL url) { super(url); @@ -14,15 +40,11 @@ public class MkColMethod extends DavMethod { @Override public int onExecute() throws Exception { - try { - mDavResource.mkCol(null, response -> { - mResponse = response; - return Unit.INSTANCE; - }); + mDavResource.mkCol(null, response -> { + mResponse = response; + return Unit.INSTANCE; + }); - } catch (UnauthorizedException davException) { - // Do nothing, we will use the 401 code to handle the situation - } return super.getStatusCode(); } -} +} \ No newline at end of file diff --git a/src/com/owncloud/android/lib/common/http/methods/webdav/MoveMethod.java b/src/com/owncloud/android/lib/common/http/methods/webdav/MoveMethod.java index 9004f8a1..27a2c918 100644 --- a/src/com/owncloud/android/lib/common/http/methods/webdav/MoveMethod.java +++ b/src/com/owncloud/android/lib/common/http/methods/webdav/MoveMethod.java @@ -1,14 +1,40 @@ +/* ownCloud Android Library is available under MIT license + * Copyright (C) 2018 ownCloud GmbH. + * + * 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.common.http.methods.webdav; import com.owncloud.android.lib.common.http.HttpConstants; import java.net.URL; -import at.bitfire.dav4android.exception.UnauthorizedException; import kotlin.Unit; -import kotlin.jvm.functions.Function1; -import okhttp3.Response; +/** + * Move calls wrapper + * @author Christian Schabesberger + * @author David González Verdugo + */ public class MoveMethod extends DavMethod { final String destinationUrl; final boolean forceOverride; @@ -21,19 +47,15 @@ public class MoveMethod extends DavMethod { @Override public int onExecute() throws Exception { - try { - mDavResource.move( - destinationUrl, - forceOverride, - super.getRequestHeader(HttpConstants.OC_TOTAL_LENGTH_HEADER), - super.getRequestHeader(HttpConstants.OC_X_OC_MTIME_HEADER), response -> { - mResponse = response; - return Unit.INSTANCE; - }); + mDavResource.move( + destinationUrl, + forceOverride, + super.getRequestHeader(HttpConstants.OC_TOTAL_LENGTH_HEADER), + super.getRequestHeader(HttpConstants.OC_X_OC_MTIME_HEADER), response -> { + mResponse = response; + return Unit.INSTANCE; + }); - } catch (UnauthorizedException davException) { - // Do nothing, we will use the 401 code to handle the situation - } return super.getStatusCode(); } -} +} \ No newline at end of file diff --git a/src/com/owncloud/android/lib/common/http/methods/webdav/PropfindMethod.java b/src/com/owncloud/android/lib/common/http/methods/webdav/PropfindMethod.java index fd4590b0..31ce12c4 100644 --- a/src/com/owncloud/android/lib/common/http/methods/webdav/PropfindMethod.java +++ b/src/com/owncloud/android/lib/common/http/methods/webdav/PropfindMethod.java @@ -32,7 +32,6 @@ import java.util.List; import at.bitfire.dav4android.Property; import at.bitfire.dav4android.Response; import at.bitfire.dav4android.exception.DavException; -import at.bitfire.dav4android.exception.UnauthorizedException; import kotlin.Unit; /** @@ -58,29 +57,24 @@ public class PropfindMethod extends DavMethod { } @Override - public int onExecute() throws IOException, DavException { - try { - mDavResource.propfind(mDepth, mPropertiesToRequest, - (Response response, Response.HrefRelation hrefRelation) -> { - switch (hrefRelation) { - case MEMBER: - mMembers.add(response); - break; - case SELF: - mRoot = response; - break; - case OTHER: - default: - } - return Unit.INSTANCE; - }, response -> { - mResponse = response; - return Unit.INSTANCE; - }); - } catch (UnauthorizedException davException) { - // Do nothing, we will use the 401 code to handle the situation - return davException.getCode(); - } + public int onExecute() throws IOException, DavException{ + mDavResource.propfind(mDepth, mPropertiesToRequest, + (Response response, Response.HrefRelation hrefRelation) -> { + switch (hrefRelation) { + case MEMBER: + mMembers.add(response); + break; + case SELF: + mRoot = response; + break; + case OTHER: + default: + } + return Unit.INSTANCE; + }, response -> { + mResponse = response; + return Unit.INSTANCE; + }); return getStatusCode(); } diff --git a/src/com/owncloud/android/lib/common/http/methods/webdav/PutMethod.java b/src/com/owncloud/android/lib/common/http/methods/webdav/PutMethod.java index 9de2f324..f5b889df 100644 --- a/src/com/owncloud/android/lib/common/http/methods/webdav/PutMethod.java +++ b/src/com/owncloud/android/lib/common/http/methods/webdav/PutMethod.java @@ -29,14 +29,8 @@ import com.owncloud.android.lib.common.http.HttpConstants; import java.io.IOException; import java.net.URL; -import at.bitfire.dav4android.exception.DavException; import at.bitfire.dav4android.exception.HttpException; -import at.bitfire.dav4android.exception.UnauthorizedException; import kotlin.Unit; -import kotlin.jvm.functions.Function1; -import okhttp3.HttpUrl; -import okhttp3.RequestBody; -import okhttp3.Response; /** * Put calls wrapper @@ -50,20 +44,15 @@ public class PutMethod extends DavMethod { @Override public int onExecute() throws IOException, HttpException { - try { - mDavResource.put( - mRequestBody, - super.getRequestHeader(HttpConstants.IF_MATCH_HEADER), - super.getRequestHeader(HttpConstants.CONTENT_TYPE_HEADER), - super.getRequestHeader(HttpConstants.OC_TOTAL_LENGTH_HEADER), - super.getRequestHeader(HttpConstants.OC_X_OC_MTIME_HEADER), response -> { - mResponse = response; - return Unit.INSTANCE; - }); - - } catch (UnauthorizedException davException) { - // Do nothing, we will use the 401 code to handle the situation - } + mDavResource.put( + mRequestBody, + super.getRequestHeader(HttpConstants.IF_MATCH_HEADER), + super.getRequestHeader(HttpConstants.CONTENT_TYPE_HEADER), + super.getRequestHeader(HttpConstants.OC_TOTAL_LENGTH_HEADER), + super.getRequestHeader(HttpConstants.OC_X_OC_MTIME_HEADER), response -> { + mResponse = response; + return Unit.INSTANCE; + }); return super.getStatusCode(); } diff --git a/src/com/owncloud/android/lib/common/operations/RemoteOperationResult.java b/src/com/owncloud/android/lib/common/operations/RemoteOperationResult.java index 03e5028d..6c233512 100644 --- a/src/com/owncloud/android/lib/common/operations/RemoteOperationResult.java +++ b/src/com/owncloud/android/lib/common/operations/RemoteOperationResult.java @@ -577,4 +577,4 @@ public class RemoteOperationResult public T getData() { return mData; } -} +} \ No newline at end of file diff --git a/src/com/owncloud/android/lib/resources/files/ExistenceCheckRemoteOperation.java b/src/com/owncloud/android/lib/resources/files/ExistenceCheckRemoteOperation.java index 67d7c61e..b62eb47b 100644 --- a/src/com/owncloud/android/lib/resources/files/ExistenceCheckRemoteOperation.java +++ b/src/com/owncloud/android/lib/resources/files/ExistenceCheckRemoteOperation.java @@ -82,8 +82,8 @@ public class ExistenceCheckRemoteOperation extends RemoteOperation { PropfindMethod propfindMethod = new PropfindMethod( new URL(client.getNewFilesWebDavUri() + WebdavUtils.encodePath(mPath)), 0, - DavUtils.getAllPropset()); - + DavUtils.getAllPropset() + ); propfindMethod.setReadTimeout(TIMEOUT, TimeUnit.SECONDS); propfindMethod.setConnectionTimeout(TIMEOUT, TimeUnit.SECONDS);