mirror of https://github.com/grpc/grpc-java.git
core: generifiy ServiceProvider class (#3886)
Moving all the common code among different service provider classes to one place.
This commit is contained in:
parent
417765b814
commit
2996207c20
|
|
@ -0,0 +1,74 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2017, gRPC Authors All rights reserved.
|
||||||
|
*
|
||||||
|
* 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 io.grpc;
|
||||||
|
|
||||||
|
import com.google.common.annotations.VisibleForTesting;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Internal
|
||||||
|
public final class InternalServiceProviders {
|
||||||
|
private InternalServiceProviders() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Accessor for method.
|
||||||
|
*/
|
||||||
|
public static <T> T load(
|
||||||
|
Class<T> klass,
|
||||||
|
Iterable<Class<?>> hardcoded,
|
||||||
|
ClassLoader classLoader,
|
||||||
|
PriorityAccessor<T> priorityAccessor) {
|
||||||
|
return ServiceProviders.load(klass, hardcoded, classLoader, priorityAccessor);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Accessor for method.
|
||||||
|
*/
|
||||||
|
public static <T> List<T> loadAll(
|
||||||
|
Class<T> klass,
|
||||||
|
Iterable<Class<?>> hardCodedClasses,
|
||||||
|
ClassLoader classLoader,
|
||||||
|
PriorityAccessor<T> priorityAccessor) {
|
||||||
|
return ServiceProviders.loadAll(klass, hardCodedClasses, classLoader, priorityAccessor);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Accessor for method.
|
||||||
|
*/
|
||||||
|
@VisibleForTesting
|
||||||
|
public static <T> Iterable<T> getCandidatesViaServiceLoader(Class<T> klass, ClassLoader cl) {
|
||||||
|
return ServiceProviders.getCandidatesViaServiceLoader(klass, cl);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Accessor for method.
|
||||||
|
*/
|
||||||
|
@VisibleForTesting
|
||||||
|
public static <T> Iterable<T> getCandidatesViaHardCoded(
|
||||||
|
Class<T> klass, Iterable<Class<?>> hardcoded) {
|
||||||
|
return ServiceProviders.getCandidatesViaHardCoded(klass, hardcoded);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Accessor for {@link ServiceProviders#isAndroid}.
|
||||||
|
*/
|
||||||
|
public static boolean isAndroid(ClassLoader cl) {
|
||||||
|
return ServiceProviders.isAndroid(cl);
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface PriorityAccessor<T> extends ServiceProviders.PriorityAccessor<T> {}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,153 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2017, gRPC Authors All rights reserved.
|
||||||
|
*
|
||||||
|
* 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 io.grpc;
|
||||||
|
|
||||||
|
import com.google.common.annotations.VisibleForTesting;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.ServiceConfigurationError;
|
||||||
|
import java.util.ServiceLoader;
|
||||||
|
|
||||||
|
final class ServiceProviders {
|
||||||
|
private ServiceProviders() {
|
||||||
|
// do not instantiate
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If this is not Android, returns the highest priority implementation of the class via
|
||||||
|
* {@link ServiceLoader}.
|
||||||
|
* If this is Android, returns an instance of the highest priority class in {@code hardcoded}.
|
||||||
|
*/
|
||||||
|
public static <T> T load(
|
||||||
|
Class<T> klass,
|
||||||
|
Iterable<Class<?>> hardcoded,
|
||||||
|
ClassLoader cl,
|
||||||
|
PriorityAccessor<T> priorityAccessor) {
|
||||||
|
List<T> candidates = loadAll(klass, hardcoded, cl, priorityAccessor);
|
||||||
|
if (candidates.isEmpty()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return candidates.get(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If this is not Android, returns all available implementations discovered via
|
||||||
|
* {@link ServiceLoader}.
|
||||||
|
* If this is Android, returns all available implementations in {@code hardcoded}.
|
||||||
|
* The list is sorted in descending priority order.
|
||||||
|
*/
|
||||||
|
public static <T> List<T> loadAll(
|
||||||
|
Class<T> klass,
|
||||||
|
Iterable<Class<?>> hardcoded,
|
||||||
|
ClassLoader cl,
|
||||||
|
final PriorityAccessor<T> priorityAccessor) {
|
||||||
|
Iterable<T> candidates;
|
||||||
|
if (isAndroid(cl)) {
|
||||||
|
candidates = getCandidatesViaHardCoded(klass, hardcoded);
|
||||||
|
} else {
|
||||||
|
candidates = getCandidatesViaServiceLoader(klass, cl);
|
||||||
|
}
|
||||||
|
List<T> list = new ArrayList<T>();
|
||||||
|
for (T current: candidates) {
|
||||||
|
if (!priorityAccessor.isAvailable(current)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
list.add(current);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sort descending based on priority.
|
||||||
|
Collections.sort(list, Collections.reverseOrder(new Comparator<T>() {
|
||||||
|
@Override
|
||||||
|
public int compare(T f1, T f2) {
|
||||||
|
return priorityAccessor.getPriority(f1) - priorityAccessor.getPriority(f2);
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
return Collections.unmodifiableList(list);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if the {@link ClassLoader} is for android.
|
||||||
|
*/
|
||||||
|
static boolean isAndroid(ClassLoader cl) {
|
||||||
|
try {
|
||||||
|
// Specify a class loader instead of null because we may be running under Robolectric
|
||||||
|
Class.forName("android.app.Application", /*initialize=*/ false, cl);
|
||||||
|
return true;
|
||||||
|
} catch (Exception e) {
|
||||||
|
// If Application isn't loaded, it might as well not be Android.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads service providers for the {@code klass} service using {@link ServiceLoader}.
|
||||||
|
*/
|
||||||
|
@VisibleForTesting
|
||||||
|
public static <T> Iterable<T> getCandidatesViaServiceLoader(Class<T> klass, ClassLoader cl) {
|
||||||
|
Iterable<T> i = ServiceLoader.load(klass, cl);
|
||||||
|
// Attempt to load using the context class loader and ServiceLoader.
|
||||||
|
// This allows frameworks like http://aries.apache.org/modules/spi-fly.html to plug in.
|
||||||
|
if (!i.iterator().hasNext()) {
|
||||||
|
i = ServiceLoader.load(klass);
|
||||||
|
}
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load providers from a hard-coded list. This avoids using getResource(), which has performance
|
||||||
|
* problems on Android (see https://github.com/grpc/grpc-java/issues/2037).
|
||||||
|
*/
|
||||||
|
@VisibleForTesting
|
||||||
|
static <T> Iterable<T> getCandidatesViaHardCoded(Class<T> klass, Iterable<Class<?>> hardcoded) {
|
||||||
|
List<T> list = new ArrayList<T>();
|
||||||
|
for (Class<?> candidate : hardcoded) {
|
||||||
|
list.add(create(klass, candidate));
|
||||||
|
}
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
@VisibleForTesting
|
||||||
|
static <T> T create(Class<T> klass, Class<?> rawClass) {
|
||||||
|
try {
|
||||||
|
return rawClass.asSubclass(klass).getConstructor().newInstance();
|
||||||
|
} catch (Throwable t) {
|
||||||
|
throw new ServiceConfigurationError(
|
||||||
|
String.format("Provider %s could not be instantiated %s", rawClass.getName(), t), t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An interface that allows us to get priority information about a provider.
|
||||||
|
*/
|
||||||
|
public interface PriorityAccessor<T> {
|
||||||
|
/**
|
||||||
|
* Checks this provider is available for use, taking the current environment into consideration.
|
||||||
|
* If {@code false}, no other methods are safe to be called.
|
||||||
|
*/
|
||||||
|
boolean isAvailable(T provider);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A priority, from 0 to 10 that this provider should be used, taking the current environment
|
||||||
|
* into consideration. 5 should be considered the default, and then tweaked based on environment
|
||||||
|
* detection. A priority of 0 does not imply that the provider wouldn't work; just that it
|
||||||
|
* should be last in line.
|
||||||
|
*/
|
||||||
|
int getPriority(T provider);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,316 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2015, gRPC Authors All rights reserved.
|
||||||
|
*
|
||||||
|
* 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 io.grpc;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertFalse;
|
||||||
|
import static org.junit.Assert.assertNull;
|
||||||
|
import static org.junit.Assert.assertSame;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
import static org.junit.Assert.fail;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableList;
|
||||||
|
import io.grpc.InternalServiceProviders.PriorityAccessor;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.ServiceConfigurationError;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.junit.runners.JUnit4;
|
||||||
|
|
||||||
|
/** Unit tests for {@link ServiceProviders}. */
|
||||||
|
@RunWith(JUnit4.class)
|
||||||
|
public class ServiceProvidersTest {
|
||||||
|
private static final List<Class<?>> NO_HARDCODED = Collections.emptyList();
|
||||||
|
private static final PriorityAccessor<FooProvider> ACCESSOR =
|
||||||
|
new PriorityAccessor<FooProvider>() {
|
||||||
|
@Override
|
||||||
|
public boolean isAvailable(FooProvider provider) {
|
||||||
|
return provider.isAvailable();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getPriority(FooProvider provider) {
|
||||||
|
return provider.priority();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
private final String serviceFile = "META-INF/services/io.grpc.ServiceProvidersTest$FooProvider";
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void contextClassLoaderProvider() {
|
||||||
|
ClassLoader ccl = Thread.currentThread().getContextClassLoader();
|
||||||
|
try {
|
||||||
|
ClassLoader cl = new ReplacingClassLoader(
|
||||||
|
getClass().getClassLoader(),
|
||||||
|
serviceFile,
|
||||||
|
"io/grpc/ServiceProvidersTest$FooProvider-multipleProvider.txt");
|
||||||
|
|
||||||
|
// test that the context classloader is used as fallback
|
||||||
|
ClassLoader rcll = new ReplacingClassLoader(
|
||||||
|
getClass().getClassLoader(),
|
||||||
|
serviceFile,
|
||||||
|
"io/grpc/ServiceProvidersTest$FooProvider-empty.txt");
|
||||||
|
Thread.currentThread().setContextClassLoader(rcll);
|
||||||
|
assertEquals(
|
||||||
|
Available7Provider.class,
|
||||||
|
ServiceProviders.load(FooProvider.class, NO_HARDCODED, cl, ACCESSOR).getClass());
|
||||||
|
} finally {
|
||||||
|
Thread.currentThread().setContextClassLoader(ccl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void noProvider() {
|
||||||
|
ClassLoader ccl = Thread.currentThread().getContextClassLoader();
|
||||||
|
try {
|
||||||
|
ClassLoader cl = new ReplacingClassLoader(
|
||||||
|
getClass().getClassLoader(),
|
||||||
|
serviceFile,
|
||||||
|
"io/grpc/ServiceProvidersTest$FooProvider-doesNotExist.txt");
|
||||||
|
Thread.currentThread().setContextClassLoader(cl);
|
||||||
|
assertNull(ServiceProviders.load(FooProvider.class, NO_HARDCODED, cl, ACCESSOR));
|
||||||
|
} finally {
|
||||||
|
Thread.currentThread().setContextClassLoader(ccl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void multipleProvider() throws Exception {
|
||||||
|
ClassLoader cl = new ReplacingClassLoader(getClass().getClassLoader(), serviceFile,
|
||||||
|
"io/grpc/ServiceProvidersTest$FooProvider-multipleProvider.txt");
|
||||||
|
assertSame(
|
||||||
|
Available7Provider.class,
|
||||||
|
ServiceProviders.load(FooProvider.class, NO_HARDCODED, cl, ACCESSOR).getClass());
|
||||||
|
|
||||||
|
List<FooProvider> providers = ServiceProviders.loadAll(
|
||||||
|
FooProvider.class, NO_HARDCODED, cl, ACCESSOR);
|
||||||
|
assertEquals(3, providers.size());
|
||||||
|
assertEquals(Available7Provider.class, providers.get(0).getClass());
|
||||||
|
assertEquals(Available5Provider.class, providers.get(1).getClass());
|
||||||
|
assertEquals(Available0Provider.class, providers.get(2).getClass());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void unavailableProvider() {
|
||||||
|
// tries to load Available7 and UnavailableProvider, which has priority 10
|
||||||
|
ClassLoader cl = new ReplacingClassLoader(getClass().getClassLoader(), serviceFile,
|
||||||
|
"io/grpc/ServiceProvidersTest$FooProvider-unavailableProvider.txt");
|
||||||
|
assertEquals(
|
||||||
|
Available7Provider.class,
|
||||||
|
ServiceProviders.load(FooProvider.class, NO_HARDCODED, cl, ACCESSOR).getClass());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void unknownClassProvider() {
|
||||||
|
ClassLoader cl = new ReplacingClassLoader(getClass().getClassLoader(), serviceFile,
|
||||||
|
"io/grpc/ServiceProvidersTest$FooProvider-unknownClassProvider.txt");
|
||||||
|
try {
|
||||||
|
FooProvider ignored = ServiceProviders.load(FooProvider.class, NO_HARDCODED, cl, ACCESSOR);
|
||||||
|
fail("Exception expected");
|
||||||
|
} catch (ServiceConfigurationError e) {
|
||||||
|
// noop
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void exceptionSurfacedToCaller_failAtInit() {
|
||||||
|
ClassLoader cl = new ReplacingClassLoader(getClass().getClassLoader(), serviceFile,
|
||||||
|
"io/grpc/ServiceProvidersTest$FooProvider-failAtInitProvider.txt");
|
||||||
|
try {
|
||||||
|
// Even though there is a working provider, if any providers fail then we should fail
|
||||||
|
// completely to avoid returning something unexpected.
|
||||||
|
FooProvider ignored = ServiceProviders.load(FooProvider.class, NO_HARDCODED, cl, ACCESSOR);
|
||||||
|
fail("Expected exception");
|
||||||
|
} catch (ServiceConfigurationError expected) {
|
||||||
|
// noop
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void exceptionSurfacedToCaller_failAtPriority() {
|
||||||
|
ClassLoader cl = new ReplacingClassLoader(getClass().getClassLoader(), serviceFile,
|
||||||
|
"io/grpc/ServiceProvidersTest$FooProvider-failAtPriorityProvider.txt");
|
||||||
|
try {
|
||||||
|
// The exception should be surfaced to the caller
|
||||||
|
FooProvider ignored = ServiceProviders.load(FooProvider.class, NO_HARDCODED, cl, ACCESSOR);
|
||||||
|
fail("Expected exception");
|
||||||
|
} catch (FailAtPriorityProvider.PriorityException expected) {
|
||||||
|
// noop
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void exceptionSurfacedToCaller_failAtAvailable() {
|
||||||
|
ClassLoader cl = new ReplacingClassLoader(getClass().getClassLoader(), serviceFile,
|
||||||
|
"io/grpc/ServiceProvidersTest$FooProvider-failAtAvailableProvider.txt");
|
||||||
|
try {
|
||||||
|
// The exception should be surfaced to the caller
|
||||||
|
FooProvider ignored = ServiceProviders.load(FooProvider.class, NO_HARDCODED, cl, ACCESSOR);
|
||||||
|
fail("Expected exception");
|
||||||
|
} catch (FailAtAvailableProvider.AvailableException expected) {
|
||||||
|
// noop
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getCandidatesViaHardCoded_multipleProvider() throws Exception {
|
||||||
|
Iterator<FooProvider> candidates = ServiceProviders.getCandidatesViaHardCoded(
|
||||||
|
FooProvider.class,
|
||||||
|
ImmutableList.<Class<?>>of(
|
||||||
|
Available7Provider.class,
|
||||||
|
Available0Provider.class))
|
||||||
|
.iterator();
|
||||||
|
assertEquals(Available7Provider.class, candidates.next().getClass());
|
||||||
|
assertEquals(Available0Provider.class, candidates.next().getClass());
|
||||||
|
assertFalse(candidates.hasNext());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getCandidatesViaHardCoded_failAtInit() throws Exception {
|
||||||
|
try {
|
||||||
|
Iterable<FooProvider> ignored = ServiceProviders.getCandidatesViaHardCoded(
|
||||||
|
FooProvider.class,
|
||||||
|
Collections.<Class<?>>singletonList(FailAtInitProvider.class));
|
||||||
|
fail("Expected exception");
|
||||||
|
} catch (ServiceConfigurationError expected) {
|
||||||
|
// noop
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getCandidatesViaHardCoded_failAtInit_moreCandidates() throws Exception {
|
||||||
|
try {
|
||||||
|
Iterable<FooProvider> ignored = ServiceProviders.getCandidatesViaHardCoded(
|
||||||
|
FooProvider.class,
|
||||||
|
ImmutableList.<Class<?>>of(FailAtInitProvider.class, Available0Provider.class));
|
||||||
|
fail("Expected exception");
|
||||||
|
} catch (ServiceConfigurationError expected) {
|
||||||
|
// noop
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void create_throwsErrorOnMisconfiguration() throws Exception {
|
||||||
|
class PrivateClass {}
|
||||||
|
|
||||||
|
try {
|
||||||
|
FooProvider ignored = ServiceProviders.create(FooProvider.class, PrivateClass.class);
|
||||||
|
fail("Expected exception");
|
||||||
|
} catch (ServiceConfigurationError expected) {
|
||||||
|
assertTrue("Expected ClassCastException cause: " + expected.getCause(),
|
||||||
|
expected.getCause() instanceof ClassCastException);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A provider class for this unit test.
|
||||||
|
*/
|
||||||
|
public abstract static class FooProvider {
|
||||||
|
abstract boolean isAvailable();
|
||||||
|
|
||||||
|
abstract int priority();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class BaseProvider extends FooProvider {
|
||||||
|
private final boolean isAvailable;
|
||||||
|
private final int priority;
|
||||||
|
|
||||||
|
public BaseProvider(boolean isAvailable, int priority) {
|
||||||
|
this.isAvailable = isAvailable;
|
||||||
|
this.priority = priority;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isAvailable() {
|
||||||
|
return isAvailable;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int priority() {
|
||||||
|
return priority;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final class Available0Provider extends BaseProvider {
|
||||||
|
public Available0Provider() {
|
||||||
|
super(true, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final class Available5Provider extends BaseProvider {
|
||||||
|
public Available5Provider() {
|
||||||
|
super(true, 5);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final class Available7Provider extends BaseProvider {
|
||||||
|
public Available7Provider() {
|
||||||
|
super(true, 7);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final class UnavailableProvider extends BaseProvider {
|
||||||
|
public UnavailableProvider() {
|
||||||
|
super(false, 10);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final class FailAtInitProvider extends FooProvider {
|
||||||
|
public FailAtInitProvider() {
|
||||||
|
throw new RuntimeException("intentionally broken");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isAvailable() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int priority() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final class FailAtPriorityProvider extends FooProvider {
|
||||||
|
@Override
|
||||||
|
public boolean isAvailable() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int priority() {
|
||||||
|
throw new PriorityException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final class PriorityException extends RuntimeException {}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final class FailAtAvailableProvider extends FooProvider {
|
||||||
|
@Override
|
||||||
|
public boolean isAvailable() {
|
||||||
|
throw new AvailableException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int priority() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final class AvailableException extends RuntimeException {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
io.grpc.ServiceProvidersTest$FailAtAvailableProvider
|
||||||
|
io.grpc.ServiceProvidersTest$Available5Provider
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
io.grpc.ServiceProvidersTest$FailAtInitProvider
|
||||||
|
io.grpc.ServiceProvidersTest$Available5Provider
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
io.grpc.ServiceProvidersTest$FailAtPriorityProvider
|
||||||
|
io.grpc.ServiceProvidersTest$Available5Provider
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
io.grpc.ServiceProvidersTest$Available5Provider
|
||||||
|
io.grpc.ServiceProvidersTest$Available7Provider
|
||||||
|
io.grpc.ServiceProvidersTest$Available0Provider
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
io.grpc.ServiceProvidersTest$UnavailableProvider
|
||||||
|
io.grpc.ServiceProvidersTest$Available7Provider
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
io.grpc.ServiceProvidersTest$UnknownClassProvider
|
||||||
Loading…
Reference in New Issue