From 3a5b40645a927d81db9ca8eb1dd5af70c892b72c Mon Sep 17 00:00:00 2001 From: Stephane Nicoll Date: Fri, 29 Jul 2022 13:48:49 +0200 Subject: [PATCH] Restore support for C3P0 Closes gh-31920 --- .../DataSourceAutoConfigurationTests.java | 4 +-- .../src/docs/asciidoc/data/sql.adoc | 1 + .../spring-boot-parent/build.gradle | 7 +++++ spring-boot-project/spring-boot/build.gradle | 1 + .../boot/jdbc/DataSourceBuilder.java | 27 +++++++++++++++++++ .../boot/jdbc/DataSourceBuilderTests.java | 14 ++++++++++ 6 files changed, 52 insertions(+), 2 deletions(-) diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jdbc/DataSourceAutoConfigurationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jdbc/DataSourceAutoConfigurationTests.java index 7cc2f74cf2d6..ed83807540f6 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jdbc/DataSourceAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/jdbc/DataSourceAutoConfigurationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2021 the original author or authors. + * Copyright 2012-2022 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -253,7 +253,7 @@ void whenNoInitializationRelatedSpringDataSourcePropertiesAreConfiguredThenIniti private static Function hideConnectionPools() { return (runner) -> runner.withClassLoader(new FilteredClassLoader("org.apache.tomcat", "com.zaxxer.hikari", - "org.apache.commons.dbcp2", "oracle.ucp.jdbc")); + "org.apache.commons.dbcp2", "oracle.ucp.jdbc", "com.mchange")); } private void assertDataSource(Class expectedType, List hiddenPackages, diff --git a/spring-boot-project/spring-boot-docs/src/docs/asciidoc/data/sql.adoc b/spring-boot-project/spring-boot-docs/src/docs/asciidoc/data/sql.adoc index b6a1d0bd4e9d..967e0ee6f54f 100644 --- a/spring-boot-project/spring-boot-docs/src/docs/asciidoc/data/sql.adoc +++ b/spring-boot-project/spring-boot-docs/src/docs/asciidoc/data/sql.adoc @@ -135,6 +135,7 @@ The following connection pools are supported by `DataSourceBuilder`: * Spring Framework's `SimpleDriverDataSource` * H2 `JdbcDataSource` * PostgreSQL `PGSimpleDataSource` +* C3P0 diff --git a/spring-boot-project/spring-boot-parent/build.gradle b/spring-boot-project/spring-boot-parent/build.gradle index e096662f16c4..067caffe7ef6 100644 --- a/spring-boot-project/spring-boot-parent/build.gradle +++ b/spring-boot-project/spring-boot-parent/build.gradle @@ -27,6 +27,13 @@ bom { ] } } + library("C3P0", "0.9.5.5") { + group("com.mchange") { + modules = [ + "c3p0" + ] + } + } library("Commons Compress", "1.21") { group("org.apache.commons") { modules = [ diff --git a/spring-boot-project/spring-boot/build.gradle b/spring-boot-project/spring-boot/build.gradle index fb0e69543b25..136dda6bafc5 100644 --- a/spring-boot-project/spring-boot/build.gradle +++ b/spring-boot-project/spring-boot/build.gradle @@ -28,6 +28,7 @@ dependencies { optional("com.fasterxml.jackson.core:jackson-databind") optional("com.h2database:h2") optional("com.google.code.gson:gson") + optional("com.mchange:c3p0") optional("com.oracle.database.jdbc:ucp") optional("com.oracle.database.jdbc:ojdbc8") optional("com.samskivert:jmustache") diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/jdbc/DataSourceBuilder.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/jdbc/DataSourceBuilder.java index b8c0f8d3aeef..62d85ccc0549 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/jdbc/DataSourceBuilder.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/jdbc/DataSourceBuilder.java @@ -16,6 +16,7 @@ package org.springframework.boot.jdbc; +import java.beans.PropertyVetoException; import java.lang.reflect.Method; import java.sql.SQLException; import java.util.Collections; @@ -27,6 +28,7 @@ import javax.sql.DataSource; +import com.mchange.v2.c3p0.ComboPooledDataSource; import com.zaxxer.hikari.HikariDataSource; import oracle.jdbc.datasource.OracleDataSource; import oracle.ucp.jdbc.PoolDataSource; @@ -391,6 +393,8 @@ private static MappedDataSourceProperties lookupPooled MappedDbcp2DataSource::new); result = lookup(classLoader, type, result, "oracle.ucp.jdbc.PoolDataSourceImpl", OraclePoolDataSourceProperties::new, "oracle.jdbc.OracleConnection"); + result = lookup(classLoader, type, result, "com.mchange.v2.c3p0.ComboPooledDataSource", + ComboPooledDataSourceProperties::new); return result; } @@ -650,6 +654,29 @@ public Class getDataSourceInstanceType() { } + /** + * {@link DataSourceProperties} for C3P0. + */ + private static class ComboPooledDataSourceProperties extends MappedDataSourceProperties { + + ComboPooledDataSourceProperties() { + add(DataSourceProperty.URL, ComboPooledDataSource::getJdbcUrl, ComboPooledDataSource::setJdbcUrl); + add(DataSourceProperty.DRIVER_CLASS_NAME, ComboPooledDataSource::getDriverClass, this::setDriverClass); + add(DataSourceProperty.USERNAME, ComboPooledDataSource::getUser, ComboPooledDataSource::setUser); + add(DataSourceProperty.PASSWORD, ComboPooledDataSource::getPassword, ComboPooledDataSource::setPassword); + } + + private void setDriverClass(ComboPooledDataSource dataSource, String driverClass) { + try { + dataSource.setDriverClass(driverClass); + } + catch (PropertyVetoException ex) { + throw new IllegalArgumentException(ex); + } + } + + } + /** * {@link DataSourceProperties} for Spring's {@link SimpleDriverDataSource}. */ diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/jdbc/DataSourceBuilderTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/jdbc/DataSourceBuilderTests.java index 345c58e1aead..c80ff388af75 100644 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/jdbc/DataSourceBuilderTests.java +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/jdbc/DataSourceBuilderTests.java @@ -26,6 +26,7 @@ import javax.sql.DataSource; +import com.mchange.v2.c3p0.ComboPooledDataSource; import com.microsoft.sqlserver.jdbc.SQLServerDataSource; import com.zaxxer.hikari.HikariDataSource; import oracle.jdbc.internal.OpaqueString; @@ -384,6 +385,19 @@ void buildWhenDerivedFromCustomTypeWithTypeChange() { assertThat(testSource.getPassword()).isEqualTo("secret"); } + @Test // gh-31920 + void buildWhenC3P0TypeSpecifiedReturnsExpectedDataSource() { + this.dataSource = DataSourceBuilder.create().url("jdbc:postgresql://localhost:5432/postgres") + .type(ComboPooledDataSource.class).username("test").password("secret") + .driverClassName("com.example.Driver").build(); + assertThat(this.dataSource).isInstanceOf(ComboPooledDataSource.class); + ComboPooledDataSource c3p0DataSource = (ComboPooledDataSource) this.dataSource; + assertThat(c3p0DataSource.getJdbcUrl()).isEqualTo("jdbc:postgresql://localhost:5432/postgres"); + assertThat(c3p0DataSource.getUser()).isEqualTo("test"); + assertThat(c3p0DataSource.getPassword()).isEqualTo("secret"); + assertThat(c3p0DataSource.getDriverClass()).isEqualTo("com.example.Driver"); + } + final class HidePackagesClassLoader extends URLClassLoader { private final String[] hiddenPackages;