/* * Copyright © 2016 TIBCO Software,Inc.All rights reserved. * http://community.jaspersoft.com/project/jaspermobile-android * * Unless you have purchased a commercial license agreement from TIBCO Jaspersoft, * the following license terms apply: * * This program is part of TIBCO Jaspersoft Mobile for Android. * * TIBCO Jaspersoft Mobile is free software:you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation,either version 3of the License,or * (at your option)any later version. * * TIBCO Jaspersoft Mobile 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with TIBCO Jaspersoft Mobile for Android.If not,see * <http://www.gnu.org/licenses/lgpl>. */ package com.jaspersoft.android.jaspermobile.data.cache; import android.accounts.Account; import android.accounts.AccountManager; import android.content.Context; import android.provider.Settings; import android.support.annotation.Nullable; import com.jaspersoft.android.jaspermobile.data.entity.mapper.AccountDataMapper; import com.jaspersoft.android.jaspermobile.domain.Profile; import com.jaspersoft.android.jaspermobile.domain.executor.PostExecutionThread; import com.jaspersoft.android.jaspermobile.domain.executor.PreExecutionThread; import com.jaspersoft.android.jaspermobile.internal.di.ApplicationContext; import com.jaspersoft.android.jaspermobile.util.account.AccountStorage; import com.orhanobut.hawk.Hawk; import com.orhanobut.hawk.HawkBuilder; import com.orhanobut.hawk.Storage; import javax.inject.Inject; import javax.inject.Singleton; import rx.functions.Action1; import rx.observables.ConnectableObservable; import rx.observers.Observers; /** * @author Tom Koptel * @since 2.1.2 */ @Singleton public final class SecureStorage implements SecureCache { private final HawkBuilder hawkBuilder; private final AccountManager mAccountManager; private final AccountDataMapper mAccountDataMapper; private final PreExecutionThread mPreExecutionThread; private final PostExecutionThread mPostExecutionThread; private boolean isInitialized = false; private ConnectableObservable<Boolean> initObservable; private Profile mCurrentProfile; @Inject public SecureStorage(@ApplicationContext Context context, AccountDataMapper accountDataMapper, PreExecutionThread preExecutionThread, PostExecutionThread postExecutionThread ) { mAccountManager = AccountManager.get(context); mAccountDataMapper = accountDataMapper; mPreExecutionThread = preExecutionThread; mPostExecutionThread = postExecutionThread; String storagePassword = Settings.Secure.getString( context.getContentResolver(),Settings.Secure.ANDROID_ID); hawkBuilder = Hawk.init(context) .setEncryptionMethod(HawkBuilder.EncryptionMethod.HIGHEST) .setPassword(storagePassword); } @Override public void put(Profile profile, final String key, final String rawValue) { if (profileChanged(profile)) { setupProfileStorage(profile); } if (isInitialized) { Hawk.put(key, rawValue); } else { Boolean initialized = initObservable.toBlocking().firstOrDefault(false); if (initialized) { Hawk.put(key, rawValue); } } } @Nullable @Override public String get(Profile profile, String key) { if (profileChanged(profile)) { setupProfileStorage(profile); } try { return getFromHawk(key); } catch (IllegalArgumentException ex) { // We are catching error: "Text should contain delimiter" // This happens during migration from 2.2.1 to 2.2.2 return null; } } @Nullable private String getFromHawk(String key) { if (isInitialized) { return Hawk.get(key); } else { Boolean initialized = initObservable.toBlocking().firstOrDefault(false); if (initialized) { return Hawk.get(key); } return null; } } private boolean profileChanged(Profile profile) { return !profile.equals(mCurrentProfile); } private void setupProfileStorage(Profile profile) { Storage storage = createStorage(profile); initHawk(storage); } private Storage createStorage(Profile profile) { mCurrentProfile = profile; Account account = mAccountDataMapper.transform(profile); return new AccountStorage(mAccountManager, account); } private void initHawk(Storage storage) { isInitialized = false; initObservable = hawkBuilder .setStorage(storage) .buildRx() .subscribeOn(mPreExecutionThread.getScheduler()) .observeOn(mPostExecutionThread.getScheduler()) .publish(); initObservable.subscribe(Observers.create(new Action1<Boolean>() { @Override public void call(Boolean aBoolean) { isInitialized = aBoolean; } })); initObservable.connect(); } }