apache/gravitino

[Improvement] possible ClassCastException in JdbcCatalogMetricsSource

Open

#10,122 opened on Mar 3, 2026

View on GitHub
 (6 comments) (0 reactions) (2 assignees)Java (887 forks)auto 404
good first issueimprovement

Repository metrics

Stars
 (3,058 stars)
PR merge metrics
 (PR metrics pending)

Description

What would you like to be improved?

JdbcCatalogMetricsSource.registerDatasourceMetrics(DataSource dataSource) currently performs an unconditional cast to BasicDataSource. This makes the method unsafe for any valid DataSource implementation, and it can fail at runtime with a ClassCastException. The improvement needed is to make datasource metric registration robust across non-DBCP DataSource instances, or at minimum fail safely.

How should we improve?

Update registerDatasourceMetrics to handle non-BasicDataSource inputs safely, rather than casting directly.

Here's a unit test to show the issue:

public class TestJdbcCatalogMetricsSource {

  @Test
  public void testRegisterDatasourceMetricsWithNonBasicDataSource() {
    JdbcCatalogMetricsSource source = new JdbcCatalogMetricsSource("metalake", "catalog");

    DataSource nonBasicDataSource =
        new DataSource() {
          @Override
          public Connection getConnection() {
            return null;
          }

          @Override
          public Connection getConnection(String username, String password) {
            return null;
          }

          @Override
          public PrintWriter getLogWriter() {
            return null;
          }

          @Override
          public void setLogWriter(PrintWriter out) {}

          @Override
          public void setLoginTimeout(int seconds) {}

          @Override
          public int getLoginTimeout() {
            return 0;
          }

          @Override
          public Logger getParentLogger() throws SQLFeatureNotSupportedException {
            return Logger.getGlobal();
          }

          @Override
          public <T> T unwrap(Class<T> iface) throws SQLException {
            throw new SQLException("Not a wrapper");
          }

          @Override
          public boolean isWrapperFor(Class<?> iface) {
            return false;
          }
        };

    Assertions.assertDoesNotThrow(() -> source.registerDatasourceMetrics(nonBasicDataSource));
  }
}

Contributor guide