16
16
17
17
package org .springframework .boot .jdbc ;
18
18
19
+ import java .util .ArrayList ;
20
+ import java .util .Collection ;
19
21
import java .util .HashMap ;
22
+ import java .util .List ;
20
23
import java .util .Map ;
24
+ import java .util .function .Consumer ;
25
+ import java .util .function .Function ;
21
26
22
27
import javax .sql .DataSource ;
23
28
46
51
*/
47
52
public final class DataSourceBuilder <T extends DataSource > {
48
53
49
- private static final String [] DATA_SOURCE_TYPE_NAMES = new String [] { "com.zaxxer.hikari.HikariDataSource" ,
50
- "org.apache.tomcat.jdbc.pool.DataSource" , "org.apache.commons.dbcp2.BasicDataSource" };
51
-
52
54
private Class <? extends DataSource > type ;
53
55
54
- private ClassLoader classLoader ;
56
+ private final DataSourceSettingsResolver settingsResolver ;
55
57
56
- private Map <String , String > properties = new HashMap <>();
58
+ private final Map <String , String > properties = new HashMap <>();
57
59
58
60
public static DataSourceBuilder <?> create () {
59
61
return new DataSourceBuilder <>(null );
@@ -64,7 +66,7 @@ public static DataSourceBuilder<?> create(ClassLoader classLoader) {
64
66
}
65
67
66
68
private DataSourceBuilder (ClassLoader classLoader ) {
67
- this .classLoader = classLoader ;
69
+ this .settingsResolver = new DataSourceSettingsResolver ( classLoader ) ;
68
70
}
69
71
70
72
@ SuppressWarnings ("unchecked" )
@@ -87,9 +89,7 @@ private void maybeGetDriverClassName() {
87
89
private void bind (DataSource result ) {
88
90
ConfigurationPropertySource source = new MapConfigurationPropertySource (this .properties );
89
91
ConfigurationPropertyNameAliases aliases = new ConfigurationPropertyNameAliases ();
90
- aliases .addAliases ("driver-class-name" , "driver-class" );
91
- aliases .addAliases ("url" , "jdbc-url" );
92
- aliases .addAliases ("username" , "user" );
92
+ this .settingsResolver .registerAliases (result , aliases );
93
93
Binder binder = new Binder (source .withAliases (aliases ));
94
94
binder .bind (ConfigurationPropertyName .EMPTY , Bindable .ofInstance (result ));
95
95
}
@@ -120,25 +120,124 @@ public DataSourceBuilder<T> password(String password) {
120
120
return this ;
121
121
}
122
122
123
- @ SuppressWarnings ("unchecked" )
124
123
public static Class <? extends DataSource > findType (ClassLoader classLoader ) {
125
- for (String name : DATA_SOURCE_TYPE_NAMES ) {
126
- try {
127
- return (Class <? extends DataSource >) ClassUtils .forName (name , classLoader );
128
- }
129
- catch (Exception ex ) {
130
- // Swallow and continue
131
- }
132
- }
133
- return null ;
124
+ DataSourceSettings preferredDataSourceSettings = new DataSourceSettingsResolver (classLoader )
125
+ .getPreferredDataSourceSettings ();
126
+ return (preferredDataSourceSettings != null ) ? preferredDataSourceSettings .getType () : null ;
134
127
}
135
128
136
129
private Class <? extends DataSource > getType () {
137
- Class <? extends DataSource > type = (this .type != null ) ? this .type : findType (this .classLoader );
138
- if (type != null ) {
139
- return type ;
130
+ if (this .type != null ) {
131
+ return this .type ;
132
+ }
133
+ DataSourceSettings preferredDataSourceSettings = this .settingsResolver .getPreferredDataSourceSettings ();
134
+ if (preferredDataSourceSettings != null ) {
135
+ return preferredDataSourceSettings .getType ();
140
136
}
141
137
throw new IllegalStateException ("No supported DataSource type found" );
142
138
}
143
139
140
+ private static class DataSourceSettings {
141
+
142
+ private final Class <? extends DataSource > type ;
143
+
144
+ private final Consumer <ConfigurationPropertyNameAliases > aliasesCustomizer ;
145
+
146
+ DataSourceSettings (Class <? extends DataSource > type ,
147
+ Consumer <ConfigurationPropertyNameAliases > aliasesCustomizer ) {
148
+ this .type = type ;
149
+ this .aliasesCustomizer = aliasesCustomizer ;
150
+ }
151
+
152
+ DataSourceSettings (Class <? extends DataSource > type ) {
153
+ this (type , (aliases ) -> {
154
+ });
155
+ }
156
+
157
+ Class <? extends DataSource > getType () {
158
+ return this .type ;
159
+ }
160
+
161
+ void registerAliases (DataSource candidate , ConfigurationPropertyNameAliases aliases ) {
162
+ if (this .type != null && this .type .isInstance (candidate )) {
163
+ this .aliasesCustomizer .accept (aliases );
164
+ }
165
+ }
166
+
167
+ }
168
+
169
+ private static class OracleDataSourceSettings extends DataSourceSettings {
170
+
171
+ OracleDataSourceSettings (Class <? extends DataSource > type ) {
172
+ super (type , (aliases ) -> aliases .addAliases ("username" , "user" ));
173
+ }
174
+
175
+ @ Override
176
+ public Class <? extends DataSource > getType () {
177
+ return null ; // Base interface
178
+ }
179
+
180
+ }
181
+
182
+ private static class DataSourceSettingsResolver {
183
+
184
+ private final DataSourceSettings preferredDataSourceSettings ;
185
+
186
+ private final List <DataSourceSettings > allDataSourceSettings ;
187
+
188
+ DataSourceSettingsResolver (ClassLoader classLoader ) {
189
+ List <DataSourceSettings > supportedProviders = resolveAvailableDataSourceSettings (classLoader );
190
+ this .preferredDataSourceSettings = (!supportedProviders .isEmpty ()) ? supportedProviders .get (0 ) : null ;
191
+ this .allDataSourceSettings = new ArrayList <>(supportedProviders );
192
+ addIfAvailable (this .allDataSourceSettings ,
193
+ create (classLoader , "org.springframework.jdbc.datasource.SimpleDriverDataSource" ,
194
+ (type ) -> new DataSourceSettings (type ,
195
+ (aliases ) -> aliases .addAliases ("driver-class-name" , "driver-class" ))));
196
+ addIfAvailable (this .allDataSourceSettings , create (classLoader ,
197
+ "oracle.jdbc.datasource.OracleCommonDataSource" , OracleDataSourceSettings ::new ));
198
+ }
199
+
200
+ private static List <DataSourceSettings > resolveAvailableDataSourceSettings (ClassLoader classLoader ) {
201
+ List <DataSourceSettings > providers = new ArrayList <>();
202
+ addIfAvailable (providers , create (classLoader , "com.zaxxer.hikari.HikariDataSource" ,
203
+ (type ) -> new DataSourceSettings (type , (aliases ) -> aliases .addAliases ("url" , "jdbc-url" ))));
204
+ addIfAvailable (providers ,
205
+ create (classLoader , "org.apache.tomcat.jdbc.pool.DataSource" , DataSourceSettings ::new ));
206
+ addIfAvailable (providers ,
207
+ create (classLoader , "org.apache.commons.dbcp2.BasicDataSource" , DataSourceSettings ::new ));
208
+ return providers ;
209
+ }
210
+
211
+ @ SuppressWarnings ("unchecked" )
212
+ private static DataSourceSettings create (ClassLoader classLoader , String target ,
213
+ Function <Class <? extends DataSource >, DataSourceSettings > factory ) {
214
+ if (ClassUtils .isPresent (target , classLoader )) {
215
+ try {
216
+ Class <? extends DataSource > type = (Class <? extends DataSource >) ClassUtils .forName (target ,
217
+ classLoader );
218
+ return factory .apply (type );
219
+ }
220
+ catch (Exception ex ) {
221
+ // Ignore
222
+ }
223
+ }
224
+ return null ;
225
+ }
226
+
227
+ private static void addIfAvailable (Collection <DataSourceSettings > list , DataSourceSettings dataSourceSettings ) {
228
+ if (dataSourceSettings != null ) {
229
+ list .add (dataSourceSettings );
230
+ }
231
+ }
232
+
233
+ DataSourceSettings getPreferredDataSourceSettings () {
234
+ return this .preferredDataSourceSettings ;
235
+ }
236
+
237
+ void registerAliases (DataSource result , ConfigurationPropertyNameAliases aliases ) {
238
+ this .allDataSourceSettings .forEach ((settings ) -> settings .registerAliases (result , aliases ));
239
+ }
240
+
241
+ }
242
+
144
243
}
0 commit comments