@@ -156,6 +156,9 @@ public static ManagedChannelBuilder<?> forTarget(String target) {
156156 private final List <ClientInterceptor > interceptors = new ArrayList <>();
157157 NameResolverRegistry nameResolverRegistry = NameResolverRegistry .getDefaultRegistry ();
158158
159+ @ Nullable
160+ NameResolverProvider nameResolverProvider ;
161+
159162 final List <ClientTransportFilter > transportFilters = new ArrayList <>();
160163
161164 final String target ;
@@ -291,18 +294,53 @@ public ManagedChannelImplBuilder(
291294 String target , @ Nullable ChannelCredentials channelCreds , @ Nullable CallCredentials callCreds ,
292295 ClientTransportFactoryBuilder clientTransportFactoryBuilder ,
293296 @ Nullable ChannelBuilderDefaultPortProvider channelBuilderDefaultPortProvider ) {
297+ this (
298+ target ,
299+ channelCreds ,
300+ callCreds ,
301+ clientTransportFactoryBuilder ,
302+ channelBuilderDefaultPortProvider ,
303+ null ,
304+ null );
305+ }
306+
307+ /**
308+ * Creates a new managed channel builder with a target string, which can be
309+ * either a valid {@link io.grpc.NameResolver}-compliant URI, or an authority
310+ * string. Transport
311+ * implementors must provide client transport factory builder, and may set
312+ * custom channel default
313+ * port provider.
314+ *
315+ * @param channelCreds The ChannelCredentials provided by the user.
316+ * These may be used when
317+ * creating derivative channels.
318+ * @param nameResolverRegistry the registry used to look up name resolvers.
319+ * @param nameResolverProvider the provider used to look up name resolvers.
320+ */
321+ public ManagedChannelImplBuilder (
322+ String target , @ Nullable ChannelCredentials channelCreds , @ Nullable CallCredentials callCreds ,
323+ ClientTransportFactoryBuilder clientTransportFactoryBuilder ,
324+ @ Nullable ChannelBuilderDefaultPortProvider channelBuilderDefaultPortProvider ,
325+ @ Nullable NameResolverRegistry nameResolverRegistry ,
326+ @ Nullable NameResolverProvider nameResolverProvider ) {
294327 this .target = checkNotNull (target , "target" );
295328 this .channelCredentials = channelCreds ;
296329 this .callCredentials = callCreds ;
297330 this .clientTransportFactoryBuilder = checkNotNull (clientTransportFactoryBuilder ,
298331 "clientTransportFactoryBuilder" );
299332 this .directServerAddress = null ;
300333
301- if (channelBuilderDefaultPortProvider != null ) {
302- this .channelBuilderDefaultPortProvider = channelBuilderDefaultPortProvider ;
303- } else {
304- this .channelBuilderDefaultPortProvider = new ManagedChannelDefaultPortProvider ();
305- }
334+ this .channelBuilderDefaultPortProvider =
335+ channelBuilderDefaultPortProvider != null
336+ ? channelBuilderDefaultPortProvider
337+ : new ManagedChannelDefaultPortProvider ();
338+ this .nameResolverRegistry =
339+ nameResolverRegistry != null
340+ ? nameResolverRegistry
341+ : NameResolverRegistry .getDefaultRegistry ();
342+ this .nameResolverProvider = nameResolverProvider ;
343+
306344 // TODO(dnvindhya): Move configurator to all the individual builders
307345 InternalConfiguratorRegistry .configureChannelBuilder (this );
308346 }
@@ -422,6 +460,7 @@ public ManagedChannelImplBuilder nameResolverFactory(NameResolver.Factory resolv
422460 Preconditions .checkState (directServerAddress == null ,
423461 "directServerAddress is set (%s), which forbids the use of NameResolverFactory" ,
424462 directServerAddress );
463+
425464 if (resolverFactory != null ) {
426465 NameResolverRegistry reg = new NameResolverRegistry ();
427466 if (resolverFactory instanceof NameResolverProvider ) {
@@ -723,8 +762,8 @@ public ManagedChannel build() {
723762 clientTransportFactoryBuilder .buildClientTransportFactory ();
724763 ResolvedNameResolver resolvedResolver =
725764 InternalFeatureFlags .getRfc3986UrisEnabled ()
726- ? getNameResolverProviderRfc3986 (target , nameResolverRegistry )
727- : getNameResolverProvider (target , nameResolverRegistry );
765+ ? getNameResolverProviderRfc3986 (target , nameResolverRegistry , nameResolverProvider )
766+ : getNameResolverProvider (target , nameResolverRegistry , nameResolverProvider );
728767 resolvedResolver .checkAddressTypes (clientTransportFactory .getSupportedSocketAddressTypes ());
729768 return new ManagedChannelOrphanWrapper (new ManagedChannelImpl (
730769 this ,
@@ -845,7 +884,8 @@ void checkAddressTypes(
845884
846885 @ VisibleForTesting
847886 static ResolvedNameResolver getNameResolverProvider (
848- String target , NameResolverRegistry nameResolverRegistry ) {
887+ String target , NameResolverRegistry nameResolverRegistry ,
888+ NameResolverProvider nameResolverProvider ) {
849889 // Finding a NameResolver. Try using the target string as the URI. If that fails, try prepending
850890 // "dns:///".
851891 NameResolverProvider provider = null ;
@@ -860,19 +900,33 @@ static ResolvedNameResolver getNameResolverProvider(
860900 if (targetUri != null ) {
861901 // For "localhost:8080" this would likely cause provider to be null, because "localhost" is
862902 // parsed as the scheme. Will hit the next case and try "dns:///localhost:8080".
863- provider = nameResolverRegistry .getProviderForScheme (targetUri .getScheme ());
903+ // Use the explicit provider if its scheme matches the target URI.
904+ if (nameResolverProvider != null
905+ && targetUri .getScheme ().equals (nameResolverProvider .getScheme ())) {
906+ provider = nameResolverProvider ;
907+ } else {
908+ provider = nameResolverRegistry .getProviderForScheme (targetUri .getScheme ());
909+ }
864910 }
865911
866912 if (provider == null && !URI_PATTERN .matcher (target ).matches ()) {
867- // It doesn't look like a URI target. Maybe it's an authority string. Try with the default
868- // scheme from the registry.
913+ // It doesn't look like a URI target. Maybe it's an authority string. Try with
914+ // the default scheme from the registry (if provider is not specified) or
915+ // the provider's default scheme (if provider is specified).
916+ String scheme = nameResolverProvider != null
917+ ? nameResolverProvider .getScheme ()
918+ : nameResolverRegistry .getDefaultScheme ();
869919 try {
870- targetUri = new URI (nameResolverRegistry . getDefaultScheme () , "" , "/" + target , null );
920+ targetUri = new URI (scheme , "" , "/" + target , null );
871921 } catch (URISyntaxException e ) {
872- // Should not be possible.
922+ // Should not be possible
873923 throw new IllegalArgumentException (e );
874924 }
875- provider = nameResolverRegistry .getProviderForScheme (targetUri .getScheme ());
925+ if (nameResolverProvider != null ) {
926+ provider = nameResolverProvider ;
927+ } else {
928+ provider = nameResolverRegistry .getProviderForScheme (targetUri .getScheme ());
929+ }
876930 }
877931
878932 if (provider == null ) {
@@ -886,7 +940,8 @@ static ResolvedNameResolver getNameResolverProvider(
886940
887941 @ VisibleForTesting
888942 static ResolvedNameResolver getNameResolverProviderRfc3986 (
889- String target , NameResolverRegistry nameResolverRegistry ) {
943+ String target , NameResolverRegistry nameResolverRegistry ,
944+ NameResolverProvider nameResolverProvider ) {
890945 // Finding a NameResolver. Try using the target string as the URI. If that fails, try prepending
891946 // "dns:///".
892947 NameResolverProvider provider = null ;
@@ -901,15 +956,25 @@ static ResolvedNameResolver getNameResolverProviderRfc3986(
901956 if (targetUri != null ) {
902957 // For "localhost:8080" this would likely cause provider to be null, because "localhost" is
903958 // parsed as the scheme. Will hit the next case and try "dns:///localhost:8080".
904- provider = nameResolverRegistry .getProviderForScheme (targetUri .getScheme ());
959+ // Use the explicit provider if its scheme matches the target URI.
960+ if (nameResolverProvider != null
961+ && targetUri .getScheme ().equals (nameResolverProvider .getScheme ())) {
962+ provider = nameResolverProvider ;
963+ } else {
964+ provider = nameResolverRegistry .getProviderForScheme (targetUri .getScheme ());
965+ }
905966 }
906967
907968 if (provider == null && !URI_PATTERN .matcher (target ).matches ()) {
908- // It doesn't look like a URI target. Maybe it's an authority string. Try with the default
909- // scheme from the registry.
969+ // It doesn't look like a URI target. Maybe it's an authority string. Try with
970+ // the default scheme from the registry (if provider is not specified) or
971+ // the provider's default scheme (if provider is specified).
972+ String scheme = nameResolverProvider != null
973+ ? nameResolverProvider .getScheme ()
974+ : nameResolverRegistry .getDefaultScheme ();
910975 targetUri =
911976 Uri .newBuilder ()
912- .setScheme (nameResolverRegistry . getDefaultScheme () )
977+ .setScheme (scheme )
913978 .setHost ("" )
914979 .setPath ("/" + target )
915980 .build ();
0 commit comments