org.alfresco.mobile.android.platform.SessionManager.java Source code

Java tutorial

Introduction

Here is the source code for org.alfresco.mobile.android.platform.SessionManager.java

Source

/*******************************************************************************
 * Copyright (C) 2005-2014 Alfresco Software Limited.
 *
 * This file is part of Alfresco Mobile for Android.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *******************************************************************************/
package org.alfresco.mobile.android.platform;

import java.io.File;
import java.io.Serializable;
import java.lang.ref.WeakReference;
import java.net.URI;
import java.util.HashMap;
import java.util.Map;

import org.alfresco.mobile.android.api.services.ConfigService;
import org.alfresco.mobile.android.api.services.impl.cloud.CloudServiceRegistry;
import org.alfresco.mobile.android.api.services.impl.onpremise.AlfrescoOnPremiseServiceRegistry;
import org.alfresco.mobile.android.api.session.AlfrescoSession;
import org.alfresco.mobile.android.api.session.CloudSession;
import org.alfresco.mobile.android.api.session.authentication.OAuthData;
import org.alfresco.mobile.android.api.session.authentication.impl.OAuth2DataImpl;
import org.alfresco.mobile.android.async.Operator;
import org.alfresco.mobile.android.async.session.LoadSessionCallBack.LoadAccountCompletedEvent;
import org.alfresco.mobile.android.async.session.LoadSessionCallBack.LoadAccountErrorEvent;
import org.alfresco.mobile.android.async.session.LoadSessionCallBack.LoadInactiveAccountEvent;
import org.alfresco.mobile.android.async.session.LoadSessionRequest.Builder;
import org.alfresco.mobile.android.async.session.RequestSessionEvent;
import org.alfresco.mobile.android.foundation.R;
import org.alfresco.mobile.android.platform.accounts.AlfrescoAccount;
import org.alfresco.mobile.android.platform.accounts.AlfrescoAccountManager;
import org.alfresco.mobile.android.platform.accounts.AlfrescoSessionSettings;
import org.alfresco.mobile.android.platform.exception.AlfrescoExceptionHelper;
import org.alfresco.mobile.android.platform.io.AlfrescoStorageManager;
import org.alfresco.mobile.android.platform.network.NetworkHttpInvoker;
import org.alfresco.mobile.android.platform.network.NetworkTrustManager;
import org.alfresco.mobile.android.platform.utils.ConnectivityUtils;
import org.apache.chemistry.opencmis.commons.SessionParameter;

import android.accounts.AccountManager;
import android.accounts.NetworkErrorException;
import android.content.Context;
import android.os.Bundle;
import android.support.v4.util.LongSparseArray;
import android.text.TextUtils;

import com.squareup.otto.Subscribe;

/**
 * Responsible to manage sessions across activities.
 * 
 * @author Jean Marie Pascal
 */
public abstract class SessionManager extends Manager {
    protected static final Object LOCK = new Object();

    protected static Manager mInstance;

    protected LongSparseArray<AlfrescoSession> sessionIndex = new LongSparseArray<>();

    protected AlfrescoAccount currentAccount;

    protected AlfrescoAccountManager accountManager;

    // ///////////////////////////////////////////////////////////////////////////
    // CONSTRUCTOR
    // ///////////////////////////////////////////////////////////////////////////
    protected SessionManager(Context applicationContext) {
        super(applicationContext);
        accountManager = AlfrescoAccountManager.getInstance(applicationContext);
        EventBusManager.getInstance().register(this);
    }

    public static SessionManager getInstance(Context context) {
        synchronized (LOCK) {
            if (mInstance == null) {
                mInstance = Manager.getInstance(context, SessionManager.class.getSimpleName());
            }
            return (SessionManager) mInstance;
        }
    }

    // ///////////////////////////////////////////////////////////////////////////
    // LIFECYCLE
    // ///////////////////////////////////////////////////////////////////////////
    public void shutdown() {
        sessionIndex.clear();
        mInstance = null;
        currentAccount = null;
        EventBusManager.getInstance().unregister(this);
    }

