Android Open Source - google-authenticator-android Dependency Injector






From Project

Back to project page google-authenticator-android.

License

The source code is released under:

Apache License

If you think the Android project google-authenticator-android listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

/*
 * Copyright 2011 Google Inc. All Rights Reserved.
 */*from  www  . j  a  va2s . c o m*/
 * 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 com.google.android.apps.authenticator.testability;

import com.google.android.apps.authenticator.AccountDb;
import com.google.android.apps.authenticator.AuthenticatorActivity;
import com.google.android.apps.authenticator.MarketBuildOptionalFeatures;
import com.google.android.apps.authenticator.OptionalFeatures;
import com.google.android.apps.authenticator.OtpSource;
import com.google.android.apps.authenticator.TotpClock;
import com.google.android.apps.authenticator.dataimport.ExportServiceBasedImportController;
import com.google.android.apps.authenticator.dataimport.ImportController;

import android.content.Context;
import android.content.pm.PackageManager;
import android.preference.PreferenceManager;
import android.test.RenamingDelegatingContext;

import org.apache.http.client.HttpClient;
import org.apache.http.conn.ClientConnectionManager;


/**
 * Dependency injector that decouples the clients of various objects from their
 * creators/constructors and enables the injection of these objects for testing purposes.
 *
 * <p>The injector is singleton. It needs to be configured for production or test use using
 * {@link #configureForProductionIfNotConfigured(Context)} or
 * {@link #resetForIntegrationTesting(Context)}.
 * After that its clients can access the various objects such as {@link AccountDb} using the
 * respective getters (e.g., {@link #getAccountDb()}.
 *
 * <p>When testing, this class provides the means to inject different implementations of the
 * injectable objects (e.g., {@link #setAccountDb(AccountDb) setAccountDb}). To avoid inter-test
 * state-leakage, each test should invoke {@link #resetForIntegrationTesting(Context)}.
 *
 * @author klyubin@google.com (Alex Klyubin)
 */
public final class DependencyInjector {

  private static Context sContext;

  private static AccountDb sAccountDb;
  private static OtpSource sOtpProvider;
  private static TotpClock sTotpClock;
  private static PackageManager sPackageManager;
  private static StartActivityListener sStartActivityListener;
  private static HttpClient sHttpClient;
  private static ImportController sImportController;
  private static OptionalFeatures sOptionalFeatures;

  private enum Mode {
    PRODUCTION,
    INTEGRATION_TEST,
  }

  private static Mode sMode;

  private DependencyInjector() {}

  /**
   * Gets the {@link Context} passed the instances created by this injector.
   */
  public static synchronized Context getContext() {
    if (sContext == null) {
      throw new IllegalStateException("Context not set");
    }
    return sContext;
  }

  /**
   * Sets the {@link AccountDb} instance returned by this injector. This will prevent the injector
   * from creating its own instance.
   */
  public static synchronized void setAccountDb(AccountDb accountDb) {
    if (sAccountDb != null) {
      sAccountDb.close();
    }
    sAccountDb = accountDb;
  }

  public static synchronized AccountDb getAccountDb() {
    if (sAccountDb == null) {
      sAccountDb = new AccountDb(getContext());
      if (sMode != Mode.PRODUCTION) {
        sAccountDb.deleteAllData();
      }
    }
    return sAccountDb;
  }

  /**
   * Sets the {@link OtpSource} instance returned by this injector. This will prevent the injector
   * from creating its own instance.
   */
  public static synchronized void setOtpProvider(OtpSource otpProvider) {
    sOtpProvider = otpProvider;
  }

  public static synchronized OtpSource getOtpProvider() {
    if (sOtpProvider == null) {
      sOtpProvider = getOptionalFeatures().createOtpSource(getAccountDb(), getTotpClock());
    }
    return sOtpProvider;
  }

