| Index: chrome/android/java/src/org/chromium/chrome/browser/Implementations.java
|
| diff --git a/chrome/android/java/src/org/chromium/chrome/browser/Implementations.java b/chrome/android/java/src/org/chromium/chrome/browser/Implementations.java
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..1d77a5c0a1bb2a60ffff7c6178d09f05acf81e6e
|
| --- /dev/null
|
| +++ b/chrome/android/java/src/org/chromium/chrome/browser/Implementations.java
|
| @@ -0,0 +1,75 @@
|
| +// Copyright 2017 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +package org.chromium.chrome.browser;
|
| +
|
| +/**
|
| + * This class provides access to classes that may have specific downstream implementations.
|
| + */
|
| +public class Implementations {
|
| + private static final String METADATA_CLASS_NAME = "ImplementationsMetadata";
|
| +
|
| + static class Metadata {
|
| + Class<? extends Implementations> getImplementationsClass() {
|
| + return Implementations.class;
|
| + }
|
| + }
|
| +
|
| + // Initialization on demand holder idiom
|
| + private static class LazyHolder {
|
| + private static final Implementations INSTANCE = createInstance();
|
| +
|
| + @SuppressWarnings("unchecked")
|
| + private static Implementations createInstance() {
|
| + // We have to create this class by its class name since it may not be available.
|
| + Class<? extends Metadata> metadataClass;
|
| + try {
|
| + metadataClass = (Class<? extends Metadata>) Class.forName(METADATA_CLASS_NAME);
|
| + } catch (ClassNotFoundException e) {
|
| + metadataClass = Metadata.class;
|
| + }
|
| + Metadata metadata = create(Metadata.class, metadataClass);
|
| + return create(Implementations.class, metadata.getImplementationsClass());
|
| + }
|
| + }
|
| +
|
| + /**
|
| + * Instantiates an object of a given type.
|
| + * This method exists as a utility to generate objects of types that have different
|
| + * implementations upstream and downstream. To use this,
|
| + * - give the upstream class a public parameterless constructor,
|
| + * - give the downstream class a public parameterless constructor,
|
| + * - register the downstream class in the downstream Implementations getClass() method, and
|
| + * - invoke this method on the appropriate class (e.g., Implementations.create(MyType.class)).
|
| + * @param klass The class that the Chrome Application should create an instance of.
|
| + */
|
| + public static <T> T create(Class<T> klass) {
|
| + return create(klass, LazyHolder.INSTANCE.getClass(klass));
|
| + }
|
| +
|
| + /**
|
| + * Selects an appropriate implementation of a class given a build (upstream vs downstream).
|
| + * @param klass The class that we will be asked to create an implementaiton of.
|
| + */
|
| + protected <T> Class<? extends T> getClass(Class<T> klass) {
|
| + return klass;
|
| + }
|
| +
|
| + @SuppressWarnings("unchecked")
|
| + private static <T> T create(Class<T> baseClass, Class<? extends T> subClass) {
|
| + if (!baseClass.isAssignableFrom(subClass)) {
|
| + throw new RuntimeException("Asked to create an instance of type " + subClass.getName()
|
| + + " which is not a subtype of " + baseClass.getName());
|
| + }
|
| +
|
| + Object obj;
|
| + try {
|
| + obj = subClass.newInstance();
|
| + } catch (InstantiationException | IllegalAccessException e) {
|
| + throw new RuntimeException("Asked to create unexpected class: "
|
| + + subClass.getName(), e);
|
| + }
|
| + return (T) obj;
|
| + }
|
| +}
|
|
|