package com.github.gquintana.metrics.sql; /* * #%L * Metrics SQL * %% * Copyright (C) 2014 Open-Source * %% * 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. * #L% */ import com.codahale.metrics.MetricRegistry; import com.codahale.metrics.SharedMetricRegistries; import com.codahale.metrics.Timer; import com.github.gquintana.metrics.proxy.ProxyFactory; import java.lang.reflect.Constructor; import java.sql.*; import java.util.List; import java.util.Properties; import java.util.logging.Logger; /** * Metrics SQL JDBC Driver */ public class Driver implements java.sql.Driver { private static final Driver INSTANCE = new Driver(); private static boolean registered = false; private final Logger parentLogger = Logger.getLogger("com.github.gquintana.metrics"); static { register(); } private static synchronized void register() { try { if (!registered) { registered = true; DriverManager.registerDriver(INSTANCE); } } catch (SQLException e) { throw new IllegalStateException(e); } } /** * Instantiate a new object of type T * * @param clazz Object class * @param params Constructor args * @param <T> Object type * @return New object */ private static <T> T newInstance(Class<T> clazz, Object... params) throws SQLException { try { if (params == null || params.length == 0) { return clazz.newInstance(); } else { for (Constructor<?> ctor : clazz.getConstructors()) { if (ctor.getParameterTypes().length != params.length) { continue; } int paramIndex = 0; for (Class<?> paramType : ctor.getParameterTypes()) { if (!paramType.isInstance(params[paramIndex])) { break; } paramIndex++; } if (paramIndex != params.length) { continue; } @SuppressWarnings("unchecked") Constructor<T> theCtor = (Constructor<T>) ctor; return theCtor.newInstance(params); } throw new SQLException("Constructor not found for " + clazz); } } catch (ReflectiveOperationException reflectiveOperationException) { throw new SQLException(reflectiveOperationException); } } @Override public Connection connect(String url, Properties info) throws SQLException { if (!acceptsURL(url)) { return null; } DriverUrl driverUrl = DriverUrl.parse(url); MetricRegistry registry = getMetricRegistry(driverUrl); ProxyFactory factory = newInstance(driverUrl.getProxyFactoryClass()); MetricNamingStrategy namingStrategy = getMetricNamingStrategy(driverUrl); JdbcProxyFactory proxyFactory = new JdbcProxyFactory(registry, namingStrategy, factory); // Force Driver loading Class<? extends Driver> driverClass = driverUrl.getDriverClass(); // Open connection Timer.Context getTimerContext = proxyFactory.getMetricHelper().startConnectionGetTimer(); Connection rawConnection = DriverManager.getConnection(driverUrl.getCleanUrl(), info); if (getTimerContext != null) { getTimerContext.stop(); } // Wrap connection return proxyFactory.wrapConnection(rawConnection); } private MetricNamingStrategy getMetricNamingStrategy(DriverUrl driverUrl) throws SQLException { Class<? extends MetricNamingStrategy> namingStrategyClass = driverUrl.getNamingStrategyClass(); String databaseName = driverUrl.getDatabaseName(); return databaseName == null ? newInstance(namingStrategyClass) : newInstance(namingStrategyClass, databaseName); } private MetricRegistry getMetricRegistry(DriverUrl driverUrl) { String registryName = driverUrl.getRegistryName(); MetricRegistry registry; if (registryName == null) { registry = SharedMetricRegistries.tryGetDefault(); if (registry == null) { registry = SharedMetricRegistries.getOrCreate("default"); } } else { registry = SharedMetricRegistries.getOrCreate(registryName); } return registry; } @Override public boolean acceptsURL(String url) throws SQLException { return url != null && url.startsWith(DriverUrl.URL_PREFIX); } @Override public DriverPropertyInfo[] getPropertyInfo(String url, Properties info) throws SQLException { DriverUrl driverUrl = DriverUrl.parse(url); java.sql.Driver driver = DriverManager.getDriver(driverUrl.getCleanUrl()); return driver.getPropertyInfo(driverUrl.getCleanUrl(), info); } @Override public int getMajorVersion() { return 3; } @Override public int getMinorVersion() { return 1; } @Override public boolean jdbcCompliant() { return true; } @Override public Logger getParentLogger() throws SQLFeatureNotSupportedException { return parentLogger; } }