  /**
   * Sets the {@link TotpClock} instance returned by this injector. This will prevent the injector
   * from creating its own instance.
   */
  public static synchronized void setTotpClock(TotpClock totpClock) {
    sTotpClock = totpClock;
  }

  public static synchronized TotpClock getTotpClock() {
    if (sTotpClock == null) {
      sTotpClock = new TotpClock(getContext());
    }
    return sTotpClock;
  }

  /**
   * Sets the {@link PackageManager} instance returned by this injector. This will prevent the
   * injector from creating its own instance.
   */
  public static synchronized void setPackageManager(PackageManager packageManager) {
    sPackageManager = packageManager;
  }

  public static synchronized PackageManager getPackageManager() {
    if (sPackageManager == null) {
      sPackageManager = getContext().getPackageManager();
    }
    return sPackageManager;
  }

  /**
   * Sets the {@link StartActivityListener} instance returned by this injector.
   */
  public static synchronized void setStartActivityListener(StartActivityListener listener) {
    sStartActivityListener = listener;
  }

  public static synchronized StartActivityListener getStartActivityListener() {
    // Don't create an instance on demand -- the default behavior when the listener is null is to
    // proceed with launching activities.
    return sStartActivityListener;
  }

  /**
   * Sets the {@link ImportController} instance returned by this injector. This will prevent the
   * injector from creating its own instance.
   */
  public static synchronized void setDataImportController(ImportController importController) {
    sImportController = importController;
  }

  public static synchronized ImportController getDataImportController() {
    if (sImportController == null) {
      if (sMode == Mode.PRODUCTION) {
        sImportController = new ExportServiceBasedImportController();
      } else {
        // By default, use a no-op controller during tests to avoid them being dependent on the
        // presence of the "old" app on the device under test.
        sImportController = new ImportController() {
          @Override
          public void start(Context context, Listener listener) {}
        };
      }
    }
    return sImportController;
  }

  /**
   * Sets the {@link HttpClient} instance returned by this injector. This will prevent the
   * injector from creating its own instance.
   */
  public static synchronized void setHttpClient(HttpClient httpClient) {
    sHttpClient = httpClient;
  }

  public static synchronized HttpClient getHttpClient() {
    if (sHttpClient == null) {
      sHttpClient = HttpClientFactory.createHttpClient(getContext());
    }
    return sHttpClient;
  }

  public static synchronized void setOptionalFeatures(OptionalFeatures optionalFeatures) {
    sOptionalFeatures = optionalFeatures;
  }

  public static synchronized OptionalFeatures getOptionalFeatures() {
    if (sOptionalFeatures == null) {
      try {
        Class<?> resultClass = Class.forName(
            AuthenticatorActivity.class.getPackage().getName() + ".NonMarketBuildOptionalFeatures");
        try {
          sOptionalFeatures = (OptionalFeatures) resultClass.newInstance();
        } catch (Exception e) {
          throw new RuntimeException("Failed to instantiate optional features module", e);
        }
      } catch (ClassNotFoundException e) {
        sOptionalFeatures = new MarketBuildOptionalFeatures();
      }
    }
    return sOptionalFeatures;
  }

  /**
   * Clears any state and configures this injector for production use. Does nothing if the injector
   * is already configured.
   */
  public static synchronized void configureForProductionIfNotConfigured(Context context) {
    if (sMode != null) {
      return;
    }

    close();
    sMode = Mode.PRODUCTION;
    sContext = context;
  }

  /**
   * Clears any state and configures this injector to provide objects that are suitable for
   * integration testing.
   */
  // @VisibleForTesting
  public static synchronized void resetForIntegrationTesting(Context context) {
    if (context == null) {
      throw new NullPointerException("context == null");
    }

    close();

    sMode = Mode.INTEGRATION_TEST;
    RenamingDelegatingContext renamingContext = new RenamingDelegatingContext(context, "test_");
    renamingContext.makeExistingFilesAndDbsAccessible();
    sContext = new SharedPreferencesRenamingDelegatingContext(renamingContext, "test_");
    PreferenceManager.getDefaultSharedPreferences(sContext).edit().clear().commit();
  }

