diff --git a/src/main/java/com/zaxxer/hikari/HikariConfig.java b/src/main/java/com/zaxxer/hikari/HikariConfig.java index 2e7bb604..2c57deb7 100644 --- a/src/main/java/com/zaxxer/hikari/HikariConfig.java +++ b/src/main/java/com/zaxxer/hikari/HikariConfig.java @@ -42,6 +42,7 @@ import java.util.concurrent.ThreadFactory; import java.util.concurrent.ThreadLocalRandom; import static com.zaxxer.hikari.util.UtilityElf.getNullIfEmpty; +import static com.zaxxer.hikari.util.UtilityElf.safeIsAssignableFrom; import static java.util.concurrent.TimeUnit.MINUTES; import static java.util.concurrent.TimeUnit.SECONDS; @@ -758,8 +759,8 @@ public class HikariConfig implements HikariConfigMXBean if (metricRegistry != null) { metricRegistry = getObjectOrPerformJndiLookup(metricRegistry); - if (!(metricRegistry.getClass().getName().contains("MetricRegistry")) - && !(metricRegistry.getClass().getName().contains("MeterRegistry"))) { + if (!safeIsAssignableFrom(metricRegistry, "com.codahale.metrics.MetricRegistry") + && !(safeIsAssignableFrom(metricRegistry, "io.micrometer.core.instrument.MeterRegistry"))) { throw new IllegalArgumentException("Class must be instance of com.codahale.metrics.MetricRegistry or io.micrometer.core.instrument.MeterRegistry"); } } diff --git a/src/main/java/com/zaxxer/hikari/pool/HikariPool.java b/src/main/java/com/zaxxer/hikari/pool/HikariPool.java index 48506dc2..eb8e8d50 100644 --- a/src/main/java/com/zaxxer/hikari/pool/HikariPool.java +++ b/src/main/java/com/zaxxer/hikari/pool/HikariPool.java @@ -57,6 +57,7 @@ import static com.zaxxer.hikari.util.ConcurrentBag.IConcurrentBagEntry.STATE_IN_ import static com.zaxxer.hikari.util.ConcurrentBag.IConcurrentBagEntry.STATE_NOT_IN_USE; import static com.zaxxer.hikari.util.UtilityElf.createThreadPoolExecutor; import static com.zaxxer.hikari.util.UtilityElf.quietlySleep; +import static com.zaxxer.hikari.util.UtilityElf.safeIsAssignableFrom; import static java.util.Collections.unmodifiableCollection; import static java.util.concurrent.TimeUnit.MILLISECONDS; import static java.util.concurrent.TimeUnit.SECONDS; @@ -272,10 +273,10 @@ public final class HikariPool extends PoolBase implements HikariPoolMXBean, IBag */ public void setMetricRegistry(Object metricRegistry) { - if (metricRegistry != null && metricRegistry.getClass().getName().contains("MetricRegistry")) { + if (metricRegistry != null && safeIsAssignableFrom(metricRegistry, "com.codahale.metrics.MetricRegistry")) { setMetricsTrackerFactory(new CodahaleMetricsTrackerFactory((MetricRegistry) metricRegistry)); } - else if (metricRegistry != null && metricRegistry.getClass().getName().contains("MeterRegistry")) { + else if (metricRegistry != null && safeIsAssignableFrom(metricRegistry, "io.micrometer.core.instrument.MeterRegistry")) { setMetricsTrackerFactory(new MicrometerMetricsTrackerFactory((MeterRegistry) metricRegistry)); } else { diff --git a/src/main/java/com/zaxxer/hikari/util/UtilityElf.java b/src/main/java/com/zaxxer/hikari/util/UtilityElf.java index 02186b5c..b4bd5bfc 100644 --- a/src/main/java/com/zaxxer/hikari/util/UtilityElf.java +++ b/src/main/java/com/zaxxer/hikari/util/UtilityElf.java @@ -65,6 +65,21 @@ public final class UtilityElf } } + /** + * Checks whether an object is an instance of given type without throwing exception when the class is not loaded. + * @param obj the object to check + * @param className String class + * @return true if object is assignable from the type, false otherwise or when the class cannot be loaded + */ + public static boolean safeIsAssignableFrom(Object obj, String className) { + try { + Class clazz = Class.forName(className); + return clazz.isAssignableFrom(obj.getClass()); + } catch (ClassNotFoundException ignored) { + return false; + } + } + /** * Create and instance of the specified class using the constructor matching the specified * arguments. diff --git a/src/test/java/com/zaxxer/hikari/pool/TestMetrics.java b/src/test/java/com/zaxxer/hikari/pool/TestMetrics.java index 775bb494..2e05dca9 100644 --- a/src/test/java/com/zaxxer/hikari/pool/TestMetrics.java +++ b/src/test/java/com/zaxxer/hikari/pool/TestMetrics.java @@ -298,4 +298,35 @@ public class TestMetrics } } } + + @Test(expected = IllegalArgumentException.class) + public void testFakeMetricRegistryThrowsIllegalArgumentException() + { + try (HikariDataSource ds = newHikariDataSource()) { + ds.setMaximumPoolSize(1); + ds.setDataSourceClassName("com.zaxxer.hikari.mocks.StubDataSource"); + + FakeMetricRegistry metricRegistry = new FakeMetricRegistry(); + + ds.setMetricRegistry(metricRegistry); + } + } + + private static class FakeMetricRegistry {} + + @Test + public void testMetricRegistrySubclassIsAllowed() + { + try (HikariDataSource ds = newHikariDataSource()) { + ds.setMaximumPoolSize(1); + ds.setDataSourceClassName("com.zaxxer.hikari.mocks.StubDataSource"); + + ds.setMetricRegistry(new MetricRegistry() { + @Override + public Timer timer(String name) { + return super.timer(name); + } + }); + } + } }