From 4a314988b429e31a2367396335bb4673bb15c582 Mon Sep 17 00:00:00 2001 From: sergiyvamz Date: Fri, 14 Feb 2025 16:20:03 -0800 Subject: [PATCH] remove CJException dependency from MariaDb (database) dialect --- .../amazon/jdbc/PluginServiceImpl.java | 22 ++++++++++---- .../AbstractPgExceptionHandler.java | 22 +++++++++++++- .../jdbc/exceptions/ExceptionHandler.java | 19 ++++++++++++ .../jdbc/exceptions/ExceptionManager.java | 11 ++++--- .../exceptions/GenericExceptionHandler.java | 24 +++++++++++++-- .../MultiAzDbClusterPgExceptionHandler.java | 1 - .../exceptions/MySQLExceptionHandler.java | 29 ++++++++++++++----- ...AuroraInitialConnectionStrategyPlugin.java | 4 +-- .../AwsSecretsManagerConnectionPlugin.java | 3 +- .../plugin/iam/IamAuthConnectionPlugin.java | 3 +- .../GenericTargetDriverDialect.java | 5 ++++ .../MysqlConnectorJDriverHelper.java | 5 ++++ .../MysqlConnectorJTargetDriverDialect.java | 6 ++++ .../TargetDriverDialect.java | 2 ++ .../jdbc/plugin/efm/ConcurrencyTests.java | 10 +++++++ 15 files changed, 141 insertions(+), 25 deletions(-) diff --git a/wrapper/src/main/java/software/amazon/jdbc/PluginServiceImpl.java b/wrapper/src/main/java/software/amazon/jdbc/PluginServiceImpl.java index a747ccf47..5a282e20b 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/PluginServiceImpl.java +++ b/wrapper/src/main/java/software/amazon/jdbc/PluginServiceImpl.java @@ -653,11 +653,16 @@ public void releaseResources() { } @Override - public boolean isNetworkException(final Throwable throwable) { + public boolean isNetworkException(Throwable throwable) { + return this.isNetworkException(throwable, this.targetDriverDialect); + } + + @Override + public boolean isNetworkException(final Throwable throwable, @Nullable TargetDriverDialect targetDriverDialect) { if (this.exceptionHandler != null) { - return this.exceptionHandler.isNetworkException(throwable); + return this.exceptionHandler.isNetworkException(throwable, targetDriverDialect); } - return this.exceptionManager.isNetworkException(this.dialect, throwable); + return this.exceptionManager.isNetworkException(this.dialect, throwable, targetDriverDialect); } @Override @@ -669,11 +674,16 @@ public boolean isNetworkException(final String sqlState) { } @Override - public boolean isLoginException(final Throwable throwable) { + public boolean isLoginException(Throwable throwable) { + return this.isLoginException(throwable, this.targetDriverDialect); + } + + @Override + public boolean isLoginException(final Throwable throwable, @Nullable TargetDriverDialect targetDriverDialect) { if (this.exceptionHandler != null) { - return this.exceptionHandler.isLoginException(throwable); + return this.exceptionHandler.isLoginException(throwable, targetDriverDialect); } - return this.exceptionManager.isLoginException(this.dialect, throwable); + return this.exceptionManager.isLoginException(this.dialect, throwable, targetDriverDialect); } @Override diff --git a/wrapper/src/main/java/software/amazon/jdbc/exceptions/AbstractPgExceptionHandler.java b/wrapper/src/main/java/software/amazon/jdbc/exceptions/AbstractPgExceptionHandler.java index 7d51a053c..32a2eff31 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/exceptions/AbstractPgExceptionHandler.java +++ b/wrapper/src/main/java/software/amazon/jdbc/exceptions/AbstractPgExceptionHandler.java @@ -18,6 +18,9 @@ import java.sql.SQLException; import java.util.List; +import org.checkerframework.checker.nullness.qual.Nullable; +import software.amazon.jdbc.targetdriverdialect.TargetDriverDialect; +import software.amazon.jdbc.util.StringUtils; public abstract class AbstractPgExceptionHandler implements ExceptionHandler { public abstract List getNetworkErrors(); @@ -25,12 +28,22 @@ public abstract class AbstractPgExceptionHandler implements ExceptionHandler { public abstract List getAccessErrors(); @Override - public boolean isNetworkException(final Throwable throwable) { + public boolean isNetworkException(Throwable throwable) { + return this.isNetworkException(throwable, null); + } + + @Override + public boolean isNetworkException(final Throwable throwable, @Nullable TargetDriverDialect targetDriverDialect) { Throwable exception = throwable; while (exception != null) { if (exception instanceof SQLException) { return isNetworkException(((SQLException) exception).getSQLState()); + } else if (targetDriverDialect != null) { + String sqlState = targetDriverDialect.getSQLState(throwable); + if (!StringUtils.isNullOrEmpty(sqlState)) { + return isNetworkException(sqlState); + } } exception = exception.getCause(); @@ -56,6 +69,11 @@ public boolean isNetworkException(final String sqlState) { @Override public boolean isLoginException(final Throwable throwable) { + return this.isLoginException(throwable, null); + } + + @Override + public boolean isLoginException(final Throwable throwable, @Nullable TargetDriverDialect targetDriverDialect) { Throwable exception = throwable; while (exception != null) { @@ -66,6 +84,8 @@ public boolean isLoginException(final Throwable throwable) { String sqlState = null; if (exception instanceof SQLException) { sqlState = ((SQLException) exception).getSQLState(); + } else if (targetDriverDialect != null) { + sqlState = targetDriverDialect.getSQLState(throwable); } if (isLoginException(sqlState)) { diff --git a/wrapper/src/main/java/software/amazon/jdbc/exceptions/ExceptionHandler.java b/wrapper/src/main/java/software/amazon/jdbc/exceptions/ExceptionHandler.java index c760a1dda..6eed04d8c 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/exceptions/ExceptionHandler.java +++ b/wrapper/src/main/java/software/amazon/jdbc/exceptions/ExceptionHandler.java @@ -16,13 +16,32 @@ package software.amazon.jdbc.exceptions; +import org.checkerframework.checker.nullness.qual.Nullable; +import software.amazon.jdbc.targetdriverdialect.TargetDriverDialect; + public interface ExceptionHandler { + /** + * The method determines whether provided throwable is about any network issues. + * + * @deprecated Use similar method below that accepts throwable and target driver dialect. + */ + @Deprecated() boolean isNetworkException(Throwable throwable); + boolean isNetworkException(Throwable throwable, @Nullable TargetDriverDialect targetDriverDialect); + boolean isNetworkException(String sqlState); boolean isLoginException(String sqlState); + /** + * The method determines whether provided throwable is about any login or authentication issues. + * + * @deprecated Use similar method below that accepts throwable and target driver dialect. + */ + @Deprecated() boolean isLoginException(Throwable throwable); + + boolean isLoginException(Throwable throwable, @Nullable TargetDriverDialect targetDriverDialect); } diff --git a/wrapper/src/main/java/software/amazon/jdbc/exceptions/ExceptionManager.java b/wrapper/src/main/java/software/amazon/jdbc/exceptions/ExceptionManager.java index a6badc629..1c9dd5f35 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/exceptions/ExceptionManager.java +++ b/wrapper/src/main/java/software/amazon/jdbc/exceptions/ExceptionManager.java @@ -18,6 +18,7 @@ import software.amazon.jdbc.Driver; import software.amazon.jdbc.dialect.Dialect; +import software.amazon.jdbc.targetdriverdialect.TargetDriverDialect; public class ExceptionManager { @@ -41,9 +42,10 @@ public static void resetCustomHandler() { Driver.resetCustomExceptionHandler(); } - public boolean isLoginException(final Dialect dialect, final Throwable throwable) { + public boolean isLoginException( + final Dialect dialect, final Throwable throwable, final TargetDriverDialect targetDriverDialect) { final ExceptionHandler handler = getHandler(dialect); - return handler.isLoginException(throwable); + return handler.isLoginException(throwable, targetDriverDialect); } public boolean isLoginException(final Dialect dialect, final String sqlState) { @@ -51,9 +53,10 @@ public boolean isLoginException(final Dialect dialect, final String sqlState) { return handler.isLoginException(sqlState); } - public boolean isNetworkException(final Dialect dialect, final Throwable throwable) { + public boolean isNetworkException( + final Dialect dialect, final Throwable throwable, final TargetDriverDialect targetDriverDialect) { final ExceptionHandler handler = getHandler(dialect); - return handler.isNetworkException(throwable); + return handler.isNetworkException(throwable, targetDriverDialect); } public boolean isNetworkException(final Dialect dialect, final String sqlState) { diff --git a/wrapper/src/main/java/software/amazon/jdbc/exceptions/GenericExceptionHandler.java b/wrapper/src/main/java/software/amazon/jdbc/exceptions/GenericExceptionHandler.java index ba332ad17..c51af9fac 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/exceptions/GenericExceptionHandler.java +++ b/wrapper/src/main/java/software/amazon/jdbc/exceptions/GenericExceptionHandler.java @@ -19,6 +19,9 @@ import java.sql.SQLException; import java.util.Arrays; import java.util.List; +import org.checkerframework.checker.nullness.qual.Nullable; +import software.amazon.jdbc.targetdriverdialect.TargetDriverDialect; +import software.amazon.jdbc.util.StringUtils; public class GenericExceptionHandler implements ExceptionHandler { @@ -36,12 +39,22 @@ public class GenericExceptionHandler implements ExceptionHandler { ); @Override - public boolean isNetworkException(final Throwable throwable) { + public boolean isNetworkException(Throwable throwable) { + return this.isNetworkException(throwable, null); + } + + @Override + public boolean isNetworkException(final Throwable throwable, @Nullable TargetDriverDialect targetDriverDialect) { Throwable exception = throwable; while (exception != null) { if (exception instanceof SQLException) { return isNetworkException(((SQLException) exception).getSQLState()); + } else if (targetDriverDialect != null) { + String sqlState = targetDriverDialect.getSQLState(throwable); + if (!StringUtils.isNullOrEmpty(sqlState)) { + return isNetworkException(sqlState); + } } exception = exception.getCause(); @@ -66,7 +79,12 @@ public boolean isNetworkException(final String sqlState) { } @Override - public boolean isLoginException(final Throwable throwable) { + public boolean isLoginException(Throwable throwable) { + return this.isLoginException(throwable, null); + } + + @Override + public boolean isLoginException(final Throwable throwable, TargetDriverDialect targetDriverDialect) { Throwable exception = throwable; while (exception != null) { @@ -77,6 +95,8 @@ public boolean isLoginException(final Throwable throwable) { String sqlState = null; if (exception instanceof SQLException) { sqlState = ((SQLException) exception).getSQLState(); + } else if (targetDriverDialect != null) { + sqlState = targetDriverDialect.getSQLState(throwable); } if (isLoginException(sqlState)) { diff --git a/wrapper/src/main/java/software/amazon/jdbc/exceptions/MultiAzDbClusterPgExceptionHandler.java b/wrapper/src/main/java/software/amazon/jdbc/exceptions/MultiAzDbClusterPgExceptionHandler.java index b728968d4..0a69db1e1 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/exceptions/MultiAzDbClusterPgExceptionHandler.java +++ b/wrapper/src/main/java/software/amazon/jdbc/exceptions/MultiAzDbClusterPgExceptionHandler.java @@ -16,7 +16,6 @@ package software.amazon.jdbc.exceptions; -import java.sql.SQLException; import java.util.Arrays; import java.util.Collections; import java.util.List; diff --git a/wrapper/src/main/java/software/amazon/jdbc/exceptions/MySQLExceptionHandler.java b/wrapper/src/main/java/software/amazon/jdbc/exceptions/MySQLExceptionHandler.java index ecc89e6cc..dfbb8edef 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/exceptions/MySQLExceptionHandler.java +++ b/wrapper/src/main/java/software/amazon/jdbc/exceptions/MySQLExceptionHandler.java @@ -16,8 +16,10 @@ package software.amazon.jdbc.exceptions; -import com.mysql.cj.exceptions.CJException; import java.sql.SQLException; +import org.checkerframework.checker.nullness.qual.Nullable; +import software.amazon.jdbc.targetdriverdialect.TargetDriverDialect; +import software.amazon.jdbc.util.StringUtils; public class MySQLExceptionHandler implements ExceptionHandler { public static final String SQLSTATE_ACCESS_ERROR = "28000"; @@ -26,7 +28,12 @@ public class MySQLExceptionHandler implements ExceptionHandler { "setNetworkTimeout cannot be called on a closed connection"; @Override - public boolean isNetworkException(final Throwable throwable) { + public boolean isNetworkException(Throwable throwable) { + return this.isNetworkException(throwable, null); + } + + @Override + public boolean isNetworkException(final Throwable throwable, @Nullable TargetDriverDialect targetDriverDialect) { Throwable exception = throwable; while (exception != null) { @@ -44,8 +51,11 @@ public boolean isNetworkException(final Throwable throwable) { if (isNetworkException(sqlException.getSQLState()) || isHikariMariaDbNetworkException(sqlException)) { return true; } - } else if (exception instanceof CJException) { - return isNetworkException(((CJException) exception).getSQLState()); + } else if (targetDriverDialect != null) { + String sqlState = targetDriverDialect.getSQLState(throwable); + if (!StringUtils.isNullOrEmpty(sqlState)) { + return isNetworkException(sqlState); + } } exception = exception.getCause(); @@ -64,7 +74,12 @@ public boolean isNetworkException(final String sqlState) { } @Override - public boolean isLoginException(final Throwable throwable) { + public boolean isLoginException(Throwable throwable) { + return this.isLoginException(throwable, null); + } + + @Override + public boolean isLoginException(final Throwable throwable, @Nullable TargetDriverDialect targetDriverDialect) { Throwable exception = throwable; while (exception != null) { @@ -75,8 +90,8 @@ public boolean isLoginException(final Throwable throwable) { String sqlState = null; if (exception instanceof SQLException) { sqlState = ((SQLException) exception).getSQLState(); - } else if (exception instanceof CJException) { - sqlState = ((CJException) exception).getSQLState(); + } else if (targetDriverDialect != null) { + sqlState = targetDriverDialect.getSQLState(throwable); } if (isLoginException(sqlState)) { 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 af5ae459f..c2815d1b1 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/plugin/AuroraInitialConnectionStrategyPlugin.java +++ b/wrapper/src/main/java/software/amazon/jdbc/plugin/AuroraInitialConnectionStrategyPlugin.java @@ -228,7 +228,7 @@ private Connection getVerifiedWriterConnection( } catch (SQLException ex) { this.closeConnection(writerCandidateConn); - if (this.pluginService.isLoginException(ex)) { + if (this.pluginService.isLoginException(ex, this.pluginService.getTargetDriverDialect())) { throw WrapperUtils.wrapExceptionIfNeeded(SQLException.class, ex); } else { if (writerCandidate != null) { @@ -322,7 +322,7 @@ private Connection getVerifiedReaderConnection( } catch (SQLException ex) { this.closeConnection(readerCandidateConn); - if (this.pluginService.isLoginException(ex)) { + if (this.pluginService.isLoginException(ex, this.pluginService.getTargetDriverDialect())) { throw WrapperUtils.wrapExceptionIfNeeded(SQLException.class, ex); } else { if (readerCandidate != 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 763650ba6..63af4468d 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/plugin/AwsSecretsManagerConnectionPlugin.java +++ b/wrapper/src/main/java/software/amazon/jdbc/plugin/AwsSecretsManagerConnectionPlugin.java @@ -202,7 +202,8 @@ private Connection connectInternal(HostSpec hostSpec, Properties props, return connectFunc.call(); } catch (final SQLException exception) { - if (this.pluginService.isLoginException(exception) && !secretWasFetched) { + if (this.pluginService.isLoginException(exception, this.pluginService.getTargetDriverDialect()) + && !secretWasFetched) { // Login unsuccessful with cached credentials // Try to re-fetch credentials and try again 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 8622067f8..1ace641fe 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 @@ -180,7 +180,8 @@ private Connection connectInternal(String driverProtocol, HostSpec hostSpec, Pro "IamAuthConnectionPlugin.connectException", new Object[] {exception})); - if (!this.pluginService.isLoginException(exception) || !isCachedToken) { + if (!this.pluginService.isLoginException(exception, this.pluginService.getTargetDriverDialect()) + || !isCachedToken) { throw exception; } 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 1205a5f14..82f7ec37b 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/targetdriverdialect/GenericTargetDriverDialect.java +++ b/wrapper/src/main/java/software/amazon/jdbc/targetdriverdialect/GenericTargetDriverDialect.java @@ -183,4 +183,9 @@ public Set getAllowedOnConnectionMethodNames() { } }); } + + @Override + public String getSQLState(Throwable throwable) { + return null; + } } diff --git a/wrapper/src/main/java/software/amazon/jdbc/targetdriverdialect/MysqlConnectorJDriverHelper.java b/wrapper/src/main/java/software/amazon/jdbc/targetdriverdialect/MysqlConnectorJDriverHelper.java index 8e8c09b0b..0439f1266 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/targetdriverdialect/MysqlConnectorJDriverHelper.java +++ b/wrapper/src/main/java/software/amazon/jdbc/targetdriverdialect/MysqlConnectorJDriverHelper.java @@ -16,6 +16,7 @@ package software.amazon.jdbc.targetdriverdialect; +import com.mysql.cj.exceptions.CJException; import com.mysql.cj.jdbc.MysqlDataSource; import java.sql.DriverManager; import java.sql.SQLException; @@ -92,4 +93,8 @@ public void registerDriver() throws SQLException { throw new SQLException(Messages.get("MysqlConnectorJDriverHelper.canNotRegister"), e); } } + + public String getSQLState(final Throwable throwable) { + return throwable instanceof CJException ? ((CJException) throwable).getSQLState() : null; + } } 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 51dc8d105..5067b856a 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/targetdriverdialect/MysqlConnectorJTargetDriverDialect.java +++ b/wrapper/src/main/java/software/amazon/jdbc/targetdriverdialect/MysqlConnectorJTargetDriverDialect.java @@ -126,4 +126,10 @@ public Set getAllowedOnConnectionMethodNames() { } }); } + + @Override + public String getSQLState(Throwable throwable) { + final MysqlConnectorJDriverHelper helper = new MysqlConnectorJDriverHelper(); + return helper.getSQLState(throwable); + } } 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 95070fede..ad23d0e09 100644 --- a/wrapper/src/main/java/software/amazon/jdbc/targetdriverdialect/TargetDriverDialect.java +++ b/wrapper/src/main/java/software/amazon/jdbc/targetdriverdialect/TargetDriverDialect.java @@ -56,4 +56,6 @@ void prepareDataSource( boolean ping(final @NonNull Connection connection); Set getAllowedOnConnectionMethodNames(); + + String getSQLState(final Throwable throwable); } diff --git a/wrapper/src/test/java/software/amazon/jdbc/plugin/efm/ConcurrencyTests.java b/wrapper/src/test/java/software/amazon/jdbc/plugin/efm/ConcurrencyTests.java index 24bec0f8e..ba6a46cf1 100644 --- a/wrapper/src/test/java/software/amazon/jdbc/plugin/efm/ConcurrencyTests.java +++ b/wrapper/src/test/java/software/amazon/jdbc/plugin/efm/ConcurrencyTests.java @@ -603,6 +603,11 @@ public boolean isNetworkException(Throwable throwable) { return false; } + @Override + public boolean isNetworkException(Throwable throwable, @Nullable TargetDriverDialect targetDriverDialect) { + return false; + } + @Override public boolean isNetworkException(String sqlState) { return false; @@ -618,6 +623,11 @@ public boolean isLoginException(Throwable throwable) { return false; } + @Override + public boolean isLoginException(Throwable throwable, @Nullable TargetDriverDialect targetDriverDialect) { + return false; + } + @Override public Dialect getDialect() { return new UnknownDialect();