  /**
   * Closes any resources and objects held by this injector. To use the injector again, invoke
   * {@link #resetForIntegrationTesting(Context)}.
   */
  public static synchronized void close() {
    if (sAccountDb != null) {
      sAccountDb.close();
    }
    if (sHttpClient != null) {
      ClientConnectionManager httpClientConnectionManager = sHttpClient.getConnectionManager();
      if (httpClientConnectionManager != null) {
        httpClientConnectionManager.shutdown();
      }
    }

    sMode = null;
    sContext = null;
    sAccountDb = null;
    sOtpProvider = null;
    sTotpClock = null;
    sPackageManager = null;
    sStartActivityListener = null;
    sHttpClient = null;
    sImportController = null;
    sOptionalFeatures = null;
  }
}




Java Source Code List

com.google.android.apps.authenticator.AccountDb.java
com.google.android.apps.authenticator.AddOtherAccountActivity.java
com.google.android.apps.authenticator.AuthenticatorActivity.java
com.google.android.apps.authenticator.AuthenticatorApplication.java
com.google.android.apps.authenticator.Base32String.java
com.google.android.apps.authenticator.CheckCodeActivity.java
com.google.android.apps.authenticator.CountdownIndicator.java
com.google.android.apps.authenticator.EnterKeyActivity.java
com.google.android.apps.authenticator.FileUtilities.java
com.google.android.apps.authenticator.HexEncoding.java
com.google.android.apps.authenticator.MarketBuildOptionalFeatures.java
com.google.android.apps.authenticator.OptionalFeatures.java
com.google.android.apps.authenticator.OtpGenerationNotPermittedException.java
com.google.android.apps.authenticator.OtpProvider.java
com.google.android.apps.authenticator.OtpSourceException.java
com.google.android.apps.authenticator.OtpSource.java
com.google.android.apps.authenticator.PasscodeGenerator.java
com.google.android.apps.authenticator.Preconditions.java
com.google.android.apps.authenticator.RunOnThisLooperThreadExecutor.java
com.google.android.apps.authenticator.SettingsAboutActivity.java
com.google.android.apps.authenticator.SettingsActivity.java
com.google.android.apps.authenticator.TotpClock.java
com.google.android.apps.authenticator.TotpCountdownTask.java
com.google.android.apps.authenticator.TotpCounter.java
com.google.android.apps.authenticator.UserRowView.java
com.google.android.apps.authenticator.Utilities.java
com.google.android.apps.authenticator.dataimport.ExportServiceBasedImportController.java
com.google.android.apps.authenticator.dataimport.ImportController.java
com.google.android.apps.authenticator.dataimport.Importer.java
com.google.android.apps.authenticator.howitworks.IntroEnterCodeActivity.java
com.google.android.apps.authenticator.howitworks.IntroEnterPasswordActivity.java
com.google.android.apps.authenticator.howitworks.IntroVerifyDeviceActivity.java
com.google.android.apps.authenticator.testability.DependencyInjector.java
com.google.android.apps.authenticator.testability.HttpClientFactory.java
com.google.android.apps.authenticator.testability.SharedPreferencesRenamingDelegatingContext.java
com.google.android.apps.authenticator.testability.StartActivityListener.java
com.google.android.apps.authenticator.testability.TestableActivity.java
com.google.android.apps.authenticator.testability.TestablePreferenceActivity.java
com.google.android.apps.authenticator.timesync.AboutActivity.java
com.google.android.apps.authenticator.timesync.NetworkTimeProvider.java
com.google.android.apps.authenticator.timesync.SettingsTimeCorrectionActivity.java
com.google.android.apps.authenticator.timesync.SyncNowActivity.java
com.google.android.apps.authenticator.timesync.SyncNowController.java
com.google.android.apps.authenticator.wizard.WizardPageActivity.java