From e069a8cb9f4f874ee91d7c012c083899556378e9 Mon Sep 17 00:00:00 2001 From: "David A. Velasco" Date: Thu, 12 Jun 2014 16:36:24 +0200 Subject: [PATCH 1/3] Added OwnCloudAccount class and method OwnCloudSessionManager#gertClientFor(OwnCloudAccount, ...) to ease the reuse of OwnCloudClient instances after creating accounts with authentication based in external authentication providers --- .../android/lib/common/OwnCloudAccount.java | 95 +++++++++++++++++++ .../lib/common/OwnCloudBasicCredentials.java | 5 + .../lib/common/OwnCloudBearerCredentials.java | 8 +- .../lib/common/OwnCloudClientManager.java | 2 + .../lib/common/OwnCloudCredentials.java | 2 + .../common/OwnCloudCredentialsFactory.java | 6 ++ .../common/OwnCloudSamlSsoCredentials.java | 6 ++ .../lib/common/SimpleFactoryManager.java | 12 +++ .../lib/common/SingleSessionManager.java | 52 +++++++++- .../lib/common/accounts/AccountUtils.java | 10 ++ 10 files changed, 196 insertions(+), 2 deletions(-) create mode 100644 src/com/owncloud/android/lib/common/OwnCloudAccount.java diff --git a/src/com/owncloud/android/lib/common/OwnCloudAccount.java b/src/com/owncloud/android/lib/common/OwnCloudAccount.java new file mode 100644 index 00000000..ff0cf3dd --- /dev/null +++ b/src/com/owncloud/android/lib/common/OwnCloudAccount.java @@ -0,0 +1,95 @@ +/* ownCloud Android client application + * Copyright (C) 2014 ownCloud Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +package com.owncloud.android.lib.common; + + +import java.io.IOException; + +import com.owncloud.android.lib.common.accounts.AccountUtils; +import com.owncloud.android.lib.common.accounts.AccountUtils.AccountNotFoundException; + +import android.accounts.Account; +import android.accounts.AuthenticatorException; +import android.accounts.OperationCanceledException; +import android.content.Context; +import android.net.Uri; + +/** + * OwnCloud Account + * + * @author David A. Velasco + */ +public class OwnCloudAccount { + + private Uri mBaseUri; + + private OwnCloudCredentials mCredentials; + + private String mSavedAccountName; + + + public OwnCloudAccount(Account savedAccount, Context context) + throws AccountNotFoundException, AuthenticatorException, + IOException, OperationCanceledException { + + if (savedAccount == null) { + throw new IllegalArgumentException("Parameter 'savedAccount' cannot be null"); + } + if (context == null) { + throw new IllegalArgumentException("Parameter 'context' cannot be null"); + } + + mSavedAccountName = savedAccount.name; + mBaseUri = Uri.parse(AccountUtils.getBaseUrlForAccount(context, savedAccount)); + mCredentials = AccountUtils.getCredentialsForAccount(context, savedAccount); + } + + + public OwnCloudAccount(Uri baseUri, OwnCloudCredentials credentials) { + if (baseUri == null) { + throw new IllegalArgumentException("Parameter 'baseUri' cannot be null"); + } + mSavedAccountName = null; + mBaseUri = baseUri; + mCredentials = credentials != null ? + credentials : OwnCloudCredentialsFactory.getAnonymousCredentials(); + String username = credentials.getUsername(); + if (username != null) { + mSavedAccountName = AccountUtils.buildAccountName(mBaseUri, username); + } + } + + + public boolean isAnonymous() { + return (mCredentials == null); + } + + public Uri getBaseUri() { + return mBaseUri; + } + + public OwnCloudCredentials getCredentials() { + return mCredentials; + } + + public String getName() { + return mSavedAccountName; + } + + +} \ No newline at end of file diff --git a/src/com/owncloud/android/lib/common/OwnCloudBasicCredentials.java b/src/com/owncloud/android/lib/common/OwnCloudBasicCredentials.java index cb30f093..6855cfc4 100644 --- a/src/com/owncloud/android/lib/common/OwnCloudBasicCredentials.java +++ b/src/com/owncloud/android/lib/common/OwnCloudBasicCredentials.java @@ -30,6 +30,11 @@ public class OwnCloudBasicCredentials implements OwnCloudCredentials { ); } + @Override + public String getUsername() { + return mUsername; + } + @Override public String getAuthToken() { return mPassword; diff --git a/src/com/owncloud/android/lib/common/OwnCloudBearerCredentials.java b/src/com/owncloud/android/lib/common/OwnCloudBearerCredentials.java index 2a9f4515..fb6f2018 100644 --- a/src/com/owncloud/android/lib/common/OwnCloudBearerCredentials.java +++ b/src/com/owncloud/android/lib/common/OwnCloudBearerCredentials.java @@ -32,6 +32,12 @@ public class OwnCloudBearerCredentials implements OwnCloudCredentials { ); } + @Override + public String getUsername() { + // its unknown + return null; + } + @Override public String getAuthToken() { return mAccessToken; @@ -41,5 +47,5 @@ public class OwnCloudBearerCredentials implements OwnCloudCredentials { public boolean authTokenExpires() { return true; } - + } diff --git a/src/com/owncloud/android/lib/common/OwnCloudClientManager.java b/src/com/owncloud/android/lib/common/OwnCloudClientManager.java index 5372a272..7e8a9024 100644 --- a/src/com/owncloud/android/lib/common/OwnCloudClientManager.java +++ b/src/com/owncloud/android/lib/common/OwnCloudClientManager.java @@ -62,5 +62,7 @@ public interface OwnCloudClientManager { public OwnCloudClient removeClientFor(Account account, Context context) throws AccountNotFoundException, AuthenticatorException, IOException, OperationCanceledException; + + public OwnCloudClient getClientFor(OwnCloudAccount account, Context context); } diff --git a/src/com/owncloud/android/lib/common/OwnCloudCredentials.java b/src/com/owncloud/android/lib/common/OwnCloudCredentials.java index deba8177..a3fff2eb 100644 --- a/src/com/owncloud/android/lib/common/OwnCloudCredentials.java +++ b/src/com/owncloud/android/lib/common/OwnCloudCredentials.java @@ -21,6 +21,8 @@ public interface OwnCloudCredentials { public void applyTo(OwnCloudClient ownCloudClient); + public String getUsername(); + public String getAuthToken(); public boolean authTokenExpires(); diff --git a/src/com/owncloud/android/lib/common/OwnCloudCredentialsFactory.java b/src/com/owncloud/android/lib/common/OwnCloudCredentialsFactory.java index 45ee53de..951b4ae3 100644 --- a/src/com/owncloud/android/lib/common/OwnCloudCredentialsFactory.java +++ b/src/com/owncloud/android/lib/common/OwnCloudCredentialsFactory.java @@ -42,6 +42,12 @@ public class OwnCloudCredentialsFactory { public boolean authTokenExpires() { return false; } + + @Override + public String getUsername() { + // no user name + return null; + } } } diff --git a/src/com/owncloud/android/lib/common/OwnCloudSamlSsoCredentials.java b/src/com/owncloud/android/lib/common/OwnCloudSamlSsoCredentials.java index a50d3177..78c96bfa 100644 --- a/src/com/owncloud/android/lib/common/OwnCloudSamlSsoCredentials.java +++ b/src/com/owncloud/android/lib/common/OwnCloudSamlSsoCredentials.java @@ -39,6 +39,12 @@ public class OwnCloudSamlSsoCredentials implements OwnCloudCredentials { } } + @Override + public String getUsername() { + // its unknown + return null; + } + @Override public String getAuthToken() { return mSessionCookie; diff --git a/src/com/owncloud/android/lib/common/SimpleFactoryManager.java b/src/com/owncloud/android/lib/common/SimpleFactoryManager.java index fb7a0849..03839539 100644 --- a/src/com/owncloud/android/lib/common/SimpleFactoryManager.java +++ b/src/com/owncloud/android/lib/common/SimpleFactoryManager.java @@ -13,6 +13,18 @@ import com.owncloud.android.lib.common.accounts.AccountUtils.AccountNotFoundExce public class SimpleFactoryManager implements OwnCloudClientManager { + @Override + public OwnCloudClient getClientFor(OwnCloudAccount account, Context context) { + OwnCloudClient client = OwnCloudClientFactory.createOwnCloudClient( + account.getBaseUri(), + context.getApplicationContext(), + true); + + client.setCredentials(account.getCredentials()); + return client; + } + + @Override public OwnCloudClient getClientFor(Account savedAccount, Context context) throws OperationCanceledException, AuthenticatorException, AccountNotFoundException, diff --git a/src/com/owncloud/android/lib/common/SingleSessionManager.java b/src/com/owncloud/android/lib/common/SingleSessionManager.java index 4c636513..17226e5c 100644 --- a/src/com/owncloud/android/lib/common/SingleSessionManager.java +++ b/src/com/owncloud/android/lib/common/SingleSessionManager.java @@ -64,14 +64,64 @@ public class SingleSessionManager implements OwnCloudClientManager { private Map> mClientsPerServer = new HashMap>(); + private Map mClientsWithKnownUsername = + new HashMap(); + + private Map mClientsWithUnknownUsername = + new HashMap(); + public static OwnCloudClientManager getInstance() { if (mInstance == null) { mInstance = new SingleSessionManager(); } - return mInstance ; + return mInstance; } + + @Override + public synchronized OwnCloudClient getClientFor(OwnCloudAccount account, Context context) { + if (account == null) { + throw new IllegalArgumentException("Cannot get an OwnCloudClient for a null account"); + } + + OwnCloudClient client = null; + String accountName = account.getName(); + String sessionName = AccountUtils.buildAccountName( + account.getBaseUri(), + account.getCredentials().getAuthToken()); + + if (accountName != null) { + client = mClientsWithKnownUsername.get(account.getName()); + } + if (client == null) { + if (accountName != null) { + client = mClientsWithUnknownUsername.remove(sessionName); + if (client != null) { + mClientsWithKnownUsername.put(accountName, client); + } + } else { + client = mClientsWithUnknownUsername.get(sessionName); + } + } + + if (client == null) { + // no client to reuse - create a new one + client = OwnCloudClientFactory.createOwnCloudClient( + account.getBaseUri(), + context.getApplicationContext(), + true); + client.setCredentials(account.getCredentials()); + if (accountName != null) { + mClientsWithKnownUsername.put(accountName, client); + } else { + mClientsWithUnknownUsername.put(sessionName, client); + } + } + + return client; + } + @Override public synchronized OwnCloudClient getClientFor(Account savedAccount, Context context) diff --git a/src/com/owncloud/android/lib/common/accounts/AccountUtils.java b/src/com/owncloud/android/lib/common/accounts/AccountUtils.java index 8fddc4e6..60ee1e1e 100644 --- a/src/com/owncloud/android/lib/common/accounts/AccountUtils.java +++ b/src/com/owncloud/android/lib/common/accounts/AccountUtils.java @@ -37,6 +37,7 @@ import android.accounts.AccountsException; import android.accounts.AuthenticatorException; import android.accounts.OperationCanceledException; import android.content.Context; +import android.net.Uri; public class AccountUtils { public static final String WEBDAV_PATH_1_2 = "/webdav/owncloud.php"; @@ -185,6 +186,15 @@ public class AccountUtils { return credentials; } + + + public static String buildAccountName(Uri serverBaseUrl, String username) { + String accountName = username + "@" + serverBaseUrl.getHost(); + if (serverBaseUrl.getPort() >= 0) { + accountName += ":" + serverBaseUrl.getPort(); + } + return accountName; + } public static class AccountNotFoundException extends AccountsException { From 17d810fe2b74b7e481245108eb4d9d13d5e15615 Mon Sep 17 00:00:00 2001 From: "David A. Velasco" Date: Thu, 12 Jun 2014 17:28:10 +0200 Subject: [PATCH 2/3] Fixed creation of OwnCloudClientManager instances --- .../android/lib/common/OwnCloudClientManagerFactory.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/com/owncloud/android/lib/common/OwnCloudClientManagerFactory.java b/src/com/owncloud/android/lib/common/OwnCloudClientManagerFactory.java index 78b6858e..78ac9979 100644 --- a/src/com/owncloud/android/lib/common/OwnCloudClientManagerFactory.java +++ b/src/com/owncloud/android/lib/common/OwnCloudClientManagerFactory.java @@ -16,10 +16,10 @@ public class OwnCloudClientManagerFactory { public static OwnCloudClientManager newOwnCloudClientManager(Policy policy) { switch (policy) { case ALWAYS_NEW_CLIENT: - return new SingleSessionManager(); + return new SimpleFactoryManager(); case SINGLE_SESSION_PER_ACCOUNT: - return new SimpleFactoryManager(); + return new SingleSessionManager(); default: throw new IllegalArgumentException("Unknown policy"); From e6c23205ebb5cc6cef55c2e53acf99ec889bbe42 Mon Sep 17 00:00:00 2001 From: "David A. Velasco" Date: Thu, 12 Jun 2014 17:36:59 +0200 Subject: [PATCH 3/3] Fixed issue fully breaking the refresh of current folder (fixed only for SimpleFactoryManager for the moment) --- .../common/OwnCloudClientManagerFactory.java | 10 +++++++++- .../lib/common/SimpleFactoryManager.java | 16 ++++++++++++--- .../lib/common/SingleSessionManager.java | 20 ++++++++++--------- .../common/operations/RemoteOperation.java | 6 ++++-- 4 files changed, 37 insertions(+), 15 deletions(-) diff --git a/src/com/owncloud/android/lib/common/OwnCloudClientManagerFactory.java b/src/com/owncloud/android/lib/common/OwnCloudClientManagerFactory.java index 78ac9979..f8a9a2f3 100644 --- a/src/com/owncloud/android/lib/common/OwnCloudClientManagerFactory.java +++ b/src/com/owncloud/android/lib/common/OwnCloudClientManagerFactory.java @@ -8,6 +8,8 @@ public class OwnCloudClientManagerFactory { } public final static Policy DEFAULT_POLICY = Policy.ALWAYS_NEW_CLIENT; + + private static OwnCloudClientManager mDefaultSingleton; public static OwnCloudClientManager newDefaultOwnCloudClientManager() { return newOwnCloudClientManager(DEFAULT_POLICY); @@ -26,5 +28,11 @@ public class OwnCloudClientManagerFactory { } } - + public static OwnCloudClientManager getDefaultSingleton() { + if (mDefaultSingleton == null) { + mDefaultSingleton = newDefaultOwnCloudClientManager(); + } + return mDefaultSingleton; + } + } diff --git a/src/com/owncloud/android/lib/common/SimpleFactoryManager.java b/src/com/owncloud/android/lib/common/SimpleFactoryManager.java index 03839539..5ced7cc5 100644 --- a/src/com/owncloud/android/lib/common/SimpleFactoryManager.java +++ b/src/com/owncloud/android/lib/common/SimpleFactoryManager.java @@ -7,19 +7,23 @@ import android.accounts.AuthenticatorException; import android.accounts.OperationCanceledException; import android.content.Context; import android.net.Uri; +import android.util.Log; import com.owncloud.android.lib.common.accounts.AccountUtils.AccountNotFoundException; public class SimpleFactoryManager implements OwnCloudClientManager { - + private static final String TAG = OwnCloudClientManager.class.getSimpleName(); + @Override public OwnCloudClient getClientFor(OwnCloudAccount account, Context context) { + Log.d(TAG, "getClientFor(OwnCloudAccount ... : "); OwnCloudClient client = OwnCloudClientFactory.createOwnCloudClient( account.getBaseUri(), context.getApplicationContext(), true); + Log.d(TAG, " new client " + client.hashCode()); client.setCredentials(account.getCredentials()); return client; } @@ -29,15 +33,20 @@ public class SimpleFactoryManager implements OwnCloudClientManager { public OwnCloudClient getClientFor(Account savedAccount, Context context) throws OperationCanceledException, AuthenticatorException, AccountNotFoundException, IOException { - - return OwnCloudClientFactory.createOwnCloudClient( + Log.d(TAG, "getClientFor(Account ... : "); + + OwnCloudClient client = OwnCloudClientFactory.createOwnCloudClient( savedAccount, context.getApplicationContext()); + + Log.d(TAG, " new client " + client.hashCode()); + return client; } @Override public OwnCloudClient getClientFor(Uri serverBaseUri, OwnCloudCredentials credentials, Context context) { + Log.d(TAG, "getClientFor(Uri ... : "); OwnCloudClient client = OwnCloudClientFactory.createOwnCloudClient( serverBaseUri, @@ -45,6 +54,7 @@ public class SimpleFactoryManager implements OwnCloudClientManager { true); client.setCredentials(credentials); + Log.d(TAG, " new client " + client.hashCode()); return client; } diff --git a/src/com/owncloud/android/lib/common/SingleSessionManager.java b/src/com/owncloud/android/lib/common/SingleSessionManager.java index 17226e5c..99eb5daf 100644 --- a/src/com/owncloud/android/lib/common/SingleSessionManager.java +++ b/src/com/owncloud/android/lib/common/SingleSessionManager.java @@ -71,16 +71,9 @@ public class SingleSessionManager implements OwnCloudClientManager { new HashMap(); - public static OwnCloudClientManager getInstance() { - if (mInstance == null) { - mInstance = new SingleSessionManager(); - } - return mInstance; - } - - @Override public synchronized OwnCloudClient getClientFor(OwnCloudAccount account, Context context) { + Log.d(TAG, "getClientFor(OwnCloudAccount ... : "); if (account == null) { throw new IllegalArgumentException("Cannot get an OwnCloudClient for a null account"); } @@ -92,17 +85,21 @@ public class SingleSessionManager implements OwnCloudClientManager { account.getCredentials().getAuthToken()); if (accountName != null) { - client = mClientsWithKnownUsername.get(account.getName()); + client = mClientsWithKnownUsername.get(accountName); } if (client == null) { if (accountName != null) { client = mClientsWithUnknownUsername.remove(sessionName); if (client != null) { + Log.d(TAG, " reusing client {" + sessionName + ", " + client.hashCode() + "}"); mClientsWithKnownUsername.put(accountName, client); + Log.d(TAG, " moved client to {" + accountName + ", " + client.hashCode() + "}"); } } else { client = mClientsWithUnknownUsername.get(sessionName); } + } else { + Log.d(TAG, " reusing client {" + accountName + ", " + client.hashCode() + "}"); } if (client == null) { @@ -114,9 +111,14 @@ public class SingleSessionManager implements OwnCloudClientManager { client.setCredentials(account.getCredentials()); if (accountName != null) { mClientsWithKnownUsername.put(accountName, client); + Log.d(TAG, " new client {" + accountName + ", " + client.hashCode() + "}"); + } else { mClientsWithUnknownUsername.put(sessionName, client); + Log.d(TAG, " new client {" + sessionName + ", " + client.hashCode() + "}"); } + } else { + Log.d(TAG, " reusing client {" + sessionName + ", " + client.hashCode() + "}"); } return client; diff --git a/src/com/owncloud/android/lib/common/operations/RemoteOperation.java b/src/com/owncloud/android/lib/common/operations/RemoteOperation.java index fa89b24b..942be396 100644 --- a/src/com/owncloud/android/lib/common/operations/RemoteOperation.java +++ b/src/com/owncloud/android/lib/common/operations/RemoteOperation.java @@ -28,6 +28,7 @@ import java.io.IOException; import com.owncloud.android.lib.common.OwnCloudClient; import com.owncloud.android.lib.common.OwnCloudClientFactory; +import com.owncloud.android.lib.common.OwnCloudClientManagerFactory; import com.owncloud.android.lib.common.OwnCloudCredentials; import com.owncloud.android.lib.common.SingleSessionManager; import com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode; @@ -104,7 +105,8 @@ public abstract class RemoteOperation implements Runnable { mAccount = account; mContext = context.getApplicationContext(); try { - mClient = SingleSessionManager.getInstance().getClientFor(mAccount, mContext); + mClient = OwnCloudClientManagerFactory.getDefaultSingleton(). + getClientFor(mAccount, mContext); } catch (Exception e) { Log.e(TAG, "Error while trying to access to " + mAccount.name, e); return new RemoteOperationResult(e); @@ -251,7 +253,7 @@ public abstract class RemoteOperation implements Runnable { mAccount, mContext, mCallerActivity); } else { /** EOF DEPRECATED */ - mClient = SingleSessionManager.getInstance(). + mClient = OwnCloudClientManagerFactory.getDefaultSingleton(). getClientFor(mAccount, mContext); } } else {