35
35
import oracle .ucp .jdbc .PoolDataSourceImpl ;
36
36
import org .apache .commons .dbcp2 .BasicDataSource ;
37
37
import org .h2 .jdbcx .JdbcDataSource ;
38
+ import org .jspecify .annotations .Nullable ;
38
39
import org .postgresql .ds .PGSimpleDataSource ;
39
40
import org .vibur .dbcp .ViburDBCPDataSource ;
40
41
41
42
import org .springframework .beans .BeanUtils ;
42
43
import org .springframework .core .ResolvableType ;
43
44
import org .springframework .jdbc .datasource .SimpleDriverDataSource ;
45
+ import org .springframework .lang .Contract ;
44
46
import org .springframework .util .Assert ;
45
47
import org .springframework .util .ClassUtils ;
46
48
import org .springframework .util .ReflectionUtils ;
89
91
*/
90
92
public final class DataSourceBuilder <T extends DataSource > {
91
93
92
- private final ClassLoader classLoader ;
94
+ private final @ Nullable ClassLoader classLoader ;
93
95
94
96
private final Map <DataSourceProperty , String > values = new HashMap <>();
95
97
96
- private Class <T > type ;
98
+ private @ Nullable Class <T > type ;
97
99
98
- private final DataSource deriveFrom ;
100
+ private final @ Nullable DataSource deriveFrom ;
99
101
100
- private DataSourceBuilder (ClassLoader classLoader ) {
102
+ private DataSourceBuilder (@ Nullable ClassLoader classLoader ) {
101
103
this .classLoader = classLoader ;
102
104
this .deriveFrom = null ;
103
105
}
@@ -117,7 +119,7 @@ private DataSourceBuilder(T deriveFrom) {
117
119
* @return this builder
118
120
*/
119
121
@ SuppressWarnings ("unchecked" )
120
- public <D extends DataSource > DataSourceBuilder <D > type (Class <D > type ) {
122
+ public <D extends DataSource > DataSourceBuilder <D > type (@ Nullable Class <D > type ) {
121
123
this .type = (Class <T >) type ;
122
124
return (DataSourceBuilder <D >) this ;
123
125
}
@@ -147,7 +149,7 @@ public DataSourceBuilder<T> driverClassName(String driverClassName) {
147
149
* @param username the user name
148
150
* @return this builder
149
151
*/
150
- public DataSourceBuilder <T > username (String username ) {
152
+ public DataSourceBuilder <T > username (@ Nullable String username ) {
151
153
set (DataSourceProperty .USERNAME , username );
152
154
return this ;
153
155
}
@@ -157,12 +159,12 @@ public DataSourceBuilder<T> username(String username) {
157
159
* @param password the password
158
160
* @return this builder
159
161
*/
160
- public DataSourceBuilder <T > password (String password ) {
162
+ public DataSourceBuilder <T > password (@ Nullable String password ) {
161
163
set (DataSourceProperty .PASSWORD , password );
162
164
return this ;
163
165
}
164
166
165
- private void set (DataSourceProperty property , String value ) {
167
+ private void set (DataSourceProperty property , @ Nullable String value ) {
166
168
this .values .put (property , value );
167
169
}
168
170
@@ -178,7 +180,8 @@ public T build() {
178
180
Set <DataSourceProperty > applied = new HashSet <>();
179
181
for (DataSourceProperty property : DataSourceProperty .values ()) {
180
182
String value = this .values .get (property );
181
- if (value == null && deriveFromProperties != null && properties .canSet (property )) {
183
+ if (value == null && deriveFromProperties != null && this .deriveFrom != null
184
+ && properties .canSet (property )) {
182
185
value = deriveFromProperties .get (this .deriveFrom , property );
183
186
}
184
187
if (value != null ) {
@@ -193,14 +196,14 @@ public T build() {
193
196
DatabaseDriver driver = DatabaseDriver .fromJdbcUrl (url );
194
197
String driverClassName = driver .getDriverClassName ();
195
198
if (driverClassName != null ) {
196
- properties .set (dataSource , DataSourceProperty .DRIVER_CLASS_NAME , driver . getDriverClassName () );
199
+ properties .set (dataSource , DataSourceProperty .DRIVER_CLASS_NAME , driverClassName );
197
200
}
198
201
}
199
202
return dataSource ;
200
203
}
201
204
202
205
@ SuppressWarnings ("unchecked" )
203
- private DataSourceProperties <DataSource > getDeriveFromProperties () {
206
+ private @ Nullable DataSourceProperties <DataSource > getDeriveFromProperties () {
204
207
if (this .deriveFrom == null ) {
205
208
return null ;
206
209
}
@@ -220,7 +223,7 @@ public static DataSourceBuilder<?> create() {
220
223
* @param classLoader the classloader used to discover preferred settings
221
224
* @return a new {@link DataSource} builder instance
222
225
*/
223
- public static DataSourceBuilder <?> create (ClassLoader classLoader ) {
226
+ public static DataSourceBuilder <?> create (@ Nullable ClassLoader classLoader ) {
224
227
return new DataSourceBuilder <>(classLoader );
225
228
}
226
229
@@ -258,7 +261,7 @@ private static DataSource unwrap(DataSource dataSource) {
258
261
* @param classLoader the classloader used to discover preferred settings
259
262
* @return the preferred {@link DataSource} type
260
263
*/
261
- public static Class <? extends DataSource > findType (ClassLoader classLoader ) {
264
+ public static @ Nullable Class <? extends DataSource > findType (@ Nullable ClassLoader classLoader ) {
262
265
MappedDataSourceProperties <?> mappings = MappedDataSourceProperties .forType (classLoader , null );
263
266
return (mappings != null ) ? mappings .getDataSourceInstanceType () : null ;
264
267
}
@@ -294,15 +297,15 @@ public String toString() {
294
297
return this .names [0 ];
295
298
}
296
299
297
- Method findSetter (Class <?> type ) {
300
+ @ Nullable Method findSetter (Class <?> type ) {
298
301
return findMethod ("set" , type , String .class );
299
302
}
300
303
301
- Method findGetter (Class <?> type ) {
304
+ @ Nullable Method findGetter (Class <?> type ) {
302
305
return findMethod ("get" , type );
303
306
}
304
307
305
- private Method findMethod (String prefix , Class <?> type , Class <?>... paramTypes ) {
308
+ private @ Nullable Method findMethod (String prefix , Class <?> type , Class <?>... paramTypes ) {
306
309
for (String name : this .names ) {
307
310
String candidate = prefix + StringUtils .capitalize (name );
308
311
Method method = ReflectionUtils .findMethod (type , candidate , paramTypes );
@@ -323,11 +326,16 @@ private interface DataSourceProperties<T extends DataSource> {
323
326
324
327
void set (T dataSource , DataSourceProperty property , String value );
325
328
326
- String get (T dataSource , DataSourceProperty property );
329
+ @ Nullable String get (T dataSource , DataSourceProperty property );
327
330
328
- static <T extends DataSource > DataSourceProperties <T > forType (ClassLoader classLoader , Class <T > type ) {
331
+ static <T extends DataSource > DataSourceProperties <T > forType (@ Nullable ClassLoader classLoader ,
332
+ @ Nullable Class <T > type ) {
329
333
MappedDataSourceProperties <T > mapped = MappedDataSourceProperties .forType (classLoader , type );
330
- return (mapped != null ) ? mapped : new ReflectionDataSourceProperties <>(type );
334
+ if (mapped != null ) {
335
+ return mapped ;
336
+ }
337
+ Assert .state (type != null , "No supported DataSource type found" );
338
+ return new ReflectionDataSourceProperties <>(type );
331
339
}
332
340
333
341
}
@@ -338,22 +346,29 @@ private static class MappedDataSourceProperties<T extends DataSource> implements
338
346
339
347
private final Class <T > dataSourceType ;
340
348
341
- @ SuppressWarnings ("unchecked" )
342
349
MappedDataSourceProperties () {
343
- this .dataSourceType = (Class <T >) ResolvableType .forClass (MappedDataSourceProperties .class , getClass ())
350
+ this .dataSourceType = getGeneric ();
351
+ }
352
+
353
+ @ SuppressWarnings ("unchecked" )
354
+ private Class <T > getGeneric () {
355
+ Class <T > generic = (Class <T >) ResolvableType .forClass (MappedDataSourceProperties .class , getClass ())
344
356
.resolveGeneric ();
357
+ Assert .state (generic != null , "'generic' must not be null" );
358
+ return generic ;
345
359
}
346
360
347
361
@ Override
348
362
public Class <? extends T > getDataSourceInstanceType () {
349
363
return this .dataSourceType ;
350
364
}
351
365
352
- protected void add (DataSourceProperty property , Getter <T , String > getter , Setter <T , String > setter ) {
366
+ protected void add (DataSourceProperty property , @ Nullable Getter <T , String > getter , Setter <T , String > setter ) {
353
367
add (property , String .class , getter , setter );
354
368
}
355
369
356
- protected <V > void add (DataSourceProperty property , Class <V > type , Getter <T , V > getter , Setter <T , V > setter ) {
370
+ protected <V > void add (DataSourceProperty property , Class <V > type , @ Nullable Getter <T , V > getter ,
371
+ Setter <T , V > setter ) {
357
372
this .mappedProperties .put (property , new MappedDataSourceProperty <>(property , type , getter , setter ));
358
373
}
359
374
@@ -371,31 +386,32 @@ public void set(T dataSource, DataSourceProperty property, String value) {
371
386
}
372
387
373
388
@ Override
374
- public String get (T dataSource , DataSourceProperty property ) {
389
+ public @ Nullable String get (T dataSource , DataSourceProperty property ) {
375
390
MappedDataSourceProperty <T , ?> mappedProperty = getMapping (property );
376
391
if (mappedProperty != null ) {
377
392
return mappedProperty .get (dataSource );
378
393
}
379
394
return null ;
380
395
}
381
396
382
- private MappedDataSourceProperty <T , ?> getMapping (DataSourceProperty property ) {
397
+ private @ Nullable MappedDataSourceProperty <T , ?> getMapping (DataSourceProperty property ) {
383
398
MappedDataSourceProperty <T , ?> mappedProperty = this .mappedProperties .get (property );
384
399
UnsupportedDataSourcePropertyException .throwIf (!property .isOptional () && mappedProperty == null ,
385
400
() -> "No mapping found for " + property );
386
401
return mappedProperty ;
387
402
}
388
403
389
- static <T extends DataSource > MappedDataSourceProperties <T > forType (ClassLoader classLoader , Class <T > type ) {
404
+ static <T extends DataSource > @ Nullable MappedDataSourceProperties <T > forType (@ Nullable ClassLoader classLoader ,
405
+ @ Nullable Class <T > type ) {
390
406
MappedDataSourceProperties <T > pooled = lookupPooled (classLoader , type );
391
407
if (type == null || pooled != null ) {
392
408
return pooled ;
393
409
}
394
410
return lookupBasic (classLoader , type );
395
411
}
396
412
397
- private static <T extends DataSource > MappedDataSourceProperties <T > lookupPooled (ClassLoader classLoader ,
398
- Class <T > type ) {
413
+ private static <T extends DataSource > @ Nullable MappedDataSourceProperties <T > lookupPooled (
414
+ @ Nullable ClassLoader classLoader , @ Nullable Class <T > type ) {
399
415
MappedDataSourceProperties <T > result = null ;
400
416
result = lookup (classLoader , type , result , "com.zaxxer.hikari.HikariDataSource" ,
401
417
HikariDataSourceProperties ::new );
@@ -412,8 +428,8 @@ private static <T extends DataSource> MappedDataSourceProperties<T> lookupPooled
412
428
return result ;
413
429
}
414
430
415
- private static <T extends DataSource > MappedDataSourceProperties <T > lookupBasic (ClassLoader classLoader ,
416
- Class <T > dataSourceType ) {
431
+ private static <T extends DataSource > @ Nullable MappedDataSourceProperties <T > lookupBasic (
432
+ @ Nullable ClassLoader classLoader , Class <T > dataSourceType ) {
417
433
MappedDataSourceProperties <T > result = null ;
418
434
result = lookup (classLoader , dataSourceType , result ,
419
435
"org.springframework.jdbc.datasource.SimpleDriverDataSource" , SimpleDataSourceProperties ::new );
@@ -427,8 +443,9 @@ private static <T extends DataSource> MappedDataSourceProperties<T> lookupBasic(
427
443
}
428
444
429
445
@ SuppressWarnings ("unchecked" )
430
- private static <T extends DataSource > MappedDataSourceProperties <T > lookup (ClassLoader classLoader ,
431
- Class <T > dataSourceType , MappedDataSourceProperties <T > existing , String dataSourceClassName ,
446
+ private static <T extends DataSource > @ Nullable MappedDataSourceProperties <T > lookup (
447
+ @ Nullable ClassLoader classLoader , @ Nullable Class <T > dataSourceType ,
448
+ @ Nullable MappedDataSourceProperties <T > existing , String dataSourceClassName ,
432
449
Supplier <MappedDataSourceProperties <?>> propertyMappingsSupplier , String ... requiredClassNames ) {
433
450
if (existing != null || !allPresent (classLoader , dataSourceClassName , requiredClassNames )) {
434
451
return existing ;
@@ -439,7 +456,7 @@ private static <T extends DataSource> MappedDataSourceProperties<T> lookup(Class
439
456
? (MappedDataSourceProperties <T >) propertyMappings : null ;
440
457
}
441
458
442
- private static boolean allPresent (ClassLoader classLoader , String dataSourceClassName ,
459
+ private static boolean allPresent (@ Nullable ClassLoader classLoader , String dataSourceClassName ,
443
460
String [] requiredClassNames ) {
444
461
boolean result = ClassUtils .isPresent (dataSourceClassName , classLoader );
445
462
for (String requiredClassName : requiredClassNames ) {
@@ -456,11 +473,12 @@ private static class MappedDataSourceProperty<T extends DataSource, V> {
456
473
457
474
private final Class <V > type ;
458
475
459
- private final Getter <T , V > getter ;
476
+ private final @ Nullable Getter <T , V > getter ;
460
477
461
- private final Setter <T , V > setter ;
478
+ private final @ Nullable Setter <T , V > setter ;
462
479
463
- MappedDataSourceProperty (DataSourceProperty property , Class <V > type , Getter <T , V > getter , Setter <T , V > setter ) {
480
+ MappedDataSourceProperty (DataSourceProperty property , Class <V > type , @ Nullable Getter <T , V > getter ,
481
+ @ Nullable Setter <T , V > setter ) {
464
482
this .property = property ;
465
483
this .type = type ;
466
484
this .getter = getter ;
@@ -481,7 +499,7 @@ void set(T dataSource, String value) {
481
499
}
482
500
}
483
501
484
- String get (T dataSource ) {
502
+ @ Nullable String get (T dataSource ) {
485
503
try {
486
504
if (this .getter == null ) {
487
505
UnsupportedDataSourcePropertyException .throwIf (!this .property .isOptional (),
@@ -506,7 +524,8 @@ private V convertFromString(String value) {
506
524
throw new IllegalStateException ("Unsupported value type " + this .type );
507
525
}
508
526
509
- private String convertToString (V value ) {
527
+ @ Contract ("!null -> !null" )
528
+ private @ Nullable String convertToString (@ Nullable V value ) {
510
529
if (value == null ) {
511
530
return null ;
512
531
}
@@ -530,7 +549,6 @@ private static class ReflectionDataSourceProperties<T extends DataSource> implem
530
549
private final Class <T > dataSourceType ;
531
550
532
551
ReflectionDataSourceProperties (Class <T > dataSourceType ) {
533
- Assert .state (dataSourceType != null , "No supported DataSource type found" );
534
552
Map <DataSourceProperty , Method > getters = new HashMap <>();
535
553
Map <DataSourceProperty , Method > setters = new HashMap <>();
536
554
for (DataSourceProperty property : DataSourceProperty .values ()) {
@@ -542,7 +560,8 @@ private static class ReflectionDataSourceProperties<T extends DataSource> implem
542
560
this .setters = Collections .unmodifiableMap (setters );
543
561
}
544
562
545
- private void putIfNotNull (Map <DataSourceProperty , Method > map , DataSourceProperty property , Method method ) {
563
+ private void putIfNotNull (Map <DataSourceProperty , Method > map , DataSourceProperty property ,
564
+ @ Nullable Method method ) {
546
565
if (method != null ) {
547
566
map .put (property , method );
548
567
}
@@ -567,15 +586,15 @@ public void set(T dataSource, DataSourceProperty property, String value) {
567
586
}
568
587
569
588
@ Override
570
- public String get (T dataSource , DataSourceProperty property ) {
589
+ public @ Nullable String get (T dataSource , DataSourceProperty property ) {
571
590
Method method = getMethod (property , this .getters );
572
591
if (method != null ) {
573
592
return (String ) ReflectionUtils .invokeMethod (method , dataSource );
574
593
}
575
594
return null ;
576
595
}
577
596
578
- private Method getMethod (DataSourceProperty property , Map <DataSourceProperty , Method > methods ) {
597
+ private @ Nullable Method getMethod (DataSourceProperty property , Map <DataSourceProperty , Method > methods ) {
579
598
Method method = methods .get (property );
580
599
if (method == null ) {
581
600
UnsupportedDataSourcePropertyException .throwIf (!property .isOptional (),
@@ -591,7 +610,7 @@ private Method getMethod(DataSourceProperty property, Map<DataSourceProperty, Me
591
610
@ FunctionalInterface
592
611
private interface Getter <T , V > {
593
612
594
- V get (T instance ) throws SQLException ;
613
+ @ Nullable V get (T instance ) throws SQLException ;
595
614
596
615
}
597
616
0 commit comments