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

Unverified Commit 791451a5 authored by tobiasKaminsky's avatar tobiasKaminsky Committed by AndyScherzinger
Browse files

Add support for file versions

parent 8cdae45b
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@ dependencies {
    implementation 'org.parceler:parceler-api:1.1.6'
    annotationProcessor 'org.parceler:parceler:1.1.6'
    implementation group: 'com.google.code.gson', name: 'gson', version: '2.8.0'
    implementation "com.android.support:support-annotations:27.1.1"
}

android {
+17 −0
Original line number Diff line number Diff line
@@ -148,6 +148,23 @@ public class WebdavUtils {
        return propSet;
    }

    /**
     * Builds a DavPropertyNameSet with properties for versions
     * @return
     */
    public static DavPropertyNameSet getFileVersionPropSet() {
        DavPropertyNameSet propSet = new DavPropertyNameSet();
        propSet.add(DavPropertyName.GETCONTENTTYPE);
        propSet.add(DavPropertyName.RESOURCETYPE);
        propSet.add(DavPropertyName.GETCONTENTLENGTH);
        propSet.add(DavPropertyName.GETLASTMODIFIED);
        propSet.add(DavPropertyName.CREATIONDATE);
        propSet.add(WebdavEntry.EXTENDED_PROPERTY_NAME_REMOTE_ID, Namespace.getNamespace(WebdavEntry.NAMESPACE_OC));
        propSet.add(WebdavEntry.EXTENDED_PROPERTY_NAME_SIZE, Namespace.getNamespace(WebdavEntry.NAMESPACE_OC));

        return propSet;
    }

    /**
     *
     * @param rawEtag
+158 −0
Original line number Diff line number Diff line
/* ownCloud Android Library is available under MIT license
 *   Copyright (C) 2018 Nextcloud 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.resources.files;

import android.os.Parcel;
import android.os.Parcelable;

import com.owncloud.android.lib.common.network.WebdavEntry;

import java.io.Serializable;

/**
 * Contains the data of a versioned file from a WebDavEntry.
 *
 * @author Tobias Kaminsky
 */
public class FileVersion implements Parcelable, Serializable, ServerFileInterface {

    /**
     * Generated - should be refreshed every time the class changes!!
     */
    private static final long serialVersionUID = 3130865437811248455L;

    public static final String DIRECTORY = "DIR";

    private String mimeType;
    private long length;
    private long modifiedTimestamp;
    private String remoteId;

    @Override
    public boolean getIsFavorite() {
        return false;
    }

    @Override
    public String getFileName() {
        return String.valueOf(modifiedTimestamp / 1000);
    }

    public String getMimeType() {
        return mimeType;
    }

    @Override
    public String getRemotePath() {
        return "";
    }

    @Override
    public String getRemoteId() {
        return remoteId;
    }

    public void setMimeType(String mimeType) {
        this.mimeType = mimeType;
    }

    public long getFileLength() {
        return length;
    }

    public void setFileLength(long length) {
        this.length = length;
    }

    public boolean isFolder() {
        return mimeType != null && mimeType.equals(DIRECTORY);
    }

    public boolean isHidden() {
        return getFileName().startsWith(".");
    }
    
    public void setModifiedTimestamp(long modifiedTimestamp) {
        this.modifiedTimestamp = modifiedTimestamp;
    }
    
    public long getModifiedTimestamp() {
        return modifiedTimestamp;
    }

    public FileVersion(String fileId, WebdavEntry we) {
        remoteId = fileId;
        setMimeType(we.contentType());

        if (isFolder()) {
            setFileLength(we.size());
        } else {
            setFileLength(we.contentLength());
        }

        setModifiedTimestamp(we.modifiedTimestamp());
    }

    /**
     * Parcelable Methods
     */
    public static final Creator<FileVersion> CREATOR = new Creator<FileVersion>() {
        @Override
        public FileVersion createFromParcel(Parcel source) {
            return new FileVersion(source);
        }

        @Override
        public FileVersion[] newArray(int size) {
            return new FileVersion[size];
        }
    };


    /**
     * Reconstruct from parcel
     *
     * @param source The source parcel
     */
    protected FileVersion(Parcel source) {
        readFromParcel(source);
    }

    public void readFromParcel(Parcel source) {
        mimeType = source.readString();
        length = source.readLong();
    }

    @Override
    public int describeContents() {
        return this.hashCode();
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(mimeType);
        dest.writeLong(length);
    }
}
+154 −0
Original line number Diff line number Diff line
/* ownCloud Android Library is available under MIT license
 *   Copyright (C) 2018 Nextcloud 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.resources.files;

import android.support.annotation.NonNull;

import com.owncloud.android.lib.common.OwnCloudClient;
import com.owncloud.android.lib.common.network.WebdavEntry;
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.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 org.apache.jackrabbit.webdav.property.DavPropertyNameSet;

import java.util.ArrayList;

/**
 * Remote operation performing the read of remote trashbin folder on Nextcloud server.
 *
 * @author Tobias Kaminsky
 */

public class ReadFileVersionsOperation extends RemoteOperation {

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

    private String fileId;
    private String userId;
    private ArrayList<Object> versions;

    /**
     * Constructor
     *
     * @param fileId FileId of the file.
     */
    public ReadFileVersionsOperation(@NonNull String fileId, @NonNull String userId) {
        this.fileId = fileId;
        this.userId = userId;
    }

    /**
     * Performs the read operation.
     *
     * @param client Client object to communicate with the remote ownCloud server.
     */
    @Override
    protected RemoteOperationResult run(OwnCloudClient client) {
        RemoteOperationResult result = null;
        PropFindMethod query = null;

        try {
            // remote request
            if (userId.isEmpty()) {
                throw new IllegalArgumentException("UserId may not be empty!");
            }

            String uri = client.getNewWebdavUri(false) + "/versions/" + userId + "/versions/" + fileId;
            DavPropertyNameSet propSet = WebdavUtils.getFileVersionPropSet();

            query = new PropFindMethod(uri, propSet, DavConstants.DEPTH_1);
            int status = client.executeMethod(query);

            // check and process response
            boolean isSuccess = (status == HttpStatus.SC_MULTI_STATUS || status == HttpStatus.SC_OK);

            if (isSuccess) {
                // get data from remote folder
                MultiStatus dataInServer = query.getResponseBodyAsMultiStatus();
                readData(dataInServer, client);

                // Result of the operation
                result = new RemoteOperationResult(true, query);
                // Add data to the result
                if (result.isSuccess()) {
                    result.setData(versions);
                }
            } else {
                // synchronization failed
                client.exhaustResponse(query.getResponseBodyAsStream());
                result = new RemoteOperationResult(false, query);
            }
        } catch (Exception e) {
            result = new RemoteOperationResult(e);
        } finally {
            if (query != null)
                query.releaseConnection();  // let the connection available for other methods

            if (result == null) {
                result = new RemoteOperationResult(new Exception("unknown error"));
                Log_OC.e(TAG, "Synchronized file with id " + fileId + ": failed");
            } else {
                if (result.isSuccess()) {
                    Log_OC.i(TAG, "Synchronized file with id " + fileId + ": " + result.getLogMessage());
                } else {
                    if (result.isException()) {
                        Log_OC.e(TAG, "Synchronized with id " + fileId + ": " + result.getLogMessage(),
                                result.getException());
                    } else {
                        Log_OC.e(TAG, "Synchronized with id " + fileId + ": " + result.getLogMessage());
                    }
                }
            }
        }

        return result;
    }

    /**
     * Read the data retrieved from the server about the file versions.
     *
     * @param remoteData Full response got from the server with the version data.
     * @param client     Client instance to the remote server where the data were retrieved.
     */
    private void readData(MultiStatus remoteData, OwnCloudClient client) {
        versions = new ArrayList<>();

        // parse data from remote folder
        WebdavEntry we;
        String splitElement = client.getNewWebdavUri(false).getPath();

        // loop to update every child
        for (int i = 1; i < remoteData.getResponses().length; ++i) {
            we = new WebdavEntry(remoteData.getResponses()[i], splitElement);
            versions.add(new FileVersion(fileId, we));
        }
    }
}