Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 41dcc337 authored by David A. Velasco's avatar David A. Velasco
Browse files

Get that ExistenceCheckRemoteOperation remembers the sequence of followed...

Get that ExistenceCheckRemoteOperation remembers the sequence of followed redirections after its execution

Conflicts fixed:
	src/com/owncloud/android/lib/common/operations/RemoteOperationResult.java
	src/com/owncloud/android/lib/resources/files/RenameRemoteFileOperation.java
parent e48aa9c3
Loading
Loading
Loading
Loading
+45 −40
Original line number Diff line number Diff line
@@ -49,13 +49,14 @@ import android.net.Uri;

import com.owncloud.android.lib.common.OwnCloudCredentialsFactory.OwnCloudAnonymousCredentials;
import com.owncloud.android.lib.common.accounts.AccountUtils;
import com.owncloud.android.lib.common.network.RedirectionPath;
import com.owncloud.android.lib.common.network.WebdavUtils;
import com.owncloud.android.lib.common.utils.Log_OC;

public class OwnCloudClient extends HttpClient {
	
    private static final String TAG = OwnCloudClient.class.getSimpleName();
    private static final int MAX_REDIRECTIONS_COUNT = 3;
    public static final int MAX_REDIRECTIONS_COUNT = 3;
    private static final String PARAM_SINGLE_COOKIE_HEADER = "http.protocol.single-cookie-header";
    private static final boolean PARAM_SINGLE_COOKIE_HEADER_VALUE = true;
    
@@ -173,8 +174,8 @@ public class OwnCloudClient extends HttpClient {
     * @param readTimeout           Timeout to set for data reception
     * @param connectionTimeout     Timeout to set for connection establishment
     */
    public int executeMethod(HttpMethodBase method, int readTimeout, int connectionTimeout) 
    		throws HttpException, IOException {
    public int executeMethod(HttpMethodBase method, int readTimeout, int connectionTimeout) throws IOException {

        int oldSoTimeout = getParams().getSoTimeout();
        int oldConnectionTimeout = getHttpConnectionManager().getParams().getConnectionTimeout();
        try {
@@ -193,22 +194,16 @@ public class OwnCloudClient extends HttpClient {
    }


    /**
     * Requests the received method.
     *
     * Executes the method through the inherited HttpClient.executedMethod(method).
     *
     * @param method                HTTP method request.
     */
    @Override
    public int executeMethod(HttpMethod method) throws IOException, HttpException {
        try {	// just to log 
	        boolean customRedirectionNeeded = false;
	        
    public int executeMethod(HttpMethod method) throws IOException {
        try {
	            method.setFollowRedirects(mFollowRedirects);
	        } catch (Exception e) {
	        	/*
	            if (mFollowRedirects) 
	        		Log_OC.d(TAG, "setFollowRedirects failed for " + method.getName() 
	        			+ " method, custom redirection will be used if needed");
        		*/
	            customRedirectionNeeded = mFollowRedirects;
	        }

            // Update User Agent
            HttpParams params = method.getParams();
            String userAgent = OwnCloudClientManagerFactory.getUserAgent();
@@ -219,11 +214,12 @@ public class OwnCloudClient extends HttpClient {

//	        logCookiesAtRequest(method.getRequestHeaders(), "before");
//	        logCookiesAtState("before");
            method.setFollowRedirects(false);

            int status = super.executeMethod(method);

	        if (customRedirectionNeeded) {
	        	status = patchRedirection(status, method);
            if (mFollowRedirects) {
                status = followRedirection(method).getLastStatus();
            }

//	        logCookiesAtRequest(method.getRequestHeaders(), "after");
@@ -233,13 +229,16 @@ public class OwnCloudClient extends HttpClient {
            return status;

        } catch (IOException e) {
        	Log_OC.d(TAG + " #" + mInstanceNumber, "Exception occurred", e);
            //Log_OC.d(TAG + " #" + mInstanceNumber, "Exception occurred", e);
            throw e;
        }
    }

	private int patchRedirection(int status, HttpMethod method) throws HttpException, IOException {

	public RedirectionPath followRedirection(HttpMethod method) throws IOException {
        int redirectionsCount = 0;
        int status = method.getStatusCode();
        RedirectionPath result = new RedirectionPath(status, MAX_REDIRECTIONS_COUNT);
        while (redirectionsCount < MAX_REDIRECTIONS_COUNT &&
                (   status == HttpStatus.SC_MOVED_PERMANENTLY || 
                    status == HttpStatus.SC_MOVED_TEMPORARILY ||
@@ -254,18 +253,20 @@ public class OwnCloudClient extends HttpClient {
                Log_OC.d(TAG + " #" + mInstanceNumber,  
                		"Location to redirect: " + location.getValue());

                String locationStr = location.getValue();
                result.addLocation(locationStr);

                // Release the connection to avoid reach the max number of connections per host
                // due to it will be set a different url
                exhaustResponse(method.getResponseBodyAsStream());
                method.releaseConnection();

                method.setURI(new URI(location.getValue(), true));
                method.setURI(new URI(locationStr, true));
                Header destination = method.getRequestHeader("Destination");
                if (destination == null) {
                	destination = method.getRequestHeader("destination");
                }
                if (destination != null) {
                	String locationStr = location.getValue();
                	int suffixIndex = locationStr.lastIndexOf(
                	    	(mCredentials instanceof OwnCloudBearerCredentials) ? 
                	    			AccountUtils.ODAV_PATH :
@@ -281,6 +282,7 @@ public class OwnCloudClient extends HttpClient {
                    method.setRequestHeader(destination);
                }
                status = super.executeMethod(method);
                result.addStatus(status);
                redirectionsCount++;
                
            } else {
@@ -288,7 +290,7 @@ public class OwnCloudClient extends HttpClient {
                status = HttpStatus.SC_NOT_FOUND;
            }
        }
        return status;
        return result;
	}

	/**
@@ -356,6 +358,9 @@ public class OwnCloudClient extends HttpClient {
        mFollowRedirects = followRedirects;
    }

    public boolean getFollowRedirects() {
        return mFollowRedirects;
    }

	private void logCookiesAtRequest(Header[] headers, String when) {
        int counter = 0;
+127 −0
Original line number Diff line number Diff line
/* ownCloud Android Library is available under MIT license
 *
 *   @author David A. Velasco
 *
 *   Copyright (C) 2015 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.common.network;

import org.apache.http.HttpStatus;

import java.util.Arrays;


/**
 * Aggregate saving the list of URLs followed in a sequence of redirections during the exceution of a
 * {@link com.owncloud.android.lib.common.operations.RemoteOperation}, and the status codes corresponding to all
 * of them.
 *
 * The last status code saved corresponds to the first response not being a redirection, unless the sequence exceeds
 * the maximum length of redirections allowed by the {@link com.owncloud.android.lib.common.OwnCloudClient} instance
 * that ran the operation.
 *
 * If no redirection was followed, the last (and first) status code contained corresponds to the original URL in the
 * request.
 */
public class RedirectionPath {

    private int[] mStatuses = null;

    private int mLastStatus = -1;

    private String[] mLocations = null;

    private int mLastLocation = -1;
    private int maxRedirections;

    /**
     * Public constructor.
     *
     * @param status            Status code resulting of executing a request on the original URL.
     * @param maxRedirections   Maximum number of redirections that will be contained.
     * @throws IllegalArgumentException     If 'maxRedirections' is < 0
     */
    public RedirectionPath(int status, int maxRedirections) {
        if (maxRedirections < 0) {
            throw new IllegalArgumentException("maxRedirections MUST BE zero or greater");
        }
        mStatuses = new int[maxRedirections + 1];
        Arrays.fill(mStatuses, -1);
        mStatuses[++mLastStatus] = status;
    }

    /**
     * Adds a new location URL to the list of followed redirections.
     *
     * @param location      URL extracted from a 'Location' header in a redirection.
     */
    public void addLocation(String location) {
        if (mLocations == null) {
            mLocations = new String[mStatuses.length - 1];
        }
        if (mLastLocation < mLocations.length - 1) {
            mLocations[++mLastLocation] = location;
        }
    }


    /**
     * Adds a new status code to the list of status corresponding to followed redirections.
     *
     * @param status     Status code from the response of another followed redirection.
     */
    public void addStatus(int status) {
        if (mLastStatus < mStatuses.length - 1) {
            mStatuses[++mLastStatus] = status;
        }
    }

    /**
     * @return      Last status code saved.
     */
    public int getLastStatus() {
        return mStatuses[mLastStatus];
    }

    /**
     * @return      Last location followed corresponding to a permanent redirection (status code 301).
     */
    public String getLastPermanentLocation() {
        for (int i = mLastStatus; i >= 0; i--) {
            if (mStatuses[i] == HttpStatus.SC_MOVED_PERMANENTLY && i <= mLastLocation) {
                return mLocations[i];
            }
        }
        return null;
    }

    /**
     * @return      Count of locations.
     */
    public int getRedirectionsCount() {
        return mLastLocation + 1;
    }


}
+14 −5
Original line number Diff line number Diff line
@@ -60,9 +60,9 @@ import com.owncloud.android.lib.common.utils.Log_OC;
public class RemoteOperationResult implements Serializable {
	
	/** Generated - should be refreshed every time the class changes!! */;
	private static final long serialVersionUID = -9003837206000993465L;
    private static final long serialVersionUID = 25745846447996048L;

	private static final String TAG = "RemoteOperationResult";
    private static final String TAG = RemoteOperationResult.class.getSimpleName();

    public enum ResultCode {
        OK,
@@ -112,6 +112,7 @@ public class RemoteOperationResult implements Serializable {
    private ResultCode mCode = ResultCode.UNKNOWN_ERROR;
    private String mRedirectedLocation;
    private String mAuthenticate;
    private String mLastPermanentLocation = null;

    private ArrayList<Object> mData;

@@ -391,4 +392,12 @@ public class RemoteOperationResult implements Serializable {
    	return mAuthenticate;
    }

    public String getLastPermanentLocation() {
        return mLastPermanentLocation;
    }

    public void setLastPermanentLocation(String lastPermanentLocation) {
        mLastPermanentLocation = lastPermanentLocation;
    }

}
+26 −2
Original line number Diff line number Diff line
@@ -31,6 +31,7 @@ import android.content.Context;
import android.net.ConnectivityManager;

import com.owncloud.android.lib.common.OwnCloudClient;
import com.owncloud.android.lib.common.network.RedirectionPath;
import com.owncloud.android.lib.common.network.WebdavUtils;
import com.owncloud.android.lib.common.operations.RemoteOperation;
import com.owncloud.android.lib.common.operations.RemoteOperationResult;
@@ -52,6 +53,9 @@ public class ExistenceCheckRemoteOperation extends RemoteOperation {
    private Context mContext;
    private boolean mSuccessIfAbsent;

    /** Sequence of redirections followed. Available only after executing the operation */
    private RedirectionPath mRedirectionPath = null;
        // TODO move to {@link RemoteOperation}, that needs a nice refactoring

    /**
     * Full constructor. Success of the operation will depend upon the value of successIfAbsent.
@@ -75,9 +79,13 @@ public class ExistenceCheckRemoteOperation extends RemoteOperation {
        }
        RemoteOperationResult result = null;
        HeadMethod head = null;
        boolean previousFollowRedirects = client.getFollowRedirects();
        try {
            head = new HeadMethod(client.getWebdavUri() + WebdavUtils.encodePath(mPath));
            int status = client.executeMethod(head, TIMEOUT, TIMEOUT);
            client.setFollowRedirects(false);
            client.executeMethod(head, TIMEOUT, TIMEOUT);
            mRedirectionPath = client.followRedirection(head);
            int status = mRedirectionPath.getLastStatus();
            client.exhaustResponse(head.getResponseBodyAsStream());
            boolean success = (status == HttpStatus.SC_OK && !mSuccessIfAbsent) ||
                    (status == HttpStatus.SC_NOT_FOUND && mSuccessIfAbsent);
@@ -97,6 +105,7 @@ public class ExistenceCheckRemoteOperation extends RemoteOperation {
        } finally {
            if (head != null)
                head.releaseConnection();
            client.setFollowRedirects(previousFollowRedirects);
        }
        return result;
	}
@@ -109,4 +118,19 @@ public class ExistenceCheckRemoteOperation extends RemoteOperation {
    }


    /**
     * 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.
     */
    public RedirectionPath getRedirectionPath() {
        return mRedirectionPath;
    }

    /**
     * @return      'True' if the operation was executed and at least one redirection was followed.
     */
    public boolean wasRedirected() {
        return (mRedirectionPath != null && mRedirectionPath.getRedirectionsCount() > 0);
    }
}
+1 −3
Original line number Diff line number Diff line
@@ -103,9 +103,7 @@ public class GetRemoteStatusOperation extends RemoteOperation {
				);
        		get.releaseConnection();
        		get = new GetMethod(redirectedLocation);
        		status = client.executeMethod(
        				get, TRY_CONNECTION_TIMEOUT, TRY_CONNECTION_TIMEOUT
				);
        		status = client.executeMethod(get, TRY_CONNECTION_TIMEOUT, TRY_CONNECTION_TIMEOUT);
        		mLatestResult = new RemoteOperationResult(
        				(status == HttpStatus.SC_OK), 
        				status, 
+2 −2

File changed.

Contains only whitespace changes.

+1 −1

File changed.

Contains only whitespace changes.

Loading