    // ///////////////////////////////////////////////////////////////////////////
    // EVENTS RECEIVER
    // ///////////////////////////////////////////////////////////////////////////
    @Subscribe
    public void onSessionRequested(RequestSessionEvent event) {
        if (event.requestReload) {
            if (event.networkId != null) {
                android.accounts.Account acc = accountManager.getAndroidAccount(event.accountToLoad.getId());
                AccountManager manager = AccountManager.get(appContext);
                manager.setUserData(acc, AlfrescoAccount.ACCOUNT_REPOSITORY_ID, event.networkId);
            }
            createSession(event.accountToLoad);
            return;
        }

        if (event.data != null) {
            loadSession(event.accountToLoad, event.data);
        } else {
            loadSession(event.accountToLoad);
        }
    }

    // ///////////////////////////////////////////////////////////////////////////
    // ACCOUNT / SESSION MANAGEMENT
    // ///////////////////////////////////////////////////////////////////////////
    public void loadSession() {
        loadSession(null);
    }

    public void loadSession(AlfrescoAccount acc, OAuthData data) {
        if (hasSession(acc.getId())) {
            removeAccount(acc.getId());
        }
        Builder request = new Builder(data);
        Operator.with(appContext, acc).load(request);
    }

    public AlfrescoSession loadSession(AlfrescoAccount account) {
        AlfrescoSession session = null;
        AlfrescoAccount accountToLoad = getCurrentAccount();

        // First Session Loading
        if (account == null && accountToLoad == null) {
            accountToLoad = accountManager.getDefaultAccount();
            if (accountToLoad == null) {
                EventBusManager.getInstance().post(new LoadInactiveAccountEvent(null, accountToLoad));
            }
        } else if (account != null) {
            // User has choose a specific account to load
            accountToLoad = account;
        }

        if (accountToLoad == null) {
            return null;
        }

        if (accountToLoad.getActivation() != null) {
            // SEND broadcast : account is not active !
            EventBusManager.getInstance().post(new LoadInactiveAccountEvent(null, accountToLoad));
        }

        // Check if Session available for this specific account
        if (hasSession(accountToLoad.getId())) {
            session = getSession(accountToLoad.getId());
            EventBusManager.getInstance()
                    .post(new LoadAccountCompletedEvent(LoadAccountCompletedEvent.SWAP, accountToLoad));
        } else if (getCurrentAccount() == null || accountToLoad.getId() != getCurrentAccount().getId()) {
            // Create the session for the specific account
            createSession(accountToLoad);
        } else if (getCurrentAccount() != null && !hasSession(getCurrentAccount().getId())) {
            // Create the session for the specific account
            createSession(getCurrentAccount());
        }

        // Mark accountId for the specific activity.
        // Help to retrieve session associated to a specific activity
        saveAccount(accountToLoad);

        return session;
    }

    public void createSession(AlfrescoAccount currentAccount) {
        // Check Connectivity
        if (!ConnectivityUtils.hasInternetAvailable(appContext)) {
            EventBusManager.getInstance().post(new LoadAccountErrorEvent(null, currentAccount,
                    new NetworkErrorException("Not Online"),
                    AlfrescoExceptionHelper.getMessageId(appContext, new NetworkErrorException("Not Online"))));
            return;
        }

        if (hasSession(currentAccount.getId())) {
            removeAccount(currentAccount.getId());
            saveAccount(currentAccount);
        }

        Builder request = new Builder();
        Operator.with(appContext, currentAccount).load(request);
    }

    // ///////////////////////////////////////////////////////////////////////////
    // ACCOUNT / SESSION MANAGEMENT
    // ///////////////////////////////////////////////////////////////////////////
    public AlfrescoAccount getCurrentAccount() {
        return currentAccount;
    }

    public void saveAccount(AlfrescoAccount currentAccount) {
        this.currentAccount = currentAccount;
    }

    public AlfrescoSession getCurrentSession() {
        if (currentAccount == null) {
            return null;
        }
        return sessionIndex.get(currentAccount.getId());
    }

