33import java .lang .reflect .InvocationTargetException ;
44import java .sql .SQLException ;
55import java .util .Properties ;
6+ import java .util .function .Consumer ;
67import java .util .function .Supplier ;
78import java .util .logging .Level ;
89import java .util .logging .Logger ;
@@ -54,6 +55,10 @@ public class YdbConnectionProperties {
5455 static final YdbProperty <String > METADATA_URL = YdbProperty .content ("metadataURL" ,
5556 "Custom URL for the metadata service authentication" );
5657
58+ static final YdbProperty <Object > CHANNEL_INITIALIZER = YdbProperty .object ("channelInitializer" ,
59+ "Custom GRPC channel initilizer, use object instance or class full name impementing"
60+ + " Consumer<ManagedChannelBuilder>" );
61+
5762 static final YdbProperty <Object > TOKEN_PROVIDER = YdbProperty .object ("tokenProvider" ,
5863 "Custom token provider, use object instance or class full name impementing Supplier<String>" );
5964
@@ -75,6 +80,7 @@ public class YdbConnectionProperties {
7580 private final YdbValue <String > iamEndpoint ;
7681 private final YdbValue <String > metadataUrl ;
7782 private final YdbValue <Object > tokenProvider ;
83+ private final YdbValue <Object > channelInitializer ;
7884 private final YdbValue <String > grpcCompression ;
7985
8086 public YdbConnectionProperties (String username , String password , Properties props ) throws SQLException {
@@ -92,6 +98,7 @@ public YdbConnectionProperties(String username, String password, Properties prop
9298 this .iamEndpoint = IAM_ENDPOINT .readValue (props );
9399 this .metadataUrl = METADATA_URL .readValue (props );
94100 this .tokenProvider = TOKEN_PROVIDER .readValue (props );
101+ this .channelInitializer = CHANNEL_INITIALIZER .readValue (props );
95102 this .grpcCompression = GRPC_COMPRESSION .readValue (props );
96103 }
97104
@@ -203,36 +210,12 @@ public GrpcTransportBuilder applyToGrpcTransport(GrpcTransportBuilder builder) t
203210 }
204211
205212 Object provider = tokenProvider .getValue ();
206- if (provider instanceof Supplier ) {
207- Supplier <?> prov = (Supplier <?>) provider ;
208- builder = builder .withAuthProvider ((rpc ) -> () -> prov .get ().toString ());
209- } else if (provider instanceof AuthProvider ) {
210- AuthProvider prov = (AuthProvider ) provider ;
211- builder = builder .withAuthProvider (prov );
212- } else if (provider instanceof String ) {
213- String className = (String ) provider ;
214- if (!FQCN .matcher (className ).matches ()) {
215- throw new SQLException ("tokenProvider must be full class name or instance of Supplier<String>" );
216- }
213+ builder = applyTokenProvider (builder , provider );
214+ }
217215
218- try {
219- Class <?> clazz = Class .forName (className );
220- if (!Supplier .class .isAssignableFrom (clazz )) {
221- throw new SQLException ("tokenProvider " + className + " is not implement Supplier<String>" );
222- }
223- Supplier <?> prov = clazz .asSubclass (Supplier .class )
224- .getConstructor (new Class <?>[0 ])
225- .newInstance (new Object [0 ]);
226- builder = builder .withAuthProvider ((rpc ) -> () -> prov .get ().toString ());
227- } catch (ClassNotFoundException ex ) {
228- throw new SQLException ("tokenProvider " + className + " not found" , ex );
229- } catch (NoSuchMethodException | SecurityException | InstantiationException | IllegalAccessException
230- | IllegalArgumentException | InvocationTargetException ex ) {
231- throw new SQLException ("Cannot construct tokenProvider " + className , ex );
232- }
233- } else if (provider != null ) {
234- throw new SQLException ("Cannot parse tokenProvider " + provider .getClass ().getName ());
235- }
216+ if (channelInitializer .hasValue ()) {
217+ Object initializer = channelInitializer .getValue ();
218+ builder = applyChannelInitializer (builder , initializer );
236219 }
237220
238221 if (grpcCompression .hasValue ()) {
@@ -248,4 +231,74 @@ public GrpcTransportBuilder applyToGrpcTransport(GrpcTransportBuilder builder) t
248231
249232 return builder ;
250233 }
234+
235+ private GrpcTransportBuilder applyTokenProvider (GrpcTransportBuilder builder , Object provider ) throws SQLException {
236+ if (provider instanceof Supplier ) {
237+ Supplier <?> prov = (Supplier <?>) provider ;
238+ builder = builder .withAuthProvider ((rpc ) -> () -> prov .get ().toString ());
239+ } else if (provider instanceof AuthProvider ) {
240+ AuthProvider prov = (AuthProvider ) provider ;
241+ builder = builder .withAuthProvider (prov );
242+ } else if (provider instanceof String ) {
243+ String className = (String ) provider ;
244+ if (!FQCN .matcher (className ).matches ()) {
245+ throw new SQLException ("tokenProvider must be full class name or instance of Supplier<String>" );
246+ }
247+
248+ try {
249+ Class <?> clazz = Class .forName (className );
250+ if (!Supplier .class .isAssignableFrom (clazz )) {
251+ throw new SQLException ("tokenProvider " + className + " is not implement Supplier<String>" );
252+ }
253+ Supplier <?> prov = clazz .asSubclass (Supplier .class )
254+ .getConstructor (new Class <?>[0 ])
255+ .newInstance (new Object [0 ]);
256+ builder = builder .withAuthProvider ((rpc ) -> () -> prov .get ().toString ());
257+ } catch (ClassNotFoundException ex ) {
258+ throw new SQLException ("tokenProvider " + className + " not found" , ex );
259+ } catch (NoSuchMethodException | SecurityException | InstantiationException | IllegalAccessException
260+ | IllegalArgumentException | InvocationTargetException ex ) {
261+ throw new SQLException ("Cannot construct tokenProvider " + className , ex );
262+ }
263+ } else if (provider != null ) {
264+ throw new SQLException ("Cannot parse tokenProvider " + provider .getClass ().getName ());
265+ }
266+ return builder ;
267+ }
268+
269+ private GrpcTransportBuilder applyChannelInitializer (GrpcTransportBuilder builder , Object initializer )
270+ throws SQLException {
271+ if (initializer instanceof Consumer ) {
272+ @ SuppressWarnings ("unchecked" )
273+ Consumer <Object > prov = (Consumer <Object >) initializer ;
274+ builder = builder .addChannelInitializer (prov );
275+ } else if (initializer instanceof String ) {
276+ String className = (String ) initializer ;
277+ if (!FQCN .matcher (className ).matches ()) {
278+ throw new SQLException ("channelInitializer must be full class name or instance of "
279+ + "Consumer<ManagedChannelBuilder>" );
280+ }
281+
282+ try {
283+ Class <?> clazz = Class .forName (className );
284+ if (!Consumer .class .isAssignableFrom (clazz )) {
285+ throw new SQLException ("channelInitializer " + className + " is not implement "
286+ + "Consumer<ManagedChannelBuilder>" );
287+ }
288+ @ SuppressWarnings ("unchecked" )
289+ Consumer <Object > prov = clazz .asSubclass (Consumer .class )
290+ .getConstructor (new Class <?>[0 ])
291+ .newInstance (new Object [0 ]);
292+ builder = builder .addChannelInitializer (prov );
293+ } catch (ClassNotFoundException ex ) {
294+ throw new SQLException ("channelInitializer " + className + " not found" , ex );
295+ } catch (NoSuchMethodException | SecurityException | InstantiationException | IllegalAccessException
296+ | IllegalArgumentException | InvocationTargetException ex ) {
297+ throw new SQLException ("Cannot construct channelInitializer " + className , ex );
298+ }
299+ } else if (initializer != null ) {
300+ throw new SQLException ("Cannot parse channelInitializer " + initializer .getClass ().getName ());
301+ }
302+ return builder ;
303+ }
251304}
0 commit comments