diff --git a/benchmarks/src/jmh/java/software/amazon/jdbc/benchmarks/ConnectionPluginManagerBenchmarks.java b/benchmarks/src/jmh/java/software/amazon/jdbc/benchmarks/ConnectionPluginManagerBenchmarks.java index 6cb455805..f4f33e368 100644 --- a/benchmarks/src/jmh/java/software/amazon/jdbc/benchmarks/ConnectionPluginManagerBenchmarks.java +++ b/benchmarks/src/jmh/java/software/amazon/jdbc/benchmarks/ConnectionPluginManagerBenchmarks.java @@ -63,12 +63,12 @@ import software.amazon.jdbc.PluginService; import software.amazon.jdbc.PropertyDefinition; import software.amazon.jdbc.benchmarks.testplugin.BenchmarkPluginFactory; -import software.amazon.jdbc.dialect.Dialect; import software.amazon.jdbc.hostavailability.SimpleHostAvailabilityStrategy; import software.amazon.jdbc.profile.ConfigurationProfile; import software.amazon.jdbc.profile.ConfigurationProfileBuilder; import software.amazon.jdbc.targetdriverdialect.TargetDriverDialect; import software.amazon.jdbc.util.FullServicesContainer; +import software.amazon.jdbc.util.connection.ConnectConfig; import software.amazon.jdbc.util.telemetry.DefaultTelemetryFactory; import software.amazon.jdbc.util.telemetry.GaugeCallable; import software.amazon.jdbc.util.telemetry.TelemetryContext; @@ -88,16 +88,19 @@ public class ConnectionPluginManagerBenchmarks { private static final String WRITER_SESSION_ID = "MASTER_SESSION_ID"; private static final String FIELD_SERVER_ID = "SERVER_ID"; private static final String FIELD_SESSION_ID = "SESSION_ID"; - private Properties propertiesWithoutPlugins; - private Properties propertiesWithPlugins; + private static final String url = "protocol//url"; + private ConnectConfig pluginsContext; + private ConnectConfig noPluginsContext; private ConnectionPluginManager pluginManager; private ConnectionPluginManager pluginManagerWithNoPlugins; @Mock ConnectionProvider mockConnectionProvider; @Mock ConnectionWrapper mockConnectionWrapper; + @Mock ConnectConfig mockConnectConfig; @Mock FullServicesContainer mockServicesContainer; @Mock PluginService mockPluginService; @Mock PluginManagerService mockPluginManagerService; + @Mock TargetDriverDialect mockDriverDialect; @Mock TelemetryFactory mockTelemetryFactory; @Mock HostListProviderService mockHostListProvider; @Mock Connection mockConnection; @@ -123,12 +126,7 @@ public static void main(String[] args) throws RunnerException { public void setUpIteration() throws Exception { closeable = openMocks(this); - when(mockConnectionProvider.connect( - anyString(), - any(Dialect.class), - any(TargetDriverDialect.class), - any(HostSpec.class), - any(Properties.class))).thenReturn(mockConnection); + when(mockConnectionProvider.connect(any(), any(HostSpec.class))).thenReturn(mockConnection); when(mockTelemetryFactory.openTelemetryContext(anyString(), any())).thenReturn(mockTelemetryContext); when(mockTelemetryFactory.openTelemetryContext(eq(null), any())).thenReturn(mockTelemetryContext); when(mockTelemetryFactory.createCounter(anyString())).thenReturn(mockTelemetryCounter); @@ -153,24 +151,26 @@ public void setUpIteration() throws Exception { .withPluginFactories(pluginFactories) .build(); - propertiesWithoutPlugins = new Properties(); - propertiesWithoutPlugins.setProperty(PropertyDefinition.PLUGINS.name, ""); + Properties noPluginsProps = new Properties(); + noPluginsProps.setProperty(PropertyDefinition.PLUGINS.name, ""); + this.noPluginsContext = new ConnectConfig(url, mockDriverDialect, noPluginsProps); - propertiesWithPlugins = new Properties(); - propertiesWithPlugins.setProperty(PropertyDefinition.PROFILE_NAME.name, "benchmark"); - propertiesWithPlugins.setProperty(PropertyDefinition.ENABLE_TELEMETRY.name, "false"); + Properties pluginsProps = new Properties(); + pluginsProps.setProperty(PropertyDefinition.PROFILE_NAME.name, "benchmark"); + pluginsProps.setProperty(PropertyDefinition.ENABLE_TELEMETRY.name, "false"); + this.pluginsContext = new ConnectConfig(url, mockDriverDialect, pluginsProps); - TelemetryFactory telemetryFactory = new DefaultTelemetryFactory(propertiesWithPlugins); + TelemetryFactory telemetryFactory = new DefaultTelemetryFactory(pluginsProps); pluginManager = new ConnectionPluginManager(mockConnectionProvider, null, mockConnectionWrapper, telemetryFactory); - pluginManager.init(mockServicesContainer, propertiesWithPlugins, mockPluginManagerService, configurationProfile); + pluginManager.init(mockServicesContainer, pluginsProps, mockPluginManagerService, configurationProfile); pluginManagerWithNoPlugins = new ConnectionPluginManager(mockConnectionProvider, null, mockConnectionWrapper, telemetryFactory); - pluginManagerWithNoPlugins.init(mockServicesContainer, propertiesWithoutPlugins, mockPluginManagerService, null); + pluginManagerWithNoPlugins.init(mockServicesContainer, noPluginsProps, mockPluginManagerService, null); } @TearDown(Level.Iteration) @@ -182,7 +182,7 @@ public void tearDownIteration() throws Exception { public ConnectionPluginManager initConnectionPluginManagerWithNoPlugins() throws SQLException { final ConnectionPluginManager manager = new ConnectionPluginManager(mockConnectionProvider, null, mockConnectionWrapper, mockTelemetryFactory); - manager.init(mockServicesContainer, propertiesWithoutPlugins, mockPluginManagerService, configurationProfile); + manager.init(mockServicesContainer, this.noPluginsContext.getProps(), mockPluginManagerService, configurationProfile); return manager; } @@ -190,16 +190,15 @@ public ConnectionPluginManager initConnectionPluginManagerWithNoPlugins() throws public ConnectionPluginManager initConnectionPluginManagerWithPlugins() throws SQLException { final ConnectionPluginManager manager = new ConnectionPluginManager(mockConnectionProvider, null, mockConnectionWrapper, mockTelemetryFactory); - manager.init(mockServicesContainer, propertiesWithPlugins, mockPluginManagerService, configurationProfile); + manager.init(mockServicesContainer, this.pluginsContext.getProps(), mockPluginManagerService, configurationProfile); return manager; } @Benchmark public Connection connectWithPlugins() throws SQLException { return pluginManager.connect( - "driverProtocol", + mockConnectConfig, new HostSpecBuilder(new SimpleHostAvailabilityStrategy()).host("host").build(), - propertiesWithPlugins, true, null); } @@ -207,9 +206,8 @@ public Connection connectWithPlugins() throws SQLException { @Benchmark public Connection connectWithNoPlugins() throws SQLException { return pluginManagerWithNoPlugins.connect( - "driverProtocol", + mockConnectConfig, new HostSpecBuilder(new SimpleHostAvailabilityStrategy()).host("host").build(), - propertiesWithoutPlugins, true, null); } @@ -240,21 +238,13 @@ public Integer executeWithNoPlugins() { @Benchmark public ConnectionPluginManager initHostProvidersWithPlugins() throws SQLException { - pluginManager.initHostProvider( - "protocol", - "url", - propertiesWithPlugins, - mockHostListProvider); + pluginManager.initHostProvider(this.pluginsContext, mockHostListProvider); return pluginManager; } @Benchmark public ConnectionPluginManager initHostProvidersWithNoPlugins() throws SQLException { - pluginManagerWithNoPlugins.initHostProvider( - "protocol", - "url", - propertiesWithoutPlugins, - mockHostListProvider); + pluginManagerWithNoPlugins.initHostProvider(this.noPluginsContext, mockHostListProvider); return pluginManager; } diff --git a/benchmarks/src/jmh/java/software/amazon/jdbc/benchmarks/PluginBenchmarks.java b/benchmarks/src/jmh/java/software/amazon/jdbc/benchmarks/PluginBenchmarks.java index 22148f312..5554ae0fd 100644 --- a/benchmarks/src/jmh/java/software/amazon/jdbc/benchmarks/PluginBenchmarks.java +++ b/benchmarks/src/jmh/java/software/amazon/jdbc/benchmarks/PluginBenchmarks.java @@ -63,7 +63,7 @@ import software.amazon.jdbc.dialect.Dialect; import software.amazon.jdbc.hostavailability.SimpleHostAvailabilityStrategy; import software.amazon.jdbc.targetdriverdialect.TargetDriverDialect; -import software.amazon.jdbc.util.connection.ConnectionService; +import software.amazon.jdbc.util.connection.ConnectConfig; import software.amazon.jdbc.util.monitoring.MonitorService; import software.amazon.jdbc.util.storage.StorageService; import software.amazon.jdbc.util.telemetry.GaugeCallable; @@ -94,7 +94,6 @@ public class PluginBenchmarks { @Mock private StorageService mockStorageService; @Mock private MonitorService mockMonitorService; - @Mock private ConnectionService mockConnectionService; @Mock private PluginService mockPluginService; @Mock private TargetDriverDialect mockTargetDriverDialect; @Mock private Dialect mockDialect; @@ -124,7 +123,7 @@ public static void main(String[] args) throws RunnerException { @Setup(Level.Iteration) public void setUpIteration() throws Exception { closeable = MockitoAnnotations.openMocks(this); - when(mockConnectionPluginManager.connect(any(), any(), any(Properties.class), anyBoolean(), any())) + when(mockConnectionPluginManager.connect(any(), any(), anyBoolean(), any())) .thenReturn(mockConnection); when(mockConnectionPluginManager.execute( any(), any(), any(), eq(JdbcMethod.CONNECTION_CREATESTATEMENT), any(), any())) @@ -135,12 +134,7 @@ public void setUpIteration() throws Exception { when(mockTelemetryFactory.createCounter(anyString())).thenReturn(mockTelemetryCounter); // noinspection unchecked when(mockTelemetryFactory.createGauge(anyString(), any(GaugeCallable.class))).thenReturn(mockTelemetryGauge); - when(mockConnectionProvider.connect( - anyString(), - any(Dialect.class), - any(TargetDriverDialect.class), - any(HostSpec.class), - any(Properties.class))).thenReturn(mockConnection); + when(mockConnectionProvider.connect(any(ConnectConfig.class), any(HostSpec.class))).thenReturn(mockConnection); when(mockConnection.createStatement()).thenReturn(mockStatement); when(mockStatement.executeQuery(anyString())).thenReturn(mockResultSet); when(mockResultSet.next()).thenReturn(true, true, false); @@ -183,8 +177,7 @@ private ConnectionWrapper getConnectionWrapper(Properties props, String connStri mockHostListProviderService, mockPluginManagerService, mockStorageService, - mockMonitorService, - mockConnectionService); + mockMonitorService); } @Benchmark diff --git a/benchmarks/src/jmh/java/software/amazon/jdbc/benchmarks/testplugin/BenchmarkPlugin.java b/benchmarks/src/jmh/java/software/amazon/jdbc/benchmarks/testplugin/BenchmarkPlugin.java index ffed10f77..40f76e316 100644 --- a/benchmarks/src/jmh/java/software/amazon/jdbc/benchmarks/testplugin/BenchmarkPlugin.java +++ b/benchmarks/src/jmh/java/software/amazon/jdbc/benchmarks/testplugin/BenchmarkPlugin.java @@ -24,7 +24,6 @@ import java.util.HashSet; import java.util.List; import java.util.Map; -import java.util.Properties; import java.util.Set; import java.util.logging.Logger; import software.amazon.jdbc.ConnectionPlugin; @@ -37,6 +36,7 @@ import software.amazon.jdbc.OldConnectionSuggestedAction; import software.amazon.jdbc.cleanup.CanReleaseResources; import software.amazon.jdbc.hostavailability.SimpleHostAvailabilityStrategy; +import software.amazon.jdbc.util.connection.ConnectConfig; public class BenchmarkPlugin implements ConnectionPlugin, CanReleaseResources { final List resources = new ArrayList<>(); @@ -58,18 +58,21 @@ public T execute(Class resultClass, Class excepti } @Override - public Connection connect(String driverProtocol, HostSpec hostSpec, Properties props, - boolean isInitialConnection, JdbcCallable connectFunc) - throws SQLException { + public Connection connect( + final ConnectConfig connectConfig, + final HostSpec hostSpec, + final boolean isInitialConnection, + final JdbcCallable connectFunc) throws SQLException { LOGGER.finer(() -> String.format("connect=''%s''", hostSpec.getHost())); resources.add("connect"); return connectFunc.call(); } @Override - public Connection forceConnect(String driverProtocol, HostSpec hostSpec, Properties props, - boolean isInitialConnection, JdbcCallable forceConnectFunc) - throws SQLException { + public Connection forceConnect( + ConnectConfig connectConfig, + HostSpec hostSpec, + boolean isInitialConnection, JdbcCallable forceConnectFunc) throws SQLException { LOGGER.finer(() -> String.format("forceConnect=''%s''", hostSpec.getHost())); resources.add("forceConnect"); return forceConnectFunc.call(); @@ -93,10 +96,11 @@ public HostSpec getHostSpecByStrategy(List hosts, HostRole role, Strin } @Override - public void initHostProvider(String driverProtocol, String initialUrl, Properties props, + public void initHostProvider( + ConnectConfig connectConfig, HostListProviderService hostListProviderService, JdbcCallable initHostProviderFunc) { - LOGGER.finer(() -> String.format("initHostProvider=''%s''", initialUrl)); + LOGGER.finer(() -> String.format("initHostProvider=''%s''", connectConfig.getInitialConnectionString())); resources.add("initHostProvider"); } diff --git a/benchmarks/src/jmh/java/software/amazon/jdbc/benchmarks/testplugin/TestConnectionWrapper.java b/benchmarks/src/jmh/java/software/amazon/jdbc/benchmarks/testplugin/TestConnectionWrapper.java index d0ec5c063..4323d1ae6 100644 --- a/benchmarks/src/jmh/java/software/amazon/jdbc/benchmarks/testplugin/TestConnectionWrapper.java +++ b/benchmarks/src/jmh/java/software/amazon/jdbc/benchmarks/testplugin/TestConnectionWrapper.java @@ -25,7 +25,6 @@ import software.amazon.jdbc.PluginManagerService; import software.amazon.jdbc.PluginService; import software.amazon.jdbc.targetdriverdialect.TargetDriverDialect; -import software.amazon.jdbc.util.connection.ConnectionService; import software.amazon.jdbc.util.monitoring.MonitorService; import software.amazon.jdbc.util.storage.StorageService; import software.amazon.jdbc.util.telemetry.TelemetryFactory; @@ -45,8 +44,7 @@ public TestConnectionWrapper( @NonNull final HostListProviderService hostListProviderService, @NonNull final PluginManagerService pluginManagerService, @NonNull final StorageService storageService, - @NonNull final MonitorService monitorService, - @NonNull final ConnectionService connectionService) + @NonNull final MonitorService monitorService) throws SQLException { super( props, @@ -58,6 +56,7 @@ public TestConnectionWrapper( pluginService, hostListProviderService, pluginManagerService, - storageService, monitorService, connectionService); + storageService, + monitorService); } } diff --git a/docs/development-guide/LoadablePlugins.md b/docs/development-guide/LoadablePlugins.md index 6dd713a73..bd44f1342 100644 --- a/docs/development-guide/LoadablePlugins.md +++ b/docs/development-guide/LoadablePlugins.md @@ -116,9 +116,12 @@ public class BadPlugin extends AbstractConnectionPlugin { return new HashSet<>(Collections.singletonList("*")); } - @Override - public Connection connect(String driverProtocol, HostSpec hostSpec, Properties props, boolean isInitialConnection, - JdbcCallable connectFunc) throws SQLException { + @Override + public Connection connect( + final ConnectConfig connectConfig, + final HostSpec hostSpec, + final boolean isInitialConnection, + final JdbcCallable connectFunc) throws SQLException { // Bad Practice #2: using driver-specific objects. // Not all drivers support the same configuration parameters. For instance, while MySQL Connector/J Supports "database", // PGJDBC uses "dbname" for database names. @@ -167,9 +170,12 @@ public class GoodExample extends AbstractConnectionPlugin { return jdbcMethodFunc.call(); } - @Override - public Connection connect(String driverProtocol, HostSpec hostSpec, Properties props, boolean isInitialConnection, - JdbcCallable connectFunc) throws SQLException { + @Override + public Connection connect( + final ConnectConfig connectConfig, + final HostSpec hostSpec, + final boolean isInitialConnection, + final JdbcCallable connectFunc) throws SQLException { if (PropertyDefinition.USER.getString(props) == null) { PropertyDefinition.TARGET_DRIVER_USER_PROPERTY_NAME.set(props, "defaultUser"); } diff --git a/examples/AWSDriverExample/src/main/java/software/amazon/ReadWriteSplittingPostgresExample.java b/examples/AWSDriverExample/src/main/java/software/amazon/ReadWriteSplittingPostgresExample.java index 1a4b42cf7..c4a273dc9 100644 --- a/examples/AWSDriverExample/src/main/java/software/amazon/ReadWriteSplittingPostgresExample.java +++ b/examples/AWSDriverExample/src/main/java/software/amazon/ReadWriteSplittingPostgresExample.java @@ -23,8 +23,6 @@ import java.sql.SQLException; import java.sql.Statement; import java.util.Properties; -import software.amazon.jdbc.ConnectionProviderManager; -import software.amazon.jdbc.HikariPooledConnectionProvider; import software.amazon.jdbc.HostSpec; import software.amazon.jdbc.PropertyDefinition; import software.amazon.jdbc.plugin.failover.FailoverFailedSQLException; diff --git a/examples/AWSDriverExample/src/main/java/software/amazon/ReadWriteSplittingSpringJdbcTemplateMySQLExample.java b/examples/AWSDriverExample/src/main/java/software/amazon/ReadWriteSplittingSpringJdbcTemplateMySQLExample.java index ead361b58..ea914e72e 100644 --- a/examples/AWSDriverExample/src/main/java/software/amazon/ReadWriteSplittingSpringJdbcTemplateMySQLExample.java +++ b/examples/AWSDriverExample/src/main/java/software/amazon/ReadWriteSplittingSpringJdbcTemplateMySQLExample.java @@ -16,7 +16,6 @@ package software.amazon; -import com.mysql.cj.jdbc.MysqlDataSource; import com.zaxxer.hikari.HikariDataSource; import java.sql.Connection; import java.sql.SQLException; diff --git a/examples/HikariExample/src/main/java/software/amazon/HikariExample.java b/examples/HikariExample/src/main/java/software/amazon/HikariExample.java index 9bbfa03c9..8f6607798 100644 --- a/examples/HikariExample/src/main/java/software/amazon/HikariExample.java +++ b/examples/HikariExample/src/main/java/software/amazon/HikariExample.java @@ -22,7 +22,6 @@ import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; -import java.util.Properties; public class HikariExample { diff --git a/examples/SpringHibernateBalancedReaderTwoDataSourceExample/src/main/java/example/spring/Config.java b/examples/SpringHibernateBalancedReaderTwoDataSourceExample/src/main/java/example/spring/Config.java index bc404df52..d6b30ffa8 100644 --- a/examples/SpringHibernateBalancedReaderTwoDataSourceExample/src/main/java/example/spring/Config.java +++ b/examples/SpringHibernateBalancedReaderTwoDataSourceExample/src/main/java/example/spring/Config.java @@ -16,10 +16,7 @@ package example.spring; -import com.zaxxer.hikari.HikariConfig; -import java.util.Arrays; import java.util.Properties; -import java.util.concurrent.TimeUnit; import javax.persistence.EntityManagerFactory; import javax.sql.DataSource; import org.hibernate.exception.JDBCConnectionException; @@ -40,10 +37,6 @@ import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter; import org.springframework.transaction.PlatformTransactionManager; import org.springframework.transaction.annotation.EnableTransactionManagement; -import software.amazon.jdbc.HikariPooledConnectionProvider; -import software.amazon.jdbc.HostSpec; -import software.amazon.jdbc.profile.ConfigurationProfileBuilder; -import software.amazon.jdbc.profile.ConfigurationProfilePresetCodes; @Configuration @EnableTransactionManagement diff --git a/wrapper/src/main/java/software/amazon/jdbc/C3P0PooledConnectionProvider.java b/wrapper/src/main/java/software/amazon/jdbc/C3P0PooledConnectionProvider.java index dc4aa70eb..498739733 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/C3P0PooledConnectionProvider.java +++ b/wrapper/src/main/java/software/amazon/jdbc/C3P0PooledConnectionProvider.java @@ -31,10 +31,10 @@ import org.checkerframework.checker.nullness.qual.Nullable; import software.amazon.jdbc.cleanup.CanReleaseResources; import software.amazon.jdbc.dialect.Dialect; -import software.amazon.jdbc.targetdriverdialect.ConnectInfo; -import software.amazon.jdbc.targetdriverdialect.TargetDriverDialect; +import software.amazon.jdbc.targetdriverdialect.ConnectParams; import software.amazon.jdbc.util.Messages; import software.amazon.jdbc.util.PropertyUtils; +import software.amazon.jdbc.util.connection.ConnectConfig; import software.amazon.jdbc.util.storage.SlidingExpirationCache; public class C3P0PooledConnectionProvider implements PooledConnectionProvider, CanReleaseResources { @@ -56,7 +56,7 @@ public class C3P0PooledConnectionProvider implements PooledConnectionProvider, C protected static final long poolExpirationCheckNanos = TimeUnit.MINUTES.toNanos(30); @Override - public boolean acceptsUrl(@NonNull String protocol, @NonNull HostSpec hostSpec, @NonNull Properties props) { + public boolean acceptsUrl(@NonNull ConnectConfig connectConfig, @NonNull HostSpec hostSpec) { return true; } @@ -79,51 +79,52 @@ public HostSpec getHostSpecByStrategy(@NonNull List hosts, @NonNull Ho } @Override - public Connection connect(@NonNull String protocol, @NonNull Dialect dialect, - @NonNull TargetDriverDialect targetDriverDialect, @NonNull HostSpec hostSpec, - @NonNull Properties props) throws SQLException { - final Properties copy = PropertyUtils.copyProperties(props); - dialect.prepareConnectProperties(copy, protocol, hostSpec); + public Connection connect( + @NonNull ConnectConfig connectConfig, @NonNull HostSpec hostSpec) throws SQLException { + Dialect dialect = connectConfig.getDbDialect(); + Properties propsCopy = PropertyUtils.copyProperties(connectConfig.getProps()); + dialect.prepareConnectProperties(propsCopy, connectConfig.getProtocol(), hostSpec); final ComboPooledDataSource ds = databasePools.computeIfAbsent( hostSpec.getUrl(), - (key) -> createDataSource(protocol, hostSpec, copy, targetDriverDialect), + (key) -> createDataSource(connectConfig, hostSpec, propsCopy), poolExpirationCheckNanos ); - ds.setPassword(copy.getProperty(PropertyDefinition.PASSWORD.name)); + ds.setPassword(propsCopy.getProperty(PropertyDefinition.PASSWORD.name)); return ds.getConnection(); } protected ComboPooledDataSource createDataSource( - @NonNull String protocol, + @NonNull ConnectConfig connectConfig, @NonNull HostSpec hostSpec, - @NonNull Properties props, - TargetDriverDialect driverDialect) { - ConnectInfo connectInfo; + @NonNull Properties props) { + ConnectParams connectParams; + try { - connectInfo = driverDialect.prepareConnectInfo(protocol, hostSpec, props); + connectParams = + connectConfig.getDriverDialect().prepareConnectParams(connectConfig.getProtocol(), hostSpec, props); } catch (SQLException ex) { throw new RuntimeException(ex); } - final StringBuilder urlBuilder = new StringBuilder(connectInfo.url); + final StringBuilder urlBuilder = new StringBuilder(connectParams.connectionString); final StringJoiner propsJoiner = new StringJoiner("&"); - connectInfo.props.forEach((k, v) -> { + connectParams.props.forEach((k, v) -> { if (!PropertyDefinition.PASSWORD.name.equals(k) && !PropertyDefinition.USER.name.equals(k)) { propsJoiner.add(k + "=" + v); } }); - urlBuilder.append(connectInfo.url.contains("?") ? "&" : "?").append(propsJoiner); + urlBuilder.append(connectParams.connectionString.contains("?") ? "&" : "?").append(propsJoiner); ComboPooledDataSource ds = new ComboPooledDataSource(); ds.setJdbcUrl(urlBuilder.toString()); - final String user = connectInfo.props.getProperty(PropertyDefinition.USER.name); - final String password = connectInfo.props.getProperty(PropertyDefinition.PASSWORD.name); + final String user = connectParams.props.getProperty(PropertyDefinition.USER.name); + final String password = connectParams.props.getProperty(PropertyDefinition.PASSWORD.name); if (user != null) { ds.setUser(user); } diff --git a/wrapper/src/main/java/software/amazon/jdbc/ConnectionPlugin.java b/wrapper/src/main/java/software/amazon/jdbc/ConnectionPlugin.java index d2d72b05c..3a815960a 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/ConnectionPlugin.java +++ b/wrapper/src/main/java/software/amazon/jdbc/ConnectionPlugin.java @@ -21,8 +21,8 @@ import java.util.EnumSet; import java.util.List; import java.util.Map; -import java.util.Properties; import java.util.Set; +import software.amazon.jdbc.util.connection.ConnectConfig; /** * Interface for connection plugins. This class implements ways to execute a JDBC method and to clean up resources used @@ -45,7 +45,7 @@ T execute( * Establishes a connection to the given host using the given driver protocol and properties. If a * non-default {@link ConnectionProvider} has been set with * {@link Driver#setCustomConnectionProvider(ConnectionProvider)} and - * {@link ConnectionProvider#acceptsUrl(String, HostSpec, Properties)} returns true for the given + * {@link ConnectionProvider#acceptsUrl(ConnectConfig, HostSpec)} returns true for the given * protocol, host, and properties, the connection will be created by the non-default * ConnectionProvider. Otherwise, the connection will be created by the default * ConnectionProvider. The default ConnectionProvider will be {@link DriverConnectionProvider} for @@ -53,9 +53,8 @@ T execute( * {@link DataSourceConnectionProvider} for connections requested via an * {@link software.amazon.jdbc.ds.AwsWrapperDataSource}. * - * @param driverProtocol the driver protocol that should be used to establish the connection + * @param connectConfig the connection info for the original connection * @param hostSpec the host details for the desired connection - * @param props the connection properties * @param isInitialConnection a boolean indicating whether the current {@link Connection} is * establishing an initial physical connection to the database or has * already established a physical connection in the past @@ -66,9 +65,8 @@ T execute( * host */ Connection connect( - final String driverProtocol, + final ConnectConfig connectConfig, final HostSpec hostSpec, - final Properties props, final boolean isInitialConnection, final JdbcCallable connectFunc) throws SQLException; @@ -82,9 +80,8 @@ Connection connect( * requested via the {@link java.sql.DriverManager} and {@link DataSourceConnectionProvider} for * connections requested via an {@link software.amazon.jdbc.ds.AwsWrapperDataSource}. * - * @param driverProtocol the driver protocol that should be used to establish the connection + * @param connectConfig the connection info for the original connection. * @param hostSpec the host details for the desired connection - * @param props the connection properties * @param isInitialConnection a boolean indicating whether the current {@link Connection} is * establishing an initial physical connection to the database or has * already established a physical connection in the past @@ -95,9 +92,8 @@ Connection connect( * host */ Connection forceConnect( - final String driverProtocol, + final ConnectConfig connectConfig, final HostSpec hostSpec, - final Properties props, final boolean isInitialConnection, final JdbcCallable forceConnectFunc) throws SQLException; @@ -136,9 +132,7 @@ HostSpec getHostSpecByStrategy(final List hosts, final HostRole role, throws SQLException, UnsupportedOperationException; void initHostProvider( - final String driverProtocol, - final String initialUrl, - final Properties props, + final ConnectConfig connectConfig, final HostListProviderService hostListProviderService, final JdbcCallable initHostProviderFunc) throws SQLException; diff --git a/wrapper/src/main/java/software/amazon/jdbc/ConnectionPluginChainBuilder.java b/wrapper/src/main/java/software/amazon/jdbc/ConnectionPluginChainBuilder.java index 411e40cd8..943e6397e 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/ConnectionPluginChainBuilder.java +++ b/wrapper/src/main/java/software/amazon/jdbc/ConnectionPluginChainBuilder.java @@ -148,8 +148,7 @@ public List getPlugins( final ConnectionProvider effectiveConnProvider, final PluginManagerService pluginManagerService, final Properties props, - @Nullable ConfigurationProfile configurationProfile) - throws SQLException { + @Nullable ConfigurationProfile configurationProfile) throws SQLException { List plugins; List pluginFactories; diff --git a/wrapper/src/main/java/software/amazon/jdbc/ConnectionPluginManager.java b/wrapper/src/main/java/software/amazon/jdbc/ConnectionPluginManager.java index 8757e2c0a..61801a6f2 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/ConnectionPluginManager.java +++ b/wrapper/src/main/java/software/amazon/jdbc/ConnectionPluginManager.java @@ -29,7 +29,6 @@ import java.util.logging.Logger; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; -import org.jetbrains.annotations.NotNull; import software.amazon.jdbc.cleanup.CanReleaseResources; import software.amazon.jdbc.plugin.AuroraConnectionTrackerPlugin; import software.amazon.jdbc.plugin.AuroraInitialConnectionStrategyPlugin; @@ -53,6 +52,7 @@ import software.amazon.jdbc.util.Messages; import software.amazon.jdbc.util.Utils; import software.amazon.jdbc.util.WrapperUtils; +import software.amazon.jdbc.util.connection.ConnectConfig; import software.amazon.jdbc.util.telemetry.TelemetryContext; import software.amazon.jdbc.util.telemetry.TelemetryFactory; import software.amazon.jdbc.util.telemetry.TelemetryTraceLevel; @@ -170,7 +170,7 @@ public void unlock() { *

The {@link DefaultConnectionPlugin} will always be initialized and attached as the last * connection plugin in the chain. * - * @param servicesContainer the service container for the services required by this class. + * @param servicesContainer the service container for the services required by this class. * @param props the configuration of the connection * @param pluginManagerService a reference to a plugin manager service * @param configurationProfile a profile configuration defined by the user @@ -180,8 +180,7 @@ public void init( final FullServicesContainer servicesContainer, final Properties props, final PluginManagerService pluginManagerService, - @Nullable ConfigurationProfile configurationProfile) - throws SQLException { + @Nullable ConfigurationProfile configurationProfile) throws SQLException { this.props = props; this.servicesContainer = servicesContainer; @@ -355,7 +354,7 @@ public T execute( throw WrapperUtils.wrapExceptionIfNeeded( exceptionClass, new SQLException( - Messages.get("ConnectionPluginManager.invokedAgainstOldConnection", new Object[]{methodInvokeOn}))); + Messages.get("ConnectionPluginManager.invokedAgainstOldConnection", new Object[] {methodInvokeOn}))); } } @@ -372,7 +371,7 @@ public T execute( * Establishes a connection to the given host using the given driver protocol and properties. If a * non-default {@link ConnectionProvider} has been set with * {@link Driver#setCustomConnectionProvider(ConnectionProvider)} and - * {@link ConnectionProvider#acceptsUrl(String, HostSpec, Properties)} returns true for the given + * {@link ConnectionProvider#acceptsUrl(ConnectConfig, HostSpec)} returns true for the given * protocol, host, and properties, the connection will be created by the non-default * ConnectionProvider. Otherwise, the connection will be created by the default * ConnectionProvider. The default ConnectionProvider will be {@link DriverConnectionProvider} for @@ -380,9 +379,8 @@ public T execute( * {@link DataSourceConnectionProvider} for connections requested via an * {@link software.amazon.jdbc.ds.AwsWrapperDataSource}. * - * @param driverProtocol the driver protocol that should be used to establish the connection + * @param connectConfig the connection info for the original connection * @param hostSpec the host details for the desired connection - * @param props the connection properties * @param isInitialConnection a boolean indicating whether the current {@link Connection} is * establishing an initial physical connection to the database or has * already established a physical connection in the past @@ -392,9 +390,8 @@ public T execute( * host */ public Connection connect( - final String driverProtocol, + final ConnectConfig connectConfig, final HostSpec hostSpec, - final Properties props, final boolean isInitialConnection, final @Nullable ConnectionPlugin pluginToSkip) throws SQLException { @@ -406,7 +403,7 @@ public Connection connect( return executeWithSubscribedPlugins( JdbcMethod.CONNECT, (plugin, func) -> - plugin.connect(driverProtocol, hostSpec, props, isInitialConnection, func), + plugin.connect(connectConfig, hostSpec, isInitialConnection, func), () -> { throw new SQLException("Shouldn't be called."); }, @@ -431,9 +428,8 @@ public Connection connect( * requested via the {@link java.sql.DriverManager} and {@link DataSourceConnectionProvider} for * connections requested via an {@link software.amazon.jdbc.ds.AwsWrapperDataSource}. * - * @param driverProtocol the driver protocol that should be used to establish the connection + * @param connectConfig the connection info for the original connection. * @param hostSpec the host details for the desired connection - * @param props the connection properties * @param isInitialConnection a boolean indicating whether the current {@link Connection} is * establishing an initial physical connection to the database or has * already established a physical connection in the past @@ -443,9 +439,8 @@ public Connection connect( * host */ public Connection forceConnect( - final String driverProtocol, + final ConnectConfig connectConfig, final HostSpec hostSpec, - final Properties props, final boolean isInitialConnection, final @Nullable ConnectionPlugin pluginToSkip) throws SQLException { @@ -454,7 +449,7 @@ public Connection forceConnect( return executeWithSubscribedPlugins( JdbcMethod.FORCECONNECT, (plugin, func) -> - plugin.forceConnect(driverProtocol, hostSpec, props, isInitialConnection, func), + plugin.forceConnect(connectConfig, hostSpec, isInitialConnection, func), () -> { throw new SQLException("Shouldn't be called."); }, @@ -555,10 +550,7 @@ public HostSpec getHostSpecByStrategy(List hosts, HostRole role, Strin } public void initHostProvider( - final String driverProtocol, - final String initialUrl, - final Properties props, - final HostListProviderService hostListProviderService) + final ConnectConfig connectConfig, final HostListProviderService hostListProviderService) throws SQLException { TelemetryContext context = this.telemetryFactory.openTelemetryContext( "initHostProvider", TelemetryTraceLevel.NESTED); @@ -568,8 +560,7 @@ public void initHostProvider( JdbcMethod.INITHOSTPROVIDER, (PluginPipeline) (plugin, func) -> { - plugin.initHostProvider( - driverProtocol, initialUrl, props, hostListProviderService, func); + plugin.initHostProvider(connectConfig, hostListProviderService, func); return null; }, () -> { diff --git a/wrapper/src/main/java/software/amazon/jdbc/ConnectionProvider.java b/wrapper/src/main/java/software/amazon/jdbc/ConnectionProvider.java index 8fddcf269..b2980e09d 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/ConnectionProvider.java +++ b/wrapper/src/main/java/software/amazon/jdbc/ConnectionProvider.java @@ -22,8 +22,7 @@ import java.util.Properties; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; -import software.amazon.jdbc.dialect.Dialect; -import software.amazon.jdbc.targetdriverdialect.TargetDriverDialect; +import software.amazon.jdbc.util.connection.ConnectConfig; /** * Implement this interface in order to handle the physical connection creation process. @@ -34,14 +33,12 @@ public interface ConnectionProvider { * properties. Some ConnectionProvider implementations may not be able to handle certain URL * types or properties. * - * @param protocol the connection protocol (example "jdbc:mysql://") + * @param connectConfig the connection info for the original connection. * @param hostSpec the HostSpec containing the host-port information for the host to connect to - * @param props the Properties to use for the connection * @return true if this ConnectionProvider can provide connections for the given URL, otherwise * return false */ - boolean acceptsUrl( - @NonNull String protocol, @NonNull HostSpec hostSpec, @NonNull Properties props); + boolean acceptsUrl(@NonNull ConnectConfig connectConfig, @NonNull HostSpec hostSpec); /** * Indicates whether the selection strategy is supported by the connection provider. @@ -73,21 +70,12 @@ HostSpec getHostSpecByStrategy( /** * Called once per connection that needs to be created. * - * @param protocol the connection protocol (example "jdbc:mysql://") - * @param dialect the database dialect - * @param targetDriverDialect the target driver dialect + * @param connectConfig the connection info for the original connection. * @param hostSpec the HostSpec containing the host-port information for the host to connect to - * @param props the Properties to use for the connection * @return {@link Connection} resulting from the given connection information * @throws SQLException if an error occurs */ - Connection connect( - @NonNull String protocol, - @NonNull Dialect dialect, - @NonNull TargetDriverDialect targetDriverDialect, - @NonNull HostSpec hostSpec, - @NonNull Properties props) - throws SQLException; + Connection connect(@NonNull ConnectConfig connectConfig, @NonNull HostSpec hostSpec) throws SQLException; String getTargetName(); } diff --git a/wrapper/src/main/java/software/amazon/jdbc/ConnectionProviderManager.java b/wrapper/src/main/java/software/amazon/jdbc/ConnectionProviderManager.java index a8d1e6100..6ea63110a 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/ConnectionProviderManager.java +++ b/wrapper/src/main/java/software/amazon/jdbc/ConnectionProviderManager.java @@ -23,6 +23,7 @@ import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; import software.amazon.jdbc.cleanup.CanReleaseResources; +import software.amazon.jdbc.util.connection.ConnectConfig; public class ConnectionProviderManager { @@ -32,11 +33,10 @@ public class ConnectionProviderManager { /** * {@link ConnectionProviderManager} constructor. * - * @param defaultProvider the default {@link ConnectionProvider} to use if a non-default - * ConnectionProvider has not been set or the non-default - * ConnectionProvider has been set but does not accept a requested URL + * @param defaultProvider the default {@link ConnectionProvider} to use if a non-default + * ConnectionProvider has not been set or the non-default + * ConnectionProvider has been set but does not accept a requested URL * @param effectiveConnProvider the non-default {@link ConnectionProvider} to use - * */ public ConnectionProviderManager( final ConnectionProvider defaultProvider, @@ -66,21 +66,19 @@ public static void setConnectionProvider(ConnectionProvider connProvider) { * non-default ConnectionProvider will be returned. Otherwise, the default ConnectionProvider will * be returned. See {@link ConnectionProvider#acceptsUrl} for more info. * - * @param driverProtocol the driver protocol that will be used to establish the connection - * @param host the host info for the connection that will be established - * @param props the connection properties for the connection that will be established + * @param connectConfig the connection info for the original connection. + * @param host the host info for the connection that will be established * @return the {@link ConnectionProvider} to use to establish a connection using the given driver * protocol, host details, and properties */ - public ConnectionProvider getConnectionProvider( - String driverProtocol, HostSpec host, Properties props) { + public ConnectionProvider getConnectionProvider(ConnectConfig connectConfig, HostSpec host) { final ConnectionProvider customConnectionProvider = Driver.getCustomConnectionProvider(); - if (customConnectionProvider != null && customConnectionProvider.acceptsUrl(driverProtocol, host, props)) { + if (customConnectionProvider != null && customConnectionProvider.acceptsUrl(connectConfig, host)) { return customConnectionProvider; } - if (this.effectiveConnProvider != null && this.effectiveConnProvider.acceptsUrl(driverProtocol, host, props)) { + if (this.effectiveConnProvider != null && this.effectiveConnProvider.acceptsUrl(connectConfig, host)) { return this.effectiveConnProvider; } @@ -190,7 +188,6 @@ public static void releaseResources() { * for every brand-new database connection. * * @param func A function that initialize a new connection - * * @deprecated @see Driver#setConnectionInitFunc(ConnectionInitFunc) */ @Deprecated @@ -210,23 +207,21 @@ public static void resetConnectionInitFunc() { public void initConnection( final @Nullable Connection connection, - final @NonNull String protocol, - final @NonNull HostSpec hostSpec, - final @NonNull Properties props) throws SQLException { + final @NonNull ConnectConfig connectConfig, + final @NonNull HostSpec hostSpec) throws SQLException { final ConnectionInitFunc connectionInitFunc = Driver.getConnectionInitFunc(); if (connectionInitFunc == null) { return; } - connectionInitFunc.initConnection(connection, protocol, hostSpec, props); + connectionInitFunc.initConnection(connection, connectConfig, hostSpec); } public interface ConnectionInitFunc { void initConnection( final @Nullable Connection connection, - final @NonNull String protocol, - final @NonNull HostSpec hostSpec, - final @NonNull Properties props) throws SQLException; + final @NonNull ConnectConfig connectConfig, + final @NonNull HostSpec hostSpec) throws SQLException; } } diff --git a/wrapper/src/main/java/software/amazon/jdbc/DataSourceConnectionProvider.java b/wrapper/src/main/java/software/amazon/jdbc/DataSourceConnectionProvider.java index 6c5afcda3..1d6e59bf2 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/DataSourceConnectionProvider.java +++ b/wrapper/src/main/java/software/amazon/jdbc/DataSourceConnectionProvider.java @@ -30,14 +30,13 @@ import javax.sql.DataSource; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; -import software.amazon.jdbc.dialect.Dialect; import software.amazon.jdbc.exceptions.SQLLoginException; -import software.amazon.jdbc.targetdriverdialect.TargetDriverDialect; import software.amazon.jdbc.util.Messages; import software.amazon.jdbc.util.PropertyUtils; import software.amazon.jdbc.util.RdsUtils; import software.amazon.jdbc.util.SqlState; import software.amazon.jdbc.util.WrapperUtils; +import software.amazon.jdbc.util.connection.ConnectConfig; /** * This class is a basic implementation of {@link ConnectionProvider} interface. It creates and @@ -68,20 +67,8 @@ public DataSourceConnectionProvider(final @NonNull DataSource dataSource) { this.dataSourceClassName = dataSource.getClass().getName(); } - /** - * Indicates whether this ConnectionProvider can provide connections for the given host and - * properties. Some ConnectionProvider implementations may not be able to handle certain URL - * types or properties. - * - * @param protocol The connection protocol (example "jdbc:mysql://") - * @param hostSpec The HostSpec containing the host-port information for the host to connect to - * @param props The Properties to use for the connection - * @return true if this ConnectionProvider can provide connections for the given URL, otherwise - * return false - */ @Override - public boolean acceptsUrl( - @NonNull String protocol, @NonNull HostSpec hostSpec, @NonNull Properties props) { + public boolean acceptsUrl(@NonNull ConnectConfig connectConfig, @NonNull HostSpec hostSpec) { return true; } @@ -107,23 +94,16 @@ public HostSpec getHostSpecByStrategy( /** * Called once per connection that needs to be created. * - * @param protocol The connection protocol (example "jdbc:mysql://") + * @param connectConfig the connection info for the original connection. * @param hostSpec The HostSpec containing the host-port information for the host to connect to - * @param props The Properties to use for the connection * @return {@link Connection} resulting from the given connection information * @throws SQLException if an error occurs */ @Override public Connection connect( - final @NonNull String protocol, - final @NonNull Dialect dialect, - final @NonNull TargetDriverDialect targetDriverDialect, - final @NonNull HostSpec hostSpec, - final @NonNull Properties props) - throws SQLException { - - final Properties copy = PropertyUtils.copyProperties(props); - dialect.prepareConnectProperties(copy, protocol, hostSpec); + final @NonNull ConnectConfig connectConfig, final @NonNull HostSpec hostSpec) throws SQLException { + final Properties propsCopy = PropertyUtils.copyProperties(connectConfig.getProps()); + connectConfig.getDbDialect().prepareConnectProperties(propsCopy, connectConfig.getProtocol(), hostSpec); Connection conn; @@ -132,7 +112,7 @@ public Connection connect( LOGGER.finest(() -> "Use a separate DataSource object to create a connection."); // use a new data source instance to instantiate a connection final DataSource ds = createDataSource(); - conn = this.openConnection(ds, protocol, targetDriverDialect, hostSpec, copy); + conn = this.openConnection(ds, connectConfig, hostSpec, propsCopy); } else { @@ -141,7 +121,7 @@ public Connection connect( this.lock.lock(); LOGGER.finest(() -> "Use main DataSource object to create a connection."); try { - conn = this.openConnection(this.dataSource, protocol, targetDriverDialect, hostSpec, copy); + conn = this.openConnection(this.dataSource, connectConfig, hostSpec, propsCopy); } finally { this.lock.unlock(); } @@ -156,16 +136,15 @@ public Connection connect( protected Connection openConnection( final @NonNull DataSource ds, - final @NonNull String protocol, - final @NonNull TargetDriverDialect targetDriverDialect, + final @NonNull ConnectConfig connectConfig, final @NonNull HostSpec hostSpec, final @NonNull Properties props) throws SQLException { final boolean enableGreenNodeReplacement = PropertyDefinition.ENABLE_GREEN_NODE_REPLACEMENT.getBoolean(props); try { - targetDriverDialect.prepareDataSource( + connectConfig.getDriverDialect().prepareDataSource( ds, - protocol, + connectConfig.getProtocol(), hostSpec, props); return ds.getConnection(); @@ -214,9 +193,9 @@ protected Connection openConnection( .host(fixedHost) .build(); - targetDriverDialect.prepareDataSource( + connectConfig.getDriverDialect().prepareDataSource( this.dataSource, - protocol, + connectConfig.getProtocol(), connectionHostSpec, props); diff --git a/wrapper/src/main/java/software/amazon/jdbc/Driver.java b/wrapper/src/main/java/software/amazon/jdbc/Driver.java index e4f5a14af..6d18d9af2 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/Driver.java +++ b/wrapper/src/main/java/software/amazon/jdbc/Driver.java @@ -239,8 +239,8 @@ public Connection connect(final String url, final Properties info) throws SQLExc effectiveConnectionProvider = configurationProfile.getConnectionProvider(); } - FullServicesContainer - servicesContainer = new FullServicesContainerImpl(storageService, monitorService, telemetryFactory); + FullServicesContainer servicesContainer = + new FullServicesContainerImpl(storageService, monitorService, defaultConnectionProvider, telemetryFactory); return new ConnectionWrapper( servicesContainer, diff --git a/wrapper/src/main/java/software/amazon/jdbc/DriverConnectionProvider.java b/wrapper/src/main/java/software/amazon/jdbc/DriverConnectionProvider.java index e2a04e399..9ea690c3e 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/DriverConnectionProvider.java +++ b/wrapper/src/main/java/software/amazon/jdbc/DriverConnectionProvider.java @@ -28,13 +28,12 @@ import java.util.logging.Logger; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; -import software.amazon.jdbc.dialect.Dialect; import software.amazon.jdbc.exceptions.SQLLoginException; -import software.amazon.jdbc.targetdriverdialect.ConnectInfo; -import software.amazon.jdbc.targetdriverdialect.TargetDriverDialect; +import software.amazon.jdbc.targetdriverdialect.ConnectParams; import software.amazon.jdbc.util.Messages; import software.amazon.jdbc.util.PropertyUtils; import software.amazon.jdbc.util.RdsUtils; +import software.amazon.jdbc.util.connection.ConnectConfig; /** * This class is a basic implementation of {@link ConnectionProvider} interface. It creates and @@ -64,20 +63,8 @@ public DriverConnectionProvider(final java.sql.Driver driver) { this.targetDriverClassName = driver.getClass().getName(); } - /** - * Indicates whether this ConnectionProvider can provide connections for the given host and - * properties. Some ConnectionProvider implementations may not be able to handle certain URL - * types or properties. - * - * @param protocol The connection protocol (example "jdbc:mysql://") - * @param hostSpec The HostSpec containing the host-port information for the host to connect to - * @param props The Properties to use for the connection - * @return true if this ConnectionProvider can provide connections for the given URL, otherwise - * return false - */ @Override - public boolean acceptsUrl( - @NonNull String protocol, @NonNull HostSpec hostSpec, @NonNull Properties props) { + public boolean acceptsUrl(@NonNull ConnectConfig connectConfig, @NonNull HostSpec hostSpec) { return true; } @@ -103,43 +90,31 @@ public HostSpec getHostSpecByStrategy( /** * Called once per connection that needs to be created. * - * @param protocol The connection protocol (example "jdbc:mysql://") - * @param dialect The database dialect - * @param targetDriverDialect The target driver dialect + * @param connectConfig the connection info for the original connection. * @param hostSpec The HostSpec containing the host-port information for the host to connect to - * @param props The Properties to use for the connection * @return {@link Connection} resulting from the given connection information * @throws SQLException if an error occurs */ @Override - public Connection connect( - final @NonNull String protocol, - final @NonNull Dialect dialect, - final @NonNull TargetDriverDialect targetDriverDialect, - final @NonNull HostSpec hostSpec, - final @NonNull Properties props) + public Connection connect(final @NonNull ConnectConfig connectConfig, final @NonNull HostSpec hostSpec) throws SQLException { + final Properties propsCopy = PropertyUtils.copyProperties(connectConfig.getProps()); + final ConnectParams connectParams = + connectConfig.getDriverDialect().prepareConnectParams(connectConfig.getProtocol(), hostSpec, propsCopy); - // LOGGER.finest(() -> PropertyUtils.logProperties( - // PropertyUtils.maskProperties(props), "Connecting with properties: \n")); - - final Properties copy = PropertyUtils.copyProperties(props); - dialect.prepareConnectProperties(copy, protocol, hostSpec); - - final ConnectInfo connectInfo = targetDriverDialect.prepareConnectInfo(protocol, hostSpec, copy); - - LOGGER.finest(() -> "Connecting to " + connectInfo.url + connectConfig.getDbDialect().prepareConnectProperties(propsCopy, connectConfig.getProtocol(), hostSpec); + LOGGER.finest(() -> "Connecting to " + connectParams.connectionString + PropertyUtils.logProperties( - PropertyUtils.maskProperties(connectInfo.props), + PropertyUtils.maskProperties(connectParams.props), "\nwith properties: \n")); Connection conn; try { - conn = this.driver.connect(connectInfo.url, connectInfo.props); + conn = this.driver.connect(connectParams.connectionString, connectParams.props); } catch (Throwable throwable) { - if (!PropertyDefinition.ENABLE_GREEN_NODE_REPLACEMENT.getBoolean(props)) { + if (!PropertyDefinition.ENABLE_GREEN_NODE_REPLACEMENT.getBoolean(propsCopy)) { throw throwable; } @@ -184,14 +159,15 @@ public Connection connect( .host(fixedHost) .build(); - final ConnectInfo fixedConnectInfo = targetDriverDialect.prepareConnectInfo(protocol, connectionHostSpec, copy); + final ConnectParams fixedConnectParams = connectConfig.getDriverDialect().prepareConnectParams( + connectConfig.getProtocol(), connectionHostSpec, propsCopy); - LOGGER.finest(() -> "Connecting to " + fixedConnectInfo.url + LOGGER.finest(() -> "Connecting to " + fixedConnectParams.connectionString + " after correcting the hostname from " + originalHost + PropertyUtils.logProperties( - PropertyUtils.maskProperties(fixedConnectInfo.props), "\nwith properties: \n")); + PropertyUtils.maskProperties(fixedConnectParams.props), "\nwith properties: \n")); - conn = this.driver.connect(fixedConnectInfo.url, fixedConnectInfo.props); + conn = this.driver.connect(fixedConnectParams.connectionString, fixedConnectParams.props); } if (conn == null) { diff --git a/wrapper/src/main/java/software/amazon/jdbc/HikariPooledConnectionProvider.java b/wrapper/src/main/java/software/amazon/jdbc/HikariPooledConnectionProvider.java index f0d58c841..a792a3708 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/HikariPooledConnectionProvider.java +++ b/wrapper/src/main/java/software/amazon/jdbc/HikariPooledConnectionProvider.java @@ -35,14 +35,13 @@ import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; import software.amazon.jdbc.cleanup.CanReleaseResources; -import software.amazon.jdbc.dialect.Dialect; -import software.amazon.jdbc.targetdriverdialect.ConnectInfo; -import software.amazon.jdbc.targetdriverdialect.TargetDriverDialect; +import software.amazon.jdbc.targetdriverdialect.ConnectParams; import software.amazon.jdbc.util.Messages; import software.amazon.jdbc.util.Pair; import software.amazon.jdbc.util.PropertyUtils; import software.amazon.jdbc.util.RdsUrlType; import software.amazon.jdbc.util.RdsUtils; +import software.amazon.jdbc.util.connection.ConnectConfig; import software.amazon.jdbc.util.storage.SlidingExpirationCache; public class HikariPooledConnectionProvider implements PooledConnectionProvider, @@ -205,10 +204,9 @@ public HikariPooledConnectionProvider( @Override - public boolean acceptsUrl( - @NonNull String protocol, @NonNull HostSpec hostSpec, @NonNull Properties props) { + public boolean acceptsUrl(@NonNull ConnectConfig connectConfig, @NonNull HostSpec hostSpec) { if (this.acceptsUrlFunc != null) { - return this.acceptsUrlFunc.acceptsUrl(hostSpec, props); + return this.acceptsUrlFunc.acceptsUrl(hostSpec, connectConfig.getProps()); } final RdsUrlType urlType = rdsUtils.identifyRdsType(hostSpec.getHost()); @@ -241,18 +239,12 @@ public HostSpec getHostSpecByStrategy( } @Override - public Connection connect( - @NonNull String protocol, - @NonNull Dialect dialect, - @NonNull TargetDriverDialect targetDriverDialect, - @NonNull HostSpec hostSpec, - @NonNull Properties props) + public Connection connect(@NonNull ConnectConfig connectConfig, @NonNull HostSpec hostSpec) throws SQLException { - - final Properties copy = PropertyUtils.copyProperties(props); + final Properties propsCopy = PropertyUtils.copyProperties(connectConfig.getProps()); HostSpec connectionHostSpec = hostSpec; - if (PropertyDefinition.ENABLE_GREEN_NODE_REPLACEMENT.getBoolean(props) + if (PropertyDefinition.ENABLE_GREEN_NODE_REPLACEMENT.getBoolean(propsCopy) && rdsUtils.isRdsDns(hostSpec.getHost()) && rdsUtils.isGreenInstance(hostSpec.getHost())) { @@ -276,15 +268,16 @@ public Connection connect( } final HostSpec finalHostSpec = connectionHostSpec; - dialect.prepareConnectProperties(copy, protocol, finalHostSpec); + connectConfig.getDbDialect().prepareConnectProperties( + propsCopy, connectConfig.getProtocol(), finalHostSpec); final HikariDataSource ds = (HikariDataSource) HikariPoolsHolder.databasePools.computeIfAbsent( - Pair.create(hostSpec.getUrl(), getPoolKey(finalHostSpec, copy)), - (lambdaPoolKey) -> createHikariDataSource(protocol, finalHostSpec, copy, targetDriverDialect), + Pair.create(hostSpec.getUrl(), getPoolKey(finalHostSpec, propsCopy)), + (lambdaPoolKey) -> createHikariDataSource(connectConfig, finalHostSpec, propsCopy), poolExpirationCheckNanos ); - ds.setPassword(copy.getProperty(PropertyDefinition.PASSWORD.name)); + ds.setPassword(propsCopy.getProperty(PropertyDefinition.PASSWORD.name)); return ds.getConnection(); } @@ -309,43 +302,40 @@ public void releaseResources() { /** * Configures the default required settings for the internal connection pool. * - * @param config the {@link HikariConfig} to configure. By default, this method sets the - * jdbcUrl, exceptionOverrideClassName, username, and password. The - * HikariConfig passed to this method should be created via a - * {@link HikariPoolConfigurator}, which allows the user to specify any - * additional configuration properties. - * @param protocol the driver protocol that should be used to form connections - * @param hostSpec the host details used to form the connection - * @param connectionProps the connection properties - * @param targetDriverDialect the target driver dialect {@link TargetDriverDialect} + * @param config the {@link HikariConfig} to configure. By default, this method sets the + * jdbcUrl, exceptionOverrideClassName, username, and password. The + * HikariConfig passed to this method should be created via a + * {@link HikariPoolConfigurator}, which allows the user to specify any + * additional configuration properties. + * @param connectConfig the connection info for the original connection. + * @param hostSpec the host details used to form the connection + * @param connectionProps the connection properties */ protected void configurePool( final HikariConfig config, - final String protocol, + final ConnectConfig connectConfig, final HostSpec hostSpec, - final Properties connectionProps, - final @NonNull TargetDriverDialect targetDriverDialect) { - + final Properties connectionProps) { final Properties copy = PropertyUtils.copyProperties(connectionProps); - ConnectInfo connectInfo; + ConnectParams connectParams; try { - connectInfo = targetDriverDialect.prepareConnectInfo( - protocol, hostSpec, copy); + connectParams = connectConfig.getDriverDialect().prepareConnectParams( + connectConfig.getProtocol(), hostSpec, copy); } catch (SQLException ex) { throw new RuntimeException(ex); } - StringBuilder urlBuilder = new StringBuilder(connectInfo.url); + StringBuilder urlBuilder = new StringBuilder(connectParams.connectionString); final StringJoiner propsJoiner = new StringJoiner("&"); - connectInfo.props.forEach((k, v) -> { + connectParams.props.forEach((k, v) -> { if (!PropertyDefinition.PASSWORD.name.equals(k) && !PropertyDefinition.USER.name.equals(k)) { propsJoiner.add(k + "=" + v); } }); - if (connectInfo.url.contains("?")) { + if (connectParams.connectionString.contains("?")) { urlBuilder.append("&").append(propsJoiner); } else { urlBuilder.append("?").append(propsJoiner); @@ -353,8 +343,8 @@ protected void configurePool( config.setJdbcUrl(urlBuilder.toString()); - final String user = connectInfo.props.getProperty(PropertyDefinition.USER.name); - final String password = connectInfo.props.getProperty(PropertyDefinition.PASSWORD.name); + final String user = connectParams.props.getProperty(PropertyDefinition.USER.name); + final String password = connectParams.props.getProperty(PropertyDefinition.PASSWORD.name); if (user != null) { config.setUsername(user); } @@ -380,7 +370,7 @@ public int getHostCount() { public Set getHosts() { return Collections.unmodifiableSet( HikariPoolsHolder.databasePools.getEntries().keySet().stream() - .map(poolKey -> (String) poolKey.getValue1()) + .map(Pair::getValue1) .collect(Collectors.toSet())); } @@ -389,7 +379,7 @@ public Set getHosts() { * * @return a set containing every key associated with an active connection pool */ - public Set getKeys() { + public Set> getKeys() { return HikariPoolsHolder.databasePools.getEntries().keySet(); } @@ -417,18 +407,17 @@ public void logConnections() { } HikariDataSource createHikariDataSource( - final String protocol, + final ConnectConfig connectConfig, final HostSpec hostSpec, - final Properties props, - final @NonNull TargetDriverDialect targetDriverDialect) { + final Properties props) { HikariConfig config = poolConfigurator.configurePool(hostSpec, props); - configurePool(config, protocol, hostSpec, props, targetDriverDialect); + configurePool(config, connectConfig, hostSpec, props); return new HikariDataSource(config); } // For testing purposes only - void setDatabasePools(SlidingExpirationCache connectionPools) { + void setDatabasePools(SlidingExpirationCache, AutoCloseable> connectionPools) { HikariPoolsHolder.databasePools = connectionPools; } } diff --git a/wrapper/src/main/java/software/amazon/jdbc/HikariPoolsHolder.java b/wrapper/src/main/java/software/amazon/jdbc/HikariPoolsHolder.java index 7eb2389e3..bafd526f5 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/HikariPoolsHolder.java +++ b/wrapper/src/main/java/software/amazon/jdbc/HikariPoolsHolder.java @@ -20,7 +20,7 @@ import software.amazon.jdbc.util.storage.SlidingExpirationCache; public class HikariPoolsHolder { - static SlidingExpirationCache databasePools = + static SlidingExpirationCache, AutoCloseable> databasePools = new SlidingExpirationCache<>( null, (hikariDataSource) -> { diff --git a/wrapper/src/main/java/software/amazon/jdbc/HostSpecBuilder.java b/wrapper/src/main/java/software/amazon/jdbc/HostSpecBuilder.java index a84920637..ec6abdbee 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/HostSpecBuilder.java +++ b/wrapper/src/main/java/software/amazon/jdbc/HostSpecBuilder.java @@ -17,7 +17,6 @@ package software.amazon.jdbc; import java.sql.Timestamp; -import java.time.Instant; import org.checkerframework.checker.nullness.qual.NonNull; import software.amazon.jdbc.hostavailability.HostAvailability; import software.amazon.jdbc.hostavailability.HostAvailabilityStrategy; diff --git a/wrapper/src/main/java/software/amazon/jdbc/LeastConnectionsHostSelector.java b/wrapper/src/main/java/software/amazon/jdbc/LeastConnectionsHostSelector.java index 88b90624c..4a0851f05 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/LeastConnectionsHostSelector.java +++ b/wrapper/src/main/java/software/amazon/jdbc/LeastConnectionsHostSelector.java @@ -31,10 +31,10 @@ public class LeastConnectionsHostSelector implements HostSelector { public static final String STRATEGY_LEAST_CONNECTIONS = "leastConnections"; - private final SlidingExpirationCache databasePools; + private final SlidingExpirationCache, AutoCloseable> databasePools; public LeastConnectionsHostSelector( - SlidingExpirationCache databasePools) { + SlidingExpirationCache, AutoCloseable> databasePools) { this.databasePools = databasePools; } @@ -50,7 +50,7 @@ public HostSpec getHost( getNumConnections(hostSpec1, this.databasePools) - getNumConnections(hostSpec2, this.databasePools)) .collect(Collectors.toList()); - if (eligibleHosts.size() == 0) { + if (eligibleHosts.isEmpty()) { throw new SQLException(Messages.get("HostSelector.noHostsMatchingRole", new Object[]{role})); } @@ -59,10 +59,10 @@ public HostSpec getHost( private int getNumConnections( final HostSpec hostSpec, - final SlidingExpirationCache databasePools) { + final SlidingExpirationCache, AutoCloseable> databasePools) { int numConnections = 0; final String url = hostSpec.getUrl(); - for (final Map.Entry entry : + for (final Map.Entry, AutoCloseable> entry : databasePools.getEntries().entrySet()) { if (!url.equals(entry.getKey().getValue1())) { continue; diff --git a/wrapper/src/main/java/software/amazon/jdbc/PartialPluginService.java b/wrapper/src/main/java/software/amazon/jdbc/PartialPluginService.java index 36a0dc0b1..ebf26efc4 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/PartialPluginService.java +++ b/wrapper/src/main/java/software/amazon/jdbc/PartialPluginService.java @@ -48,6 +48,7 @@ import software.amazon.jdbc.util.FullServicesContainer; import software.amazon.jdbc.util.Messages; import software.amazon.jdbc.util.Utils; +import software.amazon.jdbc.util.connection.ConnectConfig; import software.amazon.jdbc.util.storage.CacheMap; import software.amazon.jdbc.util.telemetry.TelemetryFactory; @@ -65,8 +66,8 @@ public class PartialPluginService implements PluginService, CanReleaseResources, protected static final CacheMap hostAvailabilityExpiringCache = new CacheMap<>(); protected final FullServicesContainer servicesContainer; + protected final ConnectConfig connectConfig; protected final ConnectionPluginManager pluginManager; - protected final Properties props; protected volatile HostListProvider hostListProvider; protected List allHosts = new ArrayList<>(); protected HostSpec currentHostSpec; @@ -74,39 +75,22 @@ public class PartialPluginService implements PluginService, CanReleaseResources, protected boolean isInTransaction; protected final ExceptionManager exceptionManager; protected final @Nullable ExceptionHandler exceptionHandler; - protected final String originalUrl; - protected final String driverProtocol; - protected TargetDriverDialect targetDriverDialect; - protected Dialect dbDialect; protected @Nullable final ConfigurationProfile configurationProfile; protected final ConnectionProviderManager connectionProviderManager; public PartialPluginService( - @NonNull final FullServicesContainer servicesContainer, - @NonNull final Properties props, - @NonNull final String originalUrl, - @NonNull final String targetDriverProtocol, - @NonNull final TargetDriverDialect targetDriverDialect, - @NonNull final Dialect dbDialect) { + @NonNull final FullServicesContainer servicesContainer, @NonNull final ConnectConfig connectConfig) { this( servicesContainer, new ExceptionManager(), - props, - originalUrl, - targetDriverProtocol, - targetDriverDialect, - dbDialect, + connectConfig, null); } public PartialPluginService( @NonNull final FullServicesContainer servicesContainer, @NonNull final ExceptionManager exceptionManager, - @NonNull final Properties props, - @NonNull final String originalUrl, - @NonNull final String targetDriverProtocol, - @NonNull final TargetDriverDialect targetDriverDialect, - @NonNull final Dialect dbDialect, + @NonNull final ConnectConfig connectConfig, @Nullable final ConfigurationProfile configurationProfile) { this.servicesContainer = servicesContainer; this.servicesContainer.setHostListProviderService(this); @@ -114,11 +98,7 @@ public PartialPluginService( this.servicesContainer.setPluginManagerService(this); this.pluginManager = servicesContainer.getConnectionPluginManager(); - this.props = props; - this.originalUrl = originalUrl; - this.driverProtocol = targetDriverProtocol; - this.targetDriverDialect = targetDriverDialect; - this.dbDialect = dbDialect; + this.connectConfig = connectConfig; this.configurationProfile = configurationProfile; this.exceptionManager = exceptionManager; @@ -130,8 +110,8 @@ public PartialPluginService( ? this.configurationProfile.getExceptionHandler() : null; - HostListProviderSupplier supplier = this.dbDialect.getHostListProvider(); - this.hostListProvider = supplier.getProvider(this.props, this.originalUrl, this.servicesContainer); + HostListProviderSupplier supplier = this.connectConfig.getDbDialect().getHostListProvider(); + this.hostListProvider = supplier.getProvider(this.connectConfig, this.servicesContainer); } @Override @@ -182,9 +162,14 @@ public HostSpec getInitialConnectionHostSpec() { return this.initialConnectionHostSpec; } + @Override + public ConnectConfig getConnectConfig() { + return this.connectConfig; + } + @Override public String getOriginalUrl() { - return this.originalUrl; + return this.connectConfig.getInitialConnectionString(); } @Override @@ -229,13 +214,13 @@ public ConnectionProvider getDefaultConnectionProvider() { public boolean isPooledConnectionProvider(HostSpec host, Properties props) { final ConnectionProvider connectionProvider = - this.connectionProviderManager.getConnectionProvider(this.driverProtocol, host, props); + this.connectionProviderManager.getConnectionProvider(this.connectConfig, host); return (connectionProvider instanceof PooledConnectionProvider); } @Override public String getDriverProtocol() { - return this.driverProtocol; + return this.connectConfig.getProtocol(); } @Override @@ -510,8 +495,7 @@ public Connection forceConnect( final HostSpec hostSpec, final Properties props) throws SQLException { - throw new UnsupportedOperationException( - Messages.get("PartialPluginService.unexpectedMethodCall", new Object[] {"forceConnect"})); + return this.forceConnect(hostSpec, props, null); } @Override @@ -520,8 +504,7 @@ public Connection forceConnect( final Properties props, final @Nullable ConnectionPlugin pluginToSkip) throws SQLException { - throw new UnsupportedOperationException( - Messages.get("PartialPluginService.unexpectedMethodCall", new Object[] {"forceConnect"})); + return this.pluginManager.forceConnect(this.connectConfig, hostSpec, true, pluginToSkip); } private void updateHostAvailability(final List hosts) { @@ -541,7 +524,7 @@ public void releaseResources() { @Override public boolean isNetworkException(Throwable throwable) { - return this.isNetworkException(throwable, this.targetDriverDialect); + return this.isNetworkException(throwable, this.connectConfig.getDriverDialect()); } @Override @@ -549,7 +532,9 @@ public boolean isNetworkException(final Throwable throwable, @Nullable TargetDri if (this.exceptionHandler != null) { return this.exceptionHandler.isNetworkException(throwable, targetDriverDialect); } - return this.exceptionManager.isNetworkException(this.dbDialect, throwable, targetDriverDialect); + + return this.exceptionManager.isNetworkException( + this.connectConfig.getDbDialect(), throwable, targetDriverDialect); } @Override @@ -557,12 +542,13 @@ public boolean isNetworkException(final String sqlState) { if (this.exceptionHandler != null) { return this.exceptionHandler.isNetworkException(sqlState); } - return this.exceptionManager.isNetworkException(this.dbDialect, sqlState); + + return this.exceptionManager.isNetworkException(this.connectConfig.getDbDialect(), sqlState); } @Override public boolean isLoginException(Throwable throwable) { - return this.isLoginException(throwable, this.targetDriverDialect); + return this.isLoginException(throwable, this.connectConfig.getDriverDialect()); } @Override @@ -570,7 +556,9 @@ public boolean isLoginException(final Throwable throwable, @Nullable TargetDrive if (this.exceptionHandler != null) { return this.exceptionHandler.isLoginException(throwable, targetDriverDialect); } - return this.exceptionManager.isLoginException(this.dbDialect, throwable, targetDriverDialect); + + return this.exceptionManager.isLoginException( + this.connectConfig.getDbDialect(), throwable, targetDriverDialect); } @Override @@ -578,17 +566,17 @@ public boolean isLoginException(final String sqlState) { if (this.exceptionHandler != null) { return this.exceptionHandler.isLoginException(sqlState); } - return this.exceptionManager.isLoginException(this.dbDialect, sqlState); + return this.exceptionManager.isLoginException(this.connectConfig.getDbDialect(), sqlState); } @Override public Dialect getDialect() { - return this.dbDialect; + return this.connectConfig.getDbDialect(); } @Override public TargetDriverDialect getTargetDriverDialect() { - return this.targetDriverDialect; + return this.connectConfig.getDriverDialect(); } @Override @@ -636,12 +624,12 @@ public void fillAliases(Connection connection, HostSpec hostSpec) throws SQLExce @Override public HostSpecBuilder getHostSpecBuilder() { - return new HostSpecBuilder(new HostAvailabilityStrategyFactory().create(this.props)); + return new HostSpecBuilder(new HostAvailabilityStrategyFactory().create(this.connectConfig.getProps())); } @Override public Properties getProperties() { - return this.props; + return this.connectConfig.getProps(); } public TelemetryFactory getTelemetryFactory() { diff --git a/wrapper/src/main/java/software/amazon/jdbc/PluginService.java b/wrapper/src/main/java/software/amazon/jdbc/PluginService.java index 6c9180650..f84bb46d5 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/PluginService.java +++ b/wrapper/src/main/java/software/amazon/jdbc/PluginService.java @@ -29,6 +29,7 @@ import software.amazon.jdbc.hostavailability.HostAvailability; import software.amazon.jdbc.states.SessionStateService; import software.amazon.jdbc.targetdriverdialect.TargetDriverDialect; +import software.amazon.jdbc.util.connection.ConnectConfig; import software.amazon.jdbc.util.telemetry.TelemetryFactory; /** @@ -81,6 +82,13 @@ EnumSet setCurrentConnection( HostSpec getInitialConnectionHostSpec(); + /** + * Get the {@link ConnectConfig} for the current original connection. + * + * @return the {@link ConnectConfig} for the current original connection. + */ + ConnectConfig getConnectConfig(); + String getOriginalUrl(); /** diff --git a/wrapper/src/main/java/software/amazon/jdbc/PluginServiceImpl.java b/wrapper/src/main/java/software/amazon/jdbc/PluginServiceImpl.java index f6d266564..3fe66f6ff 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/PluginServiceImpl.java +++ b/wrapper/src/main/java/software/amazon/jdbc/PluginServiceImpl.java @@ -53,6 +53,7 @@ import software.amazon.jdbc.util.FullServicesContainer; import software.amazon.jdbc.util.Messages; import software.amazon.jdbc.util.Utils; +import software.amazon.jdbc.util.connection.ConnectConfig; import software.amazon.jdbc.util.storage.CacheMap; import software.amazon.jdbc.util.telemetry.TelemetryFactory; @@ -69,20 +70,16 @@ public class PluginServiceImpl implements PluginService, CanReleaseResources, protected static final long DEFAULT_STATUS_CACHE_EXPIRE_NANO = TimeUnit.MINUTES.toNanos(60); protected final ConnectionPluginManager pluginManager; - private final Properties props; - private final String originalUrl; - private final String driverProtocol; + protected final ConnectConfig connectConfig; protected volatile HostListProvider hostListProvider; protected List allHosts = new ArrayList<>(); protected Connection currentConnection; protected HostSpec currentHostSpec; protected HostSpec initialConnectionHostSpec; - private boolean isInTransaction; - private final ExceptionManager exceptionManager; + protected boolean isInTransaction; + protected final ExceptionManager exceptionManager; protected final @Nullable ExceptionHandler exceptionHandler; protected final DialectProvider dialectProvider; - protected Dialect dialect; - protected TargetDriverDialect targetDriverDialect; protected @Nullable final ConfigurationProfile configurationProfile; protected final ConnectionProviderManager connectionProviderManager; @@ -91,40 +88,20 @@ public class PluginServiceImpl implements PluginService, CanReleaseResources, protected final ReentrantLock connectionSwitchLock = new ReentrantLock(); public PluginServiceImpl( - @NonNull final FullServicesContainer servicesContainer, - @NonNull final Properties props, - @NonNull final String originalUrl, - @NonNull final String targetDriverProtocol, - @NonNull final TargetDriverDialect targetDriverDialect) + @NonNull final FullServicesContainer servicesContainer, @NonNull final ConnectConfig connectConfig) throws SQLException { - - this( - servicesContainer, - new ExceptionManager(), - props, - originalUrl, - targetDriverProtocol, - null, - targetDriverDialect, - null, - null); + this(servicesContainer, new ExceptionManager(), connectConfig, null, null, null); } public PluginServiceImpl( @NonNull final FullServicesContainer servicesContainer, - @NonNull final Properties props, - @NonNull final String originalUrl, - @NonNull final String targetDriverProtocol, - @NonNull final TargetDriverDialect targetDriverDialect, + @NonNull final ConnectConfig connectConfig, @Nullable final ConfigurationProfile configurationProfile) throws SQLException { this( servicesContainer, new ExceptionManager(), - props, - originalUrl, - targetDriverProtocol, + connectConfig, null, - targetDriverDialect, configurationProfile, null); } @@ -132,37 +109,32 @@ public PluginServiceImpl( public PluginServiceImpl( @NonNull final FullServicesContainer servicesContainer, @NonNull final ExceptionManager exceptionManager, - @NonNull final Properties props, - @NonNull final String originalUrl, - @NonNull final String targetDriverProtocol, + @NonNull final ConnectConfig connectConfig, @Nullable final DialectProvider dialectProvider, - @NonNull final TargetDriverDialect targetDriverDialect, @Nullable final ConfigurationProfile configurationProfile, @Nullable final SessionStateService sessionStateService) throws SQLException { this.servicesContainer = servicesContainer; this.pluginManager = servicesContainer.getConnectionPluginManager(); - this.props = props; - this.originalUrl = originalUrl; - this.driverProtocol = targetDriverProtocol; + this.connectConfig = connectConfig; this.configurationProfile = configurationProfile; this.exceptionManager = exceptionManager; this.dialectProvider = dialectProvider != null ? dialectProvider : new DialectManager(this); - this.targetDriverDialect = targetDriverDialect; this.connectionProviderManager = new ConnectionProviderManager( this.pluginManager.getDefaultConnProvider(), this.pluginManager.getEffectiveConnProvider()); this.sessionStateService = sessionStateService != null ? sessionStateService - : new SessionStateServiceImpl(this, this.props); + : new SessionStateServiceImpl(this, this.connectConfig.getProps()); this.exceptionHandler = this.configurationProfile != null && this.configurationProfile.getExceptionHandler() != null ? this.configurationProfile.getExceptionHandler() : null; - this.dialect = this.configurationProfile != null && this.configurationProfile.getDialect() != null + Dialect dialect = this.configurationProfile != null && this.configurationProfile.getDialect() != null ? this.configurationProfile.getDialect() - : this.dialectProvider.getDialect(this.driverProtocol, this.originalUrl, this.props); + : this.dialectProvider.getDialect(this.connectConfig); + this.connectConfig.setDbDialect(dialect); } @Override @@ -212,9 +184,14 @@ public HostSpec getInitialConnectionHostSpec() { return this.initialConnectionHostSpec; } + @Override + public ConnectConfig getConnectConfig() { + return this.connectConfig; + } + @Override public String getOriginalUrl() { - return this.originalUrl; + return this.connectConfig.getInitialConnectionString(); } @Override @@ -256,13 +233,13 @@ public ConnectionProvider getDefaultConnectionProvider() { public boolean isPooledConnectionProvider(HostSpec host, Properties props) { final ConnectionProvider connectionProvider = - this.connectionProviderManager.getConnectionProvider(this.driverProtocol, host, props); + this.connectionProviderManager.getConnectionProvider(this.connectConfig, host); return (connectionProvider instanceof PooledConnectionProvider); } @Override public String getDriverProtocol() { - return this.driverProtocol; + return this.getConnectConfig().getProtocol(); } @Override @@ -313,7 +290,8 @@ public EnumSet setCurrentConnection( this.sessionStateService.applyCurrentSessionState(connection); this.setInTransaction(false); - if (isInTransaction && PropertyDefinition.ROLLBACK_ON_SWITCH.getBoolean(this.props)) { + if (isInTransaction + && PropertyDefinition.ROLLBACK_ON_SWITCH.getBoolean(this.connectConfig.getProps())) { try { oldConnection.rollback(); } catch (final SQLException e) { @@ -614,7 +592,7 @@ public Connection connect( final @Nullable ConnectionPlugin pluginToSkip) throws SQLException { return this.pluginManager.connect( - this.driverProtocol, hostSpec, props, this.currentConnection == null, pluginToSkip); + this.connectConfig, hostSpec, this.currentConnection == null, pluginToSkip); } @Override @@ -632,7 +610,7 @@ public Connection forceConnect( final @Nullable ConnectionPlugin pluginToSkip) throws SQLException { return this.pluginManager.forceConnect( - this.driverProtocol, hostSpec, props, this.currentConnection == null, pluginToSkip); + this.connectConfig, hostSpec, this.currentConnection == null, pluginToSkip); } private void updateHostAvailability(final List hosts) { @@ -665,7 +643,7 @@ public void releaseResources() { @Override @Deprecated public boolean isNetworkException(Throwable throwable) { - return this.isNetworkException(throwable, this.targetDriverDialect); + return this.isNetworkException(throwable, this.connectConfig.getDriverDialect()); } @Override @@ -673,7 +651,7 @@ public boolean isNetworkException(final Throwable throwable, @Nullable TargetDri if (this.exceptionHandler != null) { return this.exceptionHandler.isNetworkException(throwable, targetDriverDialect); } - return this.exceptionManager.isNetworkException(this.dialect, throwable, targetDriverDialect); + return this.exceptionManager.isNetworkException(this.connectConfig.getDbDialect(), throwable, targetDriverDialect); } @Override @@ -681,13 +659,13 @@ public boolean isNetworkException(final String sqlState) { if (this.exceptionHandler != null) { return this.exceptionHandler.isNetworkException(sqlState); } - return this.exceptionManager.isNetworkException(this.dialect, sqlState); + return this.exceptionManager.isNetworkException(this.connectConfig.getDbDialect(), sqlState); } @Override @Deprecated public boolean isLoginException(Throwable throwable) { - return this.isLoginException(throwable, this.targetDriverDialect); + return this.isLoginException(throwable, this.connectConfig.getDriverDialect()); } @Override @@ -695,7 +673,7 @@ public boolean isLoginException(final Throwable throwable, @Nullable TargetDrive if (this.exceptionHandler != null) { return this.exceptionHandler.isLoginException(throwable, targetDriverDialect); } - return this.exceptionManager.isLoginException(this.dialect, throwable, targetDriverDialect); + return this.exceptionManager.isLoginException(this.connectConfig.getDbDialect(), throwable, targetDriverDialect); } @Override @@ -703,31 +681,30 @@ public boolean isLoginException(final String sqlState) { if (this.exceptionHandler != null) { return this.exceptionHandler.isLoginException(sqlState); } - return this.exceptionManager.isLoginException(this.dialect, sqlState); + return this.exceptionManager.isLoginException(this.connectConfig.getDbDialect(), sqlState); } @Override public Dialect getDialect() { - return this.dialect; + return this.connectConfig.getDbDialect(); } @Override public TargetDriverDialect getTargetDriverDialect() { - return this.targetDriverDialect; + return this.connectConfig.getDriverDialect(); } public void updateDialect(final @NonNull Connection connection) throws SQLException { - final Dialect originalDialect = this.dialect; - this.dialect = this.dialectProvider.getDialect( - this.originalUrl, - this.initialConnectionHostSpec, - connection); - if (originalDialect == this.dialect) { + final Dialect originalDialect = this.connectConfig.getDbDialect(); + Dialect currentDialect = this.dialectProvider.getDialect( + this.connectConfig.getInitialConnectionString(), this.initialConnectionHostSpec, connection); + if (originalDialect == currentDialect) { return; } - final HostListProviderSupplier supplier = this.dialect.getHostListProvider(); - this.setHostListProvider(supplier.getProvider(this.props, this.originalUrl, this.servicesContainer)); + this.connectConfig.setDbDialect(currentDialect); + final HostListProviderSupplier supplier = this.connectConfig.getDbDialect().getHostListProvider(); + this.setHostListProvider(supplier.getProvider(this.connectConfig, this.servicesContainer)); this.refreshHostList(connection); } @@ -770,12 +747,12 @@ public void fillAliases(Connection connection, HostSpec hostSpec) throws SQLExce @Override public HostSpecBuilder getHostSpecBuilder() { - return new HostSpecBuilder(new HostAvailabilityStrategyFactory().create(this.props)); + return new HostSpecBuilder(new HostAvailabilityStrategyFactory().create(this.connectConfig.getProps())); } @Override public Properties getProperties() { - return this.props; + return this.connectConfig.getProps(); } public TelemetryFactory getTelemetryFactory() { diff --git a/wrapper/src/main/java/software/amazon/jdbc/authentication/AwsCredentialsManager.java b/wrapper/src/main/java/software/amazon/jdbc/authentication/AwsCredentialsManager.java index eb463a7aa..c562dd48e 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/authentication/AwsCredentialsManager.java +++ b/wrapper/src/main/java/software/amazon/jdbc/authentication/AwsCredentialsManager.java @@ -23,7 +23,6 @@ import software.amazon.awssdk.auth.credentials.DefaultCredentialsProvider; import software.amazon.jdbc.HostSpec; import software.amazon.jdbc.PropertyDefinition; -import software.amazon.jdbc.util.Messages; import software.amazon.jdbc.util.StringUtils; public class AwsCredentialsManager { diff --git a/wrapper/src/main/java/software/amazon/jdbc/dialect/AuroraMysqlDialect.java b/wrapper/src/main/java/software/amazon/jdbc/dialect/AuroraMysqlDialect.java index e64352899..247981839 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/dialect/AuroraMysqlDialect.java +++ b/wrapper/src/main/java/software/amazon/jdbc/dialect/AuroraMysqlDialect.java @@ -89,21 +89,20 @@ public boolean isDialect(final Connection connection) { @Override public HostListProviderSupplier getHostListProvider() { - return (properties, initialUrl, servicesContainer) -> { + return (connectConfig, servicesContainer) -> { final PluginService pluginService = servicesContainer.getPluginService(); if (pluginService.isPluginInUse(FailoverConnectionPlugin.class)) { return new MonitoringRdsHostListProvider( - properties, - initialUrl, + connectConfig, servicesContainer, TOPOLOGY_QUERY, NODE_ID_QUERY, IS_READER_QUERY, IS_WRITER_QUERY); } + return new AuroraHostListProvider( - properties, - initialUrl, + connectConfig, servicesContainer, TOPOLOGY_QUERY, NODE_ID_QUERY, diff --git a/wrapper/src/main/java/software/amazon/jdbc/dialect/AuroraPgDialect.java b/wrapper/src/main/java/software/amazon/jdbc/dialect/AuroraPgDialect.java index ad21fb9f9..4499db901 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/dialect/AuroraPgDialect.java +++ b/wrapper/src/main/java/software/amazon/jdbc/dialect/AuroraPgDialect.java @@ -135,21 +135,20 @@ public boolean isDialect(final Connection connection) { @Override public HostListProviderSupplier getHostListProvider() { - return (properties, initialUrl, servicesContainer) -> { + return (connectConfig, servicesContainer) -> { final PluginService pluginService = servicesContainer.getPluginService(); if (pluginService.isPluginInUse(FailoverConnectionPlugin.class)) { return new MonitoringRdsHostListProvider( - properties, - initialUrl, + connectConfig, servicesContainer, TOPOLOGY_QUERY, NODE_ID_QUERY, IS_READER_QUERY, IS_WRITER_QUERY); } + return new AuroraHostListProvider( - properties, - initialUrl, + connectConfig, servicesContainer, TOPOLOGY_QUERY, NODE_ID_QUERY, diff --git a/wrapper/src/main/java/software/amazon/jdbc/dialect/DialectManager.java b/wrapper/src/main/java/software/amazon/jdbc/dialect/DialectManager.java index d29a1b3dd..ec63ae39d 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/dialect/DialectManager.java +++ b/wrapper/src/main/java/software/amazon/jdbc/dialect/DialectManager.java @@ -21,7 +21,6 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.Properties; import java.util.concurrent.TimeUnit; import java.util.logging.Logger; import org.checkerframework.checker.nullness.qual.NonNull; @@ -36,6 +35,7 @@ import software.amazon.jdbc.util.RdsUtils; import software.amazon.jdbc.util.StringUtils; import software.amazon.jdbc.util.Utils; +import software.amazon.jdbc.util.connection.ConnectConfig; import software.amazon.jdbc.util.storage.CacheMap; public class DialectManager implements DialectProvider { @@ -119,12 +119,7 @@ public static void resetEndpointCache() { } @Override - public Dialect getDialect( - final @NonNull String driverProtocol, - final @NonNull String url, - final @NonNull Properties props) - throws SQLException { - + public Dialect getDialect(final @NonNull ConnectConfig connectConfig) throws SQLException { this.canUpdate = false; this.dialect = null; @@ -136,10 +131,10 @@ public Dialect getDialect( return this.dialect; } - final String userDialectSetting = DIALECT.getString(props); + final String userDialectSetting = DIALECT.getString(connectConfig.getProps()); final String dialectCode = !StringUtils.isNullOrEmpty(userDialectSetting) ? userDialectSetting - : knownEndpointDialects.get(url); + : knownEndpointDialects.get(connectConfig.getInitialConnectionString()); if (!StringUtils.isNullOrEmpty(dialectCode)) { final Dialect userDialect = knownDialectsByCode.get(dialectCode); @@ -154,19 +149,19 @@ public Dialect getDialect( } } - if (StringUtils.isNullOrEmpty(driverProtocol)) { + if (StringUtils.isNullOrEmpty(connectConfig.getProtocol())) { throw new IllegalArgumentException("protocol"); } - String host = url; + String connectionString = connectConfig.getInitialConnectionString(); final List hosts = this.connectionUrlParser.getHostsFromConnectionUrl( - url, true, pluginService::getHostSpecBuilder); + connectConfig.getInitialConnectionString(), true, pluginService::getHostSpecBuilder); if (!Utils.isNullOrEmpty(hosts)) { - host = hosts.get(0).getHost(); + connectionString = hosts.get(0).getHost(); } - if (driverProtocol.contains("mysql")) { - RdsUrlType type = this.rdsHelper.identifyRdsType(host); + if (connectConfig.getProtocol().contains("mysql")) { + RdsUrlType type = this.rdsHelper.identifyRdsType(connectionString); if (type.isRdsCluster()) { this.canUpdate = true; this.dialectCode = DialectCodes.AURORA_MYSQL; @@ -187,8 +182,8 @@ public Dialect getDialect( return this.dialect; } - if (driverProtocol.contains("postgresql")) { - RdsUrlType type = this.rdsHelper.identifyRdsType(host); + if (connectConfig.getProtocol().contains("postgresql")) { + RdsUrlType type = this.rdsHelper.identifyRdsType(connectionString); if (RdsUrlType.RDS_AURORA_LIMITLESS_DB_SHARD_GROUP.equals(type)) { this.canUpdate = false; this.dialectCode = DialectCodes.AURORA_PG; @@ -215,7 +210,7 @@ public Dialect getDialect( return this.dialect; } - if (driverProtocol.contains("mariadb")) { + if (connectConfig.getProtocol().contains("mariadb")) { this.canUpdate = true; this.dialectCode = DialectCodes.MARIADB; this.dialect = knownDialectsByCode.get(DialectCodes.MARIADB); diff --git a/wrapper/src/main/java/software/amazon/jdbc/dialect/DialectProvider.java b/wrapper/src/main/java/software/amazon/jdbc/dialect/DialectProvider.java index bc90e7fdc..910124235 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/dialect/DialectProvider.java +++ b/wrapper/src/main/java/software/amazon/jdbc/dialect/DialectProvider.java @@ -18,15 +18,12 @@ import java.sql.Connection; import java.sql.SQLException; -import java.util.Properties; import org.checkerframework.checker.nullness.qual.NonNull; import software.amazon.jdbc.HostSpec; +import software.amazon.jdbc.util.connection.ConnectConfig; public interface DialectProvider { - Dialect getDialect( - final @NonNull String driverProtocol, - final @NonNull String url, - final @NonNull Properties props) throws SQLException; + Dialect getDialect(final @NonNull ConnectConfig connectConfig) throws SQLException; Dialect getDialect( final @NonNull String originalUrl, diff --git a/wrapper/src/main/java/software/amazon/jdbc/dialect/HostListProviderSupplier.java b/wrapper/src/main/java/software/amazon/jdbc/dialect/HostListProviderSupplier.java index 0dfe44dc5..d9ce81918 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/dialect/HostListProviderSupplier.java +++ b/wrapper/src/main/java/software/amazon/jdbc/dialect/HostListProviderSupplier.java @@ -16,15 +16,14 @@ package software.amazon.jdbc.dialect; -import java.util.Properties; import org.checkerframework.checker.nullness.qual.NonNull; import software.amazon.jdbc.HostListProvider; import software.amazon.jdbc.util.FullServicesContainer; +import software.amazon.jdbc.util.connection.ConnectConfig; @FunctionalInterface public interface HostListProviderSupplier { @NonNull HostListProvider getProvider( - final @NonNull Properties properties, - final String initialUrl, + final @NonNull ConnectConfig connectConfig, final @NonNull FullServicesContainer servicesContainer); } diff --git a/wrapper/src/main/java/software/amazon/jdbc/dialect/MariaDbDialect.java b/wrapper/src/main/java/software/amazon/jdbc/dialect/MariaDbDialect.java index 3b368a8a1..6a5a6e0f2 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/dialect/MariaDbDialect.java +++ b/wrapper/src/main/java/software/amazon/jdbc/dialect/MariaDbDialect.java @@ -104,8 +104,8 @@ public List getDialectUpdateCandidates() { } public HostListProviderSupplier getHostListProvider() { - return (properties, initialUrl, servicesContainer) -> - new ConnectionStringHostListProvider(properties, initialUrl, servicesContainer.getHostListProviderService()); + return (connectConfig, servicesContainer) -> + new ConnectionStringHostListProvider(connectConfig, servicesContainer.getHostListProviderService()); } @Override diff --git a/wrapper/src/main/java/software/amazon/jdbc/dialect/MysqlDialect.java b/wrapper/src/main/java/software/amazon/jdbc/dialect/MysqlDialect.java index de9f181d3..bf549dcd8 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/dialect/MysqlDialect.java +++ b/wrapper/src/main/java/software/amazon/jdbc/dialect/MysqlDialect.java @@ -105,8 +105,8 @@ public List getDialectUpdateCandidates() { } public HostListProviderSupplier getHostListProvider() { - return (properties, initialUrl, servicesContainer) -> - new ConnectionStringHostListProvider(properties, initialUrl, servicesContainer.getHostListProviderService()); + return (connectConfig, servicesContainer) -> + new ConnectionStringHostListProvider(connectConfig, servicesContainer.getHostListProviderService()); } @Override diff --git a/wrapper/src/main/java/software/amazon/jdbc/dialect/PgDialect.java b/wrapper/src/main/java/software/amazon/jdbc/dialect/PgDialect.java index 87c4c705c..a02094553 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/dialect/PgDialect.java +++ b/wrapper/src/main/java/software/amazon/jdbc/dialect/PgDialect.java @@ -106,8 +106,8 @@ public List getDialectUpdateCandidates() { @Override public HostListProviderSupplier getHostListProvider() { - return (properties, initialUrl, servicesContainer) -> - new ConnectionStringHostListProvider(properties, initialUrl, servicesContainer.getHostListProviderService()); + return (connectConfig, servicesContainer) -> + new ConnectionStringHostListProvider(connectConfig, servicesContainer.getHostListProviderService()); } @Override diff --git a/wrapper/src/main/java/software/amazon/jdbc/dialect/RdsMultiAzDbClusterMysqlDialect.java b/wrapper/src/main/java/software/amazon/jdbc/dialect/RdsMultiAzDbClusterMysqlDialect.java index 930cf1631..e8eed7f33 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/dialect/RdsMultiAzDbClusterMysqlDialect.java +++ b/wrapper/src/main/java/software/amazon/jdbc/dialect/RdsMultiAzDbClusterMysqlDialect.java @@ -94,12 +94,11 @@ public boolean isDialect(final Connection connection) { @Override public HostListProviderSupplier getHostListProvider() { - return (properties, initialUrl, servicesContainer) -> { + return (connectConfig, servicesContainer) -> { final PluginService pluginService = servicesContainer.getPluginService(); if (pluginService.isPluginInUse(FailoverConnectionPlugin.class)) { return new MonitoringRdsMultiAzHostListProvider( - properties, - initialUrl, + connectConfig, servicesContainer, TOPOLOGY_QUERY, NODE_ID_QUERY, @@ -109,8 +108,7 @@ public HostListProviderSupplier getHostListProvider() { } else { return new RdsMultiAzDbClusterListProvider( - properties, - initialUrl, + connectConfig, servicesContainer, TOPOLOGY_QUERY, NODE_ID_QUERY, diff --git a/wrapper/src/main/java/software/amazon/jdbc/dialect/RdsMultiAzDbClusterPgDialect.java b/wrapper/src/main/java/software/amazon/jdbc/dialect/RdsMultiAzDbClusterPgDialect.java index d91c867c0..fbdeced04 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/dialect/RdsMultiAzDbClusterPgDialect.java +++ b/wrapper/src/main/java/software/amazon/jdbc/dialect/RdsMultiAzDbClusterPgDialect.java @@ -80,12 +80,11 @@ public boolean isDialect(final Connection connection) { @Override public HostListProviderSupplier getHostListProvider() { - return (properties, initialUrl, servicesContainer) -> { + return (connectConfig, servicesContainer) -> { final PluginService pluginService = servicesContainer.getPluginService(); if (pluginService.isPluginInUse(FailoverConnectionPlugin.class)) { return new MonitoringRdsMultiAzHostListProvider( - properties, - initialUrl, + connectConfig, servicesContainer, TOPOLOGY_QUERY, NODE_ID_QUERY, @@ -96,8 +95,7 @@ public HostListProviderSupplier getHostListProvider() { } else { return new RdsMultiAzDbClusterListProvider( - properties, - initialUrl, + connectConfig, servicesContainer, TOPOLOGY_QUERY, NODE_ID_QUERY, diff --git a/wrapper/src/main/java/software/amazon/jdbc/dialect/UnknownDialect.java b/wrapper/src/main/java/software/amazon/jdbc/dialect/UnknownDialect.java index 65b9eb544..9fdcb3c79 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/dialect/UnknownDialect.java +++ b/wrapper/src/main/java/software/amazon/jdbc/dialect/UnknownDialect.java @@ -81,8 +81,8 @@ public List getDialectUpdateCandidates() { @Override public HostListProviderSupplier getHostListProvider() { - return (properties, initialUrl, servicesContainer) -> - new ConnectionStringHostListProvider(properties, initialUrl, servicesContainer.getHostListProviderService()); + return (connectConfig, servicesContainer) -> + new ConnectionStringHostListProvider(connectConfig, servicesContainer.getHostListProviderService()); } @Override diff --git a/wrapper/src/main/java/software/amazon/jdbc/ds/AwsWrapperDataSource.java b/wrapper/src/main/java/software/amazon/jdbc/ds/AwsWrapperDataSource.java index 0c54e018e..440a8870b 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/ds/AwsWrapperDataSource.java +++ b/wrapper/src/main/java/software/amazon/jdbc/ds/AwsWrapperDataSource.java @@ -281,8 +281,8 @@ ConnectionWrapper createConnectionWrapper( final @NonNull TargetDriverDialect targetDriverDialect, final @Nullable ConfigurationProfile configurationProfile, final TelemetryFactory telemetryFactory) throws SQLException { - FullServicesContainer - servicesContainer = new FullServicesContainerImpl(storageService, monitorService, telemetryFactory); + FullServicesContainer servicesContainer = + new FullServicesContainerImpl(storageService, monitorService, defaultProvider, telemetryFactory); return new ConnectionWrapper( servicesContainer, props, diff --git a/wrapper/src/main/java/software/amazon/jdbc/hostavailability/HostAvailabilityStrategy.java b/wrapper/src/main/java/software/amazon/jdbc/hostavailability/HostAvailabilityStrategy.java index 659fdae2b..9f04b54c6 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/hostavailability/HostAvailabilityStrategy.java +++ b/wrapper/src/main/java/software/amazon/jdbc/hostavailability/HostAvailabilityStrategy.java @@ -16,8 +16,6 @@ package software.amazon.jdbc.hostavailability; -import software.amazon.jdbc.AwsWrapperProperty; - public interface HostAvailabilityStrategy { void setHostAvailability(HostAvailability hostAvailability); diff --git a/wrapper/src/main/java/software/amazon/jdbc/hostlistprovider/AuroraHostListProvider.java b/wrapper/src/main/java/software/amazon/jdbc/hostlistprovider/AuroraHostListProvider.java index fc53f9e1d..3c76d93ae 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/hostlistprovider/AuroraHostListProvider.java +++ b/wrapper/src/main/java/software/amazon/jdbc/hostlistprovider/AuroraHostListProvider.java @@ -17,9 +17,9 @@ package software.amazon.jdbc.hostlistprovider; -import java.util.Properties; import java.util.logging.Logger; import software.amazon.jdbc.util.FullServicesContainer; +import software.amazon.jdbc.util.connection.ConnectConfig; public class AuroraHostListProvider extends RdsHostListProvider { @@ -27,14 +27,13 @@ public class AuroraHostListProvider extends RdsHostListProvider { static final Logger LOGGER = Logger.getLogger(AuroraHostListProvider.class.getName()); public AuroraHostListProvider( - final Properties properties, - final String originalUrl, + final ConnectConfig connectConfig, final FullServicesContainer servicesContainer, final String topologyQuery, final String nodeIdQuery, final String isReaderQuery) { - super(properties, - originalUrl, + super( + connectConfig, servicesContainer, topologyQuery, nodeIdQuery, diff --git a/wrapper/src/main/java/software/amazon/jdbc/hostlistprovider/ConnectionStringHostListProvider.java b/wrapper/src/main/java/software/amazon/jdbc/hostlistprovider/ConnectionStringHostListProvider.java index 80f55bdad..7cdfe78c6 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/hostlistprovider/ConnectionStringHostListProvider.java +++ b/wrapper/src/main/java/software/amazon/jdbc/hostlistprovider/ConnectionStringHostListProvider.java @@ -21,7 +21,6 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; -import java.util.Properties; import java.util.logging.Logger; import org.checkerframework.checker.nullness.qual.NonNull; import software.amazon.jdbc.AwsWrapperProperty; @@ -30,17 +29,17 @@ import software.amazon.jdbc.HostSpec; import software.amazon.jdbc.util.ConnectionUrlParser; import software.amazon.jdbc.util.Messages; +import software.amazon.jdbc.util.connection.ConnectConfig; public class ConnectionStringHostListProvider implements StaticHostListProvider { private static final Logger LOGGER = Logger.getLogger(ConnectionStringHostListProvider.class.getName()); final List hostList = new ArrayList<>(); - Properties properties; private boolean isInitialized = false; private final boolean isSingleWriterConnectionString; private final ConnectionUrlParser connectionUrlParser; - private final String initialUrl; + private final ConnectConfig connectConfig; private final HostListProviderService hostListProviderService; public static final AwsWrapperProperty SINGLE_WRITER_CONNECTION_STRING = @@ -51,20 +50,17 @@ public class ConnectionStringHostListProvider implements StaticHostListProvider + "cluster has only one writer. The writer must be the first host in the connection string"); public ConnectionStringHostListProvider( - final @NonNull Properties properties, - final String initialUrl, + final @NonNull ConnectConfig connectConfig, final @NonNull HostListProviderService hostListProviderService) { - this(properties, initialUrl, hostListProviderService, new ConnectionUrlParser()); + this(connectConfig, hostListProviderService, new ConnectionUrlParser()); } ConnectionStringHostListProvider( - final @NonNull Properties properties, - final String initialUrl, + final @NonNull ConnectConfig connectConfig, final @NonNull HostListProviderService hostListProviderService, final @NonNull ConnectionUrlParser connectionUrlParser) { - - this.isSingleWriterConnectionString = SINGLE_WRITER_CONNECTION_STRING.getBoolean(properties); - this.initialUrl = initialUrl; + this.connectConfig = connectConfig; + this.isSingleWriterConnectionString = SINGLE_WRITER_CONNECTION_STRING.getBoolean(connectConfig.getProps()); this.connectionUrlParser = connectionUrlParser; this.hostListProviderService = hostListProviderService; } @@ -74,11 +70,13 @@ private void init() throws SQLException { return; } this.hostList.addAll( - this.connectionUrlParser.getHostsFromConnectionUrl(this.initialUrl, this.isSingleWriterConnectionString, + this.connectionUrlParser.getHostsFromConnectionUrl( + this.connectConfig.getInitialConnectionString(), + this.isSingleWriterConnectionString, () -> this.hostListProviderService.getHostSpecBuilder())); if (this.hostList.isEmpty()) { throw new SQLException(Messages.get("ConnectionStringHostListProvider.parsedListEmpty", - new Object[] {this.initialUrl})); + new Object[] {this.connectConfig.getInitialConnectionString()})); } this.hostListProviderService.setInitialConnectionHostSpec(this.hostList.get(0)); this.isInitialized = true; diff --git a/wrapper/src/main/java/software/amazon/jdbc/hostlistprovider/RdsHostListProvider.java b/wrapper/src/main/java/software/amazon/jdbc/hostlistprovider/RdsHostListProvider.java index 738eebcc3..77d5252e7 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/hostlistprovider/RdsHostListProvider.java +++ b/wrapper/src/main/java/software/amazon/jdbc/hostlistprovider/RdsHostListProvider.java @@ -55,6 +55,7 @@ import software.amazon.jdbc.util.StringUtils; import software.amazon.jdbc.util.SynchronousExecutor; import software.amazon.jdbc.util.Utils; +import software.amazon.jdbc.util.connection.ConnectConfig; import software.amazon.jdbc.util.storage.CacheMap; public class RdsHostListProvider implements DynamicHostListProvider { @@ -94,7 +95,7 @@ public class RdsHostListProvider implements DynamicHostListProvider { protected final FullServicesContainer servicesContainer; protected final HostListProviderService hostListProviderService; - protected final String originalUrl; + protected final ConnectConfig connectConfig; protected final String topologyQuery; protected final String nodeIdQuery; protected final String isReaderQuery; @@ -116,21 +117,17 @@ public class RdsHostListProvider implements DynamicHostListProvider { protected volatile boolean isInitialized = false; - protected Properties properties; - static { PropertyDefinition.registerPluginProperties(RdsHostListProvider.class); } public RdsHostListProvider( - final Properties properties, - final String originalUrl, + final ConnectConfig connectConfig, final FullServicesContainer servicesContainer, final String topologyQuery, final String nodeIdQuery, final String isReaderQuery) { - this.properties = properties; - this.originalUrl = originalUrl; + this.connectConfig = connectConfig; this.servicesContainer = servicesContainer; this.hostListProviderService = servicesContainer.getHostListProviderService(); this.topologyQuery = topologyQuery; @@ -151,22 +148,23 @@ protected void init() throws SQLException { // initial topology is based on connection string this.initialHostList = - connectionUrlParser.getHostsFromConnectionUrl(this.originalUrl, false, + connectionUrlParser.getHostsFromConnectionUrl(this.connectConfig.getInitialConnectionString(), false, this.hostListProviderService::getHostSpecBuilder); if (this.initialHostList == null || this.initialHostList.isEmpty()) { throw new SQLException(Messages.get("RdsHostListProvider.parsedListEmpty", - new Object[] {this.originalUrl})); + new Object[] {this.connectConfig.getInitialConnectionString()})); } this.initialHostSpec = this.initialHostList.get(0); this.hostListProviderService.setInitialConnectionHostSpec(this.initialHostSpec); this.clusterId = UUID.randomUUID().toString(); this.isPrimaryClusterId = false; + Properties props = this.connectConfig.getProps(); this.refreshRateNano = - TimeUnit.MILLISECONDS.toNanos(CLUSTER_TOPOLOGY_REFRESH_RATE_MS.getInteger(properties)); + TimeUnit.MILLISECONDS.toNanos(CLUSTER_TOPOLOGY_REFRESH_RATE_MS.getInteger(props)); HostSpecBuilder hostSpecBuilder = this.hostListProviderService.getHostSpecBuilder(); - String clusterInstancePattern = CLUSTER_INSTANCE_HOST_PATTERN.getString(this.properties); + String clusterInstancePattern = CLUSTER_INSTANCE_HOST_PATTERN.getString(props); if (clusterInstancePattern != null) { this.clusterInstanceTemplate = ConnectionUrlParser.parseHostPortPair(clusterInstancePattern, () -> hostSpecBuilder); @@ -183,7 +181,7 @@ protected void init() throws SQLException { this.rdsUrlType = rdsHelper.identifyRdsType(this.initialHostSpec.getHost()); - final String clusterIdSetting = CLUSTER_ID.getString(this.properties); + final String clusterIdSetting = CLUSTER_ID.getString(props); if (!StringUtils.isNullOrEmpty(clusterIdSetting)) { this.clusterId = clusterIdSetting; } else if (rdsUrlType == RdsUrlType.RDS_PROXY) { @@ -297,9 +295,7 @@ protected ClusterSuggestedResult getSuggestedClusterId(final String url) { if (key.equals(url)) { return new ClusterSuggestedResult(url, isPrimaryCluster); } - if (hosts == null) { - continue; - } + for (final HostSpec host : hosts) { if (host.getHostAndPort().equals(url)) { LOGGER.finest(() -> Messages.get("RdsHostListProvider.suggestedClusterId", diff --git a/wrapper/src/main/java/software/amazon/jdbc/hostlistprovider/RdsMultiAzDbClusterListProvider.java b/wrapper/src/main/java/software/amazon/jdbc/hostlistprovider/RdsMultiAzDbClusterListProvider.java index a63323176..761344458 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/hostlistprovider/RdsMultiAzDbClusterListProvider.java +++ b/wrapper/src/main/java/software/amazon/jdbc/hostlistprovider/RdsMultiAzDbClusterListProvider.java @@ -26,13 +26,13 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.List; -import java.util.Properties; import java.util.logging.Logger; import software.amazon.jdbc.HostRole; import software.amazon.jdbc.HostSpec; import software.amazon.jdbc.hostavailability.HostAvailability; import software.amazon.jdbc.util.FullServicesContainer; import software.amazon.jdbc.util.Messages; +import software.amazon.jdbc.util.connection.ConnectConfig; public class RdsMultiAzDbClusterListProvider extends RdsHostListProvider { private final String fetchWriterNodeQuery; @@ -40,8 +40,7 @@ public class RdsMultiAzDbClusterListProvider extends RdsHostListProvider { static final Logger LOGGER = Logger.getLogger(RdsMultiAzDbClusterListProvider.class.getName()); public RdsMultiAzDbClusterListProvider( - final Properties properties, - final String originalUrl, + final ConnectConfig connectConfig, final FullServicesContainer servicesContainer, final String topologyQuery, final String nodeIdQuery, @@ -49,8 +48,8 @@ public RdsMultiAzDbClusterListProvider( final String fetchWriterNodeQuery, final String fetchWriterNodeQueryHeader ) { - super(properties, - originalUrl, + super( + connectConfig, servicesContainer, topologyQuery, nodeIdQuery, diff --git a/wrapper/src/main/java/software/amazon/jdbc/hostlistprovider/monitoring/ClusterTopologyMonitorImpl.java b/wrapper/src/main/java/software/amazon/jdbc/hostlistprovider/monitoring/ClusterTopologyMonitorImpl.java index 4e7b62de1..72526e112 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/hostlistprovider/monitoring/ClusterTopologyMonitorImpl.java +++ b/wrapper/src/main/java/software/amazon/jdbc/hostlistprovider/monitoring/ClusterTopologyMonitorImpl.java @@ -42,22 +42,21 @@ import java.util.stream.Collectors; import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; -import software.amazon.jdbc.HostListProviderService; import software.amazon.jdbc.HostRole; import software.amazon.jdbc.HostSpec; import software.amazon.jdbc.PropertyDefinition; import software.amazon.jdbc.hostavailability.HostAvailability; import software.amazon.jdbc.hostlistprovider.Topology; import software.amazon.jdbc.util.ExecutorFactory; +import software.amazon.jdbc.util.FullServicesContainer; import software.amazon.jdbc.util.Messages; import software.amazon.jdbc.util.PropertyUtils; import software.amazon.jdbc.util.RdsUtils; +import software.amazon.jdbc.util.ServiceUtility; import software.amazon.jdbc.util.StringUtils; import software.amazon.jdbc.util.SynchronousExecutor; import software.amazon.jdbc.util.Utils; -import software.amazon.jdbc.util.connection.ConnectionService; import software.amazon.jdbc.util.monitoring.AbstractMonitor; -import software.amazon.jdbc.util.storage.StorageService; public class ClusterTopologyMonitorImpl extends AbstractMonitor implements ClusterTopologyMonitor { @@ -80,15 +79,13 @@ public class ClusterTopologyMonitorImpl extends AbstractMonitor implements Clust protected final long refreshRateNano; protected final long highRefreshRateNano; + protected final FullServicesContainer servicesContainer; protected final Properties properties; protected final Properties monitoringProperties; protected final HostSpec initialHostSpec; - protected final StorageService storageService; - protected final ConnectionService connectionService; protected final String topologyQuery; protected final String nodeIdQuery; protected final String writerTopologyQuery; - protected final HostListProviderService hostListProviderService; protected final HostSpec clusterInstanceTemplate; protected String clusterId; @@ -109,12 +106,10 @@ public class ClusterTopologyMonitorImpl extends AbstractMonitor implements Clust protected final AtomicReference> nodeThreadsLatestTopology = new AtomicReference<>(null); public ClusterTopologyMonitorImpl( + final FullServicesContainer servicesContainer, final String clusterId, - final StorageService storageService, - final ConnectionService connectionService, final HostSpec initialHostSpec, final Properties properties, - final HostListProviderService hostListProviderService, final HostSpec clusterInstanceTemplate, final long refreshRateNano, final long highRefreshRateNano, @@ -124,9 +119,7 @@ public ClusterTopologyMonitorImpl( super(monitorTerminationTimeoutSec); this.clusterId = clusterId; - this.storageService = storageService; - this.connectionService = connectionService; - this.hostListProviderService = hostListProviderService; + this.servicesContainer = servicesContainer; this.initialHostSpec = initialHostSpec; this.clusterInstanceTemplate = clusterInstanceTemplate; this.properties = properties; @@ -251,7 +244,7 @@ protected List waitTillTopologyGetsUpdated(final long timeoutMs) throw } private List getStoredHosts() { - Topology topology = storageService.get(Topology.class, this.clusterId); + Topology topology = this.servicesContainer.getStorageService().get(Topology.class, this.clusterId); return topology == null ? null : topology.getHosts(); } @@ -277,7 +270,7 @@ public void close() { } @Override - public void monitor() { + public void monitor() throws Exception { try { LOGGER.finest(() -> Messages.get( "ClusterTopologyMonitorImpl.startMonitoringThread", @@ -309,15 +302,27 @@ public void monitor() { if (hosts != null && !this.isVerifiedWriterConnection) { for (HostSpec hostSpec : hosts) { + // A list is used to store the exception since lambdas require references to outer variables to be + // final. This allows us to identify if an error occurred while creating the node monitoring worker. + final List exceptionList = new ArrayList<>(); this.submittedNodes.computeIfAbsent(hostSpec.getHost(), (key) -> { final ExecutorService nodeExecutorServiceCopy = this.nodeExecutorService; if (nodeExecutorServiceCopy != null) { - this.nodeExecutorService.submit( - this.getNodeMonitoringWorker(hostSpec, this.writerHostSpec.get())); + try { + this.nodeExecutorService.submit( + this.getNodeMonitoringWorker(hostSpec, this.writerHostSpec.get())); + } catch (SQLException e) { + exceptionList.add(e); + return null; + } } return true; }); + + if (!exceptionList.isEmpty()) { + throw exceptionList.get(0); + } } // It's not possible to call shutdown() on this.nodeExecutorService since more node may be added later. } @@ -358,12 +363,25 @@ public void monitor() { List hosts = this.nodeThreadsLatestTopology.get(); if (hosts != null && !this.nodeThreadsStop.get()) { for (HostSpec hostSpec : hosts) { + // A list is used to store the exception since lambdas require references to outer variables to be + // final. This allows us to identify if an error occurred while creating the node monitoring worker. + final List exceptionList = new ArrayList<>(); this.submittedNodes.computeIfAbsent(hostSpec.getHost(), (key) -> { - this.nodeExecutorService.submit( - this.getNodeMonitoringWorker(hostSpec, this.writerHostSpec.get())); + try { + this.nodeExecutorService.submit( + this.getNodeMonitoringWorker(hostSpec, this.writerHostSpec.get())); + } catch (SQLException e) { + exceptionList.add(e); + return null; + } + return true; }); + + if (!exceptionList.isEmpty()) { + throw exceptionList.get(0); + } } // It's not possible to call shutdown() on this.nodeExecutorService since more node may be added later. } @@ -423,6 +441,7 @@ public void monitor() { ex); } + throw ex; } finally { this.stop.set(true); this.shutdownNodeExecutorService(); @@ -480,8 +499,19 @@ protected boolean isInPanicMode() { || !this.isVerifiedWriterConnection; } - protected Runnable getNodeMonitoringWorker(final HostSpec hostSpec, final @Nullable HostSpec writerHostSpec) { - return new NodeMonitoringWorker(this, hostSpec, writerHostSpec); + protected Runnable getNodeMonitoringWorker( + final HostSpec hostSpec, final @Nullable HostSpec writerHostSpec) throws SQLException { + return new NodeMonitoringWorker(this.getNewServicesContainer(), this, hostSpec, writerHostSpec); + } + + protected FullServicesContainer getNewServicesContainer() throws SQLException { + return ServiceUtility.getInstance().createServiceContainer( + this.servicesContainer.getStorageService(), + this.servicesContainer.getMonitorService(), + this.servicesContainer.getDefaultConnectionProvider(), + this.servicesContainer.getTelemetryFactory(), + this.servicesContainer.getPluginService().getConnectConfig() + ); } protected List openAnyConnectionAndUpdateTopology() { @@ -492,7 +522,7 @@ protected List openAnyConnectionAndUpdateTopology() { // open a new connection try { - conn = this.connectionService.open(this.initialHostSpec, this.monitoringProperties); + conn = this.servicesContainer.getPluginService().forceConnect(this.initialHostSpec, this.monitoringProperties); } catch (SQLException ex) { // can't connect return null; @@ -625,7 +655,7 @@ protected void delay(boolean useHighRefreshRate) throws InterruptedException { protected void updateTopologyCache(final @NonNull List hosts) { synchronized (this.requestToUpdateTopology) { - storageService.set(this.clusterId, new Topology(hosts)); + this.servicesContainer.getStorageService().set(this.clusterId, new Topology(hosts)); synchronized (this.topologyUpdated) { this.requestToUpdateTopology.set(false); @@ -769,7 +799,7 @@ protected HostSpec createHost( ? this.clusterInstanceTemplate.getPort() : this.initialHostSpec.getPort(); - final HostSpec hostSpec = this.hostListProviderService.getHostSpecBuilder() + final HostSpec hostSpec = this.servicesContainer.getHostListProviderService().getHostSpecBuilder() .host(endpoint) .port(port) .role(isWriter ? HostRole.WRITER : HostRole.READER) @@ -791,16 +821,19 @@ private static class NodeMonitoringWorker implements Runnable { private static final Logger LOGGER = Logger.getLogger(NodeMonitoringWorker.class.getName()); + protected final FullServicesContainer servicesContainer; protected final ClusterTopologyMonitorImpl monitor; protected final HostSpec hostSpec; protected final @Nullable HostSpec writerHostSpec; protected boolean writerChanged = false; public NodeMonitoringWorker( + final FullServicesContainer servicesContainer, final ClusterTopologyMonitorImpl monitor, final HostSpec hostSpec, final @Nullable HostSpec writerHostSpec ) { + this.servicesContainer = servicesContainer; this.monitor = monitor; this.hostSpec = hostSpec; this.writerHostSpec = writerHostSpec; @@ -818,7 +851,7 @@ public void run() { if (connection == null) { try { - connection = this.monitor.connectionService.open( + connection = this.servicesContainer.getPluginService().forceConnect( hostSpec, this.monitor.monitoringProperties); } catch (SQLException ex) { // A problem occurred while connecting. We will try again on the next iteration. diff --git a/wrapper/src/main/java/software/amazon/jdbc/hostlistprovider/monitoring/MonitoringRdsHostListProvider.java b/wrapper/src/main/java/software/amazon/jdbc/hostlistprovider/monitoring/MonitoringRdsHostListProvider.java index df1c140a6..e60553d26 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/hostlistprovider/monitoring/MonitoringRdsHostListProvider.java +++ b/wrapper/src/main/java/software/amazon/jdbc/hostlistprovider/monitoring/MonitoringRdsHostListProvider.java @@ -19,7 +19,6 @@ import java.sql.Connection; import java.sql.SQLException; import java.util.List; -import java.util.Properties; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import java.util.logging.Logger; @@ -32,7 +31,7 @@ import software.amazon.jdbc.hostlistprovider.RdsHostListProvider; import software.amazon.jdbc.hostlistprovider.Topology; import software.amazon.jdbc.util.FullServicesContainer; -import software.amazon.jdbc.util.connection.ConnectionService; +import software.amazon.jdbc.util.connection.ConnectConfig; import software.amazon.jdbc.util.monitoring.MonitorService; import software.amazon.jdbc.util.storage.StorageService; @@ -57,19 +56,18 @@ public class MonitoringRdsHostListProvider extends RdsHostListProvider protected final String writerTopologyQuery; public MonitoringRdsHostListProvider( - final Properties properties, - final String originalUrl, + final ConnectConfig connectConfig, final FullServicesContainer servicesContainer, final String topologyQuery, final String nodeIdQuery, final String isReaderQuery, final String writerTopologyQuery) { - super(properties, originalUrl, servicesContainer, topologyQuery, nodeIdQuery, isReaderQuery); + super(connectConfig, servicesContainer, topologyQuery, nodeIdQuery, isReaderQuery); this.servicesContainer = servicesContainer; this.pluginService = servicesContainer.getPluginService(); this.writerTopologyQuery = writerTopologyQuery; this.highRefreshRateNano = TimeUnit.MILLISECONDS.toNanos( - CLUSTER_TOPOLOGY_HIGH_REFRESH_RATE_MS.getLong(this.properties)); + CLUSTER_TOPOLOGY_HIGH_REFRESH_RATE_MS.getLong(this.connectConfig.getProps())); } public static void clearCache() { @@ -86,20 +84,14 @@ protected ClusterTopologyMonitor initMonitor() throws SQLException { ClusterTopologyMonitorImpl.class, this.clusterId, this.servicesContainer.getStorageService(), - this.pluginService.getTelemetryFactory(), - this.pluginService.getDefaultConnectionProvider(), - this.originalUrl, - this.pluginService.getDriverProtocol(), - this.pluginService.getTargetDriverDialect(), - this.pluginService.getDialect(), - this.properties, - (ConnectionService connectionService, PluginService monitorPluginService) -> new ClusterTopologyMonitorImpl( + this.servicesContainer.getTelemetryFactory(), + this.servicesContainer.getDefaultConnectionProvider(), + this.connectConfig, + (servicesContainer) -> new ClusterTopologyMonitorImpl( + this.servicesContainer, this.clusterId, - this.servicesContainer.getStorageService(), - connectionService, this.initialHostSpec, - this.properties, - this.servicesContainer.getHostListProviderService(), + this.connectConfig.getProps(), this.clusterInstanceTemplate, this.refreshRateNano, this.highRefreshRateNano, @@ -133,14 +125,10 @@ protected void clusterIdChanged(final String oldClusterId) throws SQLException { ClusterTopologyMonitorImpl.class, this.clusterId, this.servicesContainer.getStorageService(), - this.pluginService.getTelemetryFactory(), - this.pluginService.getDefaultConnectionProvider(), - this.originalUrl, - this.pluginService.getDriverProtocol(), - this.pluginService.getTargetDriverDialect(), - this.pluginService.getDialect(), - this.properties, - (connectionService, pluginService) -> existingMonitor); + this.servicesContainer.getTelemetryFactory(), + this.servicesContainer.getDefaultConnectionProvider(), + this.connectConfig, + (servicesContainer) -> existingMonitor); assert monitorService.get(ClusterTopologyMonitorImpl.class, this.clusterId) == existingMonitor; existingMonitor.setClusterId(this.clusterId); monitorService.remove(ClusterTopologyMonitorImpl.class, oldClusterId); diff --git a/wrapper/src/main/java/software/amazon/jdbc/hostlistprovider/monitoring/MonitoringRdsMultiAzHostListProvider.java b/wrapper/src/main/java/software/amazon/jdbc/hostlistprovider/monitoring/MonitoringRdsMultiAzHostListProvider.java index ab1eb9b23..fff4234a0 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/hostlistprovider/monitoring/MonitoringRdsMultiAzHostListProvider.java +++ b/wrapper/src/main/java/software/amazon/jdbc/hostlistprovider/monitoring/MonitoringRdsMultiAzHostListProvider.java @@ -17,9 +17,9 @@ package software.amazon.jdbc.hostlistprovider.monitoring; import java.sql.SQLException; -import java.util.Properties; import java.util.logging.Logger; import software.amazon.jdbc.util.FullServicesContainer; +import software.amazon.jdbc.util.connection.ConnectConfig; public class MonitoringRdsMultiAzHostListProvider extends MonitoringRdsHostListProvider { @@ -29,8 +29,7 @@ public class MonitoringRdsMultiAzHostListProvider extends MonitoringRdsHostListP protected final String fetchWriterNodeColumnName; public MonitoringRdsMultiAzHostListProvider( - final Properties properties, - final String originalUrl, + final ConnectConfig connectConfig, final FullServicesContainer servicesContainer, final String topologyQuery, final String nodeIdQuery, @@ -38,8 +37,7 @@ public MonitoringRdsMultiAzHostListProvider( final String fetchWriterNodeQuery, final String fetchWriterNodeColumnName) { super( - properties, - originalUrl, + connectConfig, servicesContainer, topologyQuery, nodeIdQuery, @@ -51,23 +49,18 @@ public MonitoringRdsMultiAzHostListProvider( @Override protected ClusterTopologyMonitor initMonitor() throws SQLException { - return this.servicesContainer.getMonitorService().runIfAbsent(MultiAzClusterTopologyMonitorImpl.class, + return this.servicesContainer.getMonitorService().runIfAbsent( + MultiAzClusterTopologyMonitorImpl.class, this.clusterId, this.servicesContainer.getStorageService(), - this.pluginService.getTelemetryFactory(), - this.pluginService.getDefaultConnectionProvider(), - this.originalUrl, - this.pluginService.getDriverProtocol(), - this.pluginService.getTargetDriverDialect(), - this.pluginService.getDialect(), - this.properties, - (connectionService, pluginService) -> new MultiAzClusterTopologyMonitorImpl( + this.servicesContainer.getTelemetryFactory(), + this.servicesContainer.getDefaultConnectionProvider(), + this.connectConfig, + (servicesContainer) -> new MultiAzClusterTopologyMonitorImpl( + servicesContainer, this.clusterId, - this.servicesContainer.getStorageService(), - connectionService, this.initialHostSpec, - this.properties, - this.hostListProviderService, + this.connectConfig.getProps(), this.clusterInstanceTemplate, this.refreshRateNano, this.highRefreshRateNano, diff --git a/wrapper/src/main/java/software/amazon/jdbc/hostlistprovider/monitoring/MultiAzClusterTopologyMonitorImpl.java b/wrapper/src/main/java/software/amazon/jdbc/hostlistprovider/monitoring/MultiAzClusterTopologyMonitorImpl.java index 6e3c3b388..6ff7e9677 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/hostlistprovider/monitoring/MultiAzClusterTopologyMonitorImpl.java +++ b/wrapper/src/main/java/software/amazon/jdbc/hostlistprovider/monitoring/MultiAzClusterTopologyMonitorImpl.java @@ -24,11 +24,9 @@ import java.time.Instant; import java.util.Properties; import java.util.logging.Logger; -import software.amazon.jdbc.HostListProviderService; import software.amazon.jdbc.HostSpec; +import software.amazon.jdbc.util.FullServicesContainer; import software.amazon.jdbc.util.StringUtils; -import software.amazon.jdbc.util.connection.ConnectionService; -import software.amazon.jdbc.util.storage.StorageService; public class MultiAzClusterTopologyMonitorImpl extends ClusterTopologyMonitorImpl { @@ -38,12 +36,10 @@ public class MultiAzClusterTopologyMonitorImpl extends ClusterTopologyMonitorImp protected final String fetchWriterNodeColumnName; public MultiAzClusterTopologyMonitorImpl( + final FullServicesContainer servicesContainer, final String clusterId, - final StorageService storageService, - final ConnectionService connectionService, final HostSpec initialHostSpec, final Properties properties, - final HostListProviderService hostListProviderService, final HostSpec clusterInstanceTemplate, final long refreshRateNano, final long highRefreshRateNano, @@ -53,12 +49,10 @@ public MultiAzClusterTopologyMonitorImpl( final String fetchWriterNodeQuery, final String fetchWriterNodeColumnName) { super( + servicesContainer, clusterId, - storageService, - connectionService, initialHostSpec, properties, - hostListProviderService, clusterInstanceTemplate, refreshRateNano, highRefreshRateNano, diff --git a/wrapper/src/main/java/software/amazon/jdbc/plugin/AbstractConnectionPlugin.java b/wrapper/src/main/java/software/amazon/jdbc/plugin/AbstractConnectionPlugin.java index 035e4ecf9..14c0b8e83 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/plugin/AbstractConnectionPlugin.java +++ b/wrapper/src/main/java/software/amazon/jdbc/plugin/AbstractConnectionPlugin.java @@ -21,7 +21,6 @@ import java.util.EnumSet; import java.util.List; import java.util.Map; -import java.util.Properties; import java.util.Set; import software.amazon.jdbc.ConnectionPlugin; import software.amazon.jdbc.HostListProviderService; @@ -30,6 +29,7 @@ import software.amazon.jdbc.JdbcCallable; import software.amazon.jdbc.NodeChangeOptions; import software.amazon.jdbc.OldConnectionSuggestedAction; +import software.amazon.jdbc.util.connection.ConnectConfig; public abstract class AbstractConnectionPlugin implements ConnectionPlugin { @@ -50,9 +50,8 @@ public T execute( @Override public Connection connect( - final String driverProtocol, + final ConnectConfig connectConfig, final HostSpec hostSpec, - final Properties props, final boolean isInitialConnection, final JdbcCallable connectFunc) throws SQLException { @@ -61,9 +60,8 @@ public Connection connect( @Override public Connection forceConnect( - final String driverProtocol, + final ConnectConfig connectConfig, final HostSpec hostSpec, - final Properties props, final boolean isInitialConnection, final JdbcCallable forceConnectFunc) throws SQLException { @@ -89,9 +87,7 @@ public HostSpec getHostSpecByStrategy(final List hosts, final HostRole @Override public void initHostProvider( - final String driverProtocol, - final String initialUrl, - final Properties props, + final ConnectConfig connectConfig, final HostListProviderService hostListProviderService, final JdbcCallable initHostProviderFunc) throws SQLException { diff --git a/wrapper/src/main/java/software/amazon/jdbc/plugin/AuroraConnectionTrackerPlugin.java b/wrapper/src/main/java/software/amazon/jdbc/plugin/AuroraConnectionTrackerPlugin.java index 9b42d33ea..138020ae0 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/plugin/AuroraConnectionTrackerPlugin.java +++ b/wrapper/src/main/java/software/amazon/jdbc/plugin/AuroraConnectionTrackerPlugin.java @@ -36,6 +36,7 @@ import software.amazon.jdbc.util.RdsUrlType; import software.amazon.jdbc.util.RdsUtils; import software.amazon.jdbc.util.Utils; +import software.amazon.jdbc.util.connection.ConnectConfig; public class AuroraConnectionTrackerPlugin extends AbstractConnectionPlugin { @@ -82,8 +83,11 @@ public Set getSubscribedMethods() { } @Override - public Connection connect(final String driverProtocol, final HostSpec hostSpec, final Properties props, - final boolean isInitialConnection, final JdbcCallable connectFunc) throws SQLException { + public Connection connect( + final ConnectConfig connectConfig, + final HostSpec hostSpec, + final boolean isInitialConnection, + final JdbcCallable connectFunc) throws SQLException { final Connection conn = connectFunc.call(); diff --git a/wrapper/src/main/java/software/amazon/jdbc/plugin/AuroraInitialConnectionStrategyPlugin.java b/wrapper/src/main/java/software/amazon/jdbc/plugin/AuroraInitialConnectionStrategyPlugin.java index 01b9bf8e9..6093c19f6 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/plugin/AuroraInitialConnectionStrategyPlugin.java +++ b/wrapper/src/main/java/software/amazon/jdbc/plugin/AuroraInitialConnectionStrategyPlugin.java @@ -39,6 +39,7 @@ import software.amazon.jdbc.util.RdsUtils; import software.amazon.jdbc.util.Utils; import software.amazon.jdbc.util.WrapperUtils; +import software.amazon.jdbc.util.connection.ConnectConfig; public class AuroraInitialConnectionStrategyPlugin extends AbstractConnectionPlugin { @@ -97,10 +98,10 @@ public static VerifyOpenedConnectionType fromValue(String value) { } private final PluginService pluginService; - private HostListProviderService hostListProviderService; private final RdsUtils rdsUtils = new RdsUtils(); + private final VerifyOpenedConnectionType verifyOpenedConnectionType; + private HostListProviderService hostListProviderService; - private VerifyOpenedConnectionType verifyOpenedConnectionType = null; static { PropertyDefinition.registerPluginProperties(AuroraInitialConnectionStrategyPlugin.class); @@ -119,9 +120,7 @@ public Set getSubscribedMethods() { @Override public void initHostProvider( - final String driverProtocol, - final String initialUrl, - final Properties props, + final ConnectConfig connectConfig, final HostListProviderService hostListProviderService, final JdbcCallable initHostProviderFunc) throws SQLException { @@ -134,15 +133,13 @@ public void initHostProvider( @Override public Connection connect( - final String driverProtocol, + final ConnectConfig connectConfig, final HostSpec hostSpec, - final Properties props, final boolean isInitialConnection, final JdbcCallable connectFunc) throws SQLException { - final RdsUrlType type = this.rdsUtils.identifyRdsType(hostSpec.getHost()); - + final Properties props = connectConfig.getProps(); if (type == RdsUrlType.RDS_WRITER_CLUSTER || isInitialConnection && this.verifyOpenedConnectionType == VerifyOpenedConnectionType.WRITER) { Connection writerCandidateConn = this.getVerifiedWriterConnection(props, isInitialConnection, connectFunc); @@ -369,8 +366,6 @@ private HostSpec getReader(final Properties props) throws SQLException { if (this.pluginService.acceptsStrategy(HostRole.READER, strategy)) { try { return this.pluginService.getHostSpecByStrategy(HostRole.READER, strategy); - } catch (UnsupportedOperationException ex) { - throw ex; } catch (SQLException ex) { // host isn't found return null; diff --git a/wrapper/src/main/java/software/amazon/jdbc/plugin/AwsSecretsManagerConnectionPlugin.java b/wrapper/src/main/java/software/amazon/jdbc/plugin/AwsSecretsManagerConnectionPlugin.java index e5986cc23..0fc4d5058 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/plugin/AwsSecretsManagerConnectionPlugin.java +++ b/wrapper/src/main/java/software/amazon/jdbc/plugin/AwsSecretsManagerConnectionPlugin.java @@ -50,6 +50,7 @@ import software.amazon.jdbc.util.Pair; import software.amazon.jdbc.util.RegionUtils; import software.amazon.jdbc.util.StringUtils; +import software.amazon.jdbc.util.connection.ConnectConfig; import software.amazon.jdbc.util.telemetry.TelemetryContext; import software.amazon.jdbc.util.telemetry.TelemetryCounter; import software.amazon.jdbc.util.telemetry.TelemetryFactory; @@ -184,13 +185,12 @@ public Set getSubscribedMethods() { @Override public Connection connect( - final String driverProtocol, + final ConnectConfig connectConfig, final HostSpec hostSpec, - final Properties props, final boolean isInitialConnection, final JdbcCallable connectFunc) throws SQLException { - return connectInternal(hostSpec, props, connectFunc); + return connectInternal(hostSpec, connectConfig.getProps(), connectFunc); } private Connection connectInternal(HostSpec hostSpec, Properties props, @@ -226,13 +226,12 @@ private Connection connectInternal(HostSpec hostSpec, Properties props, @Override public Connection forceConnect( - final String driverProtocol, + final ConnectConfig connectConfig, final HostSpec hostSpec, - final Properties props, final boolean isInitialConnection, final JdbcCallable forceConnectFunc) throws SQLException { - return connectInternal(hostSpec, props, forceConnectFunc); + return connectInternal(hostSpec, connectConfig.getProps(), forceConnectFunc); } /** diff --git a/wrapper/src/main/java/software/amazon/jdbc/plugin/ConnectTimeConnectionPlugin.java b/wrapper/src/main/java/software/amazon/jdbc/plugin/ConnectTimeConnectionPlugin.java index 4eaea61fe..ccb56d843 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/plugin/ConnectTimeConnectionPlugin.java +++ b/wrapper/src/main/java/software/amazon/jdbc/plugin/ConnectTimeConnectionPlugin.java @@ -21,12 +21,12 @@ import java.util.Arrays; import java.util.Collections; import java.util.HashSet; -import java.util.Properties; import java.util.Set; import java.util.logging.Logger; import software.amazon.jdbc.HostSpec; import software.amazon.jdbc.JdbcCallable; import software.amazon.jdbc.util.Messages; +import software.amazon.jdbc.util.connection.ConnectConfig; public class ConnectTimeConnectionPlugin extends AbstractConnectionPlugin { @@ -43,8 +43,11 @@ public Set getSubscribedMethods() { } @Override - public Connection connect(String driverProtocol, HostSpec hostSpec, Properties props, - boolean isInitialConnection, JdbcCallable connectFunc) throws SQLException { + public Connection connect( + ConnectConfig connectConfig, + HostSpec hostSpec, + boolean isInitialConnection, + JdbcCallable connectFunc) throws SQLException { final long startTime = System.nanoTime(); final Connection result = connectFunc.call(); @@ -59,9 +62,11 @@ public Connection connect(String driverProtocol, HostSpec hostSpec, Properties p } @Override - public Connection forceConnect(String driverProtocol, HostSpec hostSpec, Properties props, - boolean isInitialConnection, JdbcCallable forceConnectFunc) - throws SQLException { + public Connection forceConnect( + ConnectConfig connectConfig, + HostSpec hostSpec, + boolean isInitialConnection, + JdbcCallable forceConnectFunc) throws SQLException { final long startTime = System.nanoTime(); final Connection result = forceConnectFunc.call(); diff --git a/wrapper/src/main/java/software/amazon/jdbc/plugin/DefaultConnectionPlugin.java b/wrapper/src/main/java/software/amazon/jdbc/plugin/DefaultConnectionPlugin.java index 32a1ad509..b8706c0fd 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/plugin/DefaultConnectionPlugin.java +++ b/wrapper/src/main/java/software/amazon/jdbc/plugin/DefaultConnectionPlugin.java @@ -25,7 +25,6 @@ import java.util.HashSet; import java.util.List; import java.util.Map; -import java.util.Properties; import java.util.Set; import java.util.logging.Logger; import java.util.stream.Collectors; @@ -46,6 +45,7 @@ import software.amazon.jdbc.util.Messages; import software.amazon.jdbc.util.SqlMethodAnalyzer; import software.amazon.jdbc.util.WrapperUtils; +import software.amazon.jdbc.util.connection.ConnectConfig; import software.amazon.jdbc.util.telemetry.TelemetryContext; import software.amazon.jdbc.util.telemetry.TelemetryFactory; import software.amazon.jdbc.util.telemetry.TelemetryTraceLevel; @@ -74,27 +74,15 @@ public DefaultConnectionPlugin( final PluginManagerService pluginManagerService) { this(pluginService, defaultConnProvider, - effectiveConnProvider, pluginManagerService, new ConnectionProviderManager(defaultConnProvider, effectiveConnProvider)); } public DefaultConnectionPlugin( - final PluginService pluginService, - final ConnectionProvider defaultConnProvider, - final @Nullable ConnectionProvider effectiveConnProvider, - final PluginManagerService pluginManagerService, - final ConnectionProviderManager connProviderManager) { - if (pluginService == null) { - throw new IllegalArgumentException("pluginService"); - } - if (pluginManagerService == null) { - throw new IllegalArgumentException("pluginManagerService"); - } - if (defaultConnProvider == null) { - throw new IllegalArgumentException("connectionProvider"); - } - + final @NonNull PluginService pluginService, + final @NonNull ConnectionProvider defaultConnProvider, + final @NonNull PluginManagerService pluginManagerService, + final @NonNull ConnectionProviderManager connProviderManager) { this.pluginService = pluginService; this.pluginManagerService = pluginManagerService; this.defaultConnProvider = defaultConnProvider; @@ -166,47 +154,37 @@ public T execute( @Override public Connection connect( - final String driverProtocol, + final ConnectConfig connectConfig, final HostSpec hostSpec, - final Properties props, final boolean isInitialConnection, - final JdbcCallable connectFunc) - throws SQLException { + final JdbcCallable connectFunc) throws SQLException { - ConnectionProvider connProvider = this.connProviderManager.getConnectionProvider(driverProtocol, hostSpec, props); + ConnectionProvider connProvider = this.connProviderManager.getConnectionProvider(connectConfig, hostSpec); // It's guaranteed that this plugin is always the last in plugin chain so connectFunc can be // ignored. - return connectInternal(driverProtocol, hostSpec, props, connProvider, isInitialConnection); + return connectInternal(connectConfig, hostSpec, connProvider, isInitialConnection); } private Connection connectInternal( - String driverProtocol, - HostSpec hostSpec, - Properties props, - ConnectionProvider connProvider, - final boolean isInitialConnection) - throws SQLException { - + final ConnectConfig connectConfig, + final HostSpec hostSpec, + final ConnectionProvider connProvider, + final boolean isInitialConnection) throws SQLException { TelemetryFactory telemetryFactory = this.pluginService.getTelemetryFactory(); TelemetryContext telemetryContext = telemetryFactory.openTelemetryContext( connProvider.getTargetName(), TelemetryTraceLevel.NESTED); Connection conn; try { - conn = connProvider.connect( - driverProtocol, - this.pluginService.getDialect(), - this.pluginService.getTargetDriverDialect(), - hostSpec, - props); + conn = connProvider.connect(connectConfig, hostSpec); } finally { if (telemetryContext != null) { telemetryContext.closeContext(); } } - this.connProviderManager.initConnection(conn, driverProtocol, hostSpec, props); + this.connProviderManager.initConnection(conn, connectConfig, hostSpec); this.pluginService.setAvailability(hostSpec.asAliases(), HostAvailability.AVAILABLE); if (isInitialConnection) { @@ -218,16 +196,15 @@ private Connection connectInternal( @Override public Connection forceConnect( - final String driverProtocol, + final ConnectConfig connectConfig, final HostSpec hostSpec, - final Properties props, final boolean isInitialConnection, final JdbcCallable forceConnectFunc) throws SQLException { // It's guaranteed that this plugin is always the last in plugin chain so forceConnectFunc can be // ignored. - return connectInternal(driverProtocol, hostSpec, props, this.defaultConnProvider, isInitialConnection); + return connectInternal(connectConfig, hostSpec, this.defaultConnProvider, isInitialConnection); } @Override @@ -265,9 +242,7 @@ public HostSpec getHostSpecByStrategy(final List hosts, final HostRole @Override public void initHostProvider( - final String driverProtocol, - final String initialUrl, - final Properties props, + final ConnectConfig connectConfig, final HostListProviderService hostListProviderService, final JdbcCallable initHostProviderFunc) throws SQLException { diff --git a/wrapper/src/main/java/software/amazon/jdbc/plugin/bluegreen/BlueGreenConnectionPlugin.java b/wrapper/src/main/java/software/amazon/jdbc/plugin/bluegreen/BlueGreenConnectionPlugin.java index 7bfe67b35..2e92202ad 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/plugin/bluegreen/BlueGreenConnectionPlugin.java +++ b/wrapper/src/main/java/software/amazon/jdbc/plugin/bluegreen/BlueGreenConnectionPlugin.java @@ -42,6 +42,7 @@ import software.amazon.jdbc.plugin.iam.IamAuthConnectionPlugin; import software.amazon.jdbc.util.FullServicesContainer; import software.amazon.jdbc.util.RdsUtils; +import software.amazon.jdbc.util.connection.ConnectConfig; import software.amazon.jdbc.util.storage.StorageService; import software.amazon.jdbc.util.telemetry.TelemetryFactory; @@ -126,9 +127,8 @@ public Set getSubscribedMethods() { @Override public Connection connect( - final String driverProtocol, + final ConnectConfig connectConfig, final HostSpec hostSpec, - final Properties props, final boolean isInitialConnection, final JdbcCallable connectFunc) throws SQLException { diff --git a/wrapper/src/main/java/software/amazon/jdbc/plugin/bluegreen/BlueGreenStatusMonitor.java b/wrapper/src/main/java/software/amazon/jdbc/plugin/bluegreen/BlueGreenStatusMonitor.java index a3a717638..77cfe037c 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/plugin/bluegreen/BlueGreenStatusMonitor.java +++ b/wrapper/src/main/java/software/amazon/jdbc/plugin/bluegreen/BlueGreenStatusMonitor.java @@ -57,6 +57,7 @@ import software.amazon.jdbc.util.Messages; import software.amazon.jdbc.util.PropertyUtils; import software.amazon.jdbc.util.RdsUtils; +import software.amazon.jdbc.util.connection.ConnectConfig; public class BlueGreenStatusMonitor { @@ -598,7 +599,8 @@ protected void initHostListProvider() { return; } - final Properties hostListProperties = PropertyUtils.copyProperties(this.props); + final ConnectConfig originalContext = this.pluginService.getConnectConfig(); + final Properties hostListProperties = originalContext.getProps(); // Need to instantiate a separate HostListProvider with // a special unique clusterId to avoid interference with other HostListProviders opened for this cluster. @@ -610,16 +612,14 @@ protected void initHostListProvider() { LOGGER.finest(() -> Messages.get("bgd.createHostListProvider", new Object[] {this.role, RdsHostListProvider.CLUSTER_ID.getString(hostListProperties)})); - String protocol = this.connectionUrlParser.getProtocol(this.pluginService.getOriginalUrl()); final HostSpec connectionHostSpecCopy = this.connectionHostSpec.get(); if (connectionHostSpecCopy != null) { - String hostListProviderUrl = String.format("%s%s/", protocol, connectionHostSpecCopy.getHostAndPort()); - this.hostListProvider = this.pluginService.getDialect() - .getHostListProvider() - .getProvider( - hostListProperties, - hostListProviderUrl, - this.servicesContainer); + String hostListProviderUrl = + String.format("%s%s/", originalContext.getProtocol(), connectionHostSpecCopy.getHostAndPort()); + ConnectConfig newContext = new ConnectConfig( + hostListProviderUrl, originalContext.getProtocol(), originalContext.getDriverDialect(), hostListProperties); + this.hostListProvider = + this.pluginService.getDialect().getHostListProvider().getProvider(newContext, this.servicesContainer); } else { LOGGER.warning(() -> Messages.get("bgd.hostSpecNull")); } diff --git a/wrapper/src/main/java/software/amazon/jdbc/plugin/customendpoint/CustomEndpointPlugin.java b/wrapper/src/main/java/software/amazon/jdbc/plugin/customendpoint/CustomEndpointPlugin.java index 22b385923..1c77e9468 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/plugin/customendpoint/CustomEndpointPlugin.java +++ b/wrapper/src/main/java/software/amazon/jdbc/plugin/customendpoint/CustomEndpointPlugin.java @@ -41,6 +41,7 @@ import software.amazon.jdbc.util.RegionUtils; import software.amazon.jdbc.util.StringUtils; import software.amazon.jdbc.util.WrapperUtils; +import software.amazon.jdbc.util.connection.ConnectConfig; import software.amazon.jdbc.util.monitoring.MonitorErrorResponse; import software.amazon.jdbc.util.telemetry.TelemetryCounter; import software.amazon.jdbc.util.telemetry.TelemetryFactory; @@ -163,12 +164,10 @@ public Set getSubscribedMethods() { @Override public Connection connect( - final String driverProtocol, + final ConnectConfig connectConfig, final HostSpec hostSpec, - final Properties props, final boolean isInitialConnection, - final JdbcCallable connectFunc) - throws SQLException { + final JdbcCallable connectFunc) throws SQLException { if (!this.rdsUtils.isRdsCustomClusterDns(hostSpec.getHost())) { return connectFunc.call(); } @@ -218,14 +217,10 @@ protected CustomEndpointMonitor createMonitorIfAbsent(Properties props) throws S this.servicesContainer.getStorageService(), this.pluginService.getTelemetryFactory(), this.pluginService.getDefaultConnectionProvider(), - this.pluginService.getOriginalUrl(), - this.pluginService.getDriverProtocol(), - this.pluginService.getTargetDriverDialect(), - this.pluginService.getDialect(), - this.props, - (connectionService, pluginService) -> new CustomEndpointMonitorImpl( - this.servicesContainer.getStorageService(), - this.servicesContainer.getTelemetryFactory(), + this.pluginService.getConnectConfig(), + (servicesContainer) -> new CustomEndpointMonitorImpl( + servicesContainer.getStorageService(), + servicesContainer.getTelemetryFactory(), this.customEndpointHostSpec, this.customEndpointId, this.region, diff --git a/wrapper/src/main/java/software/amazon/jdbc/plugin/dev/DeveloperConnectionPlugin.java b/wrapper/src/main/java/software/amazon/jdbc/plugin/dev/DeveloperConnectionPlugin.java index 5335b444c..e92cf6db8 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/plugin/dev/DeveloperConnectionPlugin.java +++ b/wrapper/src/main/java/software/amazon/jdbc/plugin/dev/DeveloperConnectionPlugin.java @@ -20,7 +20,6 @@ import java.sql.SQLException; import java.util.Collections; import java.util.HashSet; -import java.util.Properties; import java.util.Set; import java.util.logging.Logger; import org.checkerframework.checker.nullness.qual.NonNull; @@ -29,6 +28,7 @@ import software.amazon.jdbc.plugin.AbstractConnectionPlugin; import software.amazon.jdbc.util.StringUtils; import software.amazon.jdbc.util.WrapperUtils; +import software.amazon.jdbc.util.connection.ConnectConfig; public class DeveloperConnectionPlugin extends AbstractConnectionPlugin implements ExceptionSimulator { @@ -142,34 +142,29 @@ protected void raiseException( @Override public Connection connect( - final String driverProtocol, + final ConnectConfig connectConfig, final HostSpec hostSpec, - final Properties props, final boolean isInitialConnection, - final JdbcCallable connectFunc) - throws SQLException { - - this.raiseExceptionOnConnectIfNeeded(driverProtocol, hostSpec, props, isInitialConnection); - return super.connect(driverProtocol, hostSpec, props, isInitialConnection, connectFunc); + final JdbcCallable connectFunc) throws SQLException { + this.raiseExceptionOnConnectIfNeeded(connectConfig, hostSpec, isInitialConnection); + return super.connect(connectConfig, hostSpec, isInitialConnection, connectFunc); } @Override public Connection forceConnect( - final String driverProtocol, + final ConnectConfig connectConfig, final HostSpec hostSpec, - final Properties props, final boolean isInitialConnection, final JdbcCallable forceConnectFunc) throws SQLException { - this.raiseExceptionOnConnectIfNeeded(driverProtocol, hostSpec, props, isInitialConnection); - return super.connect(driverProtocol, hostSpec, props, isInitialConnection, forceConnectFunc); + this.raiseExceptionOnConnectIfNeeded(connectConfig, hostSpec, isInitialConnection); + return super.connect(connectConfig, hostSpec, isInitialConnection, forceConnectFunc); } protected void raiseExceptionOnConnectIfNeeded( - final String driverProtocol, + final ConnectConfig connectConfig, final HostSpec hostSpec, - final Properties props, final boolean isInitialConnection) throws SQLException { @@ -178,10 +173,7 @@ protected void raiseExceptionOnConnectIfNeeded( } else if (ExceptionSimulatorManager.connectCallback != null) { this.raiseExceptionOnConnect( ExceptionSimulatorManager.connectCallback.getExceptionToRaise( - driverProtocol, - hostSpec, - props, - isInitialConnection)); + connectConfig, hostSpec, isInitialConnection)); } } diff --git a/wrapper/src/main/java/software/amazon/jdbc/plugin/dev/ExceptionSimulatorConnectCallback.java b/wrapper/src/main/java/software/amazon/jdbc/plugin/dev/ExceptionSimulatorConnectCallback.java index aff02da98..ae4c187e0 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/plugin/dev/ExceptionSimulatorConnectCallback.java +++ b/wrapper/src/main/java/software/amazon/jdbc/plugin/dev/ExceptionSimulatorConnectCallback.java @@ -17,13 +17,12 @@ package software.amazon.jdbc.plugin.dev; import java.sql.SQLException; -import java.util.Properties; import software.amazon.jdbc.HostSpec; +import software.amazon.jdbc.util.connection.ConnectConfig; public interface ExceptionSimulatorConnectCallback { SQLException getExceptionToRaise( - final String driverProtocol, + final ConnectConfig connectConfig, final HostSpec hostSpec, - final Properties props, final boolean isInitialConnection); } diff --git a/wrapper/src/main/java/software/amazon/jdbc/plugin/efm/HostMonitoringConnectionPlugin.java b/wrapper/src/main/java/software/amazon/jdbc/plugin/efm/HostMonitoringConnectionPlugin.java index be9f56746..c42183ede 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/plugin/efm/HostMonitoringConnectionPlugin.java +++ b/wrapper/src/main/java/software/amazon/jdbc/plugin/efm/HostMonitoringConnectionPlugin.java @@ -40,6 +40,7 @@ import software.amazon.jdbc.util.Messages; import software.amazon.jdbc.util.RdsUrlType; import software.amazon.jdbc.util.RdsUtils; +import software.amazon.jdbc.util.connection.ConnectConfig; /** * Monitor the server while the connection is executing methods for more sophisticated failure @@ -269,12 +270,10 @@ public OldConnectionSuggestedAction notifyConnectionChanged(final EnumSet connectFunc) - throws SQLException { + final JdbcCallable connectFunc) throws SQLException { final Connection conn = connectFunc.call(); diff --git a/wrapper/src/main/java/software/amazon/jdbc/plugin/efm2/HostMonitorImpl.java b/wrapper/src/main/java/software/amazon/jdbc/plugin/efm2/HostMonitorImpl.java index 5a858b856..7f13420b8 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/plugin/efm2/HostMonitorImpl.java +++ b/wrapper/src/main/java/software/amazon/jdbc/plugin/efm2/HostMonitorImpl.java @@ -33,9 +33,9 @@ import org.checkerframework.checker.nullness.qual.NonNull; import software.amazon.jdbc.HostSpec; import software.amazon.jdbc.util.ExecutorFactory; +import software.amazon.jdbc.util.FullServicesContainer; import software.amazon.jdbc.util.Messages; import software.amazon.jdbc.util.PropertyUtils; -import software.amazon.jdbc.util.connection.ConnectionService; import software.amazon.jdbc.util.monitoring.AbstractMonitor; import software.amazon.jdbc.util.telemetry.TelemetryContext; import software.amazon.jdbc.util.telemetry.TelemetryCounter; @@ -59,7 +59,7 @@ public class HostMonitorImpl extends AbstractMonitor implements HostMonitor { private final Queue> activeContexts = new ConcurrentLinkedQueue<>(); private final Map>> newContexts = new ConcurrentHashMap<>(); - private final ConnectionService connectionService; + private final FullServicesContainer servicesContainer; private final TelemetryFactory telemetryFactory; private final Properties properties; private final HostSpec hostSpec; @@ -78,8 +78,7 @@ public class HostMonitorImpl extends AbstractMonitor implements HostMonitor { /** * Store the monitoring configuration for a connection. * - * @param connectionService The service to use to create the monitoring connection. - * @param telemetryFactory The telemetry factory to use to create telemetry data. + * @param servicesContainer The telemetry factory to use to create telemetry data. * @param hostSpec The {@link HostSpec} of the server this {@link HostMonitorImpl} * instance is monitoring. * @param properties The {@link Properties} containing additional monitoring @@ -90,8 +89,7 @@ public class HostMonitorImpl extends AbstractMonitor implements HostMonitor { * @param abortedConnectionsCounter Aborted connection telemetry counter. */ public HostMonitorImpl( - final @NonNull ConnectionService connectionService, - final @NonNull TelemetryFactory telemetryFactory, + final @NonNull FullServicesContainer servicesContainer, final @NonNull HostSpec hostSpec, final @NonNull Properties properties, final int failureDetectionTimeMillis, @@ -99,9 +97,8 @@ public HostMonitorImpl( final int failureDetectionCount, final TelemetryCounter abortedConnectionsCounter) { super(TERMINATION_TIMEOUT_SEC, ExecutorFactory.newFixedThreadPool(2, "efm2-monitor")); - - this.connectionService = connectionService; - this.telemetryFactory = telemetryFactory; + this.servicesContainer = servicesContainer; + this.telemetryFactory = servicesContainer.getTelemetryFactory(); this.hostSpec = hostSpec; this.properties = properties; this.failureDetectionTimeNano = TimeUnit.MILLISECONDS.toNanos(failureDetectionTimeMillis); @@ -317,7 +314,8 @@ boolean checkConnectionStatus() { }); LOGGER.finest(() -> "Opening a monitoring connection to " + this.hostSpec.getUrl()); - this.monitoringConn = this.connectionService.open(this.hostSpec, monitoringConnProperties); + this.monitoringConn = + this.servicesContainer.getPluginService().forceConnect(this.hostSpec, monitoringConnProperties); LOGGER.finest(() -> "Opened monitoring connection: " + this.monitoringConn); return true; } diff --git a/wrapper/src/main/java/software/amazon/jdbc/plugin/efm2/HostMonitorServiceImpl.java b/wrapper/src/main/java/software/amazon/jdbc/plugin/efm2/HostMonitorServiceImpl.java index a0ca9f14f..e0ba7e625 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/plugin/efm2/HostMonitorServiceImpl.java +++ b/wrapper/src/main/java/software/amazon/jdbc/plugin/efm2/HostMonitorServiceImpl.java @@ -156,14 +156,9 @@ protected HostMonitor getMonitor( this.serviceContainer.getStorageService(), this.telemetryFactory, this.pluginService.getDefaultConnectionProvider(), - this.pluginService.getOriginalUrl(), - this.pluginService.getDriverProtocol(), - this.pluginService.getTargetDriverDialect(), - this.pluginService.getDialect(), - this.pluginService.getProperties(), - (connectionService, pluginService) -> new HostMonitorImpl( - connectionService, - pluginService.getTelemetryFactory(), + this.pluginService.getConnectConfig(), + (servicesContainer) -> new HostMonitorImpl( + servicesContainer, hostSpec, properties, failureDetectionTimeMillis, diff --git a/wrapper/src/main/java/software/amazon/jdbc/plugin/efm2/HostMonitoringConnectionPlugin.java b/wrapper/src/main/java/software/amazon/jdbc/plugin/efm2/HostMonitoringConnectionPlugin.java index 0e7472939..fe81c3927 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/plugin/efm2/HostMonitoringConnectionPlugin.java +++ b/wrapper/src/main/java/software/amazon/jdbc/plugin/efm2/HostMonitoringConnectionPlugin.java @@ -41,6 +41,7 @@ import software.amazon.jdbc.util.RdsUrlType; import software.amazon.jdbc.util.RdsUtils; import software.amazon.jdbc.util.WrapperUtils; +import software.amazon.jdbc.util.connection.ConnectConfig; /** * Monitor the server while the connection is executing methods for more sophisticated failure @@ -227,12 +228,10 @@ public OldConnectionSuggestedAction notifyConnectionChanged(final EnumSet connectFunc) - throws SQLException { + final JdbcCallable connectFunc) throws SQLException { final Connection conn = connectFunc.call(); diff --git a/wrapper/src/main/java/software/amazon/jdbc/plugin/failover/ClusterAwareReaderFailoverHandler.java b/wrapper/src/main/java/software/amazon/jdbc/plugin/failover/ClusterAwareReaderFailoverHandler.java index 7cb4f7b5a..2be799bfc 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/plugin/failover/ClusterAwareReaderFailoverHandler.java +++ b/wrapper/src/main/java/software/amazon/jdbc/plugin/failover/ClusterAwareReaderFailoverHandler.java @@ -33,19 +33,16 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import java.util.logging.Logger; -import software.amazon.jdbc.ConnectionPluginManager; import software.amazon.jdbc.HostRole; import software.amazon.jdbc.HostSpec; -import software.amazon.jdbc.PartialPluginService; import software.amazon.jdbc.PluginService; import software.amazon.jdbc.hostavailability.HostAvailability; import software.amazon.jdbc.util.ExecutorFactory; import software.amazon.jdbc.util.FullServicesContainer; -import software.amazon.jdbc.util.FullServicesContainerImpl; import software.amazon.jdbc.util.Messages; import software.amazon.jdbc.util.PropertyUtils; +import software.amazon.jdbc.util.ServiceUtility; import software.amazon.jdbc.util.Utils; -import software.amazon.jdbc.util.connection.ConnectionService; /** * An implementation of ReaderFailoverHandler. @@ -67,7 +64,6 @@ public class ClusterAwareReaderFailoverHandler implements ReaderFailoverHandler protected static final int DEFAULT_READER_CONNECT_TIMEOUT = 30000; // 30 sec protected final Map hostAvailabilityMap = new ConcurrentHashMap<>(); protected final FullServicesContainer servicesContainer; - protected final ConnectionService connectionService; protected final PluginService pluginService; protected Properties props; protected int maxFailoverTimeoutMs; @@ -78,16 +74,13 @@ public class ClusterAwareReaderFailoverHandler implements ReaderFailoverHandler * ClusterAwareReaderFailoverHandler constructor. * * @param servicesContainer the service container for the services required by this class. - * @param connectionService the service to use to create new connections during failover. * @param props the initial connection properties to copy over to the new reader. */ public ClusterAwareReaderFailoverHandler( final FullServicesContainer servicesContainer, - final ConnectionService connectionService, final Properties props) { this( servicesContainer, - connectionService, props, DEFAULT_FAILOVER_TIMEOUT, DEFAULT_READER_CONNECT_TIMEOUT, @@ -98,7 +91,6 @@ public ClusterAwareReaderFailoverHandler( * ClusterAwareReaderFailoverHandler constructor. * * @param servicesContainer the service container for the services required by this class. - * @param connectionService the service to use to create new connections during failover. * @param props the initial connection properties to copy over to the new reader. * @param maxFailoverTimeoutMs maximum allowed time for the entire reader failover process. * @param timeoutMs maximum allowed time in milliseconds for each reader connection attempt during @@ -107,13 +99,11 @@ public ClusterAwareReaderFailoverHandler( */ public ClusterAwareReaderFailoverHandler( final FullServicesContainer servicesContainer, - final ConnectionService connectionService, final Properties props, final int maxFailoverTimeoutMs, final int timeoutMs, final boolean isStrictReaderRequired) { this.servicesContainer = servicesContainer; - this.connectionService = connectionService; this.pluginService = servicesContainer.getPluginService(); this.props = props; this.maxFailoverTimeoutMs = maxFailoverTimeoutMs; @@ -339,8 +329,7 @@ private ReaderFailoverResult getResultFromNextTaskBatch( final int numTasks = i + 1 < hosts.size() ? 2 : 1; completionService.submit( new ConnectionAttemptTask( - this.connectionService, - getNewPluginService(), + getNewServicesContainer(), this.hostAvailabilityMap, hosts.get(i), this.props, @@ -348,8 +337,7 @@ private ReaderFailoverResult getResultFromNextTaskBatch( if (numTasks == 2) { completionService.submit( new ConnectionAttemptTask( - this.connectionService, - getNewPluginService(), + getNewServicesContainer(), this.hostAvailabilityMap, hosts.get(i + 1), this.props, @@ -370,6 +358,16 @@ private ReaderFailoverResult getResultFromNextTaskBatch( return new ReaderFailoverResult(null, null, false); } + protected FullServicesContainer getNewServicesContainer() throws SQLException { + return ServiceUtility.getInstance().createServiceContainer( + this.servicesContainer.getStorageService(), + this.servicesContainer.getMonitorService(), + this.pluginService.getDefaultConnectionProvider(), + this.servicesContainer.getTelemetryFactory(), + this.pluginService.getConnectConfig() + ); + } + private ReaderFailoverResult getNextResult(final CompletionService service) throws SQLException { try { @@ -392,33 +390,7 @@ private ReaderFailoverResult getNextResult(final CompletionService { - private final ConnectionService connectionService; private final PluginService pluginService; private final Map availabilityMap; private final HostSpec newHost; @@ -426,14 +398,12 @@ private static class ConnectionAttemptTask implements Callable availabilityMap, final HostSpec newHost, final Properties props, final boolean isStrictReaderRequired) { - this.connectionService = connectionService; - this.pluginService = pluginService; + this.pluginService = servicesContainer.getPluginService(); this.availabilityMap = availabilityMap; this.newHost = newHost; this.props = props; @@ -454,7 +424,7 @@ public ReaderFailoverResult call() { final Properties copy = new Properties(); copy.putAll(props); - final Connection conn = this.connectionService.open(this.newHost, copy); + final Connection conn = this.pluginService.forceConnect(this.newHost, copy); this.availabilityMap.put(this.newHost.getHost(), HostAvailability.AVAILABLE); if (this.isStrictReaderRequired) { diff --git a/wrapper/src/main/java/software/amazon/jdbc/plugin/failover/ClusterAwareWriterFailoverHandler.java b/wrapper/src/main/java/software/amazon/jdbc/plugin/failover/ClusterAwareWriterFailoverHandler.java index b01f249a2..43dc6ce69 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/plugin/failover/ClusterAwareWriterFailoverHandler.java +++ b/wrapper/src/main/java/software/amazon/jdbc/plugin/failover/ClusterAwareWriterFailoverHandler.java @@ -32,18 +32,15 @@ import java.util.concurrent.TimeUnit; import java.util.logging.Level; import java.util.logging.Logger; -import software.amazon.jdbc.ConnectionPluginManager; import software.amazon.jdbc.HostSpec; -import software.amazon.jdbc.PartialPluginService; import software.amazon.jdbc.PluginService; import software.amazon.jdbc.hostavailability.HostAvailability; import software.amazon.jdbc.util.ExecutorFactory; import software.amazon.jdbc.util.FullServicesContainer; -import software.amazon.jdbc.util.FullServicesContainerImpl; import software.amazon.jdbc.util.Messages; import software.amazon.jdbc.util.PropertyUtils; +import software.amazon.jdbc.util.ServiceUtility; import software.amazon.jdbc.util.Utils; -import software.amazon.jdbc.util.connection.ConnectionService; /** * An implementation of WriterFailoverHandler. @@ -60,7 +57,6 @@ public class ClusterAwareWriterFailoverHandler implements WriterFailoverHandler protected final Properties initialConnectionProps; protected final FullServicesContainer servicesContainer; - protected final ConnectionService connectionService; protected final PluginService pluginService; protected final ReaderFailoverHandler readerFailoverHandler; protected final Map hostAvailabilityMap = new ConcurrentHashMap<>(); @@ -70,11 +66,9 @@ public class ClusterAwareWriterFailoverHandler implements WriterFailoverHandler public ClusterAwareWriterFailoverHandler( final FullServicesContainer servicesContainer, - final ConnectionService connectionService, final ReaderFailoverHandler readerFailoverHandler, final Properties initialConnectionProps) { this.servicesContainer = servicesContainer; - this.connectionService = connectionService; this.pluginService = servicesContainer.getPluginService(); this.readerFailoverHandler = readerFailoverHandler; this.initialConnectionProps = initialConnectionProps; @@ -82,7 +76,6 @@ public ClusterAwareWriterFailoverHandler( public ClusterAwareWriterFailoverHandler( final FullServicesContainer servicesContainer, - final ConnectionService connectionService, final ReaderFailoverHandler readerFailoverHandler, final Properties initialConnectionProps, final int failoverTimeoutMs, @@ -90,7 +83,6 @@ public ClusterAwareWriterFailoverHandler( final int reconnectWriterIntervalMs) { this( servicesContainer, - connectionService, readerFailoverHandler, initialConnectionProps); this.maxFailoverTimeoutMs = failoverTimeoutMs; @@ -104,8 +96,7 @@ public Map getHostAvailabilityMap() { } @Override - public WriterFailoverResult failover(final List currentTopology) - throws SQLException { + public WriterFailoverResult failover(final List currentTopology) throws SQLException { if (Utils.isNullOrEmpty(currentTopology)) { LOGGER.severe(() -> Messages.get("ClusterAwareWriterFailoverHandler.failoverCalledWithInvalidTopology")); return DEFAULT_RESULT; @@ -155,8 +146,7 @@ private void submitTasks( if (!singleTask) { completionService.submit( new ReconnectToWriterHandler( - this.connectionService, - this.getNewPluginService(), + this.getNewServicesContainer(), this.hostAvailabilityMap, writerHost, this.initialConnectionProps, @@ -165,8 +155,7 @@ private void submitTasks( completionService.submit( new WaitForNewWriterHandler( - this.connectionService, - this.getNewPluginService(), + this.getNewServicesContainer(), this.hostAvailabilityMap, this.readerFailoverHandler, writerHost, @@ -177,29 +166,16 @@ private void submitTasks( executorService.shutdown(); } - // Each task should get its own PluginService since they execute concurrently and PluginService was not designed to - // be thread-safe. - protected PluginService getNewPluginService() throws SQLException { - FullServicesContainer newServicesContainer = new FullServicesContainerImpl( + protected FullServicesContainer getNewServicesContainer() throws SQLException { + // Each task should get its own FullServicesContainer since they execute concurrently and PluginService was not + // designed to be thread-safe. + return ServiceUtility.getInstance().createServiceContainer( this.servicesContainer.getStorageService(), this.servicesContainer.getMonitorService(), - this.servicesContainer.getTelemetryFactory() + this.pluginService.getDefaultConnectionProvider(), + this.servicesContainer.getTelemetryFactory(), + this.pluginService.getConnectConfig() ); - - ConnectionPluginManager pluginManager = new ConnectionPluginManager( - this.pluginService.getDefaultConnectionProvider(), null, null, servicesContainer.getTelemetryFactory()); - newServicesContainer.setConnectionPluginManager(pluginManager); - PartialPluginService pluginService = new PartialPluginService( - newServicesContainer, - this.initialConnectionProps, - this.pluginService.getOriginalUrl(), - this.pluginService.getDriverProtocol(), - this.pluginService.getTargetDriverDialect(), - this.pluginService.getDialect() - ); - - pluginManager.init(newServicesContainer, this.initialConnectionProps, pluginService, null); - return pluginService; } private WriterFailoverResult getNextResult( @@ -275,8 +251,6 @@ private SQLException createInterruptedException(final InterruptedException e) { * Internal class responsible for re-connecting to the current writer (aka TaskA). */ private static class ReconnectToWriterHandler implements Callable { - - private final ConnectionService connectionService; private final PluginService pluginService; private final Map availabilityMap; private final HostSpec originalWriterHost; @@ -284,14 +258,12 @@ private static class ReconnectToWriterHandler implements Callable availabilityMap, final HostSpec originalWriterHost, final Properties props, final int reconnectWriterIntervalMs) { - this.connectionService = connectionService; - this.pluginService = pluginService; + this.pluginService = servicesContainer.getPluginService(); this.availabilityMap = availabilityMap; this.originalWriterHost = originalWriterHost; this.props = props; @@ -315,7 +287,7 @@ public WriterFailoverResult call() { conn.close(); } - conn = this.connectionService.open(this.originalWriterHost, this.props); + conn = this.pluginService.forceConnect(this.originalWriterHost, this.props); this.pluginService.forceRefreshHostList(conn); latestTopology = this.pluginService.getAllHosts(); } catch (final SQLException exception) { @@ -358,6 +330,10 @@ public WriterFailoverResult call() { private boolean isCurrentHostWriter(final List latestTopology) { final HostSpec latestWriter = Utils.getWriter(latestTopology); + if (latestWriter == null) { + return false; + } + final Set latestWriterAllAliases = latestWriter.asAliases(); final Set currentAliases = this.originalWriterHost.asAliases(); @@ -371,8 +347,6 @@ private boolean isCurrentHostWriter(final List latestTopology) { * elected writer (aka TaskB). */ private static class WaitForNewWriterHandler implements Callable { - - private final ConnectionService connectionService; private final PluginService pluginService; private final Map availabilityMap; private final ReaderFailoverHandler readerFailoverHandler; @@ -385,16 +359,14 @@ private static class WaitForNewWriterHandler implements Callable availabilityMap, final ReaderFailoverHandler readerFailoverHandler, final HostSpec originalWriterHost, final Properties props, final int readTopologyIntervalMs, final List currentTopology) { - this.connectionService = connectionService; - this.pluginService = pluginService; + this.pluginService = servicesContainer.getPluginService(); this.availabilityMap = availabilityMap; this.readerFailoverHandler = readerFailoverHandler; this.originalWriterHost = originalWriterHost; @@ -537,7 +509,7 @@ private boolean connectToWriter(final HostSpec writerCandidate) { new Object[] {writerCandidate.getUrl()})); try { // connect to the new writer - this.currentConnection = this.connectionService.open(writerCandidate, this.props); + this.currentConnection = this.pluginService.forceConnect(writerCandidate, this.props); this.availabilityMap.put(writerCandidate.getHost(), HostAvailability.AVAILABLE); return true; } catch (final SQLException exception) { diff --git a/wrapper/src/main/java/software/amazon/jdbc/plugin/failover/FailoverConnectionPlugin.java b/wrapper/src/main/java/software/amazon/jdbc/plugin/failover/FailoverConnectionPlugin.java index c9d90e764..78584dded 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/plugin/failover/FailoverConnectionPlugin.java +++ b/wrapper/src/main/java/software/amazon/jdbc/plugin/failover/FailoverConnectionPlugin.java @@ -28,7 +28,7 @@ import java.util.Set; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; -import java.util.function.Function; +import java.util.function.Supplier; import java.util.logging.Level; import java.util.logging.Logger; import org.checkerframework.checker.nullness.qual.Nullable; @@ -53,8 +53,7 @@ import software.amazon.jdbc.util.SqlState; import software.amazon.jdbc.util.Utils; import software.amazon.jdbc.util.WrapperUtils; -import software.amazon.jdbc.util.connection.ConnectionService; -import software.amazon.jdbc.util.connection.ConnectionServiceImpl; +import software.amazon.jdbc.util.connection.ConnectConfig; import software.amazon.jdbc.util.telemetry.TelemetryContext; import software.amazon.jdbc.util.telemetry.TelemetryCounter; import software.amazon.jdbc.util.telemetry.TelemetryFactory; @@ -96,7 +95,6 @@ public class FailoverConnectionPlugin extends AbstractConnectionPlugin { private final Set subscribedMethods; private final PluginService pluginService; private final FullServicesContainer servicesContainer; - private ConnectionService connectionService; protected final Properties properties; protected boolean enableFailoverSetting; protected boolean enableConnectFailover; @@ -119,8 +117,8 @@ public class FailoverConnectionPlugin extends AbstractConnectionPlugin { private RdsUrlType rdsUrlType = null; private HostListProviderService hostListProviderService; private final AuroraStaleDnsHelper staleDnsHelper; - private Function writerFailoverHandlerSupplier; - private Function readerFailoverHandlerSupplier; + private Supplier writerFailoverHandlerSupplier; + private Supplier readerFailoverHandlerSupplier; public static final AwsWrapperProperty FAILOVER_CLUSTER_TOPOLOGY_REFRESH_RATE_MS = new AwsWrapperProperty( @@ -304,27 +302,23 @@ public T execute( @Override public void initHostProvider( - final String driverProtocol, - final String initialUrl, - final Properties properties, + final ConnectConfig connectConfig, final HostListProviderService hostListProviderService, final JdbcCallable initHostProviderFunc) throws SQLException { initHostProvider( hostListProviderService, initHostProviderFunc, - (connectionService) -> + () -> new ClusterAwareReaderFailoverHandler( this.servicesContainer, - connectionService, this.properties, this.failoverTimeoutMsSetting, this.failoverReaderConnectTimeoutMsSetting, this.failoverMode == FailoverMode.STRICT_READER), - (connectionService) -> + () -> new ClusterAwareWriterFailoverHandler( this.servicesContainer, - connectionService, this.readerFailoverHandler, this.properties, this.failoverTimeoutMsSetting, @@ -335,8 +329,8 @@ public void initHostProvider( void initHostProvider( final HostListProviderService hostListProviderService, final JdbcCallable initHostProviderFunc, - final Function readerFailoverHandlerSupplier, - final Function writerFailoverHandlerSupplier) + final Supplier readerFailoverHandlerSupplier, + final Supplier writerFailoverHandlerSupplier) throws SQLException { this.readerFailoverHandlerSupplier = readerFailoverHandlerSupplier; this.writerFailoverHandlerSupplier = writerFailoverHandlerSupplier; @@ -603,10 +597,6 @@ protected void failover(@Nullable final HostSpec failedHost) throws SQLException this.pluginService.setAvailability(failedHost.asAliases(), HostAvailability.NOT_AVAILABLE); } - if (this.connectionService == null) { - this.connectionService = getConnectionService(); - } - if (this.failoverMode == FailoverMode.STRICT_WRITER) { failoverWriter(); } else { @@ -614,20 +604,6 @@ protected void failover(@Nullable final HostSpec failedHost) throws SQLException } } - protected ConnectionService getConnectionService() throws SQLException { - return new ConnectionServiceImpl( - servicesContainer.getStorageService(), - servicesContainer.getMonitorService(), - servicesContainer.getTelemetryFactory(), - this.pluginService.getDefaultConnectionProvider(), - this.pluginService.getOriginalUrl(), - this.pluginService.getDriverProtocol(), - this.pluginService.getTargetDriverDialect(), - this.pluginService.getDialect(), - properties - ); - } - protected void failoverReader(final HostSpec failedHostSpec) throws SQLException { TelemetryFactory telemetryFactory = this.pluginService.getTelemetryFactory(); TelemetryContext telemetryContext = telemetryFactory.openTelemetryContext( @@ -640,7 +616,7 @@ protected void failoverReader(final HostSpec failedHostSpec) throws SQLException if (this.readerFailoverHandlerSupplier == null) { throw new SQLException(Messages.get("Failover.nullReaderFailoverHandlerSupplier")); } - this.readerFailoverHandler = this.readerFailoverHandlerSupplier.apply(this.connectionService); + this.readerFailoverHandler = this.readerFailoverHandlerSupplier.get(); } final long failoverStartNano = System.nanoTime(); @@ -743,14 +719,14 @@ protected void failoverWriter() throws SQLException { if (this.readerFailoverHandlerSupplier == null) { throw new SQLException(Messages.get("Failover.nullReaderFailoverHandlerSupplier")); } - this.readerFailoverHandler = this.readerFailoverHandlerSupplier.apply(this.connectionService); + this.readerFailoverHandler = this.readerFailoverHandlerSupplier.get(); } if (this.writerFailoverHandler == null) { if (this.writerFailoverHandlerSupplier == null) { throw new SQLException(Messages.get("Failover.nullWriterFailoverHandlerSupplier")); } - this.writerFailoverHandler = this.writerFailoverHandlerSupplier.apply(this.connectionService); + this.writerFailoverHandler = this.writerFailoverHandlerSupplier.get(); } long failoverStartTimeNano = System.nanoTime(); @@ -928,19 +904,16 @@ private boolean canDirectExecute(final String methodName) { @Override public Connection connect( - final String driverProtocol, + final ConnectConfig connectConfig, final HostSpec hostSpec, - final Properties props, final boolean isInitialConnection, - final JdbcCallable connectFunc) - throws SQLException { + final JdbcCallable connectFunc) throws SQLException { this.initFailoverMode(); Connection conn = null; try { - conn = - this.staleDnsHelper.getVerifiedConnection(isInitialConnection, this.hostListProviderService, - driverProtocol, hostSpec, props, connectFunc); + conn = this.staleDnsHelper.getVerifiedConnection( + isInitialConnection, this.hostListProviderService, connectConfig, hostSpec, connectFunc); } catch (final SQLException e) { if (!this.enableConnectFailover || !shouldExceptionTriggerConnectionSwitch(e)) { throw e; diff --git a/wrapper/src/main/java/software/amazon/jdbc/plugin/failover2/FailoverConnectionPlugin.java b/wrapper/src/main/java/software/amazon/jdbc/plugin/failover2/FailoverConnectionPlugin.java index 76a0ec244..ec8c961a4 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/plugin/failover2/FailoverConnectionPlugin.java +++ b/wrapper/src/main/java/software/amazon/jdbc/plugin/failover2/FailoverConnectionPlugin.java @@ -53,6 +53,7 @@ import software.amazon.jdbc.util.SqlState; import software.amazon.jdbc.util.Utils; import software.amazon.jdbc.util.WrapperUtils; +import software.amazon.jdbc.util.connection.ConnectConfig; import software.amazon.jdbc.util.telemetry.TelemetryContext; import software.amazon.jdbc.util.telemetry.TelemetryCounter; import software.amazon.jdbc.util.telemetry.TelemetryFactory; @@ -232,9 +233,7 @@ public T execute( @Override public void initHostProvider( - final String driverProtocol, - final String initialUrl, - final Properties properties, + final ConnectConfig connectConfig, final HostListProviderService hostListProviderService, final JdbcCallable initHostProviderFunc) throws SQLException { @@ -728,20 +727,17 @@ protected void initFailoverMode() { @Override public Connection connect( - final String driverProtocol, + final ConnectConfig connectConfig, final HostSpec hostSpec, - final Properties props, final boolean isInitialConnection, - final JdbcCallable connectFunc) - throws SQLException { - + final JdbcCallable connectFunc) throws SQLException { this.initFailoverMode(); Connection conn = null; - + Properties props = connectConfig.getProps(); if (!ENABLE_CONNECT_FAILOVER.getBoolean(props)) { - return this.staleDnsHelper.getVerifiedConnection(isInitialConnection, this.hostListProviderService, - driverProtocol, hostSpec, props, connectFunc); + return this.staleDnsHelper.getVerifiedConnection( + isInitialConnection, this.hostListProviderService, connectConfig, hostSpec, connectFunc); } final HostSpec hostSpecWithAvailability = this.pluginService.getHosts().stream() @@ -753,8 +749,8 @@ public Connection connect( || hostSpecWithAvailability.getAvailability() != HostAvailability.NOT_AVAILABLE) { try { - conn = this.staleDnsHelper.getVerifiedConnection(isInitialConnection, this.hostListProviderService, - driverProtocol, hostSpec, props, connectFunc); + conn = this.staleDnsHelper.getVerifiedConnection( + isInitialConnection, this.hostListProviderService, connectConfig, hostSpec, connectFunc); } catch (final SQLException e) { if (!this.shouldExceptionTriggerConnectionSwitch(e)) { throw e; diff --git a/wrapper/src/main/java/software/amazon/jdbc/plugin/federatedauth/CredentialsProviderFactory.java b/wrapper/src/main/java/software/amazon/jdbc/plugin/federatedauth/CredentialsProviderFactory.java index a43396bf9..655fbdda4 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/plugin/federatedauth/CredentialsProviderFactory.java +++ b/wrapper/src/main/java/software/amazon/jdbc/plugin/federatedauth/CredentialsProviderFactory.java @@ -16,7 +16,6 @@ package software.amazon.jdbc.plugin.federatedauth; -import java.io.Closeable; import java.sql.SQLException; import java.util.Properties; import org.checkerframework.checker.nullness.qual.NonNull; diff --git a/wrapper/src/main/java/software/amazon/jdbc/plugin/federatedauth/FederatedAuthPlugin.java b/wrapper/src/main/java/software/amazon/jdbc/plugin/federatedauth/FederatedAuthPlugin.java index 6a06e1d68..6315282ad 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/plugin/federatedauth/FederatedAuthPlugin.java +++ b/wrapper/src/main/java/software/amazon/jdbc/plugin/federatedauth/FederatedAuthPlugin.java @@ -42,6 +42,7 @@ import software.amazon.jdbc.util.RdsUtils; import software.amazon.jdbc.util.RegionUtils; import software.amazon.jdbc.util.StringUtils; +import software.amazon.jdbc.util.connection.ConnectConfig; import software.amazon.jdbc.util.telemetry.TelemetryCounter; import software.amazon.jdbc.util.telemetry.TelemetryFactory; import software.amazon.jdbc.util.telemetry.TelemetryGauge; @@ -152,27 +153,26 @@ public FederatedAuthPlugin(final PluginService pluginService, @Override public Connection connect( - final String driverProtocol, + final ConnectConfig connectConfig, final HostSpec hostSpec, - final Properties props, final boolean isInitialConnection, - final JdbcCallable connectFunc) - throws SQLException { - return connectInternal(hostSpec, props, connectFunc); + final JdbcCallable connectFunc) throws SQLException { + return connectInternal(hostSpec, connectConfig.getProps(), connectFunc); } @Override public Connection forceConnect( - final @NonNull String driverProtocol, + final @NonNull ConnectConfig connectConfig, final @NonNull HostSpec hostSpec, - final @NonNull Properties props, final boolean isInitialConnection, final @NonNull JdbcCallable forceConnectFunc) throws SQLException { - return connectInternal(hostSpec, props, forceConnectFunc); + return connectInternal(hostSpec, connectConfig.getProps(), forceConnectFunc); } - private Connection connectInternal(final HostSpec hostSpec, final Properties props, + private Connection connectInternal( + final HostSpec hostSpec, + final Properties props, final JdbcCallable connectFunc) throws SQLException { this.samlUtils.checkIdpCredentialsWithFallback(IDP_USERNAME, IDP_PASSWORD, props); diff --git a/wrapper/src/main/java/software/amazon/jdbc/plugin/federatedauth/OktaAuthPlugin.java b/wrapper/src/main/java/software/amazon/jdbc/plugin/federatedauth/OktaAuthPlugin.java index 7e47ff479..3bd2ea31c 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/plugin/federatedauth/OktaAuthPlugin.java +++ b/wrapper/src/main/java/software/amazon/jdbc/plugin/federatedauth/OktaAuthPlugin.java @@ -40,6 +40,7 @@ import software.amazon.jdbc.util.RdsUtils; import software.amazon.jdbc.util.RegionUtils; import software.amazon.jdbc.util.StringUtils; +import software.amazon.jdbc.util.connection.ConnectConfig; import software.amazon.jdbc.util.telemetry.TelemetryCounter; import software.amazon.jdbc.util.telemetry.TelemetryFactory; import software.amazon.jdbc.util.telemetry.TelemetryGauge; @@ -132,16 +133,22 @@ public Set getSubscribedMethods() { } @Override - public Connection connect(String driverProtocol, HostSpec hostSpec, Properties props, - boolean isInitialConnection, JdbcCallable connectFunc) throws SQLException { - return connectInternal(hostSpec, props, connectFunc); + public Connection connect( + final ConnectConfig connectConfig, + final HostSpec hostSpec, + final boolean isInitialConnection, + final JdbcCallable connectFunc) throws SQLException { + return connectInternal(hostSpec, connectConfig.getProps(), connectFunc); } @Override - public Connection forceConnect(String driverProtocol, HostSpec hostSpec, Properties props, - boolean isInitialConnection, JdbcCallable forceConnectFunc) + public Connection forceConnect( + ConnectConfig connectConfig, + HostSpec hostSpec, + boolean isInitialConnection, + JdbcCallable forceConnectFunc) throws SQLException { - return connectInternal(hostSpec, props, forceConnectFunc); + return connectInternal(hostSpec, connectConfig.getProps(), forceConnectFunc); } private Connection connectInternal(final HostSpec hostSpec, final Properties props, diff --git a/wrapper/src/main/java/software/amazon/jdbc/plugin/iam/IamAuthConnectionPlugin.java b/wrapper/src/main/java/software/amazon/jdbc/plugin/iam/IamAuthConnectionPlugin.java index 5541ac917..1fa787778 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/plugin/iam/IamAuthConnectionPlugin.java +++ b/wrapper/src/main/java/software/amazon/jdbc/plugin/iam/IamAuthConnectionPlugin.java @@ -40,6 +40,7 @@ import software.amazon.jdbc.util.RdsUtils; import software.amazon.jdbc.util.RegionUtils; import software.amazon.jdbc.util.StringUtils; +import software.amazon.jdbc.util.connection.ConnectConfig; import software.amazon.jdbc.util.telemetry.TelemetryCounter; import software.amazon.jdbc.util.telemetry.TelemetryFactory; import software.amazon.jdbc.util.telemetry.TelemetryGauge; @@ -106,17 +107,18 @@ public Set getSubscribedMethods() { @Override public Connection connect( - final String driverProtocol, + final ConnectConfig connectConfig, final HostSpec hostSpec, - final Properties props, final boolean isInitialConnection, - final JdbcCallable connectFunc) - throws SQLException { - return connectInternal(driverProtocol, hostSpec, props, connectFunc); + final JdbcCallable connectFunc) throws SQLException { + return connectInternal(connectConfig, hostSpec, connectFunc); } - private Connection connectInternal(String driverProtocol, HostSpec hostSpec, Properties props, + private Connection connectInternal( + ConnectConfig connectConfig, + HostSpec hostSpec, JdbcCallable connectFunc) throws SQLException { + Properties props = connectConfig.getProps(); if (StringUtils.isNullOrEmpty(PropertyDefinition.USER.getString(props))) { throw new SQLException(PropertyDefinition.USER.name + " is null or empty."); } @@ -224,13 +226,12 @@ private Connection connectInternal(String driverProtocol, HostSpec hostSpec, Pro @Override public Connection forceConnect( - final @NonNull String driverProtocol, + final @NonNull ConnectConfig connectConfig, final @NonNull HostSpec hostSpec, - final @NonNull Properties props, final boolean isInitialConnection, final @NonNull JdbcCallable forceConnectFunc) throws SQLException { - return connectInternal(driverProtocol, hostSpec, props, forceConnectFunc); + return connectInternal(connectConfig, hostSpec, forceConnectFunc); } public static void clearCache() { diff --git a/wrapper/src/main/java/software/amazon/jdbc/plugin/limitless/LimitlessConnectionPlugin.java b/wrapper/src/main/java/software/amazon/jdbc/plugin/limitless/LimitlessConnectionPlugin.java index 2bff9680c..10832a975 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/plugin/limitless/LimitlessConnectionPlugin.java +++ b/wrapper/src/main/java/software/amazon/jdbc/plugin/limitless/LimitlessConnectionPlugin.java @@ -35,6 +35,7 @@ import software.amazon.jdbc.plugin.AbstractConnectionPlugin; import software.amazon.jdbc.util.FullServicesContainer; import software.amazon.jdbc.util.Messages; +import software.amazon.jdbc.util.connection.ConnectConfig; public class LimitlessConnectionPlugin extends AbstractConnectionPlugin { @@ -103,12 +104,10 @@ public LimitlessConnectionPlugin( @Override public Connection connect( - final String driverProtocol, + final ConnectConfig connectConfig, final HostSpec hostSpec, - final Properties props, final boolean isInitialConnection, - final JdbcCallable connectFunc) - throws SQLException { + final JdbcCallable connectFunc) throws SQLException { Connection conn = null; @@ -131,7 +130,7 @@ public Connection connect( final LimitlessConnectionContext context = new LimitlessConnectionContext( hostSpec, - props, + connectConfig.getProps(), conn, connectFunc, null, diff --git a/wrapper/src/main/java/software/amazon/jdbc/plugin/limitless/LimitlessRouterMonitor.java b/wrapper/src/main/java/software/amazon/jdbc/plugin/limitless/LimitlessRouterMonitor.java index cd983896a..f4075a285 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/plugin/limitless/LimitlessRouterMonitor.java +++ b/wrapper/src/main/java/software/amazon/jdbc/plugin/limitless/LimitlessRouterMonitor.java @@ -25,11 +25,10 @@ import java.util.logging.Logger; import org.checkerframework.checker.nullness.qual.NonNull; import software.amazon.jdbc.HostSpec; -import software.amazon.jdbc.PluginService; +import software.amazon.jdbc.util.FullServicesContainer; import software.amazon.jdbc.util.Messages; import software.amazon.jdbc.util.PropertyUtils; import software.amazon.jdbc.util.Utils; -import software.amazon.jdbc.util.connection.ConnectionService; import software.amazon.jdbc.util.monitoring.AbstractMonitor; import software.amazon.jdbc.util.storage.StorageService; import software.amazon.jdbc.util.telemetry.TelemetryContext; @@ -45,27 +44,24 @@ public class LimitlessRouterMonitor extends AbstractMonitor { protected static final long TERMINATION_TIMEOUT_SEC = 5; protected final int intervalMs; protected final @NonNull HostSpec hostSpec; + protected final @NonNull FullServicesContainer servicesContainer; protected final @NonNull StorageService storageService; protected final @NonNull String limitlessRouterCacheKey; protected final @NonNull Properties props; - protected final @NonNull ConnectionService connectionService; protected final @NonNull LimitlessQueryHelper queryHelper; protected final @NonNull TelemetryFactory telemetryFactory; protected Connection monitoringConn = null; public LimitlessRouterMonitor( - final @NonNull PluginService pluginService, - final @NonNull ConnectionService connectionService, - final @NonNull TelemetryFactory telemetryFactory, + final @NonNull FullServicesContainer servicesContainer, final @NonNull HostSpec hostSpec, - final @NonNull StorageService storageService, final @NonNull String limitlessRouterCacheKey, final @NonNull Properties props, final int intervalMs) { super(TERMINATION_TIMEOUT_SEC); - this.connectionService = connectionService; - this.storageService = storageService; - this.telemetryFactory = telemetryFactory; + this.servicesContainer = servicesContainer; + this.storageService = servicesContainer.getStorageService(); + this.telemetryFactory = servicesContainer.getTelemetryFactory(); this.hostSpec = hostSpec; this.limitlessRouterCacheKey = limitlessRouterCacheKey; this.props = PropertyUtils.copyProperties(props); @@ -81,7 +77,7 @@ public LimitlessRouterMonitor( this.props.setProperty(LimitlessConnectionPlugin.WAIT_FOR_ROUTER_INFO.name, "false"); this.intervalMs = intervalMs; - this.queryHelper = new LimitlessQueryHelper(pluginService); + this.queryHelper = new LimitlessQueryHelper(servicesContainer.getPluginService()); } @Override @@ -170,7 +166,7 @@ private void openConnection() throws SQLException { LOGGER.finest(() -> Messages.get( "LimitlessRouterMonitor.openingConnection", new Object[] {this.hostSpec.getUrl()})); - this.monitoringConn = this.connectionService.open(this.hostSpec, this.props); + this.monitoringConn = this.servicesContainer.getPluginService().forceConnect(this.hostSpec, this.props); LOGGER.finest(() -> Messages.get( "LimitlessRouterMonitor.openedConnection", new Object[] {this.monitoringConn})); diff --git a/wrapper/src/main/java/software/amazon/jdbc/plugin/limitless/LimitlessRouterService.java b/wrapper/src/main/java/software/amazon/jdbc/plugin/limitless/LimitlessRouterService.java index 2d3d87a08..1e3a04560 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/plugin/limitless/LimitlessRouterService.java +++ b/wrapper/src/main/java/software/amazon/jdbc/plugin/limitless/LimitlessRouterService.java @@ -16,9 +16,7 @@ package software.amazon.jdbc.plugin.limitless; -import java.sql.Connection; import java.sql.SQLException; -import java.util.List; import java.util.Properties; import org.checkerframework.checker.nullness.qual.NonNull; import software.amazon.jdbc.HostSpec; diff --git a/wrapper/src/main/java/software/amazon/jdbc/plugin/limitless/LimitlessRouterServiceImpl.java b/wrapper/src/main/java/software/amazon/jdbc/plugin/limitless/LimitlessRouterServiceImpl.java index 7b904c57d..51c717433 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/plugin/limitless/LimitlessRouterServiceImpl.java +++ b/wrapper/src/main/java/software/amazon/jdbc/plugin/limitless/LimitlessRouterServiceImpl.java @@ -158,12 +158,11 @@ public void establishConnection(final LimitlessConnectionContext context) throws if (this.isLoginException(e)) { throw e; } - if (selectedHostSpec != null) { - LOGGER.fine(Messages.get( - "LimitlessRouterServiceImpl.failedToConnectToHost", - new Object[] {selectedHostSpec.getHost()})); - selectedHostSpec.setAvailability(HostAvailability.NOT_AVAILABLE); - } + + LOGGER.fine(Messages.get( + "LimitlessRouterServiceImpl.failedToConnectToHost", + new Object[] {selectedHostSpec.getHost()})); + selectedHostSpec.setAvailability(HostAvailability.NOT_AVAILABLE); // Retry connect prioritising the healthiest router for best chance of // connection over load-balancing with round-robin. retryConnectWithLeastLoadedRouters(context); @@ -316,10 +315,7 @@ protected boolean isLoginException(Throwable throwable) { } @Override - public void startMonitoring(final @NonNull HostSpec hostSpec, - final @NonNull Properties props, - final int intervalMs) { - + public void startMonitoring(final @NonNull HostSpec hostSpec, final @NonNull Properties props, final int intervalMs) { try { final String limitlessRouterMonitorKey = pluginService.getHostListProvider().getClusterId(); this.servicesContainer.getMonitorService().runIfAbsent( @@ -328,17 +324,10 @@ public void startMonitoring(final @NonNull HostSpec hostSpec, this.servicesContainer.getStorageService(), this.servicesContainer.getTelemetryFactory(), this.pluginService.getDefaultConnectionProvider(), - this.pluginService.getOriginalUrl(), - this.pluginService.getDriverProtocol(), - this.pluginService.getTargetDriverDialect(), - this.pluginService.getDialect(), - props, - (connectionService, pluginService) -> new LimitlessRouterMonitor( - pluginService, - connectionService, - this.servicesContainer.getTelemetryFactory(), + this.pluginService.getConnectConfig(), + (servicesContainer) -> new LimitlessRouterMonitor( + servicesContainer, hostSpec, - this.servicesContainer.getStorageService(), limitlessRouterMonitorKey, props, intervalMs)); diff --git a/wrapper/src/main/java/software/amazon/jdbc/plugin/limitless/LimitlessRouters.java b/wrapper/src/main/java/software/amazon/jdbc/plugin/limitless/LimitlessRouters.java index 0793dbcff..ea7cab3ce 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/plugin/limitless/LimitlessRouters.java +++ b/wrapper/src/main/java/software/amazon/jdbc/plugin/limitless/LimitlessRouters.java @@ -20,7 +20,6 @@ import java.util.Objects; import org.checkerframework.checker.nullness.qual.NonNull; import software.amazon.jdbc.HostSpec; -import software.amazon.jdbc.hostlistprovider.Topology; public class LimitlessRouters { private final @NonNull List hosts; diff --git a/wrapper/src/main/java/software/amazon/jdbc/plugin/readwritesplitting/ReadWriteSplittingPlugin.java b/wrapper/src/main/java/software/amazon/jdbc/plugin/readwritesplitting/ReadWriteSplittingPlugin.java index 2d25675e2..e539432a9 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/plugin/readwritesplitting/ReadWriteSplittingPlugin.java +++ b/wrapper/src/main/java/software/amazon/jdbc/plugin/readwritesplitting/ReadWriteSplittingPlugin.java @@ -44,6 +44,7 @@ import software.amazon.jdbc.util.SqlState; import software.amazon.jdbc.util.Utils; import software.amazon.jdbc.util.WrapperUtils; +import software.amazon.jdbc.util.connection.ConnectConfig; public class ReadWriteSplittingPlugin extends AbstractConnectionPlugin implements CanReleaseResources { @@ -124,25 +125,20 @@ public Set getSubscribedMethods() { @Override public void initHostProvider( - final String driverProtocol, - final String initialUrl, - final Properties props, + final ConnectConfig connectConfig, final HostListProviderService hostListProviderService, final JdbcCallable initHostProviderFunc) throws SQLException { - this.hostListProviderService = hostListProviderService; initHostProviderFunc.call(); } @Override public Connection connect( - final String driverProtocol, + final ConnectConfig connectConfig, final HostSpec hostSpec, - final Properties props, final boolean isInitialConnection, - final @NonNull JdbcCallable connectFunc) - throws SQLException { + final JdbcCallable connectFunc) throws SQLException { if (!pluginService.acceptsStrategy(hostSpec.getRole(), this.readerSelectorStrategy)) { throw new UnsupportedOperationException( diff --git a/wrapper/src/main/java/software/amazon/jdbc/plugin/staledns/AuroraStaleDnsHelper.java b/wrapper/src/main/java/software/amazon/jdbc/plugin/staledns/AuroraStaleDnsHelper.java index 682c3080f..10d676c60 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/plugin/staledns/AuroraStaleDnsHelper.java +++ b/wrapper/src/main/java/software/amazon/jdbc/plugin/staledns/AuroraStaleDnsHelper.java @@ -23,7 +23,6 @@ import java.util.EnumSet; import java.util.List; import java.util.Map; -import java.util.Properties; import java.util.logging.Logger; import software.amazon.jdbc.HostListProviderService; import software.amazon.jdbc.HostRole; @@ -34,6 +33,7 @@ import software.amazon.jdbc.util.Messages; import software.amazon.jdbc.util.RdsUtils; import software.amazon.jdbc.util.Utils; +import software.amazon.jdbc.util.connection.ConnectConfig; import software.amazon.jdbc.util.telemetry.TelemetryCounter; import software.amazon.jdbc.util.telemetry.TelemetryFactory; @@ -61,9 +61,8 @@ public AuroraStaleDnsHelper(final PluginService pluginService) { public Connection getVerifiedConnection( final boolean isInitialConnection, final HostListProviderService hostListProviderService, - final String driverProtocol, + final ConnectConfig connectConfig, final HostSpec hostSpec, - final Properties props, final JdbcCallable connectFunc) throws SQLException { if (!this.rdsUtils.isWriterClusterDns(hostSpec.getHost())) { @@ -148,7 +147,7 @@ public Connection getVerifiedConnection( ); } - final Connection writerConn = this.pluginService.connect(this.writerHostSpec, props); + final Connection writerConn = this.pluginService.connect(this.writerHostSpec, connectConfig.getProps()); if (isInitialConnection) { hostListProviderService.setInitialConnectionHostSpec(this.writerHostSpec); } diff --git a/wrapper/src/main/java/software/amazon/jdbc/plugin/staledns/AuroraStaleDnsPlugin.java b/wrapper/src/main/java/software/amazon/jdbc/plugin/staledns/AuroraStaleDnsPlugin.java index a5babfc3c..d5c2ba2d5 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/plugin/staledns/AuroraStaleDnsPlugin.java +++ b/wrapper/src/main/java/software/amazon/jdbc/plugin/staledns/AuroraStaleDnsPlugin.java @@ -32,6 +32,7 @@ import software.amazon.jdbc.NodeChangeOptions; import software.amazon.jdbc.PluginService; import software.amazon.jdbc.plugin.AbstractConnectionPlugin; +import software.amazon.jdbc.util.connection.ConnectConfig; /** * After Aurora DB cluster fail over is completed and a cluster has elected a new writer node, the corresponding @@ -75,21 +76,17 @@ public Set getSubscribedMethods() { @Override public Connection connect( - final String driverProtocol, + final ConnectConfig connectConfig, final HostSpec hostSpec, - final Properties props, final boolean isInitialConnection, - final JdbcCallable connectFunc) - throws SQLException { - return this.helper.getVerifiedConnection(isInitialConnection, this.hostListProviderService, - driverProtocol, hostSpec, props, connectFunc); + final JdbcCallable connectFunc) throws SQLException { + return this.helper.getVerifiedConnection( + isInitialConnection, this.hostListProviderService, connectConfig, hostSpec, connectFunc); } @Override public void initHostProvider( - final String driverProtocol, - final String initialUrl, - final Properties props, + final ConnectConfig connectConfig, final HostListProviderService hostListProviderService, final JdbcCallable initHostProviderFunc) throws SQLException { this.hostListProviderService = hostListProviderService; diff --git a/wrapper/src/main/java/software/amazon/jdbc/plugin/strategy/fastestresponse/FastestResponseStrategyPlugin.java b/wrapper/src/main/java/software/amazon/jdbc/plugin/strategy/fastestresponse/FastestResponseStrategyPlugin.java index f9ae41b6d..7ddb3037b 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/plugin/strategy/fastestresponse/FastestResponseStrategyPlugin.java +++ b/wrapper/src/main/java/software/amazon/jdbc/plugin/strategy/fastestresponse/FastestResponseStrategyPlugin.java @@ -40,6 +40,7 @@ import software.amazon.jdbc.RandomHostSelector; import software.amazon.jdbc.plugin.AbstractConnectionPlugin; import software.amazon.jdbc.util.FullServicesContainer; +import software.amazon.jdbc.util.connection.ConnectConfig; import software.amazon.jdbc.util.storage.CacheMap; public class FastestResponseStrategyPlugin extends AbstractConnectionPlugin { @@ -111,13 +112,10 @@ public Set getSubscribedMethods() { @Override public Connection connect( - final String driverProtocol, + final ConnectConfig connectConfig, final HostSpec hostSpec, - final Properties props, final boolean isInitialConnection, - final JdbcCallable connectFunc) - throws SQLException { - + final JdbcCallable connectFunc) throws SQLException { Connection conn = connectFunc.call(); if (isInitialConnection) { this.hostResponseTimeService.setHosts(this.pluginService.getHosts()); diff --git a/wrapper/src/main/java/software/amazon/jdbc/plugin/strategy/fastestresponse/HostResponseTimeServiceImpl.java b/wrapper/src/main/java/software/amazon/jdbc/plugin/strategy/fastestresponse/HostResponseTimeServiceImpl.java index 824f1c5d3..2514a335a 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/plugin/strategy/fastestresponse/HostResponseTimeServiceImpl.java +++ b/wrapper/src/main/java/software/amazon/jdbc/plugin/strategy/fastestresponse/HostResponseTimeServiceImpl.java @@ -78,15 +78,10 @@ public void setHosts(final @NonNull List hosts) { hostSpec.getUrl(), servicesContainer.getStorageService(), servicesContainer.getTelemetryFactory(), - this.pluginService.getDefaultConnectionProvider(), - this.pluginService.getOriginalUrl(), - this.pluginService.getDriverProtocol(), - this.pluginService.getTargetDriverDialect(), - this.pluginService.getDialect(), - this.props, - (connectionService, pluginService) -> - new NodeResponseTimeMonitor(pluginService, connectionService, hostSpec, this.props, - this.intervalMs)); + servicesContainer.getDefaultConnectionProvider(), + this.pluginService.getConnectConfig(), + (servicesContainer) -> + new NodeResponseTimeMonitor(pluginService, hostSpec, this.props, this.intervalMs)); } catch (SQLException e) { LOGGER.warning( Messages.get("HostResponseTimeServiceImpl.errorStartingMonitor", new Object[] {hostSpec.getUrl(), e})); diff --git a/wrapper/src/main/java/software/amazon/jdbc/plugin/strategy/fastestresponse/NodeResponseTimeMonitor.java b/wrapper/src/main/java/software/amazon/jdbc/plugin/strategy/fastestresponse/NodeResponseTimeMonitor.java index 1b985c03f..36322d9c1 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/plugin/strategy/fastestresponse/NodeResponseTimeMonitor.java +++ b/wrapper/src/main/java/software/amazon/jdbc/plugin/strategy/fastestresponse/NodeResponseTimeMonitor.java @@ -31,7 +31,6 @@ import software.amazon.jdbc.util.Messages; import software.amazon.jdbc.util.PropertyUtils; import software.amazon.jdbc.util.StringUtils; -import software.amazon.jdbc.util.connection.ConnectionService; import software.amazon.jdbc.util.monitoring.AbstractMonitor; import software.amazon.jdbc.util.telemetry.TelemetryContext; import software.amazon.jdbc.util.telemetry.TelemetryFactory; @@ -56,7 +55,6 @@ public class NodeResponseTimeMonitor extends AbstractMonitor { private final @NonNull Properties props; private final @NonNull PluginService pluginService; - private final @NonNull ConnectionService connectionService; private final TelemetryFactory telemetryFactory; private final TelemetryGauge responseTimeMsGauge; @@ -65,14 +63,12 @@ public class NodeResponseTimeMonitor extends AbstractMonitor { public NodeResponseTimeMonitor( final @NonNull PluginService pluginService, - final @NonNull ConnectionService connectionService, final @NonNull HostSpec hostSpec, final @NonNull Properties props, int intervalMs) { super(TERMINATION_TIMEOUT_SEC); this.pluginService = pluginService; - this.connectionService = connectionService; this.hostSpec = hostSpec; this.props = props; this.intervalMs = intervalMs; @@ -197,7 +193,7 @@ private void openConnection() { LOGGER.finest(() -> Messages.get( "NodeResponseTimeMonitor.openingConnection", new Object[] {this.hostSpec.getUrl()})); - this.monitoringConn = this.connectionService.open(this.hostSpec, monitoringConnProperties); + this.monitoringConn = this.pluginService.forceConnect(this.hostSpec, monitoringConnProperties); LOGGER.finest(() -> Messages.get( "NodeResponseTimeMonitor.openedConnection", new Object[] {this.monitoringConn})); diff --git a/wrapper/src/main/java/software/amazon/jdbc/targetdriverdialect/ConnectInfo.java b/wrapper/src/main/java/software/amazon/jdbc/targetdriverdialect/ConnectParams.java similarity index 80% rename from wrapper/src/main/java/software/amazon/jdbc/targetdriverdialect/ConnectInfo.java rename to wrapper/src/main/java/software/amazon/jdbc/targetdriverdialect/ConnectParams.java index 06e93947d..b129e0940 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/targetdriverdialect/ConnectInfo.java +++ b/wrapper/src/main/java/software/amazon/jdbc/targetdriverdialect/ConnectParams.java @@ -18,12 +18,12 @@ import java.util.Properties; -public class ConnectInfo { - public String url; +public class ConnectParams { + public String connectionString; public Properties props; - public ConnectInfo(final String url, final Properties props) { - this.url = url; + public ConnectParams(final String connectionString, final Properties props) { + this.connectionString = connectionString; this.props = props; } } diff --git a/wrapper/src/main/java/software/amazon/jdbc/targetdriverdialect/GenericTargetDriverDialect.java b/wrapper/src/main/java/software/amazon/jdbc/targetdriverdialect/GenericTargetDriverDialect.java index e740df215..4ecceeae4 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/targetdriverdialect/GenericTargetDriverDialect.java +++ b/wrapper/src/main/java/software/amazon/jdbc/targetdriverdialect/GenericTargetDriverDialect.java @@ -186,7 +186,7 @@ public boolean isDialect(String dataSourceClass) { } @Override - public ConnectInfo prepareConnectInfo(final @NonNull String protocol, + public ConnectParams prepareConnectParams(final @NonNull String protocol, final @NonNull HostSpec hostSpec, final @NonNull Properties props) throws SQLException { @@ -200,7 +200,7 @@ public ConnectInfo prepareConnectInfo(final @NonNull String protocol, // and use them to make a connection PropertyDefinition.removeAllExceptCredentials(props); - return new ConnectInfo(urlBuilder, props); + return new ConnectParams(urlBuilder, props); } @Override diff --git a/wrapper/src/main/java/software/amazon/jdbc/targetdriverdialect/MariadbDriverHelper.java b/wrapper/src/main/java/software/amazon/jdbc/targetdriverdialect/MariadbDriverHelper.java index 8c93819c3..d67638b6b 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/targetdriverdialect/MariadbDriverHelper.java +++ b/wrapper/src/main/java/software/amazon/jdbc/targetdriverdialect/MariadbDriverHelper.java @@ -18,7 +18,6 @@ import static software.amazon.jdbc.util.ConnectionUrlBuilder.buildUrl; -import com.mysql.cj.jdbc.Driver; import java.sql.DriverManager; import java.sql.SQLException; import java.util.Collections; diff --git a/wrapper/src/main/java/software/amazon/jdbc/targetdriverdialect/MariadbTargetDriverDialect.java b/wrapper/src/main/java/software/amazon/jdbc/targetdriverdialect/MariadbTargetDriverDialect.java index 506a249d2..af986e016 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/targetdriverdialect/MariadbTargetDriverDialect.java +++ b/wrapper/src/main/java/software/amazon/jdbc/targetdriverdialect/MariadbTargetDriverDialect.java @@ -109,9 +109,9 @@ public boolean isDialect(String dataSourceClass) { } @Override - public ConnectInfo prepareConnectInfo(final @NonNull String protocol, - final @NonNull HostSpec hostSpec, - final @NonNull Properties props) throws SQLException { + public ConnectParams prepareConnectParams(final @NonNull String protocol, + final @NonNull HostSpec hostSpec, + final @NonNull Properties props) throws SQLException { final String databaseName = PropertyDefinition.DATABASE.getString(props) != null @@ -133,7 +133,7 @@ public ConnectInfo prepareConnectInfo(final @NonNull String protocol, String urlBuilder = protocol + hostSpec.getUrl() + databaseName + (permitMysqlSchemeFlag ? "?" + PERMIT_MYSQL_SCHEME : ""); - return new ConnectInfo(urlBuilder, props); + return new ConnectParams(urlBuilder, props); } @Override diff --git a/wrapper/src/main/java/software/amazon/jdbc/targetdriverdialect/MysqlConnectorJTargetDriverDialect.java b/wrapper/src/main/java/software/amazon/jdbc/targetdriverdialect/MysqlConnectorJTargetDriverDialect.java index 3548fcddf..09b1a7cf1 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/targetdriverdialect/MysqlConnectorJTargetDriverDialect.java +++ b/wrapper/src/main/java/software/amazon/jdbc/targetdriverdialect/MysqlConnectorJTargetDriverDialect.java @@ -67,9 +67,9 @@ public boolean isDialect(String dataSourceClass) { } @Override - public ConnectInfo prepareConnectInfo(final @NonNull String protocol, - final @NonNull HostSpec hostSpec, - final @NonNull Properties props) throws SQLException { + public ConnectParams prepareConnectParams(final @NonNull String protocol, + final @NonNull HostSpec hostSpec, + final @NonNull Properties props) throws SQLException { final String databaseName = PropertyDefinition.DATABASE.getString(props) != null @@ -86,7 +86,7 @@ public ConnectInfo prepareConnectInfo(final @NonNull String protocol, PropertyDefinition.SOCKET_TIMEOUT.name, PropertyDefinition.CONNECT_TIMEOUT.name); - return new ConnectInfo(urlBuilder, props); + return new ConnectParams(urlBuilder, props); } @Override diff --git a/wrapper/src/main/java/software/amazon/jdbc/targetdriverdialect/PgTargetDriverDialect.java b/wrapper/src/main/java/software/amazon/jdbc/targetdriverdialect/PgTargetDriverDialect.java index b4c56f334..b419190f1 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/targetdriverdialect/PgTargetDriverDialect.java +++ b/wrapper/src/main/java/software/amazon/jdbc/targetdriverdialect/PgTargetDriverDialect.java @@ -96,9 +96,9 @@ public boolean isDialect(String dataSourceClass) { } @Override - public ConnectInfo prepareConnectInfo(final @NonNull String protocol, - final @NonNull HostSpec hostSpec, - final @NonNull Properties props) throws SQLException { + public ConnectParams prepareConnectParams(final @NonNull String protocol, + final @NonNull HostSpec hostSpec, + final @NonNull Properties props) throws SQLException { final String databaseName = PropertyDefinition.DATABASE.getString(props) != null @@ -133,7 +133,7 @@ public ConnectInfo prepareConnectInfo(final @NonNull String protocol, String urlBuilder = protocol + hostSpec.getUrl() + databaseName; - return new ConnectInfo(urlBuilder, props); + return new ConnectParams(urlBuilder, props); } @Override diff --git a/wrapper/src/main/java/software/amazon/jdbc/targetdriverdialect/TargetDriverDialect.java b/wrapper/src/main/java/software/amazon/jdbc/targetdriverdialect/TargetDriverDialect.java index 1e3ebdcec..a9bad20b3 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/targetdriverdialect/TargetDriverDialect.java +++ b/wrapper/src/main/java/software/amazon/jdbc/targetdriverdialect/TargetDriverDialect.java @@ -31,7 +31,7 @@ public interface TargetDriverDialect { boolean isDialect(final String dataSourceClass); - ConnectInfo prepareConnectInfo(final @NonNull String protocol, + ConnectParams prepareConnectParams(final @NonNull String protocol, final @NonNull HostSpec hostSpec, final @NonNull Properties props) throws SQLException; diff --git a/wrapper/src/main/java/software/amazon/jdbc/util/ConnectionUrlParser.java b/wrapper/src/main/java/software/amazon/jdbc/util/ConnectionUrlParser.java index 81323335b..435907141 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/util/ConnectionUrlParser.java +++ b/wrapper/src/main/java/software/amazon/jdbc/util/ConnectionUrlParser.java @@ -16,7 +16,6 @@ package software.amazon.jdbc.util; -import com.fasterxml.jackson.databind.annotation.JsonAppend.Prop; import java.util.ArrayList; import java.util.List; import java.util.Map; diff --git a/wrapper/src/main/java/software/amazon/jdbc/util/FullServicesContainer.java b/wrapper/src/main/java/software/amazon/jdbc/util/FullServicesContainer.java index e276b4503..7b7857175 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/util/FullServicesContainer.java +++ b/wrapper/src/main/java/software/amazon/jdbc/util/FullServicesContainer.java @@ -17,6 +17,7 @@ package software.amazon.jdbc.util; import software.amazon.jdbc.ConnectionPluginManager; +import software.amazon.jdbc.ConnectionProvider; import software.amazon.jdbc.HostListProviderService; import software.amazon.jdbc.PluginManagerService; import software.amazon.jdbc.PluginService; @@ -36,6 +37,8 @@ public interface FullServicesContainer { MonitorService getMonitorService(); + ConnectionProvider getDefaultConnectionProvider(); + TelemetryFactory getTelemetryFactory(); ConnectionPluginManager getConnectionPluginManager(); diff --git a/wrapper/src/main/java/software/amazon/jdbc/util/FullServicesContainerImpl.java b/wrapper/src/main/java/software/amazon/jdbc/util/FullServicesContainerImpl.java index ef0a0fc53..db0ea3f57 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/util/FullServicesContainerImpl.java +++ b/wrapper/src/main/java/software/amazon/jdbc/util/FullServicesContainerImpl.java @@ -17,6 +17,7 @@ package software.amazon.jdbc.util; import software.amazon.jdbc.ConnectionPluginManager; +import software.amazon.jdbc.ConnectionProvider; import software.amazon.jdbc.HostListProviderService; import software.amazon.jdbc.PluginManagerService; import software.amazon.jdbc.PluginService; @@ -27,6 +28,7 @@ public class FullServicesContainerImpl implements FullServicesContainer { private StorageService storageService; private MonitorService monitorService; + private ConnectionProvider defaultConnProvider; private TelemetryFactory telemetryFactory; private ConnectionPluginManager connectionPluginManager; private HostListProviderService hostListProviderService; @@ -36,12 +38,13 @@ public class FullServicesContainerImpl implements FullServicesContainer { public FullServicesContainerImpl( StorageService storageService, MonitorService monitorService, + ConnectionProvider defaultConnProvider, TelemetryFactory telemetryFactory, ConnectionPluginManager connectionPluginManager, HostListProviderService hostListProviderService, PluginService pluginService, PluginManagerService pluginManagerService) { - this(storageService, monitorService, telemetryFactory); + this(storageService, monitorService, defaultConnProvider, telemetryFactory); this.connectionPluginManager = connectionPluginManager; this.hostListProviderService = hostListProviderService; this.pluginService = pluginService; @@ -51,9 +54,11 @@ public FullServicesContainerImpl( public FullServicesContainerImpl( StorageService storageService, MonitorService monitorService, + ConnectionProvider defaultConnProvider, TelemetryFactory telemetryFactory) { this.storageService = storageService; this.monitorService = monitorService; + this.defaultConnProvider = defaultConnProvider; this.telemetryFactory = telemetryFactory; } @@ -67,6 +72,11 @@ public MonitorService getMonitorService() { return this.monitorService; } + @Override + public ConnectionProvider getDefaultConnectionProvider() { + return this.defaultConnProvider; + } + @Override public TelemetryFactory getTelemetryFactory() { return this.telemetryFactory; diff --git a/wrapper/src/main/java/software/amazon/jdbc/util/PropertyUtils.java b/wrapper/src/main/java/software/amazon/jdbc/util/PropertyUtils.java index ce2f66fad..632aaac6c 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/util/PropertyUtils.java +++ b/wrapper/src/main/java/software/amazon/jdbc/util/PropertyUtils.java @@ -28,7 +28,6 @@ import java.util.Set; import java.util.logging.Logger; import org.checkerframework.checker.nullness.qual.NonNull; -import software.amazon.awssdk.services.rds.endpoints.internal.Value.Bool; import software.amazon.jdbc.AwsWrapperProperty; import software.amazon.jdbc.PropertyDefinition; diff --git a/wrapper/src/main/java/software/amazon/jdbc/util/ServiceUtility.java b/wrapper/src/main/java/software/amazon/jdbc/util/ServiceUtility.java new file mode 100644 index 000000000..a47d434b6 --- /dev/null +++ b/wrapper/src/main/java/software/amazon/jdbc/util/ServiceUtility.java @@ -0,0 +1,79 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package software.amazon.jdbc.util; + +import java.sql.SQLException; +import java.util.Properties; +import java.util.concurrent.locks.ReentrantLock; +import software.amazon.jdbc.ConnectionPluginManager; +import software.amazon.jdbc.ConnectionProvider; +import software.amazon.jdbc.PartialPluginService; +import software.amazon.jdbc.util.connection.ConnectConfig; +import software.amazon.jdbc.util.monitoring.MonitorService; +import software.amazon.jdbc.util.storage.StorageService; +import software.amazon.jdbc.util.telemetry.TelemetryFactory; + +public class ServiceUtility { + private static volatile ServiceUtility instance; + private static final ReentrantLock initLock = new ReentrantLock(); + + private ServiceUtility() { + if (instance != null) { + throw new IllegalStateException("ServiceContainerUtility singleton instance already exists."); + } + } + + public static ServiceUtility getInstance() { + if (instance != null) { + return instance; + } + + initLock.lock(); + try { + if (instance == null) { + instance = new ServiceUtility(); + } + } finally { + initLock.unlock(); + } + + return instance; + } + + public FullServicesContainer createServiceContainer( + StorageService storageService, + MonitorService monitorService, + ConnectionProvider connectionProvider, + TelemetryFactory telemetryFactory, + ConnectConfig connectConfig) throws SQLException { + FullServicesContainer servicesContainer = + new FullServicesContainerImpl(storageService, monitorService, connectionProvider, telemetryFactory); + ConnectionPluginManager pluginManager = new ConnectionPluginManager( + connectionProvider, null, null, telemetryFactory); + servicesContainer.setConnectionPluginManager(pluginManager); + + PartialPluginService partialPluginService = new PartialPluginService(servicesContainer, connectConfig); + + servicesContainer.setHostListProviderService(partialPluginService); + servicesContainer.setPluginService(partialPluginService); + servicesContainer.setPluginManagerService(partialPluginService); + + Properties propsCopy = PropertyUtils.copyProperties(connectConfig.getProps()); + pluginManager.init(servicesContainer, propsCopy, partialPluginService, null); + return servicesContainer; + } +} diff --git a/wrapper/src/main/java/software/amazon/jdbc/util/connection/ConnectConfig.java b/wrapper/src/main/java/software/amazon/jdbc/util/connection/ConnectConfig.java new file mode 100644 index 000000000..f8c7eb439 --- /dev/null +++ b/wrapper/src/main/java/software/amazon/jdbc/util/connection/ConnectConfig.java @@ -0,0 +1,67 @@ +/* + * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package software.amazon.jdbc.util.connection; + +import java.util.Properties; +import software.amazon.jdbc.dialect.Dialect; +import software.amazon.jdbc.targetdriverdialect.TargetDriverDialect; +import software.amazon.jdbc.util.ConnectionUrlParser; + +public class ConnectConfig { + protected static final ConnectionUrlParser connectionUrlParser = new ConnectionUrlParser(); + protected final String initialConnectionString; + protected final String protocol; + protected final TargetDriverDialect driverDialect; + protected final Properties props; + protected Dialect dbDialect; + + public ConnectConfig(String initialConnectionString, TargetDriverDialect driverDialect, Properties props) { + this(initialConnectionString, connectionUrlParser.getProtocol(initialConnectionString), driverDialect, props); + } + + public ConnectConfig( + String initialConnectionString, String protocol, TargetDriverDialect driverDialect, Properties props) { + this.initialConnectionString = initialConnectionString; + this.protocol = protocol; + this.driverDialect = driverDialect; + this.props = props; + } + + public String getInitialConnectionString() { + return this.initialConnectionString; + } + + public String getProtocol() { + return this.protocol; + } + + public TargetDriverDialect getDriverDialect() { + return this.driverDialect; + } + + public Properties getProps() { + return this.props; + } + + public Dialect getDbDialect() { + return this.dbDialect; + } + + public void setDbDialect(Dialect dbDialect) { + this.dbDialect = dbDialect; + } +} diff --git a/wrapper/src/main/java/software/amazon/jdbc/util/connection/ConnectionService.java b/wrapper/src/main/java/software/amazon/jdbc/util/connection/ConnectionService.java index 5a6f4fcff..e0748bc72 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/util/connection/ConnectionService.java +++ b/wrapper/src/main/java/software/amazon/jdbc/util/connection/ConnectionService.java @@ -21,7 +21,16 @@ import java.util.Properties; import software.amazon.jdbc.HostSpec; import software.amazon.jdbc.PluginService; +import software.amazon.jdbc.util.FullServicesContainer; +/** + * A service used to open new connections for internal driver use. + * + * @deprecated This interface is deprecated and will be removed in a future version. Use + * {@link software.amazon.jdbc.util.ServiceUtility#createServiceContainer} followed by + * {@link PluginService#forceConnect} instead. + */ +@Deprecated public interface ConnectionService { /** * Creates an auxiliary connection. Auxiliary connections are driver-internal connections that accomplish various @@ -31,8 +40,19 @@ public interface ConnectionService { * @param props the properties for the auxiliary connection. * @return a new connection to the given host using the given props. * @throws SQLException if an error occurs while opening the connection. + * @deprecated Use {@link software.amazon.jdbc.util.ServiceUtility#createServiceContainer} followed by + * {@link PluginService#forceConnect} instead. */ + @Deprecated Connection open(HostSpec hostSpec, Properties props) throws SQLException; + /** + * Get the {@link PluginService} associated with this {@link ConnectionService}. + * + * @return the {@link PluginService} associated with this {@link ConnectionService} + * @deprecated Use {@link software.amazon.jdbc.util.ServiceUtility#createServiceContainer} followed by + * {@link FullServicesContainer#getPluginService()} instead. + */ + @Deprecated PluginService getPluginService(); } diff --git a/wrapper/src/main/java/software/amazon/jdbc/util/connection/ConnectionServiceImpl.java b/wrapper/src/main/java/software/amazon/jdbc/util/connection/ConnectionServiceImpl.java index 0e506a112..40fca65ff 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/util/connection/ConnectionServiceImpl.java +++ b/wrapper/src/main/java/software/amazon/jdbc/util/connection/ConnectionServiceImpl.java @@ -24,59 +24,65 @@ import software.amazon.jdbc.HostSpec; import software.amazon.jdbc.PartialPluginService; import software.amazon.jdbc.PluginService; -import software.amazon.jdbc.dialect.Dialect; -import software.amazon.jdbc.targetdriverdialect.TargetDriverDialect; import software.amazon.jdbc.util.FullServicesContainer; import software.amazon.jdbc.util.FullServicesContainerImpl; import software.amazon.jdbc.util.monitoring.MonitorService; import software.amazon.jdbc.util.storage.StorageService; import software.amazon.jdbc.util.telemetry.TelemetryFactory; +/** + * A service used to open new connections for internal driver use. + * + * @deprecated This class is deprecated and will be removed in a future version. Use + * {@link software.amazon.jdbc.util.ServiceUtility#createServiceContainer} followed by + * {@link PluginService#forceConnect} instead. + */ +@Deprecated public class ConnectionServiceImpl implements ConnectionService { - protected final String targetDriverProtocol; + protected final ConnectConfig connectConfig; protected final ConnectionPluginManager pluginManager; protected final PluginService pluginService; + /** + * Constructs a {@link ConnectionServiceImpl} instance. + * + * @deprecated Use {@link software.amazon.jdbc.util.ServiceUtility#createServiceContainer} instead. + */ + @Deprecated public ConnectionServiceImpl( StorageService storageService, MonitorService monitorService, TelemetryFactory telemetryFactory, ConnectionProvider connectionProvider, - String originalUrl, - String targetDriverProtocol, - TargetDriverDialect driverDialect, - Dialect dbDialect, - Properties props) throws SQLException { - this.targetDriverProtocol = targetDriverProtocol; + ConnectConfig connectConfig) throws SQLException { + this.connectConfig = connectConfig; - FullServicesContainer - servicesContainer = new FullServicesContainerImpl(storageService, monitorService, telemetryFactory); + FullServicesContainer servicesContainer = + new FullServicesContainerImpl(storageService, monitorService, connectionProvider, telemetryFactory); this.pluginManager = new ConnectionPluginManager( connectionProvider, null, null, telemetryFactory); servicesContainer.setConnectionPluginManager(this.pluginManager); + PartialPluginService partialPluginService = new PartialPluginService(servicesContainer, this.connectConfig); - PartialPluginService partialPluginService = new PartialPluginService( - servicesContainer, - props, - originalUrl, - this.targetDriverProtocol, - driverDialect, - dbDialect - ); + servicesContainer.setHostListProviderService(partialPluginService); + servicesContainer.setPluginService(partialPluginService); + servicesContainer.setPluginManagerService(partialPluginService); this.pluginService = partialPluginService; - this.pluginManager.init(servicesContainer, props, partialPluginService, null); + this.pluginManager.init(servicesContainer, this.connectConfig.getProps(), partialPluginService, null); } @Override + @Deprecated public Connection open(HostSpec hostSpec, Properties props) throws SQLException { - return this.pluginManager.forceConnect(this.targetDriverProtocol, hostSpec, props, true, null); + return this.pluginManager.forceConnect(this.connectConfig, hostSpec, true, null); } @Override + @Deprecated public PluginService getPluginService() { return this.pluginService; } diff --git a/wrapper/src/main/java/software/amazon/jdbc/util/monitoring/Monitor.java b/wrapper/src/main/java/software/amazon/jdbc/util/monitoring/Monitor.java index d4d89dc4c..fbdd55063 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/util/monitoring/Monitor.java +++ b/wrapper/src/main/java/software/amazon/jdbc/util/monitoring/Monitor.java @@ -27,7 +27,7 @@ public interface Monitor { * submitted during the call to {@link #start()}. Additionally, the monitoring loop should regularly update the last * activity timestamp so that the {@link MonitorService} can detect whether the monitor is stuck or not. */ - void monitor(); + void monitor() throws Exception; /** * Stops the monitoring tasks for this monitor and closes all resources. diff --git a/wrapper/src/main/java/software/amazon/jdbc/util/monitoring/MonitorInitializer.java b/wrapper/src/main/java/software/amazon/jdbc/util/monitoring/MonitorInitializer.java index c4f13e6f9..e1cb59a95 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/util/monitoring/MonitorInitializer.java +++ b/wrapper/src/main/java/software/amazon/jdbc/util/monitoring/MonitorInitializer.java @@ -16,10 +16,9 @@ package software.amazon.jdbc.util.monitoring; -import software.amazon.jdbc.PluginService; -import software.amazon.jdbc.util.connection.ConnectionService; +import software.amazon.jdbc.util.FullServicesContainer; +@FunctionalInterface public interface MonitorInitializer { - - Monitor createMonitor(ConnectionService connectionService, PluginService pluginService); + Monitor createMonitor(FullServicesContainer servicesContainer); } diff --git a/wrapper/src/main/java/software/amazon/jdbc/util/monitoring/MonitorService.java b/wrapper/src/main/java/software/amazon/jdbc/util/monitoring/MonitorService.java index 6360d8acd..abce3f9a9 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/util/monitoring/MonitorService.java +++ b/wrapper/src/main/java/software/amazon/jdbc/util/monitoring/MonitorService.java @@ -17,12 +17,10 @@ package software.amazon.jdbc.util.monitoring; import java.sql.SQLException; -import java.util.Properties; import java.util.Set; import org.checkerframework.checker.nullness.qual.Nullable; import software.amazon.jdbc.ConnectionProvider; -import software.amazon.jdbc.dialect.Dialect; -import software.amazon.jdbc.targetdriverdialect.TargetDriverDialect; +import software.amazon.jdbc.util.connection.ConnectConfig; import software.amazon.jdbc.util.storage.StorageService; import software.amazon.jdbc.util.telemetry.TelemetryFactory; @@ -61,11 +59,7 @@ void registerMonitorTypeIfAbsent( * @param telemetryFactory the telemetry factory for creating telemetry data. * @param defaultConnectionProvider the connection provider to use to create new connections if the monitor * requires it. - * @param originalUrl the URL of the original database connection. - * @param driverProtocol the protocol for the underlying target driver. - * @param driverDialect the target driver dialect. - * @param dbDialect the database dialect. - * @param originalProps the properties of the original database connection. + * @param connectConfig the connection info for the original connection. * @param initializer an initializer function to use to create the monitor if it does not already exist. * @param the type of the monitor. * @return the new or existing monitor. @@ -77,11 +71,7 @@ T runIfAbsent( StorageService storageService, TelemetryFactory telemetryFactory, ConnectionProvider defaultConnectionProvider, - String originalUrl, - String driverProtocol, - TargetDriverDialect driverDialect, - Dialect dbDialect, - Properties originalProps, + ConnectConfig connectConfig, MonitorInitializer initializer) throws SQLException; /** diff --git a/wrapper/src/main/java/software/amazon/jdbc/util/monitoring/MonitorServiceImpl.java b/wrapper/src/main/java/software/amazon/jdbc/util/monitoring/MonitorServiceImpl.java index f9f784208..265c7b5a9 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/util/monitoring/MonitorServiceImpl.java +++ b/wrapper/src/main/java/software/amazon/jdbc/util/monitoring/MonitorServiceImpl.java @@ -23,7 +23,6 @@ import java.util.HashSet; import java.util.List; import java.util.Map; -import java.util.Properties; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ScheduledExecutorService; @@ -33,17 +32,15 @@ import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; import software.amazon.jdbc.ConnectionProvider; -import software.amazon.jdbc.dialect.Dialect; import software.amazon.jdbc.hostlistprovider.Topology; import software.amazon.jdbc.hostlistprovider.monitoring.ClusterTopologyMonitorImpl; import software.amazon.jdbc.hostlistprovider.monitoring.MultiAzClusterTopologyMonitorImpl; import software.amazon.jdbc.plugin.strategy.fastestresponse.NodeResponseTimeMonitor; -import software.amazon.jdbc.targetdriverdialect.TargetDriverDialect; import software.amazon.jdbc.util.ExecutorFactory; +import software.amazon.jdbc.util.FullServicesContainer; import software.amazon.jdbc.util.Messages; -import software.amazon.jdbc.util.PropertyUtils; -import software.amazon.jdbc.util.connection.ConnectionService; -import software.amazon.jdbc.util.connection.ConnectionServiceImpl; +import software.amazon.jdbc.util.ServiceUtility; +import software.amazon.jdbc.util.connection.ConnectConfig; import software.amazon.jdbc.util.events.DataAccessEvent; import software.amazon.jdbc.util.events.Event; import software.amazon.jdbc.util.events.EventPublisher; @@ -182,11 +179,7 @@ public T runIfAbsent( StorageService storageService, TelemetryFactory telemetryFactory, ConnectionProvider defaultConnectionProvider, - String originalUrl, - String driverProtocol, - TargetDriverDialect driverDialect, - Dialect dbDialect, - Properties originalProps, + ConnectConfig connectConfig, MonitorInitializer initializer) throws SQLException { CacheContainer cacheContainer = monitorCaches.get(monitorClass); if (cacheContainer == null) { @@ -204,20 +197,12 @@ public T runIfAbsent( final List exceptionList = new ArrayList<>(1); MonitorItem monitorItem = cacheContainer.getCache().computeIfAbsent(key, k -> { try { - final ConnectionService connectionService = - getConnectionService( - storageService, - telemetryFactory, - defaultConnectionProvider, - originalUrl, - driverProtocol, - driverDialect, - dbDialect, - originalProps); - final MonitorItem monitorItemInner = new MonitorItem(() -> initializer.createMonitor( - connectionService, - connectionService.getPluginService()) - ); + final FullServicesContainer servicesContainer = getNewServicesContainer( + storageService, + defaultConnectionProvider, + telemetryFactory, + connectConfig); + final MonitorItem monitorItemInner = new MonitorItem(() -> initializer.createMonitor(servicesContainer)); monitorItemInner.getMonitor().start(); return monitorItemInner; } catch (SQLException e) { @@ -239,26 +224,18 @@ public T runIfAbsent( Messages.get("MonitorServiceImpl.unexpectedMonitorClass", new Object[] {monitorClass, monitor})); } - protected ConnectionService getConnectionService( + protected FullServicesContainer getNewServicesContainer( StorageService storageService, + ConnectionProvider connectionProvider, TelemetryFactory telemetryFactory, - ConnectionProvider defaultConnectionProvider, - String originalUrl, - String driverProtocol, - TargetDriverDialect driverDialect, - Dialect dbDialect, - Properties originalProps) throws SQLException { - final Properties propsCopy = PropertyUtils.copyProperties(originalProps); - return new ConnectionServiceImpl( + ConnectConfig connectConfig) throws SQLException { + return ServiceUtility.getInstance().createServiceContainer( storageService, this, + connectionProvider, telemetryFactory, - defaultConnectionProvider, - originalUrl, - driverProtocol, - driverDialect, - dbDialect, - propsCopy); + connectConfig + ); } @Override diff --git a/wrapper/src/main/java/software/amazon/jdbc/util/storage/SlidingExpirationCache.java b/wrapper/src/main/java/software/amazon/jdbc/util/storage/SlidingExpirationCache.java index 7f670866e..604b603f2 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/util/storage/SlidingExpirationCache.java +++ b/wrapper/src/main/java/software/amazon/jdbc/util/storage/SlidingExpirationCache.java @@ -20,7 +20,6 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.Objects; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicLong; diff --git a/wrapper/src/main/java/software/amazon/jdbc/wrapper/ConnectionWrapper.java b/wrapper/src/main/java/software/amazon/jdbc/wrapper/ConnectionWrapper.java index dd99e0fee..40d7776f9 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/wrapper/ConnectionWrapper.java +++ b/wrapper/src/main/java/software/amazon/jdbc/wrapper/ConnectionWrapper.java @@ -51,14 +51,13 @@ import software.amazon.jdbc.dialect.HostListProviderSupplier; import software.amazon.jdbc.profile.ConfigurationProfile; import software.amazon.jdbc.targetdriverdialect.TargetDriverDialect; -import software.amazon.jdbc.util.ConnectionUrlParser; import software.amazon.jdbc.util.FullServicesContainer; import software.amazon.jdbc.util.FullServicesContainerImpl; import software.amazon.jdbc.util.Messages; import software.amazon.jdbc.util.SqlState; import software.amazon.jdbc.util.StringUtils; import software.amazon.jdbc.util.WrapperUtils; -import software.amazon.jdbc.util.connection.ConnectionService; +import software.amazon.jdbc.util.connection.ConnectConfig; import software.amazon.jdbc.util.monitoring.MonitorService; import software.amazon.jdbc.util.storage.StorageService; import software.amazon.jdbc.util.telemetry.TelemetryFactory; @@ -67,20 +66,17 @@ public class ConnectionWrapper implements Connection, CanReleaseResources { private static final Logger LOGGER = Logger.getLogger(ConnectionWrapper.class.getName()); + protected ConnectConfig connectConfig; protected ConnectionPluginManager pluginManager; protected TelemetryFactory telemetryFactory; protected PluginService pluginService; protected HostListProviderService hostListProviderService; protected PluginManagerService pluginManagerService; - protected String targetDriverProtocol; - protected String originalUrl; protected @Nullable ConfigurationProfile configurationProfile; protected @Nullable Throwable openConnectionStacktrace; - protected final ConnectionUrlParser connectionUrlParser = new ConnectionUrlParser(); - public ConnectionWrapper( @NonNull final FullServicesContainer servicesContainer, @NonNull final Properties props, @@ -95,8 +91,7 @@ public ConnectionWrapper( throw new IllegalArgumentException("url"); } - this.originalUrl = url; - this.targetDriverProtocol = connectionUrlParser.getProtocol(url); + this.connectConfig = new ConnectConfig(url, driverDialect, props); this.configurationProfile = configurationProfile; final ConnectionPluginManager pluginManager = @@ -106,18 +101,14 @@ public ConnectionWrapper( this, servicesContainer.getTelemetryFactory()); servicesContainer.setConnectionPluginManager(pluginManager); - final PluginServiceImpl pluginService = new PluginServiceImpl( - servicesContainer, - props, - url, - this.targetDriverProtocol, - driverDialect, - this.configurationProfile); + + final PluginServiceImpl pluginService = + new PluginServiceImpl(servicesContainer, this.connectConfig, this.configurationProfile); servicesContainer.setHostListProviderService(pluginService); servicesContainer.setPluginService(pluginService); servicesContainer.setPluginManagerService(pluginService); - init(props, servicesContainer, defaultConnectionProvider, driverDialect); + init(props, servicesContainer); if (PropertyDefinition.LOG_UNCLOSED_CONNECTIONS.getBoolean(props)) { this.openConnectionStacktrace = new Throwable(Messages.get("ConnectionWrapper.unclosedConnectionInstantiated")); @@ -136,8 +127,7 @@ protected ConnectionWrapper( @NonNull final HostListProviderService hostListProviderService, @NonNull final PluginManagerService pluginManagerService, @NonNull final StorageService storageService, - @NonNull final MonitorService monitorService, - @NonNull final ConnectionService connectionService) + @NonNull final MonitorService monitorService) throws SQLException { if (StringUtils.isNullOrEmpty(url)) { @@ -147,6 +137,7 @@ protected ConnectionWrapper( FullServicesContainer servicesContainer = new FullServicesContainerImpl( storageService, monitorService, + defaultConnectionProvider, telemetryFactory, connectionPluginManager, hostListProviderService, @@ -154,13 +145,10 @@ protected ConnectionWrapper( pluginManagerService ); - init(props, servicesContainer, defaultConnectionProvider, driverDialect); + init(props, servicesContainer); } - protected void init(final Properties props, - final FullServicesContainer servicesContainer, - final ConnectionProvider defaultConnectionProvider, - final TargetDriverDialect driverDialect) throws SQLException { + protected void init(final Properties props, final FullServicesContainer servicesContainer) throws SQLException { this.pluginManager = servicesContainer.getConnectionPluginManager(); this.telemetryFactory = servicesContainer.getTelemetryFactory(); this.pluginService = servicesContainer.getPluginService(); @@ -171,24 +159,15 @@ protected void init(final Properties props, final HostListProviderSupplier supplier = this.pluginService.getDialect().getHostListProvider(); if (supplier != null) { - final HostListProvider provider = supplier.getProvider(props, this.originalUrl, servicesContainer); + final HostListProvider provider = supplier.getProvider(this.connectConfig, servicesContainer); hostListProviderService.setHostListProvider(provider); } - this.pluginManager.initHostProvider( - this.targetDriverProtocol, this.originalUrl, props, this.hostListProviderService); - + this.pluginManager.initHostProvider(this.connectConfig, this.hostListProviderService); this.pluginService.refreshHostList(); - if (this.pluginService.getCurrentConnection() == null) { - final Connection conn = - this.pluginManager.connect( - this.targetDriverProtocol, - this.pluginService.getInitialConnectionHostSpec(), - props, - true, - null); - + final Connection conn = this.pluginManager.connect( + this.connectConfig, this.pluginService.getInitialConnectionHostSpec(), true, null); if (conn == null) { throw new SQLException(Messages.get("ConnectionWrapper.connectionNotOpen"), SqlState.UNKNOWN_STATE.getState()); } diff --git a/wrapper/src/test/java/integration/container/aurora/TestAuroraHostListProvider.java b/wrapper/src/test/java/integration/container/aurora/TestAuroraHostListProvider.java index c35f6b0f8..f695ff43f 100644 --- a/wrapper/src/test/java/integration/container/aurora/TestAuroraHostListProvider.java +++ b/wrapper/src/test/java/integration/container/aurora/TestAuroraHostListProvider.java @@ -16,15 +16,15 @@ package integration.container.aurora; -import java.util.Properties; import software.amazon.jdbc.hostlistprovider.AuroraHostListProvider; import software.amazon.jdbc.util.FullServicesContainer; +import software.amazon.jdbc.util.connection.ConnectConfig; public class TestAuroraHostListProvider extends AuroraHostListProvider { public TestAuroraHostListProvider( - FullServicesContainer servicesContainer, Properties properties, String originalUrl) { - super(properties, originalUrl, servicesContainer, "", "", ""); + ConnectConfig connectConfig, FullServicesContainer servicesContainer) { + super(connectConfig, servicesContainer, "", "", ""); } public static void clearCache() { diff --git a/wrapper/src/test/java/integration/container/aurora/TestPluginServiceImpl.java b/wrapper/src/test/java/integration/container/aurora/TestPluginServiceImpl.java index b356eb391..50d108610 100644 --- a/wrapper/src/test/java/integration/container/aurora/TestPluginServiceImpl.java +++ b/wrapper/src/test/java/integration/container/aurora/TestPluginServiceImpl.java @@ -17,23 +17,17 @@ package integration.container.aurora; import java.sql.SQLException; -import java.util.Properties; import org.checkerframework.checker.nullness.qual.NonNull; import software.amazon.jdbc.PluginServiceImpl; -import software.amazon.jdbc.targetdriverdialect.TargetDriverDialect; import software.amazon.jdbc.util.FullServicesContainer; +import software.amazon.jdbc.util.connection.ConnectConfig; public class TestPluginServiceImpl extends PluginServiceImpl { public TestPluginServiceImpl( - @NonNull FullServicesContainer servicesContainer, - @NonNull Properties props, - @NonNull String originalUrl, - String targetDriverProtocol, - @NonNull final TargetDriverDialect targetDriverDialect) + @NonNull FullServicesContainer servicesContainer, @NonNull ConnectConfig connectConfig) throws SQLException { - - super(servicesContainer, props, originalUrl, targetDriverProtocol, targetDriverDialect); + super(servicesContainer, connectConfig); } public static void clearHostAvailabilityCache() { diff --git a/wrapper/src/test/java/integration/container/tests/hibernate/HibernateTests.java b/wrapper/src/test/java/integration/container/tests/hibernate/HibernateTests.java index 01d263f6b..fd4e1eac9 100644 --- a/wrapper/src/test/java/integration/container/tests/hibernate/HibernateTests.java +++ b/wrapper/src/test/java/integration/container/tests/hibernate/HibernateTests.java @@ -20,7 +20,6 @@ import static org.junit.jupiter.api.Assertions.assertNotNull; import integration.DatabaseEngine; -import integration.DatabaseEngineDeployment; import integration.DriverHelper; import integration.TestEnvironmentFeatures; import integration.container.ConnectionStringHelper; diff --git a/wrapper/src/test/java/integration/host/TestEnvironment.java b/wrapper/src/test/java/integration/host/TestEnvironment.java index 424b741ea..ce639a152 100644 --- a/wrapper/src/test/java/integration/host/TestEnvironment.java +++ b/wrapper/src/test/java/integration/host/TestEnvironment.java @@ -50,7 +50,6 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; import java.util.logging.Logger; -import org.testcontainers.containers.BindMode; import org.testcontainers.containers.GenericContainer; import org.testcontainers.containers.Network; import org.testcontainers.containers.ToxiproxyContainer; diff --git a/wrapper/src/test/java/integration/util/ContainerHelper.java b/wrapper/src/test/java/integration/util/ContainerHelper.java index bc977dcda..6745badd8 100644 --- a/wrapper/src/test/java/integration/util/ContainerHelper.java +++ b/wrapper/src/test/java/integration/util/ContainerHelper.java @@ -42,7 +42,6 @@ import org.testcontainers.containers.ToxiproxyContainer; import org.testcontainers.containers.output.FrameConsumerResultCallback; import org.testcontainers.containers.output.OutputFrame; -import org.testcontainers.containers.startupcheck.StartupCheckStrategy; import org.testcontainers.containers.wait.strategy.LogMessageWaitStrategy; import org.testcontainers.containers.wait.strategy.Wait; import org.testcontainers.images.builder.ImageFromDockerfile; diff --git a/wrapper/src/test/java/software/amazon/jdbc/ConnectionPluginChainBuilderTests.java b/wrapper/src/test/java/software/amazon/jdbc/ConnectionPluginChainBuilderTests.java index 84efe5ba3..4352d0622 100644 --- a/wrapper/src/test/java/software/amazon/jdbc/ConnectionPluginChainBuilderTests.java +++ b/wrapper/src/test/java/software/amazon/jdbc/ConnectionPluginChainBuilderTests.java @@ -28,7 +28,6 @@ import java.util.HashSet; import java.util.List; import java.util.Properties; -import java.util.Set; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; diff --git a/wrapper/src/test/java/software/amazon/jdbc/ConnectionPluginManagerTests.java b/wrapper/src/test/java/software/amazon/jdbc/ConnectionPluginManagerTests.java index 355276ad3..8c1749b64 100644 --- a/wrapper/src/test/java/software/amazon/jdbc/ConnectionPluginManagerTests.java +++ b/wrapper/src/test/java/software/amazon/jdbc/ConnectionPluginManagerTests.java @@ -64,6 +64,7 @@ import software.amazon.jdbc.targetdriverdialect.TargetDriverDialect; import software.amazon.jdbc.util.FullServicesContainer; import software.amazon.jdbc.util.WrapperUtils; +import software.amazon.jdbc.util.connection.ConnectConfig; import software.amazon.jdbc.util.telemetry.TelemetryContext; import software.amazon.jdbc.util.telemetry.TelemetryFactory; import software.amazon.jdbc.wrapper.ConnectionWrapper; @@ -75,6 +76,7 @@ public class ConnectionPluginManagerTests { @Mock JdbcCallable mockSqlFunction; @Mock ConnectionProvider mockConnectionProvider; @Mock ConnectionWrapper mockConnectionWrapper; + @Mock ConnectConfig mockConnectConfig; @Mock TelemetryFactory mockTelemetryFactory; @Mock TelemetryContext mockTelemetryContext; @Mock FullServicesContainer mockServicesContainer; @@ -240,8 +242,8 @@ public void testConnect() throws Exception { new ConnectionPluginManager(mockConnectionProvider, null, testProperties, testPlugins, mockConnectionWrapper, mockTelemetryFactory); - final Connection conn = target.connect("any", - new HostSpecBuilder(new SimpleHostAvailabilityStrategy()).host("anyHost").build(), testProperties, + final Connection conn = target.connect(mockConnectConfig, + new HostSpecBuilder(new SimpleHostAvailabilityStrategy()).host("anyHost").build(), true, null); assertEquals(expectedConnection, conn); @@ -272,9 +274,11 @@ public void testConnectWithSkipPlugin() throws Exception { new ConnectionPluginManager(mockConnectionProvider, null, testProperties, testPlugins, mockConnectionWrapper, mockTelemetryFactory); - final Connection conn = target.connect("any", - new HostSpecBuilder(new SimpleHostAvailabilityStrategy()).host("anyHost").build(), testProperties, - true, pluginOne); + final Connection conn = target.connect( + mockConnectConfig, + new HostSpecBuilder(new SimpleHostAvailabilityStrategy()).host("anyHost").build(), + true, + pluginOne); assertEquals(expectedConnection, conn); assertEquals(2, calls.size()); @@ -303,8 +307,9 @@ public void testForceConnect() throws Exception { new ConnectionPluginManager(mockConnectionProvider, null, testProperties, testPlugins, mockConnectionWrapper, mockTelemetryFactory); - final Connection conn = target.forceConnect("any", - new HostSpecBuilder(new SimpleHostAvailabilityStrategy()).host("anyHost").build(), testProperties, + final Connection conn = target.forceConnect( + mockConnectConfig, + new HostSpecBuilder(new SimpleHostAvailabilityStrategy()).host("anyHost").build(), true, null); @@ -335,8 +340,11 @@ public void testConnectWithSQLExceptionBefore() { assertThrows( SQLException.class, - () -> target.connect("any", new HostSpecBuilder(new SimpleHostAvailabilityStrategy()).host("anyHost").build(), - testProperties, true, null)); + () -> target.connect( + mockConnectConfig, + new HostSpecBuilder(new SimpleHostAvailabilityStrategy()).host("anyHost").build(), + true, + null)); assertEquals(2, calls.size()); assertEquals("TestPluginOne:before connect", calls.get(0)); @@ -361,8 +369,11 @@ public void testConnectWithSQLExceptionAfter() { assertThrows( SQLException.class, - () -> target.connect("any", new HostSpecBuilder(new SimpleHostAvailabilityStrategy()).host("anyHost").build(), - testProperties, true, null)); + () -> target.connect( + mockConnectConfig, + new HostSpecBuilder(new SimpleHostAvailabilityStrategy()).host("anyHost").build(), + true, + null)); assertEquals(5, calls.size()); assertEquals("TestPluginOne:before connect", calls.get(0)); @@ -388,12 +399,13 @@ public void testConnectWithUnexpectedExceptionBefore() { new ConnectionPluginManager(mockConnectionProvider, null, testProperties, testPlugins, mockConnectionWrapper, mockTelemetryFactory); - final Exception ex = - assertThrows( - IllegalArgumentException.class, - () -> target.connect("any", - new HostSpecBuilder(new SimpleHostAvailabilityStrategy()).host("anyHost").build(), - testProperties, true, null)); + assertThrows( + IllegalArgumentException.class, + () -> target.connect( + mockConnectConfig, + new HostSpecBuilder(new SimpleHostAvailabilityStrategy()).host("anyHost").build(), + true, + null)); assertEquals(2, calls.size()); assertEquals("TestPluginOne:before connect", calls.get(0)); @@ -416,12 +428,13 @@ public void testConnectWithUnexpectedExceptionAfter() { new ConnectionPluginManager(mockConnectionProvider, null, testProperties, testPlugins, mockConnectionWrapper, mockTelemetryFactory); - final Exception ex = - assertThrows( - IllegalArgumentException.class, - () -> target.connect("any", - new HostSpecBuilder(new SimpleHostAvailabilityStrategy()).host("anyHost").build(), - testProperties, true, null)); + assertThrows( + IllegalArgumentException.class, + () -> target.connect( + mockConnectConfig, + new HostSpecBuilder(new SimpleHostAvailabilityStrategy()).host("anyHost").build(), + true, + null)); assertEquals(5, calls.size()); assertEquals("TestPluginOne:before connect", calls.get(0)); @@ -524,9 +537,8 @@ public void testForceConnectCachedJdbcCallForceConnect() throws Exception { null, testProperties, testPlugins, mockConnectionWrapper, mockTelemetryFactory)); Object result = target.forceConnect( - "any", + mockConnectConfig, testHostSpec, - testProperties, true, null); @@ -544,9 +556,8 @@ public void testForceConnectCachedJdbcCallForceConnect() throws Exception { calls.clear(); result = target.forceConnect( - "any", + mockConnectConfig, testHostSpec, - testProperties, true, null); @@ -667,7 +678,7 @@ public void testOverridingDefaultPluginsWithPluginCodes() throws SQLException { } @Test - public void testTwoConnectionsDoNotBlockOneAnother() throws Exception { + public void testTwoConnectionsDoNotBlockOneAnother() { final Properties testProperties = new Properties(); final ArrayList testPlugins = new ArrayList<>(); diff --git a/wrapper/src/test/java/software/amazon/jdbc/DialectDetectionTests.java b/wrapper/src/test/java/software/amazon/jdbc/DialectDetectionTests.java index 3b47f12bb..bd1a2d4d2 100644 --- a/wrapper/src/test/java/software/amazon/jdbc/DialectDetectionTests.java +++ b/wrapper/src/test/java/software/amazon/jdbc/DialectDetectionTests.java @@ -52,6 +52,7 @@ import software.amazon.jdbc.exceptions.ExceptionManager; import software.amazon.jdbc.targetdriverdialect.TargetDriverDialect; import software.amazon.jdbc.util.FullServicesContainer; +import software.amazon.jdbc.util.connection.ConnectConfig; import software.amazon.jdbc.util.storage.StorageService; public class DialectDetectionTests { @@ -61,18 +62,17 @@ public class DialectDetectionTests { private static final String MYSQL_PROTOCOL = "jdbc:mysql://"; private static final String PG_PROTOCOL = "jdbc:postgresql://"; private static final String MARIA_PROTOCOL = "jdbc:mariadb://"; - private final Properties props = new Properties(); private AutoCloseable closeable; @Mock private FullServicesContainer mockServicesContainer; @Mock private HostListProviderService mockHostListProviderService; @Mock private StorageService mockStorageService; + @Mock private TargetDriverDialect mockDriverDialect; @Mock private Connection mockConnection; @Mock private Statement mockStatement; @Mock private ResultSet mockSuccessResultSet; @Mock private ResultSet mockFailResultSet; @Mock private HostSpec mockHost; @Mock private ConnectionPluginManager mockPluginManager; - @Mock private TargetDriverDialect mockTargetDriverDialect; @Mock private ResultSetMetaData mockResultSetMetaData; @BeforeEach @@ -94,15 +94,17 @@ void cleanUp() throws Exception { } PluginServiceImpl getPluginService(String host, String protocol) throws SQLException { + return getPluginService( + new ConnectConfig(protocol + host, protocol, mockDriverDialect, new Properties())); + } + + PluginServiceImpl getPluginService(ConnectConfig connectConfig) throws SQLException { PluginServiceImpl pluginService = spy( new PluginServiceImpl( mockServicesContainer, new ExceptionManager(), - props, - protocol + host, - protocol, + connectConfig, null, - mockTargetDriverDialect, null, null)); @@ -113,8 +115,10 @@ PluginServiceImpl getPluginService(String host, String protocol) throws SQLExcep @ParameterizedTest @MethodSource("getInitialDialectArguments") public void testInitialDialectDetection(String protocol, String host, Object expectedDialect) throws SQLException { + final ConnectConfig connectConfig = + new ConnectConfig(protocol + host, protocol, mockDriverDialect, new Properties()); final DialectManager dialectManager = new DialectManager(this.getPluginService(host, protocol)); - final Dialect dialect = dialectManager.getDialect(protocol, host, new Properties()); + final Dialect dialect = dialectManager.getDialect(connectConfig); assertEquals(expectedDialect, dialect.getClass()); } @@ -138,7 +142,7 @@ void testUpdateDialectMysqlUnchanged() throws SQLException { final PluginServiceImpl target = getPluginService(LOCALHOST, MYSQL_PROTOCOL); target.setInitialConnectionHostSpec(mockHost); target.updateDialect(mockConnection); - assertEquals(MysqlDialect.class, target.dialect.getClass()); + assertEquals(MysqlDialect.class, target.getDialect().getClass()); } @Test @@ -154,7 +158,7 @@ void testUpdateDialectMysqlToRds() throws SQLException { final PluginServiceImpl target = getPluginService(LOCALHOST, MYSQL_PROTOCOL); target.setInitialConnectionHostSpec(mockHost); target.updateDialect(mockConnection); - assertEquals(RdsMysqlDialect.class, target.dialect.getClass()); + assertEquals(RdsMysqlDialect.class, target.getDialect().getClass()); } @Test @@ -168,7 +172,7 @@ void testUpdateDialectMysqlToTaz() throws SQLException { final PluginServiceImpl target = getPluginService(LOCALHOST, MYSQL_PROTOCOL); target.setInitialConnectionHostSpec(mockHost); target.updateDialect(mockConnection); - assertEquals(AuroraMysqlDialect.class, target.dialect.getClass()); + assertEquals(AuroraMysqlDialect.class, target.getDialect().getClass()); } @Test @@ -180,7 +184,7 @@ void testUpdateDialectMysqlToAurora() throws SQLException { when(mockServicesContainer.getPluginService()).thenReturn(target); target.setInitialConnectionHostSpec(mockHost); target.updateDialect(mockConnection); - assertEquals(AuroraMysqlDialect.class, target.dialect.getClass()); + assertEquals(AuroraMysqlDialect.class, target.getDialect().getClass()); } @Test @@ -189,7 +193,7 @@ void testUpdateDialectPgUnchanged() throws SQLException { final PluginServiceImpl target = getPluginService(LOCALHOST, PG_PROTOCOL); target.setInitialConnectionHostSpec(mockHost); target.updateDialect(mockConnection); - assertEquals(PgDialect.class, target.dialect.getClass()); + assertEquals(PgDialect.class, target.getDialect().getClass()); } @Test @@ -204,7 +208,7 @@ void testUpdateDialectPgToRds() throws SQLException { final PluginServiceImpl target = getPluginService(LOCALHOST, PG_PROTOCOL); target.setInitialConnectionHostSpec(mockHost); target.updateDialect(mockConnection); - assertEquals(RdsPgDialect.class, target.dialect.getClass()); + assertEquals(RdsPgDialect.class, target.getDialect().getClass()); } @Test @@ -219,7 +223,7 @@ void testUpdateDialectPgToTaz() throws SQLException { final PluginServiceImpl target = getPluginService(LOCALHOST, PG_PROTOCOL); target.setInitialConnectionHostSpec(mockHost); target.updateDialect(mockConnection); - assertEquals(RdsMultiAzDbClusterPgDialect.class, target.dialect.getClass()); + assertEquals(RdsMultiAzDbClusterPgDialect.class, target.getDialect().getClass()); } @Test @@ -234,7 +238,7 @@ void testUpdateDialectPgToAurora() throws SQLException { final PluginServiceImpl target = getPluginService(LOCALHOST, PG_PROTOCOL); target.setInitialConnectionHostSpec(mockHost); target.updateDialect(mockConnection); - assertEquals(AuroraPgDialect.class, target.dialect.getClass()); + assertEquals(AuroraPgDialect.class, target.getDialect().getClass()); } @Test @@ -243,7 +247,7 @@ void testUpdateDialectMariaUnchanged() throws SQLException { final PluginServiceImpl target = getPluginService(LOCALHOST, MARIA_PROTOCOL); target.setInitialConnectionHostSpec(mockHost); target.updateDialect(mockConnection); - assertEquals(MariaDbDialect.class, target.dialect.getClass()); + assertEquals(MariaDbDialect.class, target.getDialect().getClass()); } @Test @@ -259,7 +263,7 @@ void testUpdateDialectMariaToMysqlRds() throws SQLException { final PluginServiceImpl target = getPluginService(LOCALHOST, MARIA_PROTOCOL); target.setInitialConnectionHostSpec(mockHost); target.updateDialect(mockConnection); - assertEquals(RdsMysqlDialect.class, target.dialect.getClass()); + assertEquals(RdsMysqlDialect.class, target.getDialect().getClass()); } @Test @@ -272,7 +276,7 @@ void testUpdateDialectMariaToMysqlTaz() throws SQLException { final PluginServiceImpl target = getPluginService(LOCALHOST, MARIA_PROTOCOL); target.setInitialConnectionHostSpec(mockHost); target.updateDialect(mockConnection); - assertEquals(RdsMultiAzDbClusterMysqlDialect.class, target.dialect.getClass()); + assertEquals(RdsMultiAzDbClusterMysqlDialect.class, target.getDialect().getClass()); } @Test @@ -284,6 +288,6 @@ void testUpdateDialectMariaToMysqlAurora() throws SQLException { when(mockServicesContainer.getPluginService()).thenReturn(target); target.setInitialConnectionHostSpec(mockHost); target.updateDialect(mockConnection); - assertEquals(AuroraMysqlDialect.class, target.dialect.getClass()); + assertEquals(AuroraMysqlDialect.class, target.getDialect().getClass()); } } diff --git a/wrapper/src/test/java/software/amazon/jdbc/DialectTests.java b/wrapper/src/test/java/software/amazon/jdbc/DialectTests.java index 0caefc973..4170f8556 100644 --- a/wrapper/src/test/java/software/amazon/jdbc/DialectTests.java +++ b/wrapper/src/test/java/software/amazon/jdbc/DialectTests.java @@ -35,7 +35,6 @@ import org.mockito.MockitoAnnotations; import software.amazon.jdbc.dialect.AuroraMysqlDialect; import software.amazon.jdbc.dialect.AuroraPgDialect; -import software.amazon.jdbc.dialect.DialectManager; import software.amazon.jdbc.dialect.MariaDbDialect; import software.amazon.jdbc.dialect.MysqlDialect; import software.amazon.jdbc.dialect.PgDialect; diff --git a/wrapper/src/test/java/software/amazon/jdbc/HikariPooledConnectionProviderTest.java b/wrapper/src/test/java/software/amazon/jdbc/HikariPooledConnectionProviderTest.java index 6e5844ccf..1a7a739af 100644 --- a/wrapper/src/test/java/software/amazon/jdbc/HikariPooledConnectionProviderTest.java +++ b/wrapper/src/test/java/software/amazon/jdbc/HikariPooledConnectionProviderTest.java @@ -47,18 +47,20 @@ import org.mockito.MockitoAnnotations; import software.amazon.jdbc.dialect.Dialect; import software.amazon.jdbc.hostavailability.SimpleHostAvailabilityStrategy; -import software.amazon.jdbc.targetdriverdialect.ConnectInfo; +import software.amazon.jdbc.targetdriverdialect.ConnectParams; import software.amazon.jdbc.targetdriverdialect.TargetDriverDialect; import software.amazon.jdbc.util.Pair; +import software.amazon.jdbc.util.connection.ConnectConfig; import software.amazon.jdbc.util.storage.SlidingExpirationCache; class HikariPooledConnectionProviderTest { @Mock Connection mockConnection; + @Mock ConnectConfig mockConnectConfig; @Mock HikariDataSource mockDataSource; @Mock HostSpec mockHostSpec; @Mock HikariConfig mockConfig; - @Mock Dialect mockDialect; - @Mock TargetDriverDialect mockTargetDriverDialect; + @Mock Dialect mockDbDialect; + @Mock TargetDriverDialect mockDriverDialect; @Mock HikariDataSource dsWithNoConnections; @Mock HikariDataSource dsWith1Connection; @Mock HikariDataSource dsWith2Connections; @@ -115,6 +117,10 @@ void init() throws SQLException { when(mxBeanWith1Connection.getActiveConnections()).thenReturn(1); when(dsWith2Connections.getHikariPoolMXBean()).thenReturn(mxBeanWith2Connections); when(mxBeanWith2Connections.getActiveConnections()).thenReturn(2); + when(mockConnectConfig.getDriverDialect()).thenReturn(mockDriverDialect); + when(mockConnectConfig.getDbDialect()).thenReturn(mockDbDialect); + when(mockConnectConfig.getProps()).thenReturn(defaultProps); + when(mockConnectConfig.getProtocol()).thenReturn(protocol); } @AfterEach @@ -129,24 +135,21 @@ void tearDown() throws Exception { void testConnectWithDefaultMapping() throws SQLException { when(mockHostSpec.getUrl()).thenReturn("url"); final Set expectedUrls = new HashSet<>(Collections.singletonList("url")); - final Set expectedKeys = new HashSet<>( + final Set> expectedKeys = new HashSet<>( Collections.singletonList(Pair.create("url", user1))); provider = spy(new HikariPooledConnectionProvider((hostSpec, properties) -> mockConfig)); - doReturn(mockDataSource).when(provider).createHikariDataSource(any(), any(), any(), any()); - doReturn(new ConnectInfo("url", new Properties())) - .when(mockTargetDriverDialect).prepareConnectInfo(anyString(), any(), any()); + doReturn(mockDataSource).when(provider).createHikariDataSource(any(), any(), any()); + doReturn(new ConnectParams("url", new Properties())) + .when(mockDriverDialect).prepareConnectParams(anyString(), any(), any()); - Properties props = new Properties(); - props.setProperty(PropertyDefinition.USER.name, user1); - props.setProperty(PropertyDefinition.PASSWORD.name, password); - try (Connection conn = provider.connect(protocol, mockDialect, mockTargetDriverDialect, mockHostSpec, props)) { + try (Connection conn = provider.connect(mockConnectConfig, mockHostSpec)) { assertEquals(mockConnection, conn); assertEquals(1, provider.getHostCount()); final Set hosts = provider.getHosts(); assertEquals(expectedUrls, hosts); - final Set keys = provider.getKeys(); + final Set> keys = provider.getKeys(); assertEquals(expectedKeys, keys); } } @@ -154,22 +157,22 @@ void testConnectWithDefaultMapping() throws SQLException { @Test void testConnectWithCustomMapping() throws SQLException { when(mockHostSpec.getUrl()).thenReturn("url"); - final Set expectedKeys = new HashSet<>( + final Set> expectedKeys = new HashSet<>( Collections.singletonList(Pair.create("url", "url+someUniqueKey"))); provider = spy(new HikariPooledConnectionProvider( (hostSpec, properties) -> mockConfig, (hostSpec, properties) -> hostSpec.getUrl() + "+someUniqueKey")); - doReturn(mockDataSource).when(provider).createHikariDataSource(any(), any(), any(), any()); + doReturn(mockDataSource).when(provider).createHikariDataSource(any(), any(), any()); Properties props = new Properties(); props.setProperty(PropertyDefinition.USER.name, user1); props.setProperty(PropertyDefinition.PASSWORD.name, password); - try (Connection conn = provider.connect(protocol, mockDialect, mockTargetDriverDialect, mockHostSpec, props)) { + try (Connection conn = provider.connect(mockConnectConfig, mockHostSpec)) { assertEquals(mockConnection, conn); assertEquals(1, provider.getHostCount()); - final Set keys = provider.getKeys(); + final Set> keys = provider.getKeys(); assertEquals(expectedKeys, keys); } } @@ -180,12 +183,13 @@ public void testAcceptsUrl() { provider = new HikariPooledConnectionProvider((hostSpec, properties) -> mockConfig); assertTrue( - provider.acceptsUrl(protocol, - new HostSpecBuilder(new SimpleHostAvailabilityStrategy()).host(readerUrl2Connection).build(), - defaultProps)); + provider.acceptsUrl( + mockConnectConfig, + new HostSpecBuilder(new SimpleHostAvailabilityStrategy()).host(readerUrl2Connection).build())); assertFalse( - provider.acceptsUrl(protocol, - new HostSpecBuilder(new SimpleHostAvailabilityStrategy()).host(clusterUrl).build(), defaultProps)); + provider.acceptsUrl( + mockConnectConfig, + new HostSpecBuilder(new SimpleHostAvailabilityStrategy()).host(clusterUrl).build())); } @Test @@ -208,8 +212,8 @@ public void testLeastConnectionsStrategy() throws SQLException { assertEquals(readerUrl1Connection, selectedHost.getHost()); } - private SlidingExpirationCache getTestPoolMap() { - SlidingExpirationCache map = new SlidingExpirationCache<>(); + private SlidingExpirationCache, AutoCloseable> getTestPoolMap() { + SlidingExpirationCache, AutoCloseable> map = new SlidingExpirationCache<>(); map.computeIfAbsent(Pair.create(readerHost2Connection.getUrl(), user1), (key) -> dsWith1Connection, TimeUnit.MINUTES.toNanos(10)); map.computeIfAbsent(Pair.create(readerHost2Connection.getUrl(), user2), @@ -224,10 +228,10 @@ public void testConfigurePool() throws SQLException { provider = new HikariPooledConnectionProvider((hostSpec, properties) -> mockConfig); final String expectedJdbcUrl = protocol + readerHost1Connection.getUrl() + db + "?database=" + db; - doReturn(new ConnectInfo(protocol + readerHost1Connection.getUrl() + db, defaultProps)) - .when(mockTargetDriverDialect).prepareConnectInfo(anyString(), any(), any()); + doReturn(new ConnectParams(protocol + readerHost1Connection.getUrl() + db, defaultProps)) + .when(mockDriverDialect).prepareConnectParams(anyString(), any(), any()); - provider.configurePool(mockConfig, protocol, readerHost1Connection, defaultProps, mockTargetDriverDialect); + provider.configurePool(mockConfig, mockConnectConfig, readerHost1Connection, defaultProps); verify(mockConfig).setJdbcUrl(expectedJdbcUrl); verify(mockConfig).setUsername(user1); verify(mockConfig).setPassword(password); @@ -238,10 +242,10 @@ public void testConnectToDeletedInstance() throws SQLException { provider = spy(new HikariPooledConnectionProvider((hostSpec, properties) -> mockConfig)); doReturn(mockDataSource).when(provider) - .createHikariDataSource(eq(protocol), eq(readerHost1Connection), eq(defaultProps), eq(mockTargetDriverDialect)); + .createHikariDataSource(eq(mockConnectConfig), eq(readerHost1Connection), eq(defaultProps)); when(mockDataSource.getConnection()).thenThrow(SQLException.class); assertThrows(SQLException.class, - () -> provider.connect(protocol, mockDialect, mockTargetDriverDialect, readerHost1Connection, defaultProps)); + () -> provider.connect(mockConnectConfig, readerHost1Connection)); } } diff --git a/wrapper/src/test/java/software/amazon/jdbc/PluginServiceImplTests.java b/wrapper/src/test/java/software/amazon/jdbc/PluginServiceImplTests.java index 07a22941f..8d0bce63c 100644 --- a/wrapper/src/test/java/software/amazon/jdbc/PluginServiceImplTests.java +++ b/wrapper/src/test/java/software/amazon/jdbc/PluginServiceImplTests.java @@ -57,27 +57,20 @@ import org.mockito.MockitoAnnotations; import software.amazon.jdbc.dialect.AuroraPgDialect; import software.amazon.jdbc.dialect.Dialect; -import software.amazon.jdbc.dialect.DialectManager; import software.amazon.jdbc.dialect.MysqlDialect; -import software.amazon.jdbc.exceptions.ExceptionManager; import software.amazon.jdbc.hostavailability.HostAvailability; import software.amazon.jdbc.hostavailability.SimpleHostAvailabilityStrategy; -import software.amazon.jdbc.profile.ConfigurationProfile; -import software.amazon.jdbc.profile.ConfigurationProfileBuilder; -import software.amazon.jdbc.states.SessionStateService; -import software.amazon.jdbc.targetdriverdialect.TargetDriverDialect; import software.amazon.jdbc.util.FullServicesContainer; +import software.amazon.jdbc.util.connection.ConnectConfig; import software.amazon.jdbc.util.events.EventPublisher; import software.amazon.jdbc.util.storage.StorageService; import software.amazon.jdbc.util.storage.TestStorageServiceImpl; public class PluginServiceImplTests { - private static final Properties PROPERTIES = new Properties(); - private static final String URL = "url"; - private static final String DRIVER_PROTOCOL = "driverProtocol"; private StorageService storageService; private AutoCloseable closeable; + private Properties props = new Properties(); @Mock FullServicesContainer servicesContainer; @Mock EventPublisher mockEventPublisher; @@ -85,12 +78,9 @@ public class PluginServiceImplTests { @Mock Connection newConnection; @Mock Connection oldConnection; @Mock HostListProvider hostListProvider; - @Mock DialectManager dialectManager; - @Mock TargetDriverDialect mockTargetDriverDialect; + @Mock ConnectConfig mockConnectConfig; @Mock Statement statement; @Mock ResultSet resultSet; - ConfigurationProfile configurationProfile = ConfigurationProfileBuilder.get().withName("test").build(); - @Mock SessionStateService sessionStateService; @Captor ArgumentCaptor> argumentChanges; @Captor ArgumentCaptor>> argumentChangesMap; @@ -104,6 +94,9 @@ void setUp() throws SQLException { when(statement.executeQuery(any())).thenReturn(resultSet); when(servicesContainer.getConnectionPluginManager()).thenReturn(pluginManager); when(servicesContainer.getStorageService()).thenReturn(storageService); + when(mockConnectConfig.getProps()).thenReturn(props); + when(mockConnectConfig.getInitialConnectionString()).thenReturn("url"); + when(mockConnectConfig.getProtocol()).thenReturn("jdbc:postgresql://"); storageService = new TestStorageServiceImpl(mockEventPublisher); PluginServiceImpl.hostAvailabilityExpiringCache.clear(); } @@ -121,16 +114,7 @@ public void testOldConnectionNoSuggestion() throws SQLException { .thenReturn(EnumSet.of(OldConnectionSuggestedAction.NO_OPINION)); PluginServiceImpl target = - spy(new PluginServiceImpl( - servicesContainer, - new ExceptionManager(), - PROPERTIES, - URL, - DRIVER_PROTOCOL, - dialectManager, - mockTargetDriverDialect, - configurationProfile, - sessionStateService)); + spy(getPluginService()); target.currentConnection = oldConnection; target.currentHostSpec = new HostSpecBuilder(new SimpleHostAvailabilityStrategy()).host("old-host") .build(); @@ -144,22 +128,17 @@ public void testOldConnectionNoSuggestion() throws SQLException { verify(oldConnection, times(1)).close(); } + protected PluginServiceImpl getPluginService() throws SQLException { + return new PluginServiceImpl(servicesContainer, mockConnectConfig); + } + @Test public void testOldConnectionDisposeSuggestion() throws SQLException { when(pluginManager.notifyConnectionChanged(any(), any())) .thenReturn(EnumSet.of(OldConnectionSuggestedAction.DISPOSE)); PluginServiceImpl target = - spy(new PluginServiceImpl( - servicesContainer, - new ExceptionManager(), - PROPERTIES, - URL, - DRIVER_PROTOCOL, - dialectManager, - mockTargetDriverDialect, - configurationProfile, - sessionStateService)); + spy(getPluginService()); target.currentConnection = oldConnection; target.currentHostSpec = new HostSpecBuilder(new SimpleHostAvailabilityStrategy()).host("old-host") .build(); @@ -179,16 +158,7 @@ public void testOldConnectionPreserveSuggestion() throws SQLException { .thenReturn(EnumSet.of(OldConnectionSuggestedAction.PRESERVE)); PluginServiceImpl target = - spy(new PluginServiceImpl( - servicesContainer, - new ExceptionManager(), - PROPERTIES, - URL, - DRIVER_PROTOCOL, - dialectManager, - mockTargetDriverDialect, - configurationProfile, - sessionStateService)); + spy(getPluginService()); target.currentConnection = oldConnection; target.currentHostSpec = new HostSpecBuilder(new SimpleHostAvailabilityStrategy()).host("old-host") .build(); @@ -212,16 +182,7 @@ public void testOldConnectionMixedSuggestion() throws SQLException { OldConnectionSuggestedAction.DISPOSE)); PluginServiceImpl target = - spy(new PluginServiceImpl( - servicesContainer, - new ExceptionManager(), - PROPERTIES, - URL, - DRIVER_PROTOCOL, - dialectManager, - mockTargetDriverDialect, - configurationProfile, - sessionStateService)); + spy(getPluginService()); target.currentConnection = oldConnection; target.currentHostSpec = new HostSpecBuilder(new SimpleHostAvailabilityStrategy()).host("old-host") .build(); @@ -242,16 +203,7 @@ public void testChangesNewConnectionNewHostNewPortNewRoleNewAvailability() throw .thenReturn(EnumSet.of(OldConnectionSuggestedAction.NO_OPINION)); PluginServiceImpl target = - spy(new PluginServiceImpl( - servicesContainer, - new ExceptionManager(), - PROPERTIES, - URL, - DRIVER_PROTOCOL, - dialectManager, - mockTargetDriverDialect, - configurationProfile, - sessionStateService)); + spy(getPluginService()); target.currentConnection = oldConnection; target.currentHostSpec = new HostSpecBuilder(new SimpleHostAvailabilityStrategy()) .host("old-host").port(1000).role(HostRole.WRITER).availability(HostAvailability.AVAILABLE).build(); @@ -281,16 +233,7 @@ public void testChangesNewConnectionNewRoleNewAvailability() throws SQLException .thenReturn(EnumSet.of(OldConnectionSuggestedAction.NO_OPINION)); PluginServiceImpl target = - spy(new PluginServiceImpl( - servicesContainer, - new ExceptionManager(), - PROPERTIES, - URL, - DRIVER_PROTOCOL, - dialectManager, - mockTargetDriverDialect, - configurationProfile, - sessionStateService)); + spy(getPluginService()); target.currentConnection = oldConnection; target.currentHostSpec = new HostSpecBuilder(new SimpleHostAvailabilityStrategy()) @@ -320,16 +263,7 @@ public void testChangesNewConnection() throws SQLException { .thenReturn(EnumSet.of(OldConnectionSuggestedAction.NO_OPINION)); PluginServiceImpl target = - spy(new PluginServiceImpl( - servicesContainer, - new ExceptionManager(), - PROPERTIES, - URL, - DRIVER_PROTOCOL, - dialectManager, - mockTargetDriverDialect, - configurationProfile, - sessionStateService)); + spy(getPluginService()); target.currentConnection = oldConnection; target.currentHostSpec = new HostSpecBuilder(new SimpleHostAvailabilityStrategy()) @@ -359,16 +293,7 @@ public void testChangesNoChanges() throws SQLException { EnumSet.of(OldConnectionSuggestedAction.NO_OPINION)); PluginServiceImpl target = - spy(new PluginServiceImpl( - servicesContainer, - new ExceptionManager(), - PROPERTIES, - URL, - DRIVER_PROTOCOL, - dialectManager, - mockTargetDriverDialect, - configurationProfile, - sessionStateService)); + spy(getPluginService()); target.currentConnection = oldConnection; target.currentHostSpec = new HostSpecBuilder(new SimpleHostAvailabilityStrategy()) .host("old-host").port(1000).role(HostRole.READER).availability(HostAvailability.AVAILABLE).build(); @@ -389,17 +314,7 @@ public void testSetNodeListAdded() throws SQLException { when(hostListProvider.refresh()).thenReturn(Collections.singletonList( new HostSpecBuilder(new SimpleHostAvailabilityStrategy()).host("hostA").build())); - PluginServiceImpl target = spy( - new PluginServiceImpl( - servicesContainer, - new ExceptionManager(), - PROPERTIES, - URL, - DRIVER_PROTOCOL, - dialectManager, - mockTargetDriverDialect, - configurationProfile, - sessionStateService)); + PluginServiceImpl target = spy(getPluginService()); target.allHosts = new ArrayList<>(); target.hostListProvider = hostListProvider; @@ -423,17 +338,7 @@ public void testSetNodeListDeleted() throws SQLException { when(hostListProvider.refresh()).thenReturn(Collections.singletonList( new HostSpecBuilder(new SimpleHostAvailabilityStrategy()).host("hostB").build())); - PluginServiceImpl target = spy( - new PluginServiceImpl( - servicesContainer, - new ExceptionManager(), - PROPERTIES, - URL, - DRIVER_PROTOCOL, - dialectManager, - mockTargetDriverDialect, - configurationProfile, - sessionStateService)); + PluginServiceImpl target = spy(getPluginService()); target.allHosts = Arrays.asList( new HostSpecBuilder(new SimpleHostAvailabilityStrategy()).host("hostA").build(), new HostSpecBuilder(new SimpleHostAvailabilityStrategy()).host("hostB").build()); @@ -460,17 +365,7 @@ public void testSetNodeListChanged() throws SQLException { Collections.singletonList(new HostSpecBuilder(new SimpleHostAvailabilityStrategy()).host("hostA") .port(HostSpec.NO_PORT).role(HostRole.READER).build())); - PluginServiceImpl target = spy( - new PluginServiceImpl( - servicesContainer, - new ExceptionManager(), - PROPERTIES, - URL, - DRIVER_PROTOCOL, - dialectManager, - mockTargetDriverDialect, - configurationProfile, - sessionStateService)); + PluginServiceImpl target = spy(getPluginService()); target.allHosts = Collections.singletonList(new HostSpecBuilder(new SimpleHostAvailabilityStrategy()) .host("hostA").port(HostSpec.NO_PORT).role(HostRole.WRITER).build()); target.hostListProvider = hostListProvider; @@ -497,17 +392,7 @@ public void testSetNodeListNoChanges() throws SQLException { Collections.singletonList(new HostSpecBuilder(new SimpleHostAvailabilityStrategy()) .host("hostA").port(HostSpec.NO_PORT).role(HostRole.READER).build())); - PluginServiceImpl target = spy( - new PluginServiceImpl( - servicesContainer, - new ExceptionManager(), - PROPERTIES, - URL, - DRIVER_PROTOCOL, - dialectManager, - mockTargetDriverDialect, - configurationProfile, - sessionStateService)); + PluginServiceImpl target = spy(getPluginService()); target.allHosts = Collections.singletonList(new HostSpecBuilder(new SimpleHostAvailabilityStrategy()) .host("hostA").port(HostSpec.NO_PORT).role(HostRole.READER).build()); target.hostListProvider = hostListProvider; @@ -523,17 +408,7 @@ public void testSetNodeListNoChanges() throws SQLException { public void testNodeAvailabilityNotChanged() throws SQLException { doNothing().when(pluginManager).notifyNodeListChanged(argumentChangesMap.capture()); - PluginServiceImpl target = spy( - new PluginServiceImpl( - servicesContainer, - new ExceptionManager(), - PROPERTIES, - URL, - DRIVER_PROTOCOL, - dialectManager, - mockTargetDriverDialect, - configurationProfile, - sessionStateService)); + PluginServiceImpl target = spy(getPluginService()); target.allHosts = Collections.singletonList( new HostSpecBuilder(new SimpleHostAvailabilityStrategy()) .host("hostA").port(HostSpec.NO_PORT).role(HostRole.READER).availability(HostAvailability.AVAILABLE) @@ -552,17 +427,7 @@ public void testNodeAvailabilityNotChanged() throws SQLException { public void testNodeAvailabilityChanged_WentDown() throws SQLException { doNothing().when(pluginManager).notifyNodeListChanged(argumentChangesMap.capture()); - PluginServiceImpl target = spy( - new PluginServiceImpl( - servicesContainer, - new ExceptionManager(), - PROPERTIES, - URL, - DRIVER_PROTOCOL, - dialectManager, - mockTargetDriverDialect, - configurationProfile, - sessionStateService)); + PluginServiceImpl target = spy(getPluginService()); target.allHosts = Collections.singletonList( new HostSpecBuilder(new SimpleHostAvailabilityStrategy()) .host("hostA").port(HostSpec.NO_PORT).role(HostRole.READER).availability(HostAvailability.AVAILABLE) @@ -588,17 +453,7 @@ public void testNodeAvailabilityChanged_WentDown() throws SQLException { public void testNodeAvailabilityChanged_WentUp() throws SQLException { doNothing().when(pluginManager).notifyNodeListChanged(argumentChangesMap.capture()); - PluginServiceImpl target = spy( - new PluginServiceImpl( - servicesContainer, - new ExceptionManager(), - PROPERTIES, - URL, - DRIVER_PROTOCOL, - dialectManager, - mockTargetDriverDialect, - configurationProfile, - sessionStateService)); + PluginServiceImpl target = spy(getPluginService()); target.allHosts = Collections.singletonList( new HostSpecBuilder(new SimpleHostAvailabilityStrategy()) .host("hostA").port(HostSpec.NO_PORT).role(HostRole.READER).availability(HostAvailability.NOT_AVAILABLE) @@ -635,17 +490,7 @@ public void testNodeAvailabilityChanged_WentUp_ByAlias() throws SQLException { hostB.addAlias("ip-10-10-10-10"); hostB.addAlias("hostB.custom.domain.com"); - PluginServiceImpl target = spy( - new PluginServiceImpl( - servicesContainer, - new ExceptionManager(), - PROPERTIES, - URL, - DRIVER_PROTOCOL, - dialectManager, - mockTargetDriverDialect, - configurationProfile, - sessionStateService)); + PluginServiceImpl target = spy(getPluginService()); target.allHosts = Arrays.asList(hostA, hostB); @@ -671,7 +516,7 @@ public void testNodeAvailabilityChanged_WentUp_MultipleHostsByAlias() throws SQL final HostSpec hostA = new HostSpecBuilder(new SimpleHostAvailabilityStrategy()) .host("hostA").port(HostSpec.NO_PORT).role(HostRole.READER).availability(HostAvailability.NOT_AVAILABLE) - .build();; + .build(); hostA.addAlias("ip-10-10-10-10"); hostA.addAlias("hostA.custom.domain.com"); final HostSpec hostB = new HostSpecBuilder(new SimpleHostAvailabilityStrategy()) @@ -680,17 +525,7 @@ public void testNodeAvailabilityChanged_WentUp_MultipleHostsByAlias() throws SQL hostB.addAlias("ip-10-10-10-10"); hostB.addAlias("hostB.custom.domain.com"); - PluginServiceImpl target = spy( - new PluginServiceImpl( - servicesContainer, - new ExceptionManager(), - PROPERTIES, - URL, - DRIVER_PROTOCOL, - dialectManager, - mockTargetDriverDialect, - configurationProfile, - sessionStateService)); + PluginServiceImpl target = spy(getPluginService()); target.allHosts = Arrays.asList(hostA, hostB); @@ -758,17 +593,7 @@ void testRefreshHostList_withCachedHostAvailability() throws SQLException { when(hostListProvider.refresh()).thenReturn(newHostSpecs); when(hostListProvider.refresh(newConnection)).thenReturn(newHostSpecs2); - PluginServiceImpl target = spy( - new PluginServiceImpl( - servicesContainer, - new ExceptionManager(), - PROPERTIES, - URL, - DRIVER_PROTOCOL, - dialectManager, - mockTargetDriverDialect, - configurationProfile, - sessionStateService)); + PluginServiceImpl target = spy(getPluginService()); when(target.getHostListProvider()).thenReturn(hostListProvider); assertNotEquals(expectedHostSpecs, newHostSpecs); @@ -815,17 +640,7 @@ void testForceRefreshHostList_withCachedHostAvailability() throws SQLException { when(hostListProvider.forceRefresh()).thenReturn(newHostSpecs); when(hostListProvider.forceRefresh(newConnection)).thenReturn(newHostSpecs); - PluginServiceImpl target = spy( - new PluginServiceImpl( - servicesContainer, - new ExceptionManager(), - PROPERTIES, - URL, - DRIVER_PROTOCOL, - dialectManager, - mockTargetDriverDialect, - configurationProfile, - sessionStateService)); + PluginServiceImpl target = spy(getPluginService()); when(target.getHostListProvider()).thenReturn(hostListProvider); assertNotEquals(expectedHostSpecs, newHostSpecs); @@ -840,17 +655,7 @@ void testForceRefreshHostList_withCachedHostAvailability() throws SQLException { @Test void testIdentifyConnectionWithNoAliases() throws SQLException { - PluginServiceImpl target = spy( - new PluginServiceImpl( - servicesContainer, - new ExceptionManager(), - PROPERTIES, - URL, - DRIVER_PROTOCOL, - dialectManager, - mockTargetDriverDialect, - configurationProfile, - sessionStateService)); + PluginServiceImpl target = spy(getPluginService()); when(target.getHostListProvider()).thenReturn(hostListProvider); when(target.getDialect()).thenReturn(new MysqlDialect()); @@ -861,17 +666,7 @@ void testIdentifyConnectionWithNoAliases() throws SQLException { void testIdentifyConnectionWithAliases() throws SQLException { final HostSpec expected = new HostSpecBuilder(new SimpleHostAvailabilityStrategy()).host("test") .build(); - PluginServiceImpl target = spy( - new PluginServiceImpl( - servicesContainer, - new ExceptionManager(), - PROPERTIES, - URL, - DRIVER_PROTOCOL, - dialectManager, - mockTargetDriverDialect, - configurationProfile, - sessionStateService)); + PluginServiceImpl target = spy(getPluginService()); target.hostListProvider = hostListProvider; when(target.getHostListProvider()).thenReturn(hostListProvider); when(hostListProvider.identifyConnection(eq(newConnection))).thenReturn(expected); @@ -889,17 +684,7 @@ void testFillAliasesNonEmptyAliases() throws SQLException { .build(); oneAlias.addAlias(oneAlias.asAlias()); - PluginServiceImpl target = spy( - new PluginServiceImpl( - servicesContainer, - new ExceptionManager(), - PROPERTIES, - URL, - DRIVER_PROTOCOL, - dialectManager, - mockTargetDriverDialect, - configurationProfile, - sessionStateService)); + PluginServiceImpl target = spy(getPluginService()); assertEquals(1, oneAlias.getAliases().size()); target.fillAliases(newConnection, oneAlias); @@ -911,17 +696,7 @@ void testFillAliasesNonEmptyAliases() throws SQLException { @MethodSource("fillAliasesDialects") void testFillAliasesWithInstanceEndpoint(Dialect dialect, String[] expectedInstanceAliases) throws SQLException { final HostSpec empty = new HostSpecBuilder(new SimpleHostAvailabilityStrategy()).host("foo").build(); - PluginServiceImpl target = spy( - new PluginServiceImpl( - servicesContainer, - new ExceptionManager(), - PROPERTIES, - URL, - DRIVER_PROTOCOL, - dialectManager, - mockTargetDriverDialect, - configurationProfile, - sessionStateService)); + PluginServiceImpl target = spy(getPluginService()); target.hostListProvider = hostListProvider; when(target.getDialect()).thenReturn(dialect); when(resultSet.next()).thenReturn(true, false); // Result set contains 1 row. diff --git a/wrapper/src/test/java/software/amazon/jdbc/authentication/AwsCredentialsManagerTest.java b/wrapper/src/test/java/software/amazon/jdbc/authentication/AwsCredentialsManagerTest.java index 6028f5706..56d24e076 100644 --- a/wrapper/src/test/java/software/amazon/jdbc/authentication/AwsCredentialsManagerTest.java +++ b/wrapper/src/test/java/software/amazon/jdbc/authentication/AwsCredentialsManagerTest.java @@ -17,7 +17,6 @@ package software.amazon.jdbc.authentication; import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.when; diff --git a/wrapper/src/test/java/software/amazon/jdbc/hostlistprovider/RdsHostListProviderTest.java b/wrapper/src/test/java/software/amazon/jdbc/hostlistprovider/RdsHostListProviderTest.java index 797d151be..ac10855cf 100644 --- a/wrapper/src/test/java/software/amazon/jdbc/hostlistprovider/RdsHostListProviderTest.java +++ b/wrapper/src/test/java/software/amazon/jdbc/hostlistprovider/RdsHostListProviderTest.java @@ -64,7 +64,9 @@ import software.amazon.jdbc.hostavailability.HostAvailability; import software.amazon.jdbc.hostavailability.SimpleHostAvailabilityStrategy; import software.amazon.jdbc.hostlistprovider.RdsHostListProvider.FetchTopologyResult; +import software.amazon.jdbc.targetdriverdialect.TargetDriverDialect; import software.amazon.jdbc.util.FullServicesContainer; +import software.amazon.jdbc.util.connection.ConnectConfig; import software.amazon.jdbc.util.events.EventPublisher; import software.amazon.jdbc.util.storage.StorageService; import software.amazon.jdbc.util.storage.TestStorageServiceImpl; @@ -81,6 +83,7 @@ class RdsHostListProviderTest { @Mock private HostListProviderService mockHostListProviderService; @Mock private EventPublisher mockEventPublisher; @Mock Dialect mockTopologyAwareDialect; + @Mock TargetDriverDialect mockDriverDialect; @Captor private ArgumentCaptor queryCaptor; private AutoCloseable closeable; @@ -115,9 +118,9 @@ void tearDown() throws Exception { } private RdsHostListProvider getRdsHostListProvider(String originalUrl) throws SQLException { + ConnectConfig connectConfig = new ConnectConfig(originalUrl, mockDriverDialect, new Properties()); RdsHostListProvider provider = new RdsHostListProvider( - new Properties(), - originalUrl, + connectConfig, mockServicesContainer, "foo", "bar", "baz"); provider.init(); diff --git a/wrapper/src/test/java/software/amazon/jdbc/hostlistprovider/RdsMultiAzDbClusterListProviderTest.java b/wrapper/src/test/java/software/amazon/jdbc/hostlistprovider/RdsMultiAzDbClusterListProviderTest.java index df6d6ee50..251d96cf3 100644 --- a/wrapper/src/test/java/software/amazon/jdbc/hostlistprovider/RdsMultiAzDbClusterListProviderTest.java +++ b/wrapper/src/test/java/software/amazon/jdbc/hostlistprovider/RdsMultiAzDbClusterListProviderTest.java @@ -58,7 +58,9 @@ import software.amazon.jdbc.dialect.Dialect; import software.amazon.jdbc.hostavailability.SimpleHostAvailabilityStrategy; import software.amazon.jdbc.hostlistprovider.RdsHostListProvider.FetchTopologyResult; +import software.amazon.jdbc.targetdriverdialect.TargetDriverDialect; import software.amazon.jdbc.util.FullServicesContainer; +import software.amazon.jdbc.util.connection.ConnectConfig; import software.amazon.jdbc.util.events.EventPublisher; import software.amazon.jdbc.util.storage.StorageService; import software.amazon.jdbc.util.storage.TestStorageServiceImpl; @@ -75,6 +77,7 @@ class RdsMultiAzDbClusterListProviderTest { @Mock private HostListProviderService mockHostListProviderService; @Mock private EventPublisher mockEventPublisher; @Mock Dialect mockTopologyAwareDialect; + @Mock TargetDriverDialect mockDriverDialect; @Captor private ArgumentCaptor queryCaptor; private AutoCloseable closeable; @@ -108,9 +111,9 @@ void tearDown() throws Exception { } private RdsMultiAzDbClusterListProvider getRdsMazDbClusterHostListProvider(String originalUrl) throws SQLException { + ConnectConfig connectConfig = new ConnectConfig(originalUrl, mockDriverDialect, new Properties()); RdsMultiAzDbClusterListProvider provider = new RdsMultiAzDbClusterListProvider( - new Properties(), - originalUrl, + connectConfig, mockServicesContainer, "foo", "bar", diff --git a/wrapper/src/test/java/software/amazon/jdbc/mock/TestPluginOne.java b/wrapper/src/test/java/software/amazon/jdbc/mock/TestPluginOne.java index 9ca4c86dd..5336ec64d 100644 --- a/wrapper/src/test/java/software/amazon/jdbc/mock/TestPluginOne.java +++ b/wrapper/src/test/java/software/amazon/jdbc/mock/TestPluginOne.java @@ -19,12 +19,11 @@ import java.sql.Connection; import java.sql.SQLException; import java.util.ArrayList; -import java.util.Arrays; +import java.util.Collections; import java.util.EnumSet; import java.util.HashSet; import java.util.List; import java.util.Map; -import java.util.Properties; import java.util.Set; import software.amazon.jdbc.ConnectionPlugin; import software.amazon.jdbc.HostListProviderService; @@ -35,6 +34,7 @@ import software.amazon.jdbc.NodeChangeOptions; import software.amazon.jdbc.OldConnectionSuggestedAction; import software.amazon.jdbc.hostavailability.SimpleHostAvailabilityStrategy; +import software.amazon.jdbc.util.connection.ConnectConfig; public class TestPluginOne implements ConnectionPlugin { @@ -46,7 +46,7 @@ public class TestPluginOne implements ConnectionPlugin { public TestPluginOne(ArrayList calls) { this.calls = calls; - this.subscribedMethods = new HashSet<>(Arrays.asList("*")); + this.subscribedMethods = new HashSet<>(Collections.singletonList("*")); } @Override @@ -85,12 +85,10 @@ public T execute( @Override public Connection connect( - String driverProtocol, - HostSpec hostSpec, - Properties props, - boolean isInitialConnection, - JdbcCallable connectFunc) - throws SQLException { + final ConnectConfig connectConfig, + final HostSpec hostSpec, + final boolean isInitialConnection, + final JdbcCallable connectFunc) throws SQLException { this.calls.add(this.getClass().getSimpleName() + ":before connect"); Connection result = connectFunc.call(); @@ -100,12 +98,10 @@ public Connection connect( @Override public Connection forceConnect( - String driverProtocol, - HostSpec hostSpec, - Properties props, - boolean isInitialConnection, - JdbcCallable forceConnectFunc) - throws SQLException { + final ConnectConfig connectConfig, + final HostSpec hostSpec, + final boolean isInitialConnection, + final JdbcCallable forceConnectFunc) throws SQLException { this.calls.add(this.getClass().getSimpleName() + ":before forceConnect"); Connection result = forceConnectFunc.call(); @@ -134,13 +130,9 @@ public HostSpec getHostSpecByStrategy(List hosts, HostRole role, Strin @Override public void initHostProvider( - String driverProtocol, - String initialUrl, - Properties props, + ConnectConfig connectConfig, HostListProviderService hostListProviderService, - JdbcCallable initHostProviderFunc) - throws SQLException { - + JdbcCallable initHostProviderFunc) { // do nothing } diff --git a/wrapper/src/test/java/software/amazon/jdbc/mock/TestPluginThree.java b/wrapper/src/test/java/software/amazon/jdbc/mock/TestPluginThree.java index 6166a788a..8f545c528 100644 --- a/wrapper/src/test/java/software/amazon/jdbc/mock/TestPluginThree.java +++ b/wrapper/src/test/java/software/amazon/jdbc/mock/TestPluginThree.java @@ -21,10 +21,10 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.HashSet; -import java.util.Properties; import software.amazon.jdbc.HostSpec; import software.amazon.jdbc.JdbcCallable; import software.amazon.jdbc.JdbcMethod; +import software.amazon.jdbc.util.connection.ConnectConfig; public class TestPluginThree extends TestPluginOne { @@ -45,12 +45,10 @@ public TestPluginThree(ArrayList calls, Connection connection) { @Override public Connection connect( - String driverProtocol, - HostSpec hostSpec, - Properties props, - boolean isInitialConnection, - JdbcCallable connectFunc) - throws SQLException { + final ConnectConfig connectConfig, + final HostSpec hostSpec, + final boolean isInitialConnection, + final JdbcCallable connectFunc) throws SQLException { this.calls.add(this.getClass().getSimpleName() + ":before connect"); @@ -65,14 +63,12 @@ public Connection connect( return result; } + @Override public Connection forceConnect( - String driverProtocol, - HostSpec hostSpec, - Properties props, - boolean isInitialConnection, - JdbcCallable forceConnectFunc) - throws SQLException { - + final ConnectConfig connectConfig, + final HostSpec hostSpec, + final boolean isInitialConnection, + final JdbcCallable forceConnectFunc) throws SQLException { this.calls.add(this.getClass().getSimpleName() + ":before forceConnect"); if (this.connection != null) { diff --git a/wrapper/src/test/java/software/amazon/jdbc/mock/TestPluginThrowException.java b/wrapper/src/test/java/software/amazon/jdbc/mock/TestPluginThrowException.java index 7e793781e..f682b7b47 100644 --- a/wrapper/src/test/java/software/amazon/jdbc/mock/TestPluginThrowException.java +++ b/wrapper/src/test/java/software/amazon/jdbc/mock/TestPluginThrowException.java @@ -21,9 +21,9 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.HashSet; -import java.util.Properties; import software.amazon.jdbc.HostSpec; import software.amazon.jdbc.JdbcCallable; +import software.amazon.jdbc.util.connection.ConnectConfig; public class TestPluginThrowException extends TestPluginOne { @@ -76,12 +76,10 @@ public T execute( @Override public Connection connect( - String driverProtocol, - HostSpec hostSpec, - Properties props, - boolean isInitialConnection, - JdbcCallable connectFunc) - throws SQLException { + final ConnectConfig connectConfig, + final HostSpec hostSpec, + final boolean isInitialConnection, + final JdbcCallable connectFunc) throws SQLException { this.calls.add(this.getClass().getSimpleName() + ":before"); if (this.isBefore) { diff --git a/wrapper/src/test/java/software/amazon/jdbc/plugin/AuroraConnectionTrackerPluginTest.java b/wrapper/src/test/java/software/amazon/jdbc/plugin/AuroraConnectionTrackerPluginTest.java index 70d62ae9f..776678b8b 100644 --- a/wrapper/src/test/java/software/amazon/jdbc/plugin/AuroraConnectionTrackerPluginTest.java +++ b/wrapper/src/test/java/software/amazon/jdbc/plugin/AuroraConnectionTrackerPluginTest.java @@ -54,6 +54,7 @@ import software.amazon.jdbc.targetdriverdialect.TargetDriverDialect; import software.amazon.jdbc.util.RdsUrlType; import software.amazon.jdbc.util.RdsUtils; +import software.amazon.jdbc.util.connection.ConnectConfig; public class AuroraConnectionTrackerPluginTest { @@ -68,7 +69,7 @@ public class AuroraConnectionTrackerPluginTest { @Mock JdbcCallable mockConnectionFunction; @Mock JdbcCallable mockSqlFunction; @Mock JdbcCallable mockCloseOrAbortFunction; - @Mock TargetDriverDialect mockTargetDriverDialect; + @Mock TargetDriverDialect mockDriverDialect; private static final Object[] SQL_ARGS = {"sql"}; @@ -86,8 +87,8 @@ void setUp() throws SQLException { when(mockRdsUtils.identifyRdsType(any())).thenReturn(RdsUrlType.RDS_INSTANCE); when(mockPluginService.getCurrentConnection()).thenReturn(mockConnection); when(mockPluginService.getDialect()).thenReturn(mockTopologyAwareDialect); - when(mockPluginService.getTargetDriverDialect()).thenReturn(mockTargetDriverDialect); - when(mockTargetDriverDialect.getNetworkBoundMethodNames(any())).thenReturn(new HashSet<>()); + when(mockPluginService.getTargetDriverDialect()).thenReturn(mockDriverDialect); + when(mockDriverDialect.getNetworkBoundMethodNames(any())).thenReturn(new HashSet<>()); } @AfterEach @@ -111,10 +112,11 @@ public void testTrackNewInstanceConnections( mockRdsUtils, mockTracker); + final ConnectConfig connectConfig = + new ConnectConfig(protocol + hostSpec.getHost(), mockDriverDialect, EMPTY_PROPERTIES); final Connection actualConnection = plugin.connect( - protocol, + connectConfig, hostSpec, - EMPTY_PROPERTIES, isInitialConnection, mockConnectionFunction); @@ -131,10 +133,6 @@ public void testInvalidateOpenedConnectionsWhenWriterHostNotChange() throws SQLE .host("host") .role(HostRole.WRITER) .build(); - final HostSpec newHost = new HostSpecBuilder(new SimpleHostAvailabilityStrategy()) - .host("new-host") - .role(HostRole.WRITER) - .build(); // Host list changes during simulated failover when(mockPluginService.getAllHosts()).thenReturn(Collections.singletonList(originalHost)); @@ -236,10 +234,10 @@ static Stream testInvalidateConnectionsOnCloseOrAbortArgs() { private static Stream trackNewConnectionsParameters() { return Stream.of( - Arguments.of("postgresql", true), - Arguments.of("postgresql", false), - Arguments.of("otherProtocol", true), - Arguments.of("otherProtocol", false) + Arguments.of("jdbc:postgresql://", true), + Arguments.of("jdbc:postgresql://", false), + Arguments.of("jdbc:otherProtocol://", true), + Arguments.of("jdbc:otherProtocol://", false) ); } } diff --git a/wrapper/src/test/java/software/amazon/jdbc/plugin/AwsSecretsManagerConnectionPluginTest.java b/wrapper/src/test/java/software/amazon/jdbc/plugin/AwsSecretsManagerConnectionPluginTest.java index 22a8339c1..88de04621 100644 --- a/wrapper/src/test/java/software/amazon/jdbc/plugin/AwsSecretsManagerConnectionPluginTest.java +++ b/wrapper/src/test/java/software/amazon/jdbc/plugin/AwsSecretsManagerConnectionPluginTest.java @@ -62,17 +62,14 @@ import software.amazon.jdbc.dialect.Dialect; import software.amazon.jdbc.dialect.DialectManager; import software.amazon.jdbc.exceptions.ExceptionHandler; -import software.amazon.jdbc.exceptions.ExceptionManager; import software.amazon.jdbc.exceptions.MySQLExceptionHandler; import software.amazon.jdbc.exceptions.PgExceptionHandler; import software.amazon.jdbc.hostavailability.SimpleHostAvailabilityStrategy; -import software.amazon.jdbc.profile.ConfigurationProfile; -import software.amazon.jdbc.profile.ConfigurationProfileBuilder; -import software.amazon.jdbc.states.SessionStateService; import software.amazon.jdbc.targetdriverdialect.TargetDriverDialect; import software.amazon.jdbc.util.FullServicesContainer; import software.amazon.jdbc.util.Messages; import software.amazon.jdbc.util.Pair; +import software.amazon.jdbc.util.connection.ConnectConfig; import software.amazon.jdbc.util.telemetry.GaugeCallable; import software.amazon.jdbc.util.telemetry.TelemetryContext; import software.amazon.jdbc.util.telemetry.TelemetryCounter; @@ -82,8 +79,8 @@ @SuppressWarnings("resource") public class AwsSecretsManagerConnectionPluginTest { - private static final String TEST_PG_PROTOCOL = "jdbc:aws-wrapper:postgresql:"; - private static final String TEST_MYSQL_PROTOCOL = "jdbc:aws-wrapper:mysql:"; + private static final String TEST_PG_PROTOCOL = "jdbc:aws-wrapper:postgresql://"; + private static final String TEST_MYSQL_PROTOCOL = "jdbc:aws-wrapper:mysql://"; private static final String TEST_REGION = "us-east-2"; private static final String TEST_SECRET_ID = "secretId"; private static final String TEST_USERNAME = "testUser"; @@ -121,10 +118,7 @@ public class AwsSecretsManagerConnectionPluginTest { @Mock TelemetryContext mockTelemetryContext; @Mock TelemetryCounter mockTelemetryCounter; @Mock TelemetryGauge mockTelemetryGauge; - @Mock TargetDriverDialect mockTargetDriverDialect; - ConfigurationProfile configurationProfile = ConfigurationProfileBuilder.get().withName("test").build(); - - @Mock SessionStateService mockSessionStateService; + @Mock TargetDriverDialect mockDriverDialect; @BeforeEach public void init() throws SQLException { @@ -133,7 +127,7 @@ public void init() throws SQLException { REGION_PROPERTY.set(TEST_PROPS, TEST_REGION); SECRET_ID_PROPERTY.set(TEST_PROPS, TEST_SECRET_ID); - when(mockDialectManager.getDialect(anyString(), anyString(), any(Properties.class))) + when(mockDialectManager.getDialect(any(ConnectConfig.class))) .thenReturn(mockTopologyAwareDialect); when(mockServicesContainer.getConnectionPluginManager()).thenReturn(mockConnectionPluginManager); @@ -151,7 +145,7 @@ public void init() throws SQLException { (host, r) -> mockSecretsManagerClient, (id) -> mockGetValueRequest); - when(mockDialectManager.getDialect(anyString(), anyString(), any(Properties.class))) + when(mockDialectManager.getDialect(any(ConnectConfig.class))) .thenReturn(mockTopologyAwareDialect); when(mockService.getHostSpecBuilder()).thenReturn(new HostSpecBuilder(new SimpleHostAvailabilityStrategy())); @@ -172,7 +166,7 @@ public void testConnectWithCachedSecrets() throws SQLException { // Add initial cached secret to be used for a connection. AwsSecretsManagerCacheHolder.secretsCache.put(SECRET_CACHE_KEY, TEST_SECRET); - this.plugin.connect(TEST_PG_PROTOCOL, TEST_HOSTSPEC, TEST_PROPS, true, this.connectFunc); + this.plugin.connect(getConnectConfig(TEST_PG_PROTOCOL), TEST_HOSTSPEC, true, this.connectFunc); assertEquals(1, AwsSecretsManagerCacheHolder.secretsCache.size()); verify(this.mockSecretsManagerClient, never()).getSecretValue(this.mockGetValueRequest); @@ -181,6 +175,10 @@ public void testConnectWithCachedSecrets() throws SQLException { assertEquals(TEST_PASSWORD, TEST_PROPS.get(PropertyDefinition.PASSWORD.name)); } + protected ConnectConfig getConnectConfig(String protocol) { + return new ConnectConfig(protocol, mockDriverDialect, TEST_PROPS); + } + /** * The plugin will attempt to open a connection with an empty secret cache. The plugin will fetch the secret from the * AWS Secrets Manager. @@ -190,7 +188,7 @@ public void testConnectWithNewSecrets() throws SQLException { when(this.mockSecretsManagerClient.getSecretValue(this.mockGetValueRequest)) .thenReturn(VALID_GET_SECRET_VALUE_RESPONSE); - this.plugin.connect(TEST_PG_PROTOCOL, TEST_HOSTSPEC, TEST_PROPS, true, this.connectFunc); + this.plugin.connect(getConnectConfig(TEST_PG_PROTOCOL), TEST_HOSTSPEC, true, this.connectFunc); assertEquals(1, AwsSecretsManagerCacheHolder.secretsCache.size()); verify(this.mockSecretsManagerClient).getSecretValue(this.mockGetValueRequest); @@ -222,9 +220,8 @@ public void testFailedInitialConnectionWithUnhandledError() throws SQLException final SQLException connectionFailedException = assertThrows( SQLException.class, () -> this.plugin.connect( - TEST_PG_PROTOCOL, + getConnectConfig(TEST_PG_PROTOCOL), TEST_HOSTSPEC, - TEST_PROPS, true, this.connectFunc)); @@ -265,9 +262,8 @@ public void testConnectWithNewSecretsAfterTryingWithCachedSecrets( assertThrows( SQLException.class, () -> this.plugin.connect( - TEST_PG_PROTOCOL, + getConnectConfig(TEST_PG_PROTOCOL), TEST_HOSTSPEC, - TEST_PROPS, true, this.connectFunc)); @@ -279,16 +275,7 @@ public void testConnectWithNewSecretsAfterTryingWithCachedSecrets( } private @NotNull PluginServiceImpl getPluginService(String protocol) throws SQLException { - return new PluginServiceImpl( - mockServicesContainer, - new ExceptionManager(), - TEST_PROPS, - "url", - protocol, - mockDialectManager, - mockTargetDriverDialect, - configurationProfile, - mockSessionStateService); + return new PluginServiceImpl(mockServicesContainer, getConnectConfig(protocol)); } /** @@ -304,9 +291,8 @@ public void testFailedToReadSecrets() throws SQLException { assertThrows( SQLException.class, () -> this.plugin.connect( - TEST_PG_PROTOCOL, + getConnectConfig(TEST_PG_PROTOCOL), TEST_HOSTSPEC, - TEST_PROPS, true, this.connectFunc)); @@ -331,9 +317,8 @@ public void testFailedToGetSecrets() throws SQLException { assertThrows( SQLException.class, () -> this.plugin.connect( - TEST_PG_PROTOCOL, + getConnectConfig(TEST_PG_PROTOCOL), TEST_HOSTSPEC, - TEST_PROPS, true, this.connectFunc)); @@ -368,9 +353,8 @@ public void testFailedInitialConnectionWithWrappedGenericError(final String acce assertThrows( SQLException.class, () -> this.plugin.connect( - TEST_PG_PROTOCOL, + getConnectConfig(TEST_PG_PROTOCOL), TEST_HOSTSPEC, - TEST_PROPS, true, this.connectFunc)); @@ -400,9 +384,8 @@ public void testConnectWithWrappedMySQLException() throws SQLException { assertThrows( SQLException.class, () -> this.plugin.connect( - TEST_MYSQL_PROTOCOL, + getConnectConfig(TEST_MYSQL_PROTOCOL), TEST_HOSTSPEC, - TEST_PROPS, true, this.connectFunc)); @@ -432,9 +415,8 @@ public void testConnectWithWrappedPostgreSQLException() throws SQLException { assertThrows( SQLException.class, () -> this.plugin.connect( - TEST_PG_PROTOCOL, + getConnectConfig(TEST_PG_PROTOCOL), TEST_HOSTSPEC, - TEST_PROPS, true, this.connectFunc)); @@ -453,7 +435,7 @@ public void testConnectViaARN(final String arn, final Region expectedRegionParse SECRET_ID_PROPERTY.set(props, arn); this.plugin = spy(new AwsSecretsManagerConnectionPlugin( - new PluginServiceImpl(mockServicesContainer, props, "url", TEST_PG_PROTOCOL, mockTargetDriverDialect), + new PluginServiceImpl(mockServicesContainer, getConnectConfig(TEST_PG_PROTOCOL)), props, (host, r) -> mockSecretsManagerClient, (id) -> mockGetValueRequest)); @@ -473,7 +455,7 @@ public void testConnectionWithRegionParameterAndARN(final String arn, final Regi REGION_PROPERTY.set(props, expectedRegion.toString()); this.plugin = spy(new AwsSecretsManagerConnectionPlugin( - new PluginServiceImpl(mockServicesContainer, props, "url", TEST_PG_PROTOCOL, mockTargetDriverDialect), + new PluginServiceImpl(mockServicesContainer, getConnectConfig(TEST_PG_PROTOCOL)), props, (host, r) -> mockSecretsManagerClient, (id) -> mockGetValueRequest)); diff --git a/wrapper/src/test/java/software/amazon/jdbc/plugin/DefaultConnectionPluginTest.java b/wrapper/src/test/java/software/amazon/jdbc/plugin/DefaultConnectionPluginTest.java index d8fac47be..5c6b0ca73 100644 --- a/wrapper/src/test/java/software/amazon/jdbc/plugin/DefaultConnectionPluginTest.java +++ b/wrapper/src/test/java/software/amazon/jdbc/plugin/DefaultConnectionPluginTest.java @@ -33,7 +33,6 @@ import java.util.Arrays; import java.util.Collections; import java.util.List; -import java.util.Properties; import java.util.stream.Stream; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; @@ -49,6 +48,7 @@ import software.amazon.jdbc.JdbcCallable; import software.amazon.jdbc.PluginManagerService; import software.amazon.jdbc.PluginService; +import software.amazon.jdbc.util.connection.ConnectConfig; import software.amazon.jdbc.util.telemetry.GaugeCallable; import software.amazon.jdbc.util.telemetry.TelemetryContext; import software.amazon.jdbc.util.telemetry.TelemetryCounter; @@ -62,6 +62,7 @@ class DefaultConnectionPluginTest { @Mock PluginService pluginService; @Mock ConnectionProvider connectionProvider; @Mock PluginManagerService pluginManagerService; + @Mock ConnectConfig mockConnectConfig; @Mock JdbcCallable mockSqlFunction; @Mock JdbcCallable mockConnectFunction; @Mock Connection conn; @@ -86,11 +87,11 @@ void setUp() { when(mockTelemetryFactory.createCounter(anyString())).thenReturn(mockTelemetryCounter); // noinspection unchecked when(mockTelemetryFactory.createGauge(anyString(), any(GaugeCallable.class))).thenReturn(mockTelemetryGauge); - when(mockConnectionProviderManager.getConnectionProvider(anyString(), any(), any())) + when(mockConnectionProviderManager.getConnectionProvider(any(), any())) .thenReturn(connectionProvider); plugin = new DefaultConnectionPlugin( - pluginService, connectionProvider, null, pluginManagerService, mockConnectionProviderManager); + pluginService, connectionProvider, pluginManagerService, mockConnectionProviderManager); } @AfterEach @@ -121,9 +122,9 @@ void testExecute_closeOldConnection() throws SQLException { @Test void testConnect() throws SQLException { - plugin.connect("anyProtocol", mockHostSpec, new Properties(), true, mockConnectFunction); - verify(connectionProvider, atLeastOnce()).connect(anyString(), any(), any(), any(), any()); - verify(mockConnectionProviderManager, atLeastOnce()).initConnection(any(), anyString(), any(), any()); + plugin.connect(mockConnectConfig, mockHostSpec, true, mockConnectFunction); + verify(connectionProvider, atLeastOnce()).connect(any(), any()); + verify(mockConnectionProviderManager, atLeastOnce()).initConnection(any(), any(), any()); } private static Stream multiStatementQueries() { diff --git a/wrapper/src/test/java/software/amazon/jdbc/plugin/customendpoint/CustomEndpointPluginTest.java b/wrapper/src/test/java/software/amazon/jdbc/plugin/customendpoint/CustomEndpointPluginTest.java index 0d41c5f72..b5866c81d 100644 --- a/wrapper/src/test/java/software/amazon/jdbc/plugin/customendpoint/CustomEndpointPluginTest.java +++ b/wrapper/src/test/java/software/amazon/jdbc/plugin/customendpoint/CustomEndpointPluginTest.java @@ -48,6 +48,7 @@ import software.amazon.jdbc.hostavailability.SimpleHostAvailabilityStrategy; import software.amazon.jdbc.targetdriverdialect.TargetDriverDialect; import software.amazon.jdbc.util.FullServicesContainer; +import software.amazon.jdbc.util.connection.ConnectConfig; import software.amazon.jdbc.util.monitoring.MonitorService; import software.amazon.jdbc.util.telemetry.TelemetryCounter; import software.amazon.jdbc.util.telemetry.TelemetryFactory; @@ -64,6 +65,7 @@ public class CustomEndpointPluginTest { private final HostSpec host = hostSpecBuilder.host(customEndpointUrl).build(); @Mock private FullServicesContainer mockServicesContainer; + @Mock private ConnectConfig mockConnectConfig; @Mock private PluginService mockPluginService; @Mock private MonitorService mockMonitorService; @Mock private BiFunction mockRdsClientFunc; @@ -106,7 +108,7 @@ private CustomEndpointPlugin getSpyPlugin() throws SQLException { public void testConnect_monitorNotCreatedIfNotCustomEndpointHost() throws SQLException { CustomEndpointPlugin spyPlugin = getSpyPlugin(); - spyPlugin.connect("", writerClusterHost, props, true, mockConnectFunc); + spyPlugin.connect(mockConnectConfig, writerClusterHost, true, mockConnectFunc); verify(mockConnectFunc, times(1)).call(); verify(spyPlugin, never()).createMonitorIfAbsent(any(Properties.class)); @@ -116,7 +118,7 @@ public void testConnect_monitorNotCreatedIfNotCustomEndpointHost() throws SQLExc public void testConnect_monitorCreated() throws SQLException { CustomEndpointPlugin spyPlugin = getSpyPlugin(); - spyPlugin.connect("", host, props, true, mockConnectFunc); + spyPlugin.connect(mockConnectConfig, host, true, mockConnectFunc); verify(spyPlugin, times(1)).createMonitorIfAbsent(eq(props)); verify(mockConnectFunc, times(1)).call(); @@ -128,7 +130,7 @@ public void testConnect_timeoutWaitingForInfo() throws SQLException { CustomEndpointPlugin spyPlugin = getSpyPlugin(); when(mockMonitor.hasCustomEndpointInfo()).thenReturn(false); - assertThrows(SQLException.class, () -> spyPlugin.connect("", host, props, true, mockConnectFunc)); + assertThrows(SQLException.class, () -> spyPlugin.connect(mockConnectConfig, host, true, mockConnectFunc)); verify(spyPlugin, times(1)).createMonitorIfAbsent(eq(props)); verify(mockConnectFunc, never()).call(); diff --git a/wrapper/src/test/java/software/amazon/jdbc/plugin/dev/DeveloperConnectionPluginTest.java b/wrapper/src/test/java/software/amazon/jdbc/plugin/dev/DeveloperConnectionPluginTest.java index 638e99a4f..cbfec7329 100644 --- a/wrapper/src/test/java/software/amazon/jdbc/plugin/dev/DeveloperConnectionPluginTest.java +++ b/wrapper/src/test/java/software/amazon/jdbc/plugin/dev/DeveloperConnectionPluginTest.java @@ -73,10 +73,11 @@ void cleanUp() throws Exception { @BeforeEach void init() throws SQLException { closeable = MockitoAnnotations.openMocks(this); - servicesContainer = new FullServicesContainerImpl(mockStorageService, mockMonitorService, mockTelemetryFactory); + servicesContainer = new FullServicesContainerImpl( + mockStorageService, mockMonitorService, mockConnectionProvider, mockTelemetryFactory); - when(mockConnectionProvider.connect(any(), any(), any(), any(), any())).thenReturn(mockConnection); - when(mockConnectCallback.getExceptionToRaise(any(), any(), any(), anyBoolean())).thenReturn(null); + when(mockConnectionProvider.connect(any(), any())).thenReturn(mockConnection); + when(mockConnectCallback.getExceptionToRaise(any(), any(), anyBoolean())).thenReturn(null); when(mockConnectionPluginManager.getTelemetryFactory()).thenReturn(mockTelemetryFactory); when(mockTelemetryFactory.openTelemetryContext(anyString(), any())).thenReturn(mockTelemetryContext); @@ -325,7 +326,7 @@ public void test_RaiseExceptionOnConnectWithCallback() { props.put(DialectManager.DIALECT.name, DialectCodes.PG); final SQLException exception = new SQLException("test"); - when(mockConnectCallback.getExceptionToRaise(any(), any(), any(), anyBoolean())) + when(mockConnectCallback.getExceptionToRaise(any(), any(), anyBoolean())) .thenReturn(exception) .thenReturn(null); ExceptionSimulatorManager.setCallback(mockConnectCallback); diff --git a/wrapper/src/test/java/software/amazon/jdbc/plugin/efm/HostHostMonitorConnectionContextTest.java b/wrapper/src/test/java/software/amazon/jdbc/plugin/efm/HostMonitorConnectionContextTest.java similarity index 99% rename from wrapper/src/test/java/software/amazon/jdbc/plugin/efm/HostHostMonitorConnectionContextTest.java rename to wrapper/src/test/java/software/amazon/jdbc/plugin/efm/HostMonitorConnectionContextTest.java index 7066bbe3c..290187c50 100644 --- a/wrapper/src/test/java/software/amazon/jdbc/plugin/efm/HostHostMonitorConnectionContextTest.java +++ b/wrapper/src/test/java/software/amazon/jdbc/plugin/efm/HostMonitorConnectionContextTest.java @@ -35,7 +35,7 @@ import org.mockito.MockitoAnnotations; import software.amazon.jdbc.util.telemetry.TelemetryCounter; -class HostHostMonitorConnectionContextTest { +class HostMonitorConnectionContextTest { private static final long FAILURE_DETECTION_TIME_MILLIS = 10; private static final long FAILURE_DETECTION_INTERVAL_MILLIS = 100; private static final long FAILURE_DETECTION_COUNT = 3; diff --git a/wrapper/src/test/java/software/amazon/jdbc/plugin/efm/HostHostMonitorServiceImplTest.java b/wrapper/src/test/java/software/amazon/jdbc/plugin/efm/HostMonitorServiceImplTest.java similarity index 99% rename from wrapper/src/test/java/software/amazon/jdbc/plugin/efm/HostHostMonitorServiceImplTest.java rename to wrapper/src/test/java/software/amazon/jdbc/plugin/efm/HostMonitorServiceImplTest.java index e89279279..c9b1eca94 100644 --- a/wrapper/src/test/java/software/amazon/jdbc/plugin/efm/HostHostMonitorServiceImplTest.java +++ b/wrapper/src/test/java/software/amazon/jdbc/plugin/efm/HostMonitorServiceImplTest.java @@ -49,7 +49,7 @@ import software.amazon.jdbc.util.telemetry.TelemetryCounter; import software.amazon.jdbc.util.telemetry.TelemetryFactory; -class HostHostMonitorServiceImplTest { +class HostMonitorServiceImplTest { private static final Set NODE_KEYS = new HashSet<>(Collections.singletonList("any.node.domain")); diff --git a/wrapper/src/test/java/software/amazon/jdbc/plugin/efm/HostMonitoringConnectionPluginTest.java b/wrapper/src/test/java/software/amazon/jdbc/plugin/efm/HostMonitoringConnectionPluginTest.java index 63320e95d..b203fa0ea 100644 --- a/wrapper/src/test/java/software/amazon/jdbc/plugin/efm/HostMonitoringConnectionPluginTest.java +++ b/wrapper/src/test/java/software/amazon/jdbc/plugin/efm/HostMonitoringConnectionPluginTest.java @@ -25,7 +25,6 @@ import static org.mockito.Mockito.any; import static org.mockito.Mockito.atMostOnce; import static org.mockito.Mockito.doThrow; -import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; @@ -50,8 +49,6 @@ import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; -import org.mockito.ArgumentCaptor; -import org.mockito.Captor; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import software.amazon.jdbc.HostSpec; @@ -66,6 +63,7 @@ import software.amazon.jdbc.util.Messages; import software.amazon.jdbc.util.RdsUrlType; import software.amazon.jdbc.util.RdsUtils; +import software.amazon.jdbc.util.connection.ConnectConfig; class HostMonitoringConnectionPluginTest { @@ -79,9 +77,9 @@ class HostMonitoringConnectionPluginTest { @Mock PluginService pluginService; @Mock Dialect mockDialect; @Mock Connection connection; + @Mock ConnectConfig mockConnectConfig; @Mock Statement statement; @Mock ResultSet resultSet; - @Captor ArgumentCaptor stringArgumentCaptor; Properties properties = new Properties(); @Mock HostSpec hostSpec; @Mock HostSpec hostSpec2; @@ -96,23 +94,6 @@ class HostMonitoringConnectionPluginTest { private HostMonitoringConnectionPlugin plugin; private AutoCloseable closeable; - /** - * Generate different sets of method arguments where one argument is null to ensure {@link - * software.amazon.jdbc.plugin.efm.HostMonitoringConnectionPlugin#HostMonitoringConnectionPlugin(PluginService, - * Properties)} can handle null arguments correctly. - * - * @return different sets of arguments. - */ - private static Stream generateNullArguments() { - final PluginService pluginService = mock(PluginService.class); - final Properties properties = new Properties(); - - return Stream.of( - Arguments.of(null, null), - Arguments.of(pluginService, null), - Arguments.of(null, properties)); - } - @AfterEach void cleanUp() throws Exception { closeable.close(); @@ -227,7 +208,7 @@ void test_executeMonitoringEnabled() throws Exception { } /** - * Tests exception being thrown in the finally block when checking connection status in the execute method. + * Tests exception being thrown in the `finally` block when checking connection status in the execute method. */ @Test void test_executeCleanUp_whenCheckingConnectionStatus_throwsException() throws SQLException { @@ -248,7 +229,7 @@ void test_executeCleanUp_whenCheckingConnectionStatus_throwsException() throws S } /** - * Tests exception being thrown in the finally block + * Tests exception being thrown in the `finally` block * when an open connection object is detected for an unavailable node in the execute method. */ @Test @@ -282,7 +263,7 @@ void test_connect_exceptionRaisedDuringGenerateHostAliases() throws SQLException doThrow(new SQLException()).when(connection).createStatement(); // Ensure SQLException raised in `generateHostAliases` are ignored. - final Connection conn = plugin.connect("protocol", hostSpec, properties, true, () -> connection); + final Connection conn = plugin.connect(mockConnectConfig, hostSpec, true, () -> connection); assertNotNull(conn); } diff --git a/wrapper/src/test/java/software/amazon/jdbc/plugin/efm/MultiThreadedDefaultHostHostMonitorServiceTest.java b/wrapper/src/test/java/software/amazon/jdbc/plugin/efm/MultiThreadedDefaultHostMonitorServiceTest.java similarity index 99% rename from wrapper/src/test/java/software/amazon/jdbc/plugin/efm/MultiThreadedDefaultHostHostMonitorServiceTest.java rename to wrapper/src/test/java/software/amazon/jdbc/plugin/efm/MultiThreadedDefaultHostMonitorServiceTest.java index b4e76d3ac..afccbcc21 100644 --- a/wrapper/src/test/java/software/amazon/jdbc/plugin/efm/MultiThreadedDefaultHostHostMonitorServiceTest.java +++ b/wrapper/src/test/java/software/amazon/jdbc/plugin/efm/MultiThreadedDefaultHostMonitorServiceTest.java @@ -60,10 +60,10 @@ import software.amazon.jdbc.util.telemetry.TelemetryFactory; /** - * Multithreaded tests for {@link MultiThreadedDefaultHostHostMonitorServiceTest}. Repeats each testcase + * Multithreaded tests for {@link MultiThreadedDefaultHostMonitorServiceTest}. Repeats each testcase * multiple times. Use a cyclic barrier to ensure threads start at the same time. */ -class MultiThreadedDefaultHostHostMonitorServiceTest { +class MultiThreadedDefaultHostMonitorServiceTest { @Mock HostMonitorInitializer monitorInitializer; @Mock ExecutorServiceInitializer executorServiceInitializer; diff --git a/wrapper/src/test/java/software/amazon/jdbc/plugin/failover/ClusterAwareReaderFailoverHandlerTest.java b/wrapper/src/test/java/software/amazon/jdbc/plugin/failover/ClusterAwareReaderFailoverHandlerTest.java index 89e838acb..e4afa0936 100644 --- a/wrapper/src/test/java/software/amazon/jdbc/plugin/failover/ClusterAwareReaderFailoverHandlerTest.java +++ b/wrapper/src/test/java/software/amazon/jdbc/plugin/failover/ClusterAwareReaderFailoverHandlerTest.java @@ -48,7 +48,6 @@ import org.mockito.Mockito; import org.mockito.MockitoAnnotations; import org.mockito.stubbing.Answer; -import software.amazon.jdbc.ConnectionPluginManager; import software.amazon.jdbc.HostRole; import software.amazon.jdbc.HostSpec; import software.amazon.jdbc.HostSpecBuilder; @@ -57,13 +56,11 @@ import software.amazon.jdbc.hostavailability.HostAvailability; import software.amazon.jdbc.hostavailability.SimpleHostAvailabilityStrategy; import software.amazon.jdbc.util.FullServicesContainer; -import software.amazon.jdbc.util.connection.ConnectionService; class ClusterAwareReaderFailoverHandlerTest { - @Mock FullServicesContainer mockContainer; - @Mock ConnectionService mockConnectionService; + @Mock FullServicesContainer mockContainer1; + @Mock FullServicesContainer mockContainer2; @Mock PluginService mockPluginService; - @Mock ConnectionPluginManager mockPluginManager; @Mock Connection mockConnection; private AutoCloseable closeable; @@ -86,8 +83,8 @@ class ClusterAwareReaderFailoverHandlerTest { @BeforeEach void setUp() { closeable = MockitoAnnotations.openMocks(this); - when(mockContainer.getConnectionPluginManager()).thenReturn(mockPluginManager); - when(mockContainer.getPluginService()).thenReturn(mockPluginService); + when(mockContainer1.getPluginService()).thenReturn(mockPluginService); + when(mockContainer2.getPluginService()).thenReturn(mockPluginService); } @AfterEach @@ -108,11 +105,11 @@ public void testFailover() throws SQLException { for (int i = 0; i < hosts.size(); i++) { if (i != successHostIndex) { final SQLException exception = new SQLException("exception", "08S01", null); - when(mockConnectionService.open(hosts.get(i), properties)) + when(mockPluginService.forceConnect(hosts.get(i), properties)) .thenThrow(exception); when(mockPluginService.isNetworkException(exception, null)).thenReturn(true); } else { - when(mockConnectionService.open(hosts.get(i), properties)).thenReturn(mockConnection); + when(mockPluginService.forceConnect(hosts.get(i), properties)).thenReturn(mockConnection); } } @@ -154,7 +151,7 @@ public void testFailover_timeout() throws SQLException { final List hosts = defaultHosts; final int currentHostIndex = 2; for (HostSpec host : hosts) { - when(mockConnectionService.open(host, properties)) + when(mockPluginService.forceConnect(host, properties)) .thenAnswer((Answer) invocation -> { Thread.sleep(20000); return mockConnection; @@ -180,17 +177,17 @@ public void testFailover_timeout() throws SQLException { private ClusterAwareReaderFailoverHandler getSpyFailoverHandler() throws SQLException { ClusterAwareReaderFailoverHandler handler = - spy(new ClusterAwareReaderFailoverHandler(mockContainer, mockConnectionService, properties)); - doReturn(mockPluginService).when(handler).getNewPluginService(); + spy(new ClusterAwareReaderFailoverHandler(mockContainer1, properties)); + doReturn(mockContainer2).when(handler).getNewServicesContainer(); return handler; } private ClusterAwareReaderFailoverHandler getSpyFailoverHandler( int maxFailoverTimeoutMs, int timeoutMs, boolean isStrictReaderRequired) throws SQLException { ClusterAwareReaderFailoverHandler handler = new ClusterAwareReaderFailoverHandler( - mockContainer, mockConnectionService, properties, maxFailoverTimeoutMs, timeoutMs, isStrictReaderRequired); + mockContainer1, properties, maxFailoverTimeoutMs, timeoutMs, isStrictReaderRequired); ClusterAwareReaderFailoverHandler spyHandler = spy(handler); - doReturn(mockPluginService).when(spyHandler).getNewPluginService(); + doReturn(mockContainer2).when(spyHandler).getNewServicesContainer(); return spyHandler; } @@ -220,14 +217,14 @@ public void testGetReader_connectionSuccess() throws SQLException { final List hosts = defaultHosts.subList(0, 3); // 2 connection attempts (writer not attempted) final HostSpec slowHost = hosts.get(1); final HostSpec fastHost = hosts.get(2); - when(mockConnectionService.open(slowHost, properties)) + when(mockPluginService.forceConnect(slowHost, properties)) .thenAnswer( (Answer) invocation -> { Thread.sleep(20000); return mockConnection; }); - when(mockConnectionService.open(eq(fastHost), eq(properties))).thenReturn(mockConnection); + when(mockPluginService.forceConnect(eq(fastHost), eq(properties))).thenReturn(mockConnection); Dialect mockDialect = Mockito.mock(Dialect.class); when(mockDialect.getFailoverRestrictions()).thenReturn(EnumSet.noneOf(FailoverRestriction.class)); @@ -251,7 +248,7 @@ public void testGetReader_connectionFailure() throws SQLException { // first connection attempt to return fails // expected test result: failure to get reader final List hosts = defaultHosts.subList(0, 4); // 3 connection attempts (writer not attempted) - when(mockConnectionService.open(any(), eq(properties))).thenThrow(new SQLException("exception", "08S01", null)); + when(mockPluginService.forceConnect(any(), eq(properties))).thenThrow(new SQLException("exception", "08S01", null)); Dialect mockDialect = Mockito.mock(Dialect.class); when(mockDialect.getFailoverRestrictions()).thenReturn(EnumSet.noneOf(FailoverRestriction.class)); @@ -271,7 +268,7 @@ public void testGetReader_connectionAttemptsTimeout() throws SQLException { // first connection attempt to return times out // expected test result: failure to get reader final List hosts = defaultHosts.subList(0, 3); // 2 connection attempts (writer not attempted) - when(mockConnectionService.open(any(), eq(properties))) + when(mockPluginService.forceConnect(any(), eq(properties))) .thenAnswer( (Answer) invocation -> { @@ -384,7 +381,7 @@ public void testHostFailoverStrictReaderEnabled() throws SQLException { List hostsByPriority = target.getHostsByPriority(hosts); assertEquals(expectedHostsByPriority, hostsByPriority); - // Should pick the reader even if unavailable. The unavailable reader will be lower priority than the writer. + // Should pick the reader even if unavailable. The unavailable reader will have lower priority than the writer. reader.setAvailability(HostAvailability.NOT_AVAILABLE); expectedHostsByPriority = Arrays.asList(writer, reader); diff --git a/wrapper/src/test/java/software/amazon/jdbc/plugin/failover/ClusterAwareWriterFailoverHandlerTest.java b/wrapper/src/test/java/software/amazon/jdbc/plugin/failover/ClusterAwareWriterFailoverHandlerTest.java index 902aadfcb..b17ecbb95 100644 --- a/wrapper/src/test/java/software/amazon/jdbc/plugin/failover/ClusterAwareWriterFailoverHandlerTest.java +++ b/wrapper/src/test/java/software/amazon/jdbc/plugin/failover/ClusterAwareWriterFailoverHandlerTest.java @@ -50,11 +50,10 @@ import software.amazon.jdbc.hostavailability.HostAvailability; import software.amazon.jdbc.hostavailability.SimpleHostAvailabilityStrategy; import software.amazon.jdbc.util.FullServicesContainer; -import software.amazon.jdbc.util.connection.ConnectionService; class ClusterAwareWriterFailoverHandlerTest { - @Mock FullServicesContainer mockContainer; - @Mock ConnectionService mockConnectionService; + @Mock FullServicesContainer mockContainer1; + @Mock FullServicesContainer mockContainer2; @Mock PluginService mockPluginService; @Mock Connection mockConnection; @Mock ReaderFailoverHandler mockReaderFailoverHandler; @@ -80,7 +79,8 @@ class ClusterAwareWriterFailoverHandlerTest { @BeforeEach void setUp() { closeable = MockitoAnnotations.openMocks(this); - when(mockContainer.getPluginService()).thenReturn(mockPluginService); + when(mockContainer1.getPluginService()).thenReturn(mockPluginService); + when(mockContainer2.getPluginService()).thenReturn(mockPluginService); writer.addAlias("writer-host"); newWriterHost.addAlias("new-writer-host"); readerA.addAlias("reader-a-host"); @@ -94,9 +94,9 @@ void tearDown() throws Exception { @Test public void testReconnectToWriter_taskBReaderException() throws SQLException { - when(mockConnectionService.open(refEq(writer), eq(properties))).thenReturn(mockConnection); - when(mockConnectionService.open(refEq(readerA), eq(properties))).thenThrow(SQLException.class); - when(mockConnectionService.open(refEq(readerB), eq(properties))).thenThrow(SQLException.class); + when(mockPluginService.forceConnect(refEq(writer), eq(properties))).thenReturn(mockConnection); + when(mockPluginService.forceConnect(refEq(readerA), eq(properties))).thenThrow(SQLException.class); + when(mockPluginService.forceConnect(refEq(readerB), eq(properties))).thenThrow(SQLException.class); when(mockPluginService.getAllHosts()).thenReturn(topology); @@ -120,8 +120,7 @@ private ClusterAwareWriterFailoverHandler getSpyFailoverHandler( final int readTopologyIntervalMs, final int reconnectWriterIntervalMs) throws SQLException { ClusterAwareWriterFailoverHandler handler = new ClusterAwareWriterFailoverHandler( - mockContainer, - mockConnectionService, + mockContainer1, mockReaderFailoverHandler, properties, failoverTimeoutMs, @@ -129,7 +128,7 @@ private ClusterAwareWriterFailoverHandler getSpyFailoverHandler( reconnectWriterIntervalMs); ClusterAwareWriterFailoverHandler spyHandler = spy(handler); - doReturn(mockPluginService).when(spyHandler).getNewPluginService(); + doReturn(mockContainer2).when(spyHandler).getNewServicesContainer(); return spyHandler; } @@ -143,9 +142,9 @@ private ClusterAwareWriterFailoverHandler getSpyFailoverHandler( */ @Test public void testReconnectToWriter_SlowReaderA() throws SQLException { - when(mockConnectionService.open(refEq(writer), eq(properties))).thenReturn(mockWriterConnection); - when(mockConnectionService.open(refEq(readerB), eq(properties))).thenThrow(SQLException.class); - when(mockConnectionService.open(refEq(newWriterHost), eq(properties))).thenReturn(mockNewWriterConnection); + when(mockPluginService.forceConnect(refEq(writer), eq(properties))).thenReturn(mockWriterConnection); + when(mockPluginService.forceConnect(refEq(readerB), eq(properties))).thenThrow(SQLException.class); + when(mockPluginService.forceConnect(refEq(newWriterHost), eq(properties))).thenReturn(mockNewWriterConnection); when(mockPluginService.getAllHosts()).thenReturn(topology).thenReturn(newTopology); when(mockReaderFailoverHandler.getReaderConnection(ArgumentMatchers.anyList())) @@ -178,14 +177,14 @@ public void testReconnectToWriter_SlowReaderA() throws SQLException { */ @Test public void testReconnectToWriter_taskBDefers() throws SQLException { - when(mockConnectionService.open(refEq(writer), eq(properties))) + when(mockPluginService.forceConnect(refEq(writer), eq(properties))) .thenAnswer( (Answer) invocation -> { Thread.sleep(5000); return mockWriterConnection; }); - when(mockConnectionService.open(refEq(readerB), eq(properties))).thenThrow(SQLException.class); + when(mockPluginService.forceConnect(refEq(readerB), eq(properties))).thenThrow(SQLException.class); when(mockPluginService.getAllHosts()).thenReturn(topology); @@ -215,16 +214,16 @@ public void testReconnectToWriter_taskBDefers() throws SQLException { */ @Test public void testConnectToReaderA_SlowWriter() throws SQLException { - when(mockConnectionService.open(refEq(writer), eq(properties))) + when(mockPluginService.forceConnect(refEq(writer), eq(properties))) .thenAnswer( (Answer) invocation -> { Thread.sleep(5000); return mockWriterConnection; }); - when(mockConnectionService.open(refEq(readerA), eq(properties))).thenReturn(mockReaderAConnection); - when(mockConnectionService.open(refEq(readerB), eq(properties))).thenReturn(mockReaderBConnection); - when(mockConnectionService.open(refEq(newWriterHost), eq(properties))).thenReturn(mockNewWriterConnection); + when(mockPluginService.forceConnect(refEq(readerA), eq(properties))).thenReturn(mockReaderAConnection); + when(mockPluginService.forceConnect(refEq(readerB), eq(properties))).thenReturn(mockReaderBConnection); + when(mockPluginService.forceConnect(refEq(newWriterHost), eq(properties))).thenReturn(mockNewWriterConnection); when(mockPluginService.getAllHosts()).thenReturn(newTopology); @@ -255,10 +254,10 @@ public void testConnectToReaderA_SlowWriter() throws SQLException { */ @Test public void testConnectToReaderA_taskADefers() throws SQLException { - when(mockConnectionService.open(writer, properties)).thenReturn(mockConnection); - when(mockConnectionService.open(refEq(readerA), eq(properties))).thenReturn(mockReaderAConnection); - when(mockConnectionService.open(refEq(readerB), eq(properties))).thenReturn(mockReaderBConnection); - when(mockConnectionService.open(refEq(newWriterHost), eq(properties))) + when(mockPluginService.forceConnect(writer, properties)).thenReturn(mockConnection); + when(mockPluginService.forceConnect(refEq(readerA), eq(properties))).thenReturn(mockReaderAConnection); + when(mockPluginService.forceConnect(refEq(readerB), eq(properties))).thenReturn(mockReaderBConnection); + when(mockPluginService.forceConnect(refEq(newWriterHost), eq(properties))) .thenAnswer( (Answer) invocation -> { @@ -298,16 +297,16 @@ public void testConnectToReaderA_taskADefers() throws SQLException { */ @Test public void testFailedToConnect_failoverTimeout() throws SQLException { - when(mockConnectionService.open(refEq(writer), eq(properties))) + when(mockPluginService.forceConnect(refEq(writer), eq(properties))) .thenAnswer( (Answer) invocation -> { Thread.sleep(30000); return mockWriterConnection; }); - when(mockConnectionService.open(refEq(readerA), eq(properties))).thenReturn(mockReaderAConnection); - when(mockConnectionService.open(refEq(readerB), eq(properties))).thenReturn(mockReaderBConnection); - when(mockConnectionService.open(refEq(newWriterHost), eq(properties))) + when(mockPluginService.forceConnect(refEq(readerA), eq(properties))).thenReturn(mockReaderAConnection); + when(mockPluginService.forceConnect(refEq(readerB), eq(properties))).thenReturn(mockReaderBConnection); + when(mockPluginService.forceConnect(refEq(newWriterHost), eq(properties))) .thenAnswer( (Answer) invocation -> { @@ -348,10 +347,10 @@ public void testFailedToConnect_failoverTimeout() throws SQLException { @Test public void testFailedToConnect_taskAException_taskBWriterException() throws SQLException { final SQLException exception = new SQLException("exception", "08S01", null); - when(mockConnectionService.open(refEq(writer), eq(properties))).thenThrow(exception); - when(mockConnectionService.open(refEq(readerA), eq(properties))).thenReturn(mockReaderAConnection); - when(mockConnectionService.open(refEq(readerB), eq(properties))).thenReturn(mockReaderBConnection); - when(mockConnectionService.open(refEq(newWriterHost), eq(properties))).thenThrow(exception); + when(mockPluginService.forceConnect(refEq(writer), eq(properties))).thenThrow(exception); + when(mockPluginService.forceConnect(refEq(readerA), eq(properties))).thenReturn(mockReaderAConnection); + when(mockPluginService.forceConnect(refEq(readerB), eq(properties))).thenReturn(mockReaderBConnection); + when(mockPluginService.forceConnect(refEq(newWriterHost), eq(properties))).thenThrow(exception); when(mockPluginService.isNetworkException(eq(exception), any())).thenReturn(true); when(mockPluginService.getAllHosts()).thenReturn(newTopology); diff --git a/wrapper/src/test/java/software/amazon/jdbc/plugin/failover/FailoverConnectionPluginTest.java b/wrapper/src/test/java/software/amazon/jdbc/plugin/failover/FailoverConnectionPluginTest.java index 2be3e2858..637793772 100644 --- a/wrapper/src/test/java/software/amazon/jdbc/plugin/failover/FailoverConnectionPluginTest.java +++ b/wrapper/src/test/java/software/amazon/jdbc/plugin/failover/FailoverConnectionPluginTest.java @@ -24,7 +24,6 @@ import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.atLeastOnce; import static org.mockito.Mockito.doNothing; -import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.never; import static org.mockito.Mockito.spy; @@ -64,7 +63,6 @@ import software.amazon.jdbc.util.FullServicesContainer; import software.amazon.jdbc.util.RdsUrlType; import software.amazon.jdbc.util.SqlState; -import software.amazon.jdbc.util.connection.ConnectionService; import software.amazon.jdbc.util.telemetry.GaugeCallable; import software.amazon.jdbc.util.telemetry.TelemetryContext; import software.amazon.jdbc.util.telemetry.TelemetryCounter; @@ -83,7 +81,6 @@ class FailoverConnectionPluginTest { .host("reader1").port(1234).role(HostRole.READER).build()); @Mock FullServicesContainer mockContainer; - @Mock ConnectionService mockConnectionService; @Mock PluginService mockPluginService; @Mock Connection mockConnection; @Mock HostSpec mockHostSpec; @@ -144,7 +141,7 @@ void init() throws SQLException { } @Test - void test_notifyNodeListChanged_withFailoverDisabled() throws SQLException { + void test_notifyNodeListChanged_withFailoverDisabled() { properties.setProperty(FailoverConnectionPlugin.ENABLE_CLUSTER_AWARE_FAILOVER.name, "false"); final Map> changes = new HashMap<>(); @@ -156,7 +153,7 @@ void test_notifyNodeListChanged_withFailoverDisabled() throws SQLException { } @Test - void test_notifyNodeListChanged_withValidConnectionNotInTopology() throws SQLException { + void test_notifyNodeListChanged_withValidConnectionNotInTopology() { final Map> changes = new HashMap<>(); changes.put("cluster-host/", EnumSet.of(NodeChangeOptions.NODE_DELETED)); changes.put("instance/", EnumSet.of(NodeChangeOptions.NODE_ADDED)); @@ -250,8 +247,8 @@ void test_failoverReader_withValidFailedHostSpec_successFailover() throws SQLExc spyPlugin.initHostProvider( mockHostListProviderService, mockInitHostProviderFunc, - (connectionService) -> mockReaderFailoverHandler, - (connectionService) -> mockWriterFailoverHandler); + () -> mockReaderFailoverHandler, + () -> mockWriterFailoverHandler); final FailoverConnectionPlugin spyPlugin = spy(this.spyPlugin); doNothing().when(spyPlugin).updateTopology(true); @@ -279,8 +276,8 @@ void test_failoverReader_withNoFailedHostSpec_withException() throws SQLExceptio spyPlugin.initHostProvider( mockHostListProviderService, mockInitHostProviderFunc, - (connectionService) -> mockReaderFailoverHandler, - (connectionService) -> mockWriterFailoverHandler); + () -> mockReaderFailoverHandler, + () -> mockWriterFailoverHandler); assertThrows(SQLException.class, () -> spyPlugin.failoverReader(null)); verify(mockReaderFailoverHandler).failover(eq(hosts), eq(null)); @@ -301,8 +298,8 @@ void test_failoverWriter_failedFailover_throwsException() throws SQLException { spyPlugin.initHostProvider( mockHostListProviderService, mockInitHostProviderFunc, - (connectionService) -> mockReaderFailoverHandler, - (connectionService) -> mockWriterFailoverHandler); + () -> mockReaderFailoverHandler, + () -> mockWriterFailoverHandler); assertThrows(SQLException.class, () -> spyPlugin.failoverWriter()); verify(mockWriterFailoverHandler).failover(eq(hosts)); @@ -323,8 +320,8 @@ void test_failoverWriter_failedFailover_withNoResult() throws SQLException { spyPlugin.initHostProvider( mockHostListProviderService, mockInitHostProviderFunc, - (connectionService) -> mockReaderFailoverHandler, - (connectionService) -> mockWriterFailoverHandler); + () -> mockReaderFailoverHandler, + () -> mockWriterFailoverHandler); final SQLException exception = assertThrows(SQLException.class, () -> spyPlugin.failoverWriter()); assertEquals(SqlState.CONNECTION_UNABLE_TO_CONNECT.getState(), exception.getSQLState()); @@ -342,8 +339,8 @@ void test_failoverWriter_successFailover() throws SQLException { spyPlugin.initHostProvider( mockHostListProviderService, mockInitHostProviderFunc, - (connectionService) -> mockReaderFailoverHandler, - (connectionService) -> mockWriterFailoverHandler); + () -> mockReaderFailoverHandler, + () -> mockWriterFailoverHandler); final SQLException exception = assertThrows(FailoverSuccessSQLException.class, () -> spyPlugin.failoverWriter()); assertEquals(SqlState.COMMUNICATION_LINK_CHANGED.getState(), exception.getSQLState()); @@ -352,7 +349,7 @@ void test_failoverWriter_successFailover() throws SQLException { } @Test - void test_invalidCurrentConnection_withNoConnection() throws SQLException { + void test_invalidCurrentConnection_withNoConnection() { when(mockPluginService.getCurrentConnection()).thenReturn(null); initializePlugin(); spyPlugin.invalidateCurrentConnection(); @@ -377,7 +374,7 @@ void test_invalidateCurrentConnection_inTransaction() throws SQLException { } @Test - void test_invalidateCurrentConnection_notInTransaction() throws SQLException { + void test_invalidateCurrentConnection_notInTransaction() { when(mockPluginService.isInTransaction()).thenReturn(false); when(mockHostSpec.getHost()).thenReturn("host"); when(mockHostSpec.getPort()).thenReturn(123); @@ -438,10 +435,9 @@ void test_execute_withDirectExecute() throws SQLException { verify(mockHostListProvider, never()).getRdsUrlType(); } - private void initializePlugin() throws SQLException { + private void initializePlugin() { spyPlugin = spy(new FailoverConnectionPlugin(mockContainer, properties)); spyPlugin.setWriterFailoverHandler(mockWriterFailoverHandler); spyPlugin.setReaderFailoverHandler(mockReaderFailoverHandler); - doReturn(mockConnectionService).when(spyPlugin).getConnectionService(); } } diff --git a/wrapper/src/test/java/software/amazon/jdbc/plugin/federatedauth/FederatedAuthPluginTest.java b/wrapper/src/test/java/software/amazon/jdbc/plugin/federatedauth/FederatedAuthPluginTest.java index 7b72dae6e..f137084e1 100644 --- a/wrapper/src/test/java/software/amazon/jdbc/plugin/federatedauth/FederatedAuthPluginTest.java +++ b/wrapper/src/test/java/software/amazon/jdbc/plugin/federatedauth/FederatedAuthPluginTest.java @@ -50,6 +50,7 @@ import software.amazon.jdbc.plugin.iam.IamAuthConnectionPlugin; import software.amazon.jdbc.plugin.iam.IamTokenUtility; import software.amazon.jdbc.util.RdsUtils; +import software.amazon.jdbc.util.connection.ConnectConfig; import software.amazon.jdbc.util.telemetry.TelemetryContext; import software.amazon.jdbc.util.telemetry.TelemetryCounter; import software.amazon.jdbc.util.telemetry.TelemetryFactory; @@ -57,7 +58,6 @@ class FederatedAuthPluginTest { private static final int DEFAULT_PORT = 1234; - private static final String DRIVER_PROTOCOL = "jdbc:postgresql:"; private static final String HOST = "pg.testdb.us-east-2.rds.amazonaws.com"; private static final String IAM_HOST = "pg-123.testdb.us-east-2.rds.amazonaws.com"; private static final HostSpec HOST_SPEC = @@ -77,6 +77,7 @@ class FederatedAuthPluginTest { @Mock private IamTokenUtility mockIamTokenUtils; @Mock private CompletableFuture completableFuture; @Mock private AwsCredentialsIdentity mockAwsCredentialsIdentity; + @Mock private ConnectConfig mockConnectConfig; private Properties props; private AutoCloseable closeable; @@ -103,6 +104,7 @@ public void init() throws ExecutionException, InterruptedException, SQLException when(mockCredentialsProviderFactory.getAwsCredentialsProvider(any(), any(), any())) .thenReturn(mockAwsCredentialsProvider); when(mockAwsCredentialsProvider.resolveIdentity()).thenReturn(completableFuture); + when(mockConnectConfig.getProps()).thenReturn(props); when(completableFuture.get()).thenReturn(mockAwsCredentialsIdentity); } @@ -119,7 +121,7 @@ void testCachedToken() throws SQLException { String key = "us-east-2:pg.testdb.us-east-2.rds.amazonaws.com:" + DEFAULT_PORT + ":iamUser"; FederatedAuthCacheHolder.tokenCache.put(key, TEST_TOKEN_INFO); - plugin.connect(DRIVER_PROTOCOL, HOST_SPEC, props, true, mockLambda); + plugin.connect(mockConnectConfig, HOST_SPEC, true, mockLambda); assertEquals(DB_USER, PropertyDefinition.USER.getString(props)); assertEquals(TEST_TOKEN, PropertyDefinition.PASSWORD.getString(props)); @@ -136,7 +138,7 @@ void testExpiredCachedToken() throws SQLException { someExpiredToken, Instant.now().minusMillis(300000)); FederatedAuthCacheHolder.tokenCache.put(key, expiredTokenInfo); - spyPlugin.connect(DRIVER_PROTOCOL, HOST_SPEC, props, true, mockLambda); + spyPlugin.connect(mockConnectConfig, HOST_SPEC, true, mockLambda); verify(mockIamTokenUtils).generateAuthenticationToken(mockAwsCredentialsProvider, Region.US_EAST_2, HOST_SPEC.getHost(), @@ -151,7 +153,7 @@ void testNoCachedToken() throws SQLException { FederatedAuthPlugin spyPlugin = Mockito.spy( new FederatedAuthPlugin(mockPluginService, mockCredentialsProviderFactory, mockRdsUtils, mockIamTokenUtils)); - spyPlugin.connect(DRIVER_PROTOCOL, HOST_SPEC, props, true, mockLambda); + spyPlugin.connect(mockConnectConfig, HOST_SPEC, true, mockLambda); verify(mockIamTokenUtils).generateAuthenticationToken( mockAwsCredentialsProvider, Region.US_EAST_2, @@ -178,7 +180,7 @@ void testSpecifiedIamHostPortRegion() throws SQLException { FederatedAuthPlugin plugin = new FederatedAuthPlugin(mockPluginService, mockCredentialsProviderFactory, mockRdsUtils, mockIamTokenUtils); - plugin.connect(DRIVER_PROTOCOL, HOST_SPEC, props, true, mockLambda); + plugin.connect(mockConnectConfig, HOST_SPEC, true, mockLambda); assertEquals(DB_USER, PropertyDefinition.USER.getString(props)); assertEquals(TEST_TOKEN, PropertyDefinition.PASSWORD.getString(props)); @@ -197,7 +199,7 @@ void testIdpCredentialsFallback() throws SQLException { String key = "us-east-2:pg.testdb.us-east-2.rds.amazonaws.com:" + DEFAULT_PORT + ":iamUser"; FederatedAuthCacheHolder.tokenCache.put(key, TEST_TOKEN_INFO); - plugin.connect(DRIVER_PROTOCOL, HOST_SPEC, props, true, mockLambda); + plugin.connect(mockConnectConfig, HOST_SPEC, true, mockLambda); assertEquals(DB_USER, PropertyDefinition.USER.getString(props)); assertEquals(TEST_TOKEN, PropertyDefinition.PASSWORD.getString(props)); @@ -211,7 +213,7 @@ public void testUsingIamHost() throws SQLException { FederatedAuthPlugin spyPlugin = Mockito.spy( new FederatedAuthPlugin(mockPluginService, mockCredentialsProviderFactory, mockRdsUtils, mockIamTokenUtils)); - spyPlugin.connect(DRIVER_PROTOCOL, HOST_SPEC, props, true, mockLambda); + spyPlugin.connect(mockConnectConfig, HOST_SPEC, true, mockLambda); assertEquals(DB_USER, PropertyDefinition.USER.getString(props)); assertEquals(TEST_TOKEN, PropertyDefinition.PASSWORD.getString(props)); diff --git a/wrapper/src/test/java/software/amazon/jdbc/plugin/federatedauth/OktaAuthPluginTest.java b/wrapper/src/test/java/software/amazon/jdbc/plugin/federatedauth/OktaAuthPluginTest.java index 910e06fe1..039ce76bd 100644 --- a/wrapper/src/test/java/software/amazon/jdbc/plugin/federatedauth/OktaAuthPluginTest.java +++ b/wrapper/src/test/java/software/amazon/jdbc/plugin/federatedauth/OktaAuthPluginTest.java @@ -47,6 +47,7 @@ import software.amazon.jdbc.plugin.iam.IamAuthConnectionPlugin; import software.amazon.jdbc.plugin.iam.IamTokenUtility; import software.amazon.jdbc.util.RdsUtils; +import software.amazon.jdbc.util.connection.ConnectConfig; import software.amazon.jdbc.util.telemetry.TelemetryContext; import software.amazon.jdbc.util.telemetry.TelemetryCounter; import software.amazon.jdbc.util.telemetry.TelemetryFactory; @@ -54,7 +55,6 @@ class OktaAuthPluginTest { private static final int DEFAULT_PORT = 1234; - private static final String DRIVER_PROTOCOL = "jdbc:postgresql:"; private static final String HOST = "pg.testdb.us-east-2.rds.amazonaws.com"; private static final String IAM_HOST = "pg-123.testdb.us-east-2.rds.amazonaws.com"; @@ -73,6 +73,7 @@ class OktaAuthPluginTest { @Mock private AwsCredentialsProvider mockAwsCredentialsProvider; @Mock private RdsUtils mockRdsUtils; @Mock private IamTokenUtility mockIamTokenUtils; + @Mock private ConnectConfig mockConnectConfig; private Properties props; private AutoCloseable closeable; @@ -95,6 +96,7 @@ void setUp() throws SQLException { when(mockPluginService.getDialect()).thenReturn(mockDialect); when(mockDialect.getDefaultPort()).thenReturn(DEFAULT_PORT); when(mockPluginService.getTelemetryFactory()).thenReturn(mockTelemetryFactory); + when(mockConnectConfig.getProps()).thenReturn(props); when(mockTelemetryFactory.createCounter(any())).thenReturn(mockTelemetryCounter); when(mockTelemetryFactory.openTelemetryContext(any(), any())).thenReturn(mockTelemetryContext); when(mockCredentialsProviderFactory.getAwsCredentialsProvider(any(), any(), any())) @@ -114,7 +116,7 @@ void testCachedToken() throws SQLException { String key = "us-east-2:pg.testdb.us-east-2.rds.amazonaws.com:" + DEFAULT_PORT + ":iamUser"; OktaAuthCacheHolder.tokenCache.put(key, TEST_TOKEN_INFO); - plugin.connect(DRIVER_PROTOCOL, HOST_SPEC, props, true, mockLambda); + plugin.connect(mockConnectConfig, HOST_SPEC, true, mockLambda); assertEquals(DB_USER, PropertyDefinition.USER.getString(props)); assertEquals(TEST_TOKEN, PropertyDefinition.PASSWORD.getString(props)); @@ -131,7 +133,7 @@ void testExpiredCachedToken() throws SQLException { someExpiredToken, Instant.now().minusMillis(300000)); OktaAuthCacheHolder.tokenCache.put(key, expiredTokenInfo); - spyPlugin.connect(DRIVER_PROTOCOL, HOST_SPEC, props, true, mockLambda); + spyPlugin.connect(mockConnectConfig, HOST_SPEC, true, mockLambda); verify(mockIamTokenUtils).generateAuthenticationToken(mockAwsCredentialsProvider, Region.US_EAST_2, HOST_SPEC.getHost(), @@ -146,7 +148,7 @@ void testNoCachedToken() throws SQLException { final OktaAuthPlugin spyPlugin = new OktaAuthPlugin(mockPluginService, mockCredentialsProviderFactory, mockRdsUtils, mockIamTokenUtils); - spyPlugin.connect(DRIVER_PROTOCOL, HOST_SPEC, props, true, mockLambda); + spyPlugin.connect(mockConnectConfig, HOST_SPEC, true, mockLambda); verify(mockIamTokenUtils).generateAuthenticationToken( mockAwsCredentialsProvider, Region.US_EAST_2, @@ -173,7 +175,7 @@ void testSpecifiedIamHostPortRegion() throws SQLException { OktaAuthPlugin plugin = new OktaAuthPlugin(mockPluginService, mockCredentialsProviderFactory, mockRdsUtils, mockIamTokenUtils); - plugin.connect(DRIVER_PROTOCOL, HOST_SPEC, props, true, mockLambda); + plugin.connect(mockConnectConfig, HOST_SPEC, true, mockLambda); assertEquals(DB_USER, PropertyDefinition.USER.getString(props)); assertEquals(TEST_TOKEN, PropertyDefinition.PASSWORD.getString(props)); @@ -192,7 +194,7 @@ void testIdpCredentialsFallback() throws SQLException { final String key = "us-east-2:pg.testdb.us-east-2.rds.amazonaws.com:" + DEFAULT_PORT + ":iamUser"; OktaAuthCacheHolder.tokenCache.put(key, TEST_TOKEN_INFO); - plugin.connect(DRIVER_PROTOCOL, HOST_SPEC, props, true, mockLambda); + plugin.connect(mockConnectConfig, HOST_SPEC, true, mockLambda); assertEquals(DB_USER, PropertyDefinition.USER.getString(props)); assertEquals(TEST_TOKEN, PropertyDefinition.PASSWORD.getString(props)); @@ -206,7 +208,7 @@ public void testUsingIamHost() throws SQLException { OktaAuthPlugin spyPlugin = Mockito.spy( new OktaAuthPlugin(mockPluginService, mockCredentialsProviderFactory, mockRdsUtils, mockIamTokenUtils)); - spyPlugin.connect(DRIVER_PROTOCOL, HOST_SPEC, props, true, mockLambda); + spyPlugin.connect(mockConnectConfig, HOST_SPEC, true, mockLambda); assertEquals(DB_USER, PropertyDefinition.USER.getString(props)); assertEquals(TEST_TOKEN, PropertyDefinition.PASSWORD.getString(props)); diff --git a/wrapper/src/test/java/software/amazon/jdbc/plugin/iam/IamAuthConnectionPluginTest.java b/wrapper/src/test/java/software/amazon/jdbc/plugin/iam/IamAuthConnectionPluginTest.java index 92a0c0ff6..0d7361a87 100644 --- a/wrapper/src/test/java/software/amazon/jdbc/plugin/iam/IamAuthConnectionPluginTest.java +++ b/wrapper/src/test/java/software/amazon/jdbc/plugin/iam/IamAuthConnectionPluginTest.java @@ -44,20 +44,18 @@ import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider; import software.amazon.awssdk.auth.credentials.DefaultCredentialsProvider; import software.amazon.awssdk.regions.Region; -import software.amazon.awssdk.services.rds.RdsUtilities; -import software.amazon.awssdk.services.rds.TestDefaultRdsUtilities; import software.amazon.jdbc.Driver; import software.amazon.jdbc.HostSpec; import software.amazon.jdbc.HostSpecBuilder; import software.amazon.jdbc.JdbcCallable; import software.amazon.jdbc.PluginService; import software.amazon.jdbc.PropertyDefinition; -import software.amazon.jdbc.authentication.AwsCredentialsManager; import software.amazon.jdbc.dialect.Dialect; -import software.amazon.jdbc.hostavailability.HostAvailabilityStrategy; import software.amazon.jdbc.hostavailability.SimpleHostAvailabilityStrategy; import software.amazon.jdbc.plugin.TokenInfo; +import software.amazon.jdbc.targetdriverdialect.TargetDriverDialect; import software.amazon.jdbc.util.RdsUtils; +import software.amazon.jdbc.util.connection.ConnectConfig; import software.amazon.jdbc.util.telemetry.TelemetryContext; import software.amazon.jdbc.util.telemetry.TelemetryCounter; import software.amazon.jdbc.util.telemetry.TelemetryFactory; @@ -73,8 +71,8 @@ class IamAuthConnectionPluginTest { + DEFAULT_PG_PORT + ":postgresqlUser"; private static final String MYSQL_CACHE_KEY = "us-east-2:mysql.testdb.us-east-2.rds.amazonaws.com:" + DEFAULT_MYSQL_PORT + ":mysqlUser"; - private static final String PG_DRIVER_PROTOCOL = "jdbc:postgresql:"; - private static final String MYSQL_DRIVER_PROTOCOL = "jdbc:mysql:"; + private static final String PG_DRIVER_PROTOCOL = "jdbc:postgresql://"; + private static final String MYSQL_DRIVER_PROTOCOL = "jdbc:mysql://"; private static final HostSpec PG_HOST_SPEC = new HostSpecBuilder(new SimpleHostAvailabilityStrategy()) .host("pg.testdb.us-east-2.rds.amazonaws.com").build(); private static final HostSpec PG_HOST_SPEC_WITH_PORT = new HostSpecBuilder(new SimpleHostAvailabilityStrategy()) @@ -91,6 +89,7 @@ class IamAuthConnectionPluginTest { @Mock TelemetryContext mockTelemetryContext; @Mock JdbcCallable mockLambda; @Mock Dialect mockDialect; + @Mock TargetDriverDialect mockDriverDialect; @Mock private RdsUtils mockRdsUtils; @Mock private IamTokenUtility mockIamTokenUtils; private AutoCloseable closable; @@ -263,7 +262,8 @@ public void testTokenSetInProps(final String protocol, final HostSpec hostSpec) IamAuthConnectionPlugin targetPlugin = new IamAuthConnectionPlugin(mockPluginService, mockIamTokenUtils); doThrow(new SQLException()).when(mockLambda).call(); - assertThrows(SQLException.class, () -> targetPlugin.connect(protocol, hostSpec, props, true, mockLambda)); + ConnectConfig connectConfig = new ConnectConfig(protocol + hostSpec.getHost(), mockDriverDialect, props); + assertThrows(SQLException.class, () -> targetPlugin.connect(connectConfig, hostSpec, true, mockLambda)); verify(mockLambda, times(1)).call(); assertEquals(TEST_TOKEN, PropertyDefinition.PASSWORD.getString(props)); @@ -282,8 +282,9 @@ private void testGenerateToken( doThrow(new SQLException()).when(mockLambda).call(); + ConnectConfig connectConfig = new ConnectConfig(protocol + hostSpec.getHost(), mockDriverDialect, props); assertThrows(SQLException.class, - () -> spyPlugin.connect(protocol, hostSpec, props, true, mockLambda)); + () -> spyPlugin.connect(connectConfig, hostSpec, true, mockLambda)); verify(mockIamTokenUtils).generateAuthenticationToken( any(DefaultCredentialsProvider.class), diff --git a/wrapper/src/test/java/software/amazon/jdbc/plugin/limitless/LimitlessConnectionPluginTest.java b/wrapper/src/test/java/software/amazon/jdbc/plugin/limitless/LimitlessConnectionPluginTest.java index 411233100..ef60fad94 100644 --- a/wrapper/src/test/java/software/amazon/jdbc/plugin/limitless/LimitlessConnectionPluginTest.java +++ b/wrapper/src/test/java/software/amazon/jdbc/plugin/limitless/LimitlessConnectionPluginTest.java @@ -16,7 +16,7 @@ package software.amazon.jdbc.plugin.limitless; -import static org.junit.Assert.assertEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.doAnswer; @@ -33,10 +33,8 @@ import org.junit.jupiter.api.Test; import org.mockito.Mock; import org.mockito.MockitoAnnotations; -import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; import software.amazon.jdbc.HostListProvider; -import software.amazon.jdbc.HostRole; import software.amazon.jdbc.HostSpec; import software.amazon.jdbc.HostSpecBuilder; import software.amazon.jdbc.JdbcCallable; @@ -45,18 +43,17 @@ import software.amazon.jdbc.dialect.Dialect; import software.amazon.jdbc.dialect.PgDialect; import software.amazon.jdbc.hostavailability.SimpleHostAvailabilityStrategy; +import software.amazon.jdbc.util.connection.ConnectConfig; public class LimitlessConnectionPluginTest { - private static final String DRIVER_PROTOCOL = "jdbc:postgresql:"; private static final HostSpec INPUT_HOST_SPEC = new HostSpecBuilder(new SimpleHostAvailabilityStrategy()) .host("pg.testdb.us-east-2.rds.amazonaws.com").build(); private static final String CLUSTER_ID = "someClusterId"; - private static final HostSpec expectedSelectedHostSpec = new HostSpecBuilder(new SimpleHostAvailabilityStrategy()) - .host("expected-selected-instance").role(HostRole.WRITER).weight(Long.MAX_VALUE).build(); private static final Dialect supportedDialect = new AuroraPgDialect(); @Mock JdbcCallable mockConnectFuncLambda; + @Mock ConnectConfig mockConnectConfig; @Mock private Connection mockConnection; @Mock private PluginService mockPluginService; @Mock private HostListProvider mockHostListProvider; @@ -86,16 +83,14 @@ void cleanUp() throws Exception { @Test void testConnect() throws SQLException { - doAnswer(new Answer() { - public Void answer(InvocationOnMock invocation) { - LimitlessConnectionContext context = (LimitlessConnectionContext) invocation.getArguments()[0]; - context.setConnection(mockConnection); - return null; - } + doAnswer((Answer) invocation -> { + LimitlessConnectionContext context = (LimitlessConnectionContext) invocation.getArguments()[0]; + context.setConnection(mockConnection); + return null; }).when(mockLimitlessRouterService).establishConnection(any()); final Connection expectedConnection = mockConnection; - final Connection actualConnection = plugin.connect(DRIVER_PROTOCOL, INPUT_HOST_SPEC, props, true, + final Connection actualConnection = plugin.connect(mockConnectConfig, INPUT_HOST_SPEC, true, mockConnectFuncLambda); assertEquals(expectedConnection, actualConnection); @@ -108,17 +103,15 @@ public Void answer(InvocationOnMock invocation) { @Test void testConnectGivenNullConnection() throws SQLException { - doAnswer(new Answer() { - public Void answer(InvocationOnMock invocation) { - LimitlessConnectionContext context = (LimitlessConnectionContext) invocation.getArguments()[0]; - context.setConnection(null); - return null; - } + doAnswer((Answer) invocation -> { + LimitlessConnectionContext context = (LimitlessConnectionContext) invocation.getArguments()[0]; + context.setConnection(null); + return null; }).when(mockLimitlessRouterService).establishConnection(any()); assertThrows( SQLException.class, - () -> plugin.connect(DRIVER_PROTOCOL, INPUT_HOST_SPEC, props, true, mockConnectFuncLambda)); + () -> plugin.connect(mockConnectConfig, INPUT_HOST_SPEC, true, mockConnectFuncLambda)); verify(mockPluginService, times(1)).getDialect(); verify(mockConnectFuncLambda, times(0)).call(); @@ -134,7 +127,7 @@ void testConnectGivenUnsupportedDialect() throws SQLException { assertThrows( UnsupportedOperationException.class, - () -> plugin.connect(DRIVER_PROTOCOL, INPUT_HOST_SPEC, props, true, mockConnectFuncLambda)); + () -> plugin.connect(mockConnectConfig, INPUT_HOST_SPEC, true, mockConnectFuncLambda)); verify(mockPluginService, times(2)).getDialect(); verify(mockConnectFuncLambda, times(1)).call(); @@ -149,7 +142,7 @@ void testConnectGivenSupportedDialectAfterRefresh() throws SQLException { when(mockPluginService.getDialect()).thenReturn(unsupportedDialect, supportedDialect); final Connection expectedConnection = mockConnection; - final Connection actualConnection = plugin.connect(DRIVER_PROTOCOL, INPUT_HOST_SPEC, props, true, + final Connection actualConnection = plugin.connect(mockConnectConfig, INPUT_HOST_SPEC, true, mockConnectFuncLambda); assertEquals(expectedConnection, actualConnection); diff --git a/wrapper/src/test/java/software/amazon/jdbc/plugin/limitless/LimitlessRouterServiceImplTest.java b/wrapper/src/test/java/software/amazon/jdbc/plugin/limitless/LimitlessRouterServiceImplTest.java index b37df47a8..7c12f83fb 100644 --- a/wrapper/src/test/java/software/amazon/jdbc/plugin/limitless/LimitlessRouterServiceImplTest.java +++ b/wrapper/src/test/java/software/amazon/jdbc/plugin/limitless/LimitlessRouterServiceImplTest.java @@ -37,6 +37,7 @@ import org.junit.jupiter.api.Test; import org.mockito.Mock; import org.mockito.MockitoAnnotations; +import software.amazon.jdbc.ConnectionProvider; import software.amazon.jdbc.HighestWeightHostSelector; import software.amazon.jdbc.HostListProvider; import software.amazon.jdbc.HostRole; @@ -61,6 +62,7 @@ class LimitlessRouterServiceImplTest { private static final String CLUSTER_ID = "someClusterId"; @Mock private EventPublisher mockEventPublisher; @Mock private MonitorService mockMonitorService; + @Mock private ConnectionProvider mockConnectionProvider; @Mock private TelemetryFactory mockTelemetryFactory; @Mock private PluginService mockPluginService; @Mock private HostListProvider mockHostListProvider; @@ -84,7 +86,8 @@ public void init() throws SQLException { when(mockHostListProvider.getClusterId()).thenReturn(CLUSTER_ID); this.storageService = new StorageServiceImpl(mockEventPublisher); - servicesContainer = new FullServicesContainerImpl(this.storageService, mockMonitorService, mockTelemetryFactory); + servicesContainer = new FullServicesContainerImpl( + this.storageService, mockMonitorService, mockConnectionProvider, mockTelemetryFactory); servicesContainer.setPluginService(mockPluginService); } diff --git a/wrapper/src/test/java/software/amazon/jdbc/plugin/readwritesplitting/ReadWriteSplittingPluginTest.java b/wrapper/src/test/java/software/amazon/jdbc/plugin/readwritesplitting/ReadWriteSplittingPluginTest.java index ff7282483..22559d69e 100644 --- a/wrapper/src/test/java/software/amazon/jdbc/plugin/readwritesplitting/ReadWriteSplittingPluginTest.java +++ b/wrapper/src/test/java/software/amazon/jdbc/plugin/readwritesplitting/ReadWriteSplittingPluginTest.java @@ -30,7 +30,6 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; -import com.zaxxer.hikari.HikariConfig; import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; @@ -45,7 +44,6 @@ import org.junit.jupiter.api.Test; import org.mockito.Mock; import org.mockito.MockitoAnnotations; -import software.amazon.jdbc.HikariPooledConnectionProvider; import software.amazon.jdbc.HostListProviderService; import software.amazon.jdbc.HostRole; import software.amazon.jdbc.HostSpec; @@ -54,14 +52,12 @@ import software.amazon.jdbc.NodeChangeOptions; import software.amazon.jdbc.OldConnectionSuggestedAction; import software.amazon.jdbc.PluginService; -import software.amazon.jdbc.PropertyDefinition; -import software.amazon.jdbc.dialect.Dialect; import software.amazon.jdbc.hostavailability.SimpleHostAvailabilityStrategy; import software.amazon.jdbc.plugin.failover.FailoverSuccessSQLException; import software.amazon.jdbc.util.SqlState; +import software.amazon.jdbc.util.connection.ConnectConfig; public class ReadWriteSplittingPluginTest { - private static final String TEST_PROTOCOL = "jdbc:postgresql:"; private static final int TEST_PORT = 5432; private static final Properties defaultProps = new Properties(); @@ -96,7 +92,6 @@ public class ReadWriteSplittingPluginTest { @Mock private JdbcCallable mockConnectFunc; @Mock private JdbcCallable mockSqlFunction; @Mock private PluginService mockPluginService; - @Mock private Dialect mockDialect; @Mock private HostListProviderService mockHostListProviderService; @Mock private Connection mockWriterConn; @Mock private Connection mockNewWriterConn; @@ -106,6 +101,7 @@ public class ReadWriteSplittingPluginTest { @Mock private Connection mockReaderConn3; @Mock private Statement mockStatement; @Mock private ResultSet mockResultSet; + @Mock private ConnectConfig mockConnectConfig; @Mock private EnumSet mockChanges; @BeforeEach @@ -406,7 +402,7 @@ public void testConnectNonInitialConnection() throws SQLException { null); final Connection connection = - plugin.connect(TEST_PROTOCOL, writerHostSpec, defaultProps, false, this.mockConnectFunc); + plugin.connect(mockConnectConfig, writerHostSpec, false, this.mockConnectFunc); assertEquals(mockWriterConn, connection); verify(mockConnectFunc).call(); @@ -425,9 +421,8 @@ public void testConnectRdsInstanceUrl() throws SQLException { null, null); final Connection connection = plugin.connect( - TEST_PROTOCOL, + mockConnectConfig, instanceUrlHostSpec, - defaultProps, true, this.mockConnectFunc); @@ -448,7 +443,7 @@ public void testConnectReaderIpUrl() throws SQLException { null, null); final Connection connection = - plugin.connect(TEST_PROTOCOL, ipUrlHostSpec, defaultProps, true, this.mockConnectFunc); + plugin.connect(mockConnectConfig, ipUrlHostSpec, true, this.mockConnectFunc); assertEquals(mockReaderConn1, connection); verify(mockConnectFunc).call(); @@ -464,7 +459,7 @@ public void testConnectClusterUrl() throws SQLException { null, null); final Connection connection = - plugin.connect(TEST_PROTOCOL, clusterUrlHostSpec, defaultProps, true, this.mockConnectFunc); + plugin.connect(mockConnectConfig, clusterUrlHostSpec, true, this.mockConnectFunc); assertEquals(mockWriterConn, connection); verify(mockConnectFunc).call(); @@ -485,9 +480,8 @@ public void testConnect_errorUpdatingHostSpec() throws SQLException { assertThrows( SQLException.class, () -> plugin.connect( - TEST_PROTOCOL, + mockConnectConfig, ipUrlHostSpec, - defaultProps, true, this.mockConnectFunc)); verify(mockHostListProviderService, times(0)).setInitialConnectionHostSpec(any(HostSpec.class)); @@ -539,7 +533,7 @@ public void testExecuteClearWarningsOnClosedConnectionsIsNotCalled() throws SQLE } @Test - public void testExecuteClearWarningsOnNullConnectionsIsNotCalled() throws SQLException { + public void testExecuteClearWarningsOnNullConnectionsIsNotCalled() { final ReadWriteSplittingPlugin plugin = new ReadWriteSplittingPlugin( mockPluginService, defaultProps, @@ -610,18 +604,4 @@ public void testClosePooledWriterConnectionAfterSetReadOnly() throws SQLExceptio verify(spyPlugin, times(1)).closeConnectionIfIdle(eq(mockWriterConn)); } - - private static HikariConfig getHikariConfig(HostSpec hostSpec, Properties props) { - final HikariConfig config = new HikariConfig(); - config.setMaximumPoolSize(3); - config.setInitializationFailTimeout(75000); - config.setConnectionTimeout(10000); - return config; - } - - private static String getPoolKey(HostSpec hostSpec, Properties props) { - final String user = props.getProperty(PropertyDefinition.USER.name); - final String somePropertyValue = props.getProperty("somePropertyValue"); - return hostSpec.getUrl() + user + somePropertyValue; - } } diff --git a/wrapper/src/test/java/software/amazon/jdbc/states/SessionStateServiceImplTests.java b/wrapper/src/test/java/software/amazon/jdbc/states/SessionStateServiceImplTests.java index 8ab28907d..ed391f4cf 100644 --- a/wrapper/src/test/java/software/amazon/jdbc/states/SessionStateServiceImplTests.java +++ b/wrapper/src/test/java/software/amazon/jdbc/states/SessionStateServiceImplTests.java @@ -17,7 +17,6 @@ package software.amazon.jdbc.states; import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertThrows; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.times; diff --git a/wrapper/src/test/java/software/amazon/jdbc/util/ConnectionUrlParserTest.java b/wrapper/src/test/java/software/amazon/jdbc/util/ConnectionUrlParserTest.java index 082d2f78b..056fccd78 100644 --- a/wrapper/src/test/java/software/amazon/jdbc/util/ConnectionUrlParserTest.java +++ b/wrapper/src/test/java/software/amazon/jdbc/util/ConnectionUrlParserTest.java @@ -32,7 +32,6 @@ import software.amazon.jdbc.HostRole; import software.amazon.jdbc.HostSpec; import software.amazon.jdbc.HostSpecBuilder; -import software.amazon.jdbc.PropertyDefinition; import software.amazon.jdbc.hostavailability.SimpleHostAvailabilityStrategy; class ConnectionUrlParserTest { diff --git a/wrapper/src/test/java/software/amazon/jdbc/util/monitoring/MonitorServiceImplTest.java b/wrapper/src/test/java/software/amazon/jdbc/util/monitoring/MonitorServiceImplTest.java index 38400e9a6..605f00576 100644 --- a/wrapper/src/test/java/software/amazon/jdbc/util/monitoring/MonitorServiceImplTest.java +++ b/wrapper/src/test/java/software/amazon/jdbc/util/monitoring/MonitorServiceImplTest.java @@ -21,8 +21,8 @@ import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.spy; @@ -30,47 +30,40 @@ import java.sql.SQLException; import java.util.Collections; import java.util.HashSet; -import java.util.Properties; import java.util.concurrent.TimeUnit; import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import software.amazon.jdbc.ConnectionProvider; -import software.amazon.jdbc.dialect.Dialect; import software.amazon.jdbc.plugin.customendpoint.CustomEndpointMonitorImpl; -import software.amazon.jdbc.targetdriverdialect.TargetDriverDialect; -import software.amazon.jdbc.util.connection.ConnectionService; +import software.amazon.jdbc.util.FullServicesContainer; +import software.amazon.jdbc.util.connection.ConnectConfig; import software.amazon.jdbc.util.events.EventPublisher; import software.amazon.jdbc.util.storage.StorageService; import software.amazon.jdbc.util.telemetry.TelemetryFactory; class MonitorServiceImplTest { + @Mock FullServicesContainer mockServicesContainer; @Mock StorageService mockStorageService; - @Mock ConnectionService mockConnectionService; + @Mock ConnectConfig mockConnectConfig; @Mock ConnectionProvider mockConnectionProvider; @Mock TelemetryFactory mockTelemetryFactory; - @Mock TargetDriverDialect mockTargetDriverDialect; - @Mock Dialect mockDbDialect; @Mock EventPublisher mockPublisher; MonitorServiceImpl spyMonitorService; private AutoCloseable closeable; @BeforeEach - void setUp() { + void setUp() throws SQLException { closeable = MockitoAnnotations.openMocks(this); spyMonitorService = spy(new MonitorServiceImpl(mockPublisher)); doNothing().when(spyMonitorService).initCleanupThread(anyInt()); - - try { - doReturn(mockConnectionService).when(spyMonitorService) - .getConnectionService(any(), any(), any(), any(), any(), any(), any(), any()); - } catch (SQLException e) { - Assertions.fail( - "Encountered exception while stubbing MonitorServiceImpl#getConnectionService: " + e.getMessage()); - } + doReturn(mockServicesContainer).when(spyMonitorService).getNewServicesContainer( + eq(mockStorageService), + eq(mockConnectionProvider), + eq(mockTelemetryFactory), + eq(mockConnectConfig)); } @AfterEach @@ -95,12 +88,8 @@ public void testMonitorError_monitorReCreated() throws SQLException, Interrupted mockStorageService, mockTelemetryFactory, mockConnectionProvider, - "jdbc:postgresql://somehost/somedb", - "someProtocol", - mockTargetDriverDialect, - mockDbDialect, - new Properties(), - (connectionService, pluginService) -> new NoOpMonitor(spyMonitorService, 30) + mockConnectConfig, + (mockServicesContainer) -> new NoOpMonitor(30) ); Monitor storedMonitor = spyMonitorService.get(NoOpMonitor.class, key); @@ -139,12 +128,8 @@ public void testMonitorStuck_monitorReCreated() throws SQLException, Interrupted mockStorageService, mockTelemetryFactory, mockConnectionProvider, - "jdbc:postgresql://somehost/somedb", - "someProtocol", - mockTargetDriverDialect, - mockDbDialect, - new Properties(), - (connectionService, pluginService) -> new NoOpMonitor(spyMonitorService, 30) + mockConnectConfig, + (mockServicesContainer) -> new NoOpMonitor(30) ); Monitor storedMonitor = spyMonitorService.get(NoOpMonitor.class, key); @@ -185,12 +170,8 @@ public void testMonitorExpired() throws SQLException, InterruptedException { mockStorageService, mockTelemetryFactory, mockConnectionProvider, - "jdbc:postgresql://somehost/somedb", - "someProtocol", - mockTargetDriverDialect, - mockDbDialect, - new Properties(), - (connectionService, pluginService) -> new NoOpMonitor(spyMonitorService, 30) + mockConnectConfig, + (mockServicesContainer) -> new NoOpMonitor(30) ); Monitor storedMonitor = spyMonitorService.get(NoOpMonitor.class, key); @@ -218,14 +199,10 @@ public void testMonitorMismatch() { mockStorageService, mockTelemetryFactory, mockConnectionProvider, - "jdbc:postgresql://somehost/somedb", - "someProtocol", - mockTargetDriverDialect, - mockDbDialect, - new Properties(), + mockConnectConfig, // indicated monitor class is CustomEndpointMonitorImpl, but actual monitor is NoOpMonitor. The monitor // service should detect this and throw an exception. - (connectionService, pluginService) -> new NoOpMonitor(spyMonitorService, 30) + (mockServicesContainer) -> new NoOpMonitor(30) )); } @@ -248,12 +225,8 @@ public void testRemove() throws SQLException, InterruptedException { mockStorageService, mockTelemetryFactory, mockConnectionProvider, - "jdbc:postgresql://somehost/somedb", - "someProtocol", - mockTargetDriverDialect, - mockDbDialect, - new Properties(), - (connectionService, pluginService) -> new NoOpMonitor(spyMonitorService, 30) + mockConnectConfig, + (mockServicesContainer) -> new NoOpMonitor(30) ); assertNotNull(monitor); @@ -283,12 +256,8 @@ public void testStopAndRemove() throws SQLException, InterruptedException { mockStorageService, mockTelemetryFactory, mockConnectionProvider, - "jdbc:postgresql://somehost/somedb", - "someProtocol", - mockTargetDriverDialect, - mockDbDialect, - new Properties(), - (connectionService, pluginService) -> new NoOpMonitor(spyMonitorService, 30) + mockConnectConfig, + (mockServicesContainer) -> new NoOpMonitor(30) ); assertNotNull(monitor); @@ -300,9 +269,7 @@ public void testStopAndRemove() throws SQLException, InterruptedException { } static class NoOpMonitor extends AbstractMonitor { - protected NoOpMonitor( - MonitorService monitorService, - long terminationTimeoutSec) { + protected NoOpMonitor(long terminationTimeoutSec) { super(terminationTimeoutSec); }