    public void saveSession(AlfrescoAccount account, AlfrescoSession session) {
        sessionIndex.put(account.getId(), session);
    }

    public void saveSession(AlfrescoSession session) {
        saveSession(currentAccount, session);
    }

    public void removeAccount(long accountId) {
        if (currentAccount != null && currentAccount.getId() == accountId) {
            currentAccount = null;
        }
        sessionIndex.remove(accountId);
    }

    public boolean hasSession(Long accountId) {
        return sessionIndex.get(accountId) != null;
    }

    public AlfrescoSession getSession(Long accountId) {
        return sessionIndex.get(accountId);
    }

    // ///////////////////////////////////////////////////////////////////////////
    // SETTINGS
    // ///////////////////////////////////////////////////////////////////////////
    public Bundle getOAuthSettings() {
        return null;
    }

    public AlfrescoSessionSettings prepareSettings(AlfrescoAccount acc) {
        return new SettingsBuilder(appContext).prepare(acc).build();
    }

    public AlfrescoSessionSettings prepareSettings(AlfrescoAccount acc, OAuthData data) {
        return new SettingsBuilder(appContext).prepare(acc).build();
    }

    public AlfrescoSessionSettings prepareSettings(String baseUrl, String username, String password) {
        return new SettingsBuilder(appContext).prepare(baseUrl, username, password).build();
    }

    public AlfrescoSessionSettings prepareSettings(OAuthData oauthData) {
        return new SettingsBuilder(appContext).prepare(oauthData).build();
    }

    // ///////////////////////////////////////////////////////////////////////////
    // BUILDER
    // ///////////////////////////////////////////////////////////////////////////
    protected static class SettingsBuilder {
        protected static final String ONPREMISE_TRUSTMANAGER_CLASSNAME = "org.alfresco.mobile.binding.internal.https.trustmanager";

        protected WeakReference<Context> contextRef;

        protected Map<String, Serializable> extraSettings = new HashMap<String, Serializable>();

        protected String baseUrl;

        protected String username;

        protected String password;

        protected OAuthData oAuthData;

        protected boolean isCloud = false;

        // ///////////////////////////////////////////////////////////////////////////
        // CONSTRUCTOR
        // ///////////////////////////////////////////////////////////////////////////
        public SettingsBuilder(Context context) {
            this.contextRef = new WeakReference<Context>(context.getApplicationContext());
            prepareCommonSettings();
        }

        // ///////////////////////////////////////////////////////////////////////////
        // PREPARE
        // ///////////////////////////////////////////////////////////////////////////
        public AlfrescoSessionSettings build() {
            if (isCloud) {
                return new AlfrescoSessionSettings(oAuthData, extraSettings, true);
            } else {
                return new AlfrescoSessionSettings(baseUrl, username, password, extraSettings);
            }
        }

        // ///////////////////////////////////////////////////////////////////////////
        // OPERATION
        // ///////////////////////////////////////////////////////////////////////////
        public SettingsBuilder prepare(AlfrescoAccount acc) {
            prepareData(acc);
            return this;
        }

        // TODO Implement it !
        public SettingsBuilder prepare(OAuthData oauthData) {
            this.isCloud = true;
            this.oAuthData = oauthData;
            return this;
        }

        public SettingsBuilder prepare(AlfrescoAccount acc, OAuthData oauthData) {
            this.isCloud = true;
            this.oAuthData = oauthData;
            prepareData(acc);
            return this;
        }

        public SettingsBuilder prepare(String baseUrl, String username, String password) {
            this.isCloud = false;
            this.baseUrl = baseUrl;
            this.username = username;
            this.password = password;
            prepareConfigurationSettings(new AlfrescoAccount(baseUrl, username));
            prepareSSLSettings();
            return this;
        }

        public SettingsBuilder add(Map<String, Serializable> settings) {
            if (settings != null && !settings.isEmpty()) {
                extraSettings.putAll(settings);
            }
            return this;
        }

