Use correct type for deriveFromProperties
Fix `DataSourceBuilder` so that the type used to access `deriveFrom` properties is based on the actual instance type rather than the user-defined type which could have been changed. Fixes gh-26644
This commit is contained in:
@@ -91,7 +91,7 @@ public final class DataSourceBuilder<T extends DataSource> {
|
||||
|
||||
private Class<T> type;
|
||||
|
||||
private final T deriveFrom;
|
||||
private final DataSource deriveFrom;
|
||||
|
||||
private DataSourceBuilder(ClassLoader classLoader) {
|
||||
this.classLoader = classLoader;
|
||||
@@ -168,25 +168,18 @@ public final class DataSourceBuilder<T extends DataSource> {
|
||||
*/
|
||||
public T build() {
|
||||
DataSourceProperties<T> properties = DataSourceProperties.forType(this.classLoader, this.type);
|
||||
DataSourceProperties<T> deriveFromProperties = (this.deriveFrom != null)
|
||||
? DataSourceProperties.forType(this.classLoader, this.type) : null;
|
||||
DataSourceProperties<DataSource> deriveFromProperties = getDeriveFromProperties();
|
||||
Class<? extends T> instanceType = (this.type != null) ? this.type : properties.getDataSourceInstanceType();
|
||||
T dataSource = BeanUtils.instantiateClass(instanceType);
|
||||
Set<DataSourceProperty> applied = new HashSet<>();
|
||||
for (DataSourceProperty property : DataSourceProperty.values()) {
|
||||
if (this.values.containsKey(property)) {
|
||||
String value = this.values.get(property);
|
||||
if (value != null) {
|
||||
properties.set(dataSource, property, value);
|
||||
applied.add(property);
|
||||
}
|
||||
String value = this.values.get(property);
|
||||
if (!this.values.containsKey(property) && deriveFromProperties != null && properties.canSet(property)) {
|
||||
value = deriveFromProperties.get(this.deriveFrom, property);
|
||||
}
|
||||
else if (deriveFromProperties != null && properties.canSet(property)) {
|
||||
String value = deriveFromProperties.get(this.deriveFrom, property);
|
||||
if (value != null) {
|
||||
properties.set(dataSource, property, value);
|
||||
applied.add(property);
|
||||
}
|
||||
if (value != null) {
|
||||
properties.set(dataSource, property, value);
|
||||
applied.add(property);
|
||||
}
|
||||
}
|
||||
if (!applied.contains(DataSourceProperty.DRIVER_CLASS_NAME)
|
||||
@@ -199,6 +192,14 @@ public final class DataSourceBuilder<T extends DataSource> {
|
||||
return dataSource;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private DataSourceProperties<DataSource> getDeriveFromProperties() {
|
||||
if (this.deriveFrom == null) {
|
||||
return null;
|
||||
}
|
||||
return DataSourceProperties.forType(this.classLoader, (Class<DataSource>) this.deriveFrom.getClass());
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@link DataSourceBuilder} instance.
|
||||
* @return a new datasource builder instance
|
||||
|
||||
@@ -318,6 +318,19 @@ class DataSourceBuilderTests {
|
||||
assertThat(built.getUrl()).startsWith("jdbc:hsqldb:mem");
|
||||
}
|
||||
|
||||
@Test // gh-26644
|
||||
void buildWhenDerivedFromExistingDatabaseWithTypeChange() {
|
||||
HikariDataSource dataSource = new HikariDataSource();
|
||||
dataSource.setUsername("test");
|
||||
dataSource.setPassword("secret");
|
||||
dataSource.setJdbcUrl("jdbc:postgresql://localhost:5432/postgres");
|
||||
DataSourceBuilder<?> builder = DataSourceBuilder.derivedFrom(dataSource).type(SimpleDriverDataSource.class);
|
||||
SimpleDriverDataSource built = (SimpleDriverDataSource) builder.username("test2").password("secret2").build();
|
||||
assertThat(built.getUsername()).isEqualTo("test2");
|
||||
assertThat(built.getPassword()).isEqualTo("secret2");
|
||||
assertThat(built.getUrl()).isEqualTo("jdbc:postgresql://localhost:5432/postgres");
|
||||
}
|
||||
|
||||
final class HidePackagesClassLoader extends URLClassLoader {
|
||||
|
||||
private final String[] hiddenPackages;
|
||||
|
||||
Reference in New Issue
Block a user