1 /* 2 * Copyright 2015 The gRPC Authors 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package io.grpc; 18 19 import com.google.common.annotations.VisibleForTesting; 20 import io.grpc.ServiceProviders.PriorityAccessor; 21 import java.util.ArrayList; 22 import java.util.Iterator; 23 import java.util.List; 24 25 /** 26 * Provider of managed channels for transport agnostic consumption. 27 * 28 * <p>Implementations <em>should not</em> throw. If they do, it may interrupt class loading. If 29 * exceptions may reasonably occur for implementation-specific reasons, implementations should 30 * generally handle the exception gracefully and return {@code false} from {@link #isAvailable()}. 31 */ 32 @Internal 33 public abstract class ManagedChannelProvider { 34 @VisibleForTesting 35 static final Iterable<Class<?>> HARDCODED_CLASSES = new HardcodedClasses(); 36 37 private static final ManagedChannelProvider provider = ServiceProviders.load( 38 ManagedChannelProvider.class, 39 HARDCODED_CLASSES, 40 ManagedChannelProvider.class.getClassLoader(), 41 new PriorityAccessor<ManagedChannelProvider>() { 42 @Override 43 public boolean isAvailable(ManagedChannelProvider provider) { 44 return provider.isAvailable(); 45 } 46 47 @Override 48 public int getPriority(ManagedChannelProvider provider) { 49 return provider.priority(); 50 } 51 }); 52 53 /** 54 * Returns the ClassLoader-wide default channel. 55 * 56 * @throws ProviderNotFoundException if no provider is available 57 */ provider()58 public static ManagedChannelProvider provider() { 59 if (provider == null) { 60 throw new ProviderNotFoundException("No functional channel service provider found. " 61 + "Try adding a dependency on the grpc-okhttp, grpc-netty, or grpc-netty-shaded " 62 + "artifact"); 63 } 64 return provider; 65 } 66 67 /** 68 * Whether this provider is available for use, taking the current environment into consideration. 69 * If {@code false}, no other methods are safe to be called. 70 */ isAvailable()71 protected abstract boolean isAvailable(); 72 73 /** 74 * A priority, from 0 to 10 that this provider should be used, taking the current environment into 75 * consideration. 5 should be considered the default, and then tweaked based on environment 76 * detection. A priority of 0 does not imply that the provider wouldn't work; just that it should 77 * be last in line. 78 */ priority()79 protected abstract int priority(); 80 81 /** 82 * Creates a new builder with the given host and port. 83 */ builderForAddress(String name, int port)84 protected abstract ManagedChannelBuilder<?> builderForAddress(String name, int port); 85 86 /** 87 * Creates a new builder with the given target URI. 88 */ builderForTarget(String target)89 protected abstract ManagedChannelBuilder<?> builderForTarget(String target); 90 91 /** 92 * Thrown when no suitable {@link ManagedChannelProvider} objects can be found. 93 */ 94 public static final class ProviderNotFoundException extends RuntimeException { 95 private static final long serialVersionUID = 1; 96 ProviderNotFoundException(String msg)97 public ProviderNotFoundException(String msg) { 98 super(msg); 99 } 100 } 101 102 private static final class HardcodedClasses implements Iterable<Class<?>> { 103 @Override iterator()104 public Iterator<Class<?>> iterator() { 105 List<Class<?>> list = new ArrayList<Class<?>>(); 106 try { 107 list.add(Class.forName("io.grpc.okhttp.OkHttpChannelProvider")); 108 } catch (ClassNotFoundException ex) { 109 // ignore 110 } 111 try { 112 list.add(Class.forName("io.grpc.netty.NettyChannelProvider")); 113 } catch (ClassNotFoundException ex) { 114 // ignore 115 } 116 return list.iterator(); 117 } 118 } 119 } 120