        public SettingsBuilder add(String key, Serializable value) {
            if (!TextUtils.isEmpty(key) && value != null) {
                extraSettings.put(key, value);
            }
            return this;
        }

        // ///////////////////////////////////////////////////////////////////////////
        // GENERATE BUNDLE
        // ///////////////////////////////////////////////////////////////////////////
        protected void prepareData(AlfrescoAccount acc) {
            switch (acc.getTypeId()) {
            case AlfrescoAccount.TYPE_ALFRESCO_CLOUD:
                isCloud = true;
                baseUrl = acc.getUrl();
                oAuthData = new OAuth2DataImpl(getContext().getString(R.string.oauth_api_key),
                        getContext().getString(R.string.oauth_api_secret), acc.getAccessToken(),
                        acc.getRefreshToken());
                prepareCloudSettings(acc.getRepositoryId());
                break;
            case AlfrescoAccount.TYPE_ALFRESCO_TEST_BASIC:
            case AlfrescoAccount.TYPE_ALFRESCO_CMIS:
                isCloud = false;
                baseUrl = acc.getUrl();
                username = acc.getUsername();
                password = acc.getPassword();
                prepareConfigurationSettings(acc);
                prepareSSLSettings();
                break;
            default:
                break;
            }
        }

        protected void prepareConfigurationSettings(AlfrescoAccount acc) {
            extraSettings.put(ConfigService.CONFIGURATION_INIT, ConfigService.CONFIGURATION_INIT_DEFAULT);
            extraSettings.put(ConfigService.CONFIGURATION_FOLDER,
                    AlfrescoStorageManager.getInstance(getContext()).getConfigurationFolder(acc).getPath());
        }

        protected void prepareCommonSettings() {
            // Default settings for Alfresco Application
            extraSettings.put(AlfrescoSession.ONPREMISE_SERVICES_CLASSNAME,
                    AlfrescoOnPremiseServiceRegistry.class.getCanonicalName());
            extraSettings.put(SessionParameter.CONNECT_TIMEOUT, "10000");
            extraSettings.put(SessionParameter.READ_TIMEOUT, "60000");
            extraSettings.put(AlfrescoSession.EXTRACT_METADATA, true);
            extraSettings.put(AlfrescoSession.CREATE_THUMBNAIL, true);
            extraSettings.put(AlfrescoSession.HTTP_CHUNK_TRANSFERT, "true");
            // extraSettings.put(SessionParameter.CLIENT_COMPRESSION, "true");
            extraSettings.put(AlfrescoSession.HTTP_INVOKER_CLASSNAME, NetworkHttpInvoker.class.getName());
            extraSettings.put(AlfrescoSession.CACHE_FOLDER,
                    AlfrescoStorageManager.getInstance(getContext()).getCacheDir("AlfrescoMobile").getPath());
        }

        protected void prepareCloudSettings(String repositoryId) {
            extraSettings.put(AlfrescoSession.CLOUD_SERVICES_CLASSNAME,
                    CloudServiceRegistry.class.getCanonicalName());
            if (repositoryId != null && !repositoryId.isEmpty()) {
                extraSettings.put(CloudSession.CLOUD_NETWORK_ID, repositoryId);
            }
            extraSettings.put(AlfrescoSession.HTTP_ACCEPT_ENCODING, "false");
            extraSettings.put(AlfrescoSession.HTTP_CHUNK_TRANSFERT, "true");
        }

        protected void prepareSSLSettings() {
            // ssl certificate
            try {
                URI url = new URI(baseUrl);
                File f = AlfrescoStorageManager.getInstance(getContext())
                        .getFileInPrivateFolder(url.getHost() + ".properties");
                if (f.exists() && f.isFile()) {
                    AlfrescoNotificationManager.getInstance(getContext()).showToast(R.string.security_ssl_disable);
                    extraSettings.put(ONPREMISE_TRUSTMANAGER_CLASSNAME, NetworkTrustManager.class.getName());
                }
            } catch (Exception e) {
                // Nothing special
            }
        }

        private Context getContext() {
            return contextRef.get();
        }
    }
}