feat: add pCloud implementation
This commit is contained in:
parent
bb4572b9d0
commit
80dce5ec60
@ -0,0 +1,37 @@
|
|||||||
|
package org.cryptomator.data.cloud.pcloud;
|
||||||
|
|
||||||
|
public enum PCloudApiErrorCodes {
|
||||||
|
LOGIN_REQUIRED(1000),
|
||||||
|
NO_FULL_PATH_OR_NAME_FOLDER_ID_PROVIDED(1001),
|
||||||
|
NO_FULL_PATH_OR_FOLDER_ID_PROVIDED(1002),
|
||||||
|
NO_DESTINATION_PROVIDED(1016),
|
||||||
|
INVALID_FOLDER_ID(1017),
|
||||||
|
INVALID_DESTINATION(1037),
|
||||||
|
PROVIDE_URL(1040),
|
||||||
|
LOGIN_FAILED(2000),
|
||||||
|
INVALID_FILE_FOLDER_NAME(2001),
|
||||||
|
COMPONENT_OF_PARENT_DIRECTORY_DOES_NOT_EXIST(2002),
|
||||||
|
ACCESS_DENIED(2003),
|
||||||
|
FILE_OR_FOLDER_ALREADY_EXISTS(2004),
|
||||||
|
DIRECTORY_DOES_NOT_EXIST(2005),
|
||||||
|
FOLDER_NOT_EMPTY(2006),
|
||||||
|
CANNOT_DELETE_ROOT_FOLDER(2007),
|
||||||
|
USER_OVER_QUOTA(2008),
|
||||||
|
FILE_NOT_FOUND(2009),
|
||||||
|
SHARED_FOLDER_IN_SHARED_FOLDER(2023),
|
||||||
|
ACTIVE_SHARES_OR_SHAREREQUESTS_PRESENT(2028),
|
||||||
|
CANNOT_RENAME_ROOT_FOLDER(2042),
|
||||||
|
CANNOT_MOVE_FOLDER_INTO_SUBFOLDER_OF_ITSELF(2043),
|
||||||
|
INVALID_ACCESS_TOKEN(2094),
|
||||||
|
TOO_MANY_LOGIN_TRIES_FROM_IP(4000),
|
||||||
|
INTERNAL_ERROR(5000),
|
||||||
|
INTERNAL_UPLOAD_ERROR(5001);
|
||||||
|
|
||||||
|
private final int value;
|
||||||
|
|
||||||
|
PCloudApiErrorCodes(final int newValue) {
|
||||||
|
value = newValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getValue() { return value; }
|
||||||
|
}
|
@ -0,0 +1,54 @@
|
|||||||
|
package org.cryptomator.data.cloud.pcloud;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
|
||||||
|
import com.pcloud.sdk.ApiClient;
|
||||||
|
import com.pcloud.sdk.Authenticators;
|
||||||
|
import com.pcloud.sdk.PCloudSdk;
|
||||||
|
|
||||||
|
import org.cryptomator.data.cloud.okhttplogging.HttpLoggingInterceptor;
|
||||||
|
import org.cryptomator.util.SharedPreferencesHandler;
|
||||||
|
import org.cryptomator.util.file.LruFileCacheUtil;
|
||||||
|
|
||||||
|
import okhttp3.Cache;
|
||||||
|
import okhttp3.Interceptor;
|
||||||
|
import okhttp3.OkHttpClient;
|
||||||
|
import timber.log.Timber;
|
||||||
|
|
||||||
|
import static org.cryptomator.data.util.NetworkTimeout.CONNECTION;
|
||||||
|
import static org.cryptomator.data.util.NetworkTimeout.READ;
|
||||||
|
import static org.cryptomator.data.util.NetworkTimeout.WRITE;
|
||||||
|
|
||||||
|
class PCloudClientFactory {
|
||||||
|
|
||||||
|
private ApiClient apiClient;
|
||||||
|
|
||||||
|
private static Interceptor httpLoggingInterceptor(Context context) {
|
||||||
|
return new HttpLoggingInterceptor(message -> Timber.tag("OkHttp").d(message), context);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ApiClient getClient(String accessToken, String url, Context context) {
|
||||||
|
if (apiClient == null) {
|
||||||
|
final SharedPreferencesHandler sharedPreferencesHandler = new SharedPreferencesHandler(context);
|
||||||
|
apiClient = createApiClient(accessToken, url, context, sharedPreferencesHandler.useLruCache(), sharedPreferencesHandler.lruCacheSize());
|
||||||
|
}
|
||||||
|
return apiClient;
|
||||||
|
}
|
||||||
|
|
||||||
|
private ApiClient createApiClient(String accessToken, String url, Context context, boolean useLruCache, int lruCacheSize) {
|
||||||
|
OkHttpClient.Builder okHttpClientBuilder = new OkHttpClient() //
|
||||||
|
.newBuilder() //
|
||||||
|
.connectTimeout(CONNECTION.getTimeout(), CONNECTION.getUnit()) //
|
||||||
|
.readTimeout(READ.getTimeout(), READ.getUnit()) //
|
||||||
|
.writeTimeout(WRITE.getTimeout(), WRITE.getUnit()) //
|
||||||
|
.addInterceptor(httpLoggingInterceptor(context)); //;
|
||||||
|
|
||||||
|
if (useLruCache) {
|
||||||
|
okHttpClientBuilder.cache(new Cache(new LruFileCacheUtil(context).resolve(LruFileCacheUtil.Cache.PCLOUD), lruCacheSize));
|
||||||
|
}
|
||||||
|
|
||||||
|
OkHttpClient okHttpClient = okHttpClientBuilder.build();
|
||||||
|
|
||||||
|
return PCloudSdk.newClientBuilder().authenticator(Authenticators.newOAuthAuthenticator(accessToken)).withClient(okHttpClient).apiHost(url).create();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,209 @@
|
|||||||
|
package org.cryptomator.data.cloud.pcloud;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
|
||||||
|
import com.pcloud.sdk.ApiError;
|
||||||
|
|
||||||
|
import org.cryptomator.data.cloud.InterceptingCloudContentRepository;
|
||||||
|
import org.cryptomator.domain.PCloudCloud;
|
||||||
|
import org.cryptomator.domain.exception.BackendException;
|
||||||
|
import org.cryptomator.domain.exception.CloudNodeAlreadyExistsException;
|
||||||
|
import org.cryptomator.domain.exception.FatalBackendException;
|
||||||
|
import org.cryptomator.domain.exception.NetworkConnectionException;
|
||||||
|
import org.cryptomator.domain.exception.NoSuchCloudFileException;
|
||||||
|
import org.cryptomator.domain.exception.authentication.WrongCredentialsException;
|
||||||
|
import org.cryptomator.domain.repository.CloudContentRepository;
|
||||||
|
import org.cryptomator.domain.usecases.ProgressAware;
|
||||||
|
import org.cryptomator.domain.usecases.cloud.DataSource;
|
||||||
|
import org.cryptomator.domain.usecases.cloud.DownloadState;
|
||||||
|
import org.cryptomator.domain.usecases.cloud.UploadState;
|
||||||
|
import org.cryptomator.util.Optional;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static org.cryptomator.util.ExceptionUtil.contains;
|
||||||
|
|
||||||
|
class PCloudCloudContentRepository extends InterceptingCloudContentRepository<PCloudCloud, PCloudNode, PCloudFolder, PCloudFile> {
|
||||||
|
|
||||||
|
private final PCloudCloud cloud;
|
||||||
|
|
||||||
|
public PCloudCloudContentRepository(PCloudCloud cloud, Context context) {
|
||||||
|
super(new Intercepted(cloud, context));
|
||||||
|
this.cloud = cloud;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void throwWrappedIfRequired(Exception e) throws BackendException {
|
||||||
|
throwConnectionErrorIfRequired(e);
|
||||||
|
throwWrongCredentialsExceptionIfRequired(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void throwConnectionErrorIfRequired(Exception e) throws NetworkConnectionException {
|
||||||
|
if (contains(e, IOException.class)) {
|
||||||
|
throw new NetworkConnectionException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void throwWrongCredentialsExceptionIfRequired(Exception e) {
|
||||||
|
if (e instanceof ApiError && ((ApiError) e).errorCode() == PCloudApiErrorCodes.INVALID_ACCESS_TOKEN.getValue()) {
|
||||||
|
throw new WrongCredentialsException(cloud);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class Intercepted implements CloudContentRepository<PCloudCloud, PCloudNode, PCloudFolder, PCloudFile> {
|
||||||
|
|
||||||
|
private final PCloudImpl cloud;
|
||||||
|
|
||||||
|
public Intercepted(PCloudCloud cloud, Context context) {
|
||||||
|
this.cloud = new PCloudImpl(cloud, context);
|
||||||
|
}
|
||||||
|
|
||||||
|
public PCloudFolder root(PCloudCloud cloud) {
|
||||||
|
return this.cloud.root();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PCloudFolder resolve(PCloudCloud cloud, String path) {
|
||||||
|
return this.cloud.resolve(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PCloudFile file(PCloudFolder parent, String name) {
|
||||||
|
return cloud.file(parent, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PCloudFile file(PCloudFolder parent, String name, Optional<Long> size) throws BackendException {
|
||||||
|
return cloud.file(parent, name, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PCloudFolder folder(PCloudFolder parent, String name) {
|
||||||
|
return cloud.folder(parent, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean exists(PCloudNode node) throws BackendException {
|
||||||
|
try {
|
||||||
|
return cloud.exists(node);
|
||||||
|
} catch (ApiError|IOException e) {
|
||||||
|
throw new FatalBackendException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<PCloudNode> list(PCloudFolder folder) throws BackendException {
|
||||||
|
try {
|
||||||
|
return cloud.list(folder);
|
||||||
|
} catch (ApiError | IOException e) {
|
||||||
|
if (e instanceof ApiError) {
|
||||||
|
if (((ApiError) e).errorCode() == PCloudApiErrorCodes.DIRECTORY_DOES_NOT_EXIST.getValue()) {
|
||||||
|
throw new NoSuchCloudFileException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new FatalBackendException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PCloudFolder create(PCloudFolder folder) throws BackendException {
|
||||||
|
try {
|
||||||
|
return cloud.create(folder);
|
||||||
|
} catch (ApiError | IOException e) {
|
||||||
|
if (e instanceof ApiError) {
|
||||||
|
if (((ApiError) e).errorCode() == PCloudApiErrorCodes.FILE_OR_FOLDER_ALREADY_EXISTS.getValue())
|
||||||
|
throw new CloudNodeAlreadyExistsException(folder.getName());
|
||||||
|
}
|
||||||
|
throw new FatalBackendException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PCloudFolder move(PCloudFolder source, PCloudFolder target) throws BackendException {
|
||||||
|
try {
|
||||||
|
return (PCloudFolder) cloud.move(source, target);
|
||||||
|
} catch (ApiError | IOException e) {
|
||||||
|
if (e instanceof ApiError) {
|
||||||
|
if (((ApiError)e).errorCode() == PCloudApiErrorCodes.DIRECTORY_DOES_NOT_EXIST.getValue()) {
|
||||||
|
throw new NoSuchCloudFileException(source.getName());
|
||||||
|
} else if (((ApiError)e).errorCode() == PCloudApiErrorCodes.FILE_OR_FOLDER_ALREADY_EXISTS.getValue()) {
|
||||||
|
throw new CloudNodeAlreadyExistsException(target.getName());
|
||||||
|
}
|
||||||
|
throw new CloudNodeAlreadyExistsException(target.getName());
|
||||||
|
}
|
||||||
|
throw new FatalBackendException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PCloudFile move(PCloudFile source, PCloudFile target) throws BackendException {
|
||||||
|
try {
|
||||||
|
return (PCloudFile) cloud.move(source, target);
|
||||||
|
} catch (ApiError | IOException e) {
|
||||||
|
if (e instanceof ApiError) {
|
||||||
|
if (((ApiError)e).errorCode() == PCloudApiErrorCodes.FILE_NOT_FOUND.getValue()) {
|
||||||
|
throw new NoSuchCloudFileException(source.getName());
|
||||||
|
} else if (((ApiError)e).errorCode() == PCloudApiErrorCodes.FILE_OR_FOLDER_ALREADY_EXISTS.getValue()) {
|
||||||
|
throw new CloudNodeAlreadyExistsException(target.getName());
|
||||||
|
}
|
||||||
|
throw new CloudNodeAlreadyExistsException(target.getName());
|
||||||
|
}
|
||||||
|
throw new FatalBackendException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PCloudFile write(PCloudFile uploadFile, DataSource data, ProgressAware<UploadState> progressAware, boolean replace, long size) throws BackendException {
|
||||||
|
try {
|
||||||
|
return cloud.write(uploadFile, data, progressAware, replace, size);
|
||||||
|
} catch (ApiError | IOException e) {
|
||||||
|
if (((ApiError)e).errorCode() == PCloudApiErrorCodes.FILE_NOT_FOUND.getValue()) {
|
||||||
|
throw new NoSuchCloudFileException(uploadFile.getName());
|
||||||
|
}
|
||||||
|
throw new FatalBackendException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void read(PCloudFile file, Optional<File> encryptedTmpFile, OutputStream data, ProgressAware<DownloadState> progressAware) throws BackendException {
|
||||||
|
try {
|
||||||
|
cloud.read(file, data, progressAware);
|
||||||
|
} catch (ApiError | IOException e) {
|
||||||
|
if (((ApiError)e).errorCode() == PCloudApiErrorCodes.FILE_NOT_FOUND.getValue()) {
|
||||||
|
throw new NoSuchCloudFileException(file.getName());
|
||||||
|
}
|
||||||
|
throw new FatalBackendException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void delete(PCloudNode node) throws BackendException {
|
||||||
|
try {
|
||||||
|
cloud.delete(node);
|
||||||
|
} catch (ApiError | IOException e) {
|
||||||
|
if (((ApiError)e).errorCode() == PCloudApiErrorCodes.FILE_NOT_FOUND.getValue()) {
|
||||||
|
throw new NoSuchCloudFileException(node.getName());
|
||||||
|
}
|
||||||
|
throw new FatalBackendException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String checkAuthenticationAndRetrieveCurrentAccount(PCloudCloud cloud) throws BackendException {
|
||||||
|
try {
|
||||||
|
return this.cloud.currentAccount();
|
||||||
|
} catch (ApiError | IOException e) {
|
||||||
|
throw new FatalBackendException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void logout(PCloudCloud cloud) throws BackendException {
|
||||||
|
// empty
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,243 @@
|
|||||||
|
package org.cryptomator.data.cloud.pcloud;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
|
||||||
|
import com.pcloud.sdk.ApiClient;
|
||||||
|
import com.pcloud.sdk.ApiError;
|
||||||
|
import com.pcloud.sdk.DataSink;
|
||||||
|
import com.pcloud.sdk.DownloadOptions;
|
||||||
|
import com.pcloud.sdk.FileLink;
|
||||||
|
import com.pcloud.sdk.ProgressListener;
|
||||||
|
import com.pcloud.sdk.RemoteEntry;
|
||||||
|
import com.pcloud.sdk.RemoteFile;
|
||||||
|
import com.pcloud.sdk.RemoteFolder;
|
||||||
|
import com.pcloud.sdk.UploadOptions;
|
||||||
|
import com.pcloud.sdk.UserInfo;
|
||||||
|
|
||||||
|
import org.cryptomator.data.util.CopyStream;
|
||||||
|
import org.cryptomator.domain.CloudFile;
|
||||||
|
import org.cryptomator.domain.CloudFolder;
|
||||||
|
import org.cryptomator.domain.CloudNode;
|
||||||
|
import org.cryptomator.domain.PCloudCloud;
|
||||||
|
import org.cryptomator.domain.exception.CloudNodeAlreadyExistsException;
|
||||||
|
import org.cryptomator.domain.exception.authentication.NoAuthenticationProvidedException;
|
||||||
|
import org.cryptomator.domain.usecases.ProgressAware;
|
||||||
|
import org.cryptomator.domain.usecases.cloud.DataSource;
|
||||||
|
import org.cryptomator.domain.usecases.cloud.DownloadState;
|
||||||
|
import org.cryptomator.domain.usecases.cloud.Progress;
|
||||||
|
import org.cryptomator.domain.usecases.cloud.UploadState;
|
||||||
|
import org.cryptomator.util.Optional;
|
||||||
|
import org.cryptomator.util.crypto.CredentialCryptor;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import okio.BufferedSink;
|
||||||
|
import okio.BufferedSource;
|
||||||
|
import okio.Okio;
|
||||||
|
import okio.Source;
|
||||||
|
|
||||||
|
import static org.cryptomator.domain.usecases.cloud.Progress.progress;
|
||||||
|
|
||||||
|
class PCloudImpl {
|
||||||
|
|
||||||
|
private static final int DIRECTORY_DOES_NOT_EXIST = 2005;
|
||||||
|
private static final int INVALID_FILE_OR_FOLDER_NAME = 2001;
|
||||||
|
|
||||||
|
private final PCloudClientFactory clientFactory = new PCloudClientFactory();
|
||||||
|
private final PCloudCloud cloud;
|
||||||
|
private final RootPCloudFolder root;
|
||||||
|
private final Context context;
|
||||||
|
|
||||||
|
PCloudImpl(PCloudCloud cloud, Context context) {
|
||||||
|
if (cloud.accessToken() == null) {
|
||||||
|
throw new NoAuthenticationProvidedException(cloud);
|
||||||
|
}
|
||||||
|
this.cloud = cloud;
|
||||||
|
this.root = new RootPCloudFolder(cloud);
|
||||||
|
this.context = context;
|
||||||
|
}
|
||||||
|
|
||||||
|
private ApiClient client() {
|
||||||
|
return clientFactory.getClient(decrypt(cloud.accessToken()), cloud.url(), context);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String decrypt(String password) {
|
||||||
|
return CredentialCryptor //
|
||||||
|
.getInstance(context) //
|
||||||
|
.decrypt(password);
|
||||||
|
}
|
||||||
|
|
||||||
|
public PCloudFolder root() {
|
||||||
|
return root;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PCloudFolder resolve(String path) {
|
||||||
|
if (path.startsWith("/")) {
|
||||||
|
path = path.substring(1);
|
||||||
|
}
|
||||||
|
String[] names = path.split("/");
|
||||||
|
PCloudFolder folder = root;
|
||||||
|
for (String name : names) {
|
||||||
|
folder = folder(folder, name);
|
||||||
|
}
|
||||||
|
return folder;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PCloudFile file(CloudFolder folder, String name) {
|
||||||
|
return file(folder, name, Optional.empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
public PCloudFile file(CloudFolder folder, String name, Optional<Long> size) {
|
||||||
|
return PCloudCloudNodeFactory.file( //
|
||||||
|
(PCloudFolder) folder, //
|
||||||
|
name, //
|
||||||
|
size, //
|
||||||
|
folder.getPath() + '/' + name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public PCloudFolder folder(CloudFolder folder, String name) {
|
||||||
|
return PCloudCloudNodeFactory.folder( //
|
||||||
|
(PCloudFolder) folder, //
|
||||||
|
name, //
|
||||||
|
folder.getPath() + '/' + name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean exists(CloudNode node) throws ApiError, IOException {
|
||||||
|
try {
|
||||||
|
if (node instanceof PCloudFolder) {
|
||||||
|
client().listFolder(((PCloudFolder) node).getPath()).execute();
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
client().stat(((PCloudFile)node).getPath()).execute();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} catch (ApiError e) {
|
||||||
|
if (e.errorCode() == DIRECTORY_DOES_NOT_EXIST || e.errorCode() == INVALID_FILE_OR_FOLDER_NAME) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<PCloudNode> list(CloudFolder folder) throws ApiError, IOException {
|
||||||
|
List<PCloudNode> result = new ArrayList<>();
|
||||||
|
RemoteFolder listFolderResult = null;
|
||||||
|
List<RemoteEntry> entryMetadata = listFolderResult.children();
|
||||||
|
for (RemoteEntry metadata : entryMetadata) {
|
||||||
|
result.add(PCloudCloudNodeFactory.from( //
|
||||||
|
(PCloudFolder) folder, //
|
||||||
|
metadata));
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PCloudFolder create(CloudFolder folder) throws ApiError, IOException {
|
||||||
|
RemoteFolder createFolderResult = client() //
|
||||||
|
.createFolder(((PCloudFolder)folder.getParent()).getId(), folder.getName()) //
|
||||||
|
.execute();
|
||||||
|
|
||||||
|
return PCloudCloudNodeFactory.from( //
|
||||||
|
(PCloudFolder) folder.getParent(), //
|
||||||
|
createFolderResult.asFolder());
|
||||||
|
}
|
||||||
|
|
||||||
|
public CloudNode move(CloudNode source, CloudNode target) throws ApiError, IOException {
|
||||||
|
RemoteEntry relocationResult;
|
||||||
|
if (source instanceof PCloudFolder) {
|
||||||
|
relocationResult = client().moveFolder(((PCloudFolder) source).getId(), ((PCloudFolder) target).getId()).execute();
|
||||||
|
} else {
|
||||||
|
relocationResult = client().moveFile(((PCloudFile) source).getId(), ((PCloudFolder) target).getId()).execute();
|
||||||
|
}
|
||||||
|
|
||||||
|
return PCloudCloudNodeFactory.from( //
|
||||||
|
(PCloudFolder) target.getParent(), //
|
||||||
|
relocationResult);
|
||||||
|
}
|
||||||
|
|
||||||
|
public PCloudFile write(PCloudFile file, DataSource data, final ProgressAware<UploadState> progressAware, boolean replace, long size) throws ApiError, IOException, CloudNodeAlreadyExistsException {
|
||||||
|
if (exists(file) && !replace) {
|
||||||
|
throw new CloudNodeAlreadyExistsException("CloudNode already exists and replace is false");
|
||||||
|
}
|
||||||
|
|
||||||
|
progressAware.onProgress(Progress.started(UploadState.upload(file)));
|
||||||
|
UploadOptions uploadOptions = UploadOptions.DEFAULT;
|
||||||
|
if (replace) {
|
||||||
|
uploadOptions = UploadOptions.OVERRIDE_FILE;
|
||||||
|
}
|
||||||
|
|
||||||
|
RemoteFile uploadedFile = uploadFile(file, data, progressAware, uploadOptions, size);
|
||||||
|
|
||||||
|
progressAware.onProgress(Progress.completed(UploadState.upload(file)));
|
||||||
|
|
||||||
|
return PCloudCloudNodeFactory.from( //
|
||||||
|
file.getParent(), //
|
||||||
|
uploadedFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
private RemoteFile uploadFile(final PCloudFile file, DataSource data, final ProgressAware<UploadState> progressAware, UploadOptions uploadOptions, final long size) //
|
||||||
|
throws ApiError, IOException {
|
||||||
|
ProgressListener listener = (done, total) -> progressAware.onProgress( //
|
||||||
|
progress(UploadState.upload(file)) //
|
||||||
|
.between(0) //
|
||||||
|
.and(size) //
|
||||||
|
.withValue(done));
|
||||||
|
|
||||||
|
com.pcloud.sdk.DataSource pCloudDataSource = new com.pcloud.sdk.DataSource() {
|
||||||
|
@Override
|
||||||
|
public void writeTo(BufferedSink sink) throws IOException {
|
||||||
|
try (Source source = Okio.source(data.open(context))) {
|
||||||
|
sink.writeAll(source);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return client() //
|
||||||
|
.createFile(((PCloudFolder) file.getParent()).getId(), file.getName(), pCloudDataSource, new Date(), listener, uploadOptions) //
|
||||||
|
.execute();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void read(CloudFile file, OutputStream data, final ProgressAware<DownloadState> progressAware) throws ApiError, IOException {
|
||||||
|
progressAware.onProgress(Progress.started(DownloadState.download(file)));
|
||||||
|
|
||||||
|
FileLink fileLink = client().createFileLink(((PCloudFile) file).getId(), DownloadOptions.DEFAULT).execute();
|
||||||
|
|
||||||
|
ProgressListener listener = (done, total) -> progressAware.onProgress( //
|
||||||
|
progress(DownloadState.download(file)) //
|
||||||
|
.between(0) //
|
||||||
|
.and(file.getSize().orElse(Long.MAX_VALUE)) //
|
||||||
|
.withValue(done));
|
||||||
|
|
||||||
|
DataSink sink = new DataSink() {
|
||||||
|
@Override
|
||||||
|
public void readAll(BufferedSource source) throws IOException {
|
||||||
|
CopyStream.copyStreamToStream(source.getBuffer().inputStream(), data);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
client().download(fileLink, sink, listener).execute();
|
||||||
|
|
||||||
|
progressAware.onProgress(Progress.completed(DownloadState.download(file)));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void delete(CloudNode node) throws ApiError, IOException {
|
||||||
|
if (node instanceof PCloudFolder) {
|
||||||
|
client() //
|
||||||
|
.deleteFolder(((PCloudFolder) node).getId()).execute();
|
||||||
|
} else {
|
||||||
|
client() //
|
||||||
|
.deleteFile(((PCloudFile) node).getId()).execute();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public String currentAccount() throws ApiError, IOException {
|
||||||
|
UserInfo currentAccount = client() //
|
||||||
|
.getUserInfo() //
|
||||||
|
.execute();
|
||||||
|
return currentAccount.email();
|
||||||
|
}
|
||||||
|
}
|
@ -21,13 +21,14 @@ class LruFileCacheUtil(context: Context) {
|
|||||||
private val parent: File = context.cacheDir
|
private val parent: File = context.cacheDir
|
||||||
|
|
||||||
enum class Cache {
|
enum class Cache {
|
||||||
DROPBOX, WEBDAV, ONEDRIVE, GOOGLE_DRIVE
|
DROPBOX, WEBDAV, PCLOUD, ONEDRIVE, GOOGLE_DRIVE
|
||||||
}
|
}
|
||||||
|
|
||||||
fun resolve(cache: Cache?): File {
|
fun resolve(cache: Cache?): File {
|
||||||
return when (cache) {
|
return when (cache) {
|
||||||
Cache.DROPBOX -> File(parent, "LruCacheDropbox")
|
Cache.DROPBOX -> File(parent, "LruCacheDropbox")
|
||||||
Cache.WEBDAV -> File(parent, "LruCacheWebdav")
|
Cache.WEBDAV -> File(parent, "LruCacheWebdav")
|
||||||
|
Cache.PCLOUD -> File(parent, "LruCachePCloud")
|
||||||
Cache.ONEDRIVE -> File(parent, "LruCacheOneDrive")
|
Cache.ONEDRIVE -> File(parent, "LruCacheOneDrive")
|
||||||
Cache.GOOGLE_DRIVE -> File(parent, "LruCacheGoogleDrive")
|
Cache.GOOGLE_DRIVE -> File(parent, "LruCacheGoogleDrive")
|
||||||
else -> throw IllegalStateException()
|
else -> throw IllegalStateException()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user