1
0
mirror of https://github.com/owncloud/android-library.git synced 2025-06-07 16:06:08 +00:00

Update GetRemoteUserQuotaOperation to use the recent wrapper with propfind

This commit is contained in:
davigonz 2018-06-12 12:19:38 +02:00
parent 1631b9b55a
commit a0478826b4
7 changed files with 138 additions and 95 deletions

View File

@ -24,6 +24,9 @@
package com.owncloud.android.lib.common.http; package com.owncloud.android.lib.common.http;
/**
* @author David González Verdugo
*/
public class HttpConstants { public class HttpConstants {
/** /**

View File

@ -0,0 +1,33 @@
/* 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;
/**
* @author David González Verdugo
*/
public class DavConstants {
public static final int DEPTH_0 = 0;
public static final int DEPTH_1 = 1;
}

View File

@ -0,0 +1,15 @@
package com.owncloud.android.lib.common.http.methods.webdav;
import at.bitfire.dav4android.Property;
import at.bitfire.dav4android.PropertyUtils;
public class DavUtils {
public static final Property.Name[] getAllPropset() {
return PropertyUtils.INSTANCE.getAllPropSet();
}
public static final Property.Name[] getQuotaPropSet() {
return PropertyUtils.INSTANCE.getQuotaPropset();
}
}

View File

@ -28,7 +28,7 @@ import java.io.IOException;
import java.util.Set; import java.util.Set;
import at.bitfire.dav4android.DavResource; import at.bitfire.dav4android.DavResource;
import at.bitfire.dav4android.PropertyUtils; import at.bitfire.dav4android.Property;
import at.bitfire.dav4android.exception.DavException; import at.bitfire.dav4android.exception.DavException;
import at.bitfire.dav4android.exception.HttpException; import at.bitfire.dav4android.exception.HttpException;
import at.bitfire.dav4android.exception.UnauthorizedException; import at.bitfire.dav4android.exception.UnauthorizedException;
@ -41,17 +41,19 @@ import okhttp3.HttpUrl;
public class PropfindMethod extends DavMethod { public class PropfindMethod extends DavMethod {
private int mDepth; private int mDepth;
private Property.Name[] mProperties;
private Set<DavResource> mMembers; private Set<DavResource> mMembers;
public PropfindMethod(HttpUrl httpUrl, int depth) { public PropfindMethod(HttpUrl httpUrl, int depth, Property.Name[] properties) {
super(httpUrl); super(httpUrl);
mDepth = depth; mDepth = depth;
mProperties = properties;
}; };
@Override @Override
public int execute() throws IOException, HttpException, DavException { public int execute() throws IOException, HttpException, DavException {
try { try {
mDavResource.propfind(mDepth, PropertyUtils.INSTANCE.getAllPropSet()); mDavResource.propfind(mDepth, mProperties);
mMembers = mDavResource.getMembers(); mMembers = mDavResource.getMembers();
} catch (UnauthorizedException davException) { } catch (UnauthorizedException davException) {
// Do nothing, we will use the 401 code to handle the situation // Do nothing, we will use the 401 code to handle the situation

View File

@ -1,22 +1,22 @@
/* ownCloud Android Library is available under MIT license /* ownCloud Android Library is available under MIT license
* Copyright (C) 2016 ownCloud GmbH. * Copyright (C) 2016 ownCloud GmbH.
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights * in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is * copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions: * furnished to do so, subject to the following conditions:
* *
* The above copyright notice and this permission notice shall be included in * The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software. * all copies or substantial portions of the Software.
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE. * THE SOFTWARE.
* *
@ -27,6 +27,7 @@ package com.owncloud.android.lib.resources.files;
import com.owncloud.android.lib.common.OwnCloudClient; import com.owncloud.android.lib.common.OwnCloudClient;
import com.owncloud.android.lib.common.http.HttpConstants; import com.owncloud.android.lib.common.http.HttpConstants;
import com.owncloud.android.lib.common.http.HttpUtils; import com.owncloud.android.lib.common.http.HttpUtils;
import com.owncloud.android.lib.common.http.methods.webdav.DavUtils;
import com.owncloud.android.lib.common.http.methods.webdav.PropfindMethod; import com.owncloud.android.lib.common.http.methods.webdav.PropfindMethod;
import com.owncloud.android.lib.common.network.RedirectionPath; import com.owncloud.android.lib.common.network.RedirectionPath;
import com.owncloud.android.lib.common.network.WebdavUtils; import com.owncloud.android.lib.common.network.WebdavUtils;
@ -34,37 +35,40 @@ import com.owncloud.android.lib.common.operations.RemoteOperation;
import com.owncloud.android.lib.common.operations.RemoteOperationResult; import com.owncloud.android.lib.common.operations.RemoteOperationResult;
import com.owncloud.android.lib.common.utils.Log_OC; import com.owncloud.android.lib.common.utils.Log_OC;
import okhttp3.HttpUrl;
import static com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode.OK; import static com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode.OK;
/** /**
* Operation to check the existence or absence of a path in a remote server. * Operation to check the existence or absence of a path in a remote server.
* *
* @author David A. Velasco * @author David A. Velasco
* @author David GonzálezVerdugo * @author David GonzálezVerdugo
*/ */
public class ExistenceCheckRemoteOperation extends RemoteOperation { public class ExistenceCheckRemoteOperation extends RemoteOperation {
/** Maximum time to wait for a response from the server in MILLISECONDs. */ /**
* Maximum time to wait for a response from the server in MILLISECONDs.
*/
public static final int TIMEOUT = 10000; public static final int TIMEOUT = 10000;
private static final String TAG = ExistenceCheckRemoteOperation.class.getSimpleName(); private static final String TAG = ExistenceCheckRemoteOperation.class.getSimpleName();
private static final int FORBIDDEN_ERROR = 403; private static final int FORBIDDEN_ERROR = 403;
private static final int SERVICE_UNAVAILABLE_ERROR = 503; private static final int SERVICE_UNAVAILABLE_ERROR = 503;
private String mPath; private String mPath;
private boolean mSuccessIfAbsent; private boolean mSuccessIfAbsent;
/** Sequence of redirections followed. Available only after executing the operation */ /**
* Sequence of redirections followed. Available only after executing the operation
*/
private RedirectionPath mRedirectionPath = null; private RedirectionPath mRedirectionPath = null;
/** /**
* Full constructor. Success of the operation will depend upon the value of successIfAbsent. * 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 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 * @param successIfAbsent When 'true', the operation finishes in success if the path does
* NOT exist in the remote server (HTTP 404). * NOT exist in the remote server (HTTP 404).
*/ */
public ExistenceCheckRemoteOperation(String remotePath, boolean successIfAbsent) { public ExistenceCheckRemoteOperation(String remotePath, boolean successIfAbsent) {
mPath = (remotePath != null) ? remotePath : ""; mPath = (remotePath != null) ? remotePath : "";
@ -72,7 +76,7 @@ public class ExistenceCheckRemoteOperation extends RemoteOperation {
} }
@Override @Override
protected RemoteOperationResult run(OwnCloudClient client) { protected RemoteOperationResult run(OwnCloudClient client) {
RemoteOperationResult result; RemoteOperationResult result;
// TODO Complete redirection stuff, although OkHttp should follow redirections by default // TODO Complete redirection stuff, although OkHttp should follow redirections by default
@ -83,7 +87,8 @@ public class ExistenceCheckRemoteOperation extends RemoteOperation {
// client.setFollowRedirects(false); // client.setFollowRedirects(false);
PropfindMethod propfindMethod = new PropfindMethod( PropfindMethod propfindMethod = new PropfindMethod(
HttpUtils.stringUrlToHttpUrl(client.getNewWebDavUri() + WebdavUtils.encodePath(mPath)), HttpUtils.stringUrlToHttpUrl(client.getNewWebDavUri() + WebdavUtils.encodePath(mPath)),
0); 0,
DavUtils.getAllPropset());
int status = client.executeHttpMethod(propfindMethod); int status = client.executeHttpMethod(propfindMethod);
@ -108,32 +113,32 @@ public class ExistenceCheckRemoteOperation extends RemoteOperation {
Log_OC.d(TAG, "Existence check for " + client.getWebdavUri() + Log_OC.d(TAG, "Existence check for " + client.getWebdavUri() +
WebdavUtils.encodePath(mPath) + " targeting for " + WebdavUtils.encodePath(mPath) + " targeting for " +
(mSuccessIfAbsent ? " absence " : " existence ") + (mSuccessIfAbsent ? " absence " : " existence ") +
"finished with HTTP status " + status + (!isSuccess(status)?"(FAIL)":"")); "finished with HTTP status " + status + (!isSuccess(status) ? "(FAIL)" : ""));
} catch (Exception e) { } catch (Exception e) {
result = new RemoteOperationResult(e); result = new RemoteOperationResult(e);
Log_OC.e(TAG, "Existence check for " + client.getWebdavUri() + Log_OC.e(TAG, "Existence check for " + client.getWebdavUri() +
WebdavUtils.encodePath(mPath) + " targeting for " + WebdavUtils.encodePath(mPath) + " targeting for " +
(mSuccessIfAbsent ? " absence " : " existence ") + ": " + (mSuccessIfAbsent ? " absence " : " existence ") + ": " +
result.getLogMessage(), result.getException()); result.getLogMessage(), result.getException());
} finally { } finally {
// client.setFollowRedirects(previousFollowRedirects); // client.setFollowRedirects(previousFollowRedirects);
} }
return result; return result;
} }
/** /**
* Gets the sequence of redirections followed during the execution of the operation. * Gets the sequence of redirections followed during the execution of the operation.
* *
* @return Sequence of redirections followed, if any, or NULL if the operation was not executed. * @return Sequence of redirections followed, if any, or NULL if the operation was not executed.
*/ */
public RedirectionPath getRedirectionPath() { public RedirectionPath getRedirectionPath() {
return mRedirectionPath; return mRedirectionPath;
} }
/** /**
* @return 'True' if the operation was executed and at least one redirection was followed. * @return 'True' if the operation was executed and at least one redirection was followed.
*/ */
public boolean wasRedirected() { public boolean wasRedirected() {
return (mRedirectionPath != null && mRedirectionPath.getRedirectionsCount() > 0); return (mRedirectionPath != null && mRedirectionPath.getRedirectionsCount() > 0);

View File

@ -26,6 +26,9 @@ package com.owncloud.android.lib.resources.files;
import com.owncloud.android.lib.common.OwnCloudClient; import com.owncloud.android.lib.common.OwnCloudClient;
import com.owncloud.android.lib.common.http.HttpConstants; import com.owncloud.android.lib.common.http.HttpConstants;
import com.owncloud.android.lib.common.http.HttpUtils;
import com.owncloud.android.lib.common.http.methods.webdav.DavConstants;
import com.owncloud.android.lib.common.http.methods.webdav.DavUtils;
import com.owncloud.android.lib.common.http.methods.webdav.PropfindMethod; import com.owncloud.android.lib.common.http.methods.webdav.PropfindMethod;
import com.owncloud.android.lib.common.network.WebdavUtils; import com.owncloud.android.lib.common.network.WebdavUtils;
import com.owncloud.android.lib.common.operations.RemoteOperation; import com.owncloud.android.lib.common.operations.RemoteOperation;
@ -35,7 +38,6 @@ import com.owncloud.android.lib.common.utils.Log_OC;
import java.util.ArrayList; import java.util.ArrayList;
import at.bitfire.dav4android.DavResource; import at.bitfire.dav4android.DavResource;
import okhttp3.HttpUrl;
import static com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode.OK; import static com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode.OK;
@ -72,15 +74,14 @@ public class ReadRemoteFolderOperation extends RemoteOperation {
RemoteOperationResult result = null; RemoteOperationResult result = null;
try { try {
PropfindMethod propfindMethod = new PropfindMethod( PropfindMethod propfindMethod = new PropfindMethod(
HttpUrl.parse(client.getNewWebDavUri() + WebdavUtils.encodePath(mRemotePath)), HttpUtils.stringUrlToHttpUrl(client.getNewWebDavUri() + WebdavUtils.encodePath(mRemotePath)),
1); DavConstants.DEPTH_1,
DavUtils.getAllPropset());
int status = client.executeHttpMethod(propfindMethod); int status = client.executeHttpMethod(propfindMethod);
if (isSuccess(status)) { if (isSuccess(status)) {
ArrayList<Object> mFolderAndFiles = new ArrayList<>(); ArrayList<Object> mFolderAndFiles = new ArrayList<>();
// parse data from remote folder // parse data from remote folder

View File

@ -28,42 +28,36 @@
package com.owncloud.android.lib.resources.users; package com.owncloud.android.lib.resources.users;
import com.owncloud.android.lib.common.OwnCloudClient; import com.owncloud.android.lib.common.OwnCloudClient;
import com.owncloud.android.lib.common.network.WebdavEntry; import com.owncloud.android.lib.common.http.HttpConstants;
import com.owncloud.android.lib.common.http.HttpUtils;
import com.owncloud.android.lib.common.http.methods.webdav.DavUtils;
import com.owncloud.android.lib.common.http.methods.webdav.PropfindMethod;
import com.owncloud.android.lib.common.network.WebdavUtils; import com.owncloud.android.lib.common.network.WebdavUtils;
import com.owncloud.android.lib.common.operations.RemoteOperation; import com.owncloud.android.lib.common.operations.RemoteOperation;
import com.owncloud.android.lib.common.operations.RemoteOperationResult; import com.owncloud.android.lib.common.operations.RemoteOperationResult;
import com.owncloud.android.lib.common.utils.Log_OC; import com.owncloud.android.lib.common.utils.Log_OC;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.jackrabbit.webdav.DavConstants;
import org.apache.jackrabbit.webdav.MultiStatus;
import org.apache.jackrabbit.webdav.client.methods.PropFindMethod;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList; import java.util.ArrayList;
import at.bitfire.dav4android.PropertyCollection;
import at.bitfire.dav4android.property.QuotaAvailableBytes;
import at.bitfire.dav4android.property.QuotaUsedBytes;
import static com.owncloud.android.lib.common.http.methods.webdav.DavConstants.DEPTH_0;
import static com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode.OK;
/** /**
* @author marcello * @author marcello
* @author David González Verdugo * @author David González Verdugo
*/ */
public class GetRemoteUserQuotaOperation extends RemoteOperation { public class GetRemoteUserQuotaOperation extends RemoteOperation {
static public class Quota { static public class RemoteQuota {
// Not computed yet, e.g. external storage mounted but folder sizes need scanning
public static final int PENDING_FREE_QUOTA = -1;
// Storage not accessible, e.g. external storage with no API to ask for the free space
public static final int UNKNOWN_FREE_QUOTA = -2;
// Quota using all the storage
public static final int UNLIMITED_FREE_QUOTA = -3;
long mFree, mUsed, mTotal; long mFree, mUsed, mTotal;
double mRelative; double mRelative;
public Quota(long free, long used, long total, double relative) { public RemoteQuota(long free, long used, long total, double relative) {
mFree = free; mFree = free;
mUsed = used; mUsed = used;
mTotal = total; mTotal = total;
@ -92,34 +86,31 @@ public class GetRemoteUserQuotaOperation extends RemoteOperation {
@Override @Override
protected RemoteOperationResult run(OwnCloudClient client) { protected RemoteOperationResult run(OwnCloudClient client) {
RemoteOperationResult result = null; RemoteOperationResult result = null;
PropFindMethod query = null;
try { try {
// remote request PropfindMethod propfindMethod = new PropfindMethod(
query = new PropFindMethod(client.getWebdavUri() + WebdavUtils.encodePath(mRemotePath), HttpUtils.stringUrlToHttpUrl(client.getNewWebDavUri() + WebdavUtils.encodePath(mRemotePath)),
WebdavUtils.getQuotaPropSet(), DEPTH_0,
DavConstants.DEPTH_0); DavUtils.getQuotaPropSet()
);
int status = client.executeMethod(query); int status = client.executeHttpMethod(propfindMethod);
if (isSuccess(status)) { if (isSuccess(status)) {
// get data from remote folder RemoteQuota remoteQuota = readData(propfindMethod.getDavResource().getProperties());
MultiStatus dataInServer = query.getResponseBodyAsMultiStatus();
Quota quota = readData(dataInServer, client);
// Result of the operation result = new RemoteOperationResult(OK);
result = new RemoteOperationResult(true, query);
ArrayList<Object> data = new ArrayList<>(); ArrayList<Object> data = new ArrayList<>();
data.add(quota); data.add(remoteQuota);
// Add data to the result // Add data to the result
if (result.isSuccess()) { if (result.isSuccess()) {
result.setData(data); result.setData(data);
} }
} else {
// synchronization failed } else { // synchronization failed
result = new RemoteOperationResult(false, query); result = new RemoteOperationResult(propfindMethod);
} }
} catch (Exception e) { } catch (Exception e) {
@ -127,8 +118,6 @@ public class GetRemoteUserQuotaOperation extends RemoteOperation {
} finally { } finally {
if (query != null)
query.releaseConnection(); // let the connection available for other methods
if (result.isSuccess()) { if (result.isSuccess()) {
Log_OC.i(TAG, "Get quota from " + mRemotePath + ": " + result.getLogMessage()); Log_OC.i(TAG, "Get quota from " + mRemotePath + ": " + result.getLogMessage());
} else { } else {
@ -145,46 +134,41 @@ public class GetRemoteUserQuotaOperation extends RemoteOperation {
} }
private boolean isSuccess(int status) { private boolean isSuccess(int status) {
return status == HttpStatus.SC_MULTI_STATUS || status == HttpStatus.SC_OK; return status == HttpConstants.HTTP_MULTI_STATUS || status == HttpConstants.HTTP_OK;
} }
/** /**
* Read the data retrieved from the server about the quota * Read the data retrieved from the server about the quota
* *
* @param remoteData Full response got from the server with the data of the quota * @param properties WebDAV properties containing quota data
* @param client Client instance to the remote server where the data were retrieved * @return new {@link RemoteQuota} instance representing the data read from the server
* @return new Quota instance representing the data read from the server
*/ */
private Quota readData(MultiStatus remoteData, OwnCloudClient client) { private RemoteQuota readData(PropertyCollection properties) {
// parse data from remote folder long quotaAvailable = properties.get(QuotaAvailableBytes.class).getQuotaAvailableBytes();
WebdavEntry we = new WebdavEntry(remoteData.getResponses()[0], client.getWebdavUri().getPath()); long quotaUsed = properties.get(QuotaUsedBytes.class).getQuotaUsedBytes();
// If there's a special case, available bytes will contain a negative code // If there's a special case, quota available will contain a negative code
// -1, PENDING: Not computed yet, e.g. external storage mounted but folder sizes need scanning // -1, PENDING: Not computed yet, e.g. external storage mounted but folder sizes need scanning
// -2, UNKNOWN: Storage not accessible, e.g. external storage with no API to ask for the free space // -2, UNKNOWN: Storage not accessible, e.g. external storage with no API to ask for the free space
// -3, UNLIMITED: Quota using all the storage // -3, UNLIMITED: Quota using all the storage
if (we.quotaAvailableBytes().compareTo(new BigDecimal(1)) == -1) { if (quotaAvailable < 0) {
return new Quota( return new RemoteQuota(
we.quotaAvailableBytes().longValue(), quotaAvailable,
we.quotaUsedBytes().longValue(), quotaUsed,
0, 0,
0 0
); );
} else { } else {
long totalQuota = quotaAvailable + quotaUsed;
double relativeQuota = (double)(quotaUsed * 100)/totalQuota;
double roundedRelativeQuota = Math.round(relativeQuota * 100)/100.0d;
BigDecimal totalQuota = we.quotaAvailableBytes().add(we.quotaUsedBytes()); return new RemoteQuota(
quotaAvailable,
BigDecimal relativeQuota = we.quotaUsedBytes() quotaUsed,
.multiply(new BigDecimal(100)) totalQuota,
.divide(totalQuota, 2, RoundingMode.HALF_UP); roundedRelativeQuota
return new Quota(
we.quotaAvailableBytes().longValue(),
we.quotaUsedBytes().longValue(),
totalQuota.longValue(),
relativeQuota.doubleValue()
); );
} }
} }