All Downloads are FREE. Search and download functionalities are using the official Maven repository.

patterntesting.runtime.monitor.db.ProxyDriver Maven / Gradle / Ivy

/*
 * $Id: ProxyDriver.java,v 1.6 2016/03/02 21:15:20 oboehm Exp $
 *
 * Copyright (c) 2014 by Oliver Boehm
 *
 * 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 orimplied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * (c)reated 27.03.2014 by oliver ([email protected])
 */

package patterntesting.runtime.monitor.db;

import java.sql.Connection;
import java.sql.Driver;
import java.sql.DriverManager;
import java.sql.DriverPropertyInfo;
import java.sql.SQLException;
import java.sql.SQLFeatureNotSupportedException;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Properties;
import java.util.Set;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * This JDBC driver acts like a proxy between PatternTesting and the real JDBC
 * driver to be able to monitor JDBC access. It was inspired by the JAMonDriver
 * of the JAMon framework.
 * 

* This driver is registered for JDBC URLs beginning with "jdbc:proxy: * ...". This prefix must follow the real driver path. E.g. if you want to use * HSQL as database your URL make look like * "jdbc:proxy:hsqldb:file:/tmp/oli". *

* * @author oliver * @version $Revision: 1.6 $ * @since 1.4.1 (27.03.2014) */ public class ProxyDriver implements Driver { private static final String JDBC_URL_PREFIX = "jdbc:proxy:"; private static final Logger LOG = LoggerFactory.getLogger(ProxyDriver.class); private static final Map KNOWN_DRIVERS = new HashMap(); /** Register class as JDBC driver. */ static { register(); KNOWN_DRIVERS.put("hsqldb", "org.hsqldb.jdbc.JDBCDriver"); KNOWN_DRIVERS.put("informix-sqli", "com.informix.jdbc.IfxDriver"); KNOWN_DRIVERS.put("jturbo", "com.newatlanta.jturbo.driver.Driver"); KNOWN_DRIVERS.put("sqlserver", "com.microsoft.sqlserver.jdbc.SQLServerDriver"); } private static String getKnownDriverFor(final String jdbcURL) { String[] parts = StringUtils.split(jdbcURL + ":x", ':'); return KNOWN_DRIVERS.get(parts[1].toLowerCase()); } /** * Registers the driver as JDBC driver. *

* Because the implementation how the {@link DriverManager} finds the * corresponding driver for a given JDBC-URL is a little stupid - it tries * out all drivers if it can work with the URL. In case of problems (e.g. if * the network is down) it throws the first {@link SQLException} it got and * rethrow it - but this may be not the rease but the error message that the * protocoll "jdbc:proxy:..." can not be understood. *

*

* This is the reason why first all registered drivers are first * deregistered and the registered again. This guarantees that the * ProxyDriver is the first registered driver. *

*/ public static void register() { Driver driver = new ProxyDriver(); try { Set deregistered = deregisterDrivers(); DriverManager.registerDriver(driver); registerDrivers(deregistered); LOG.debug("{} successful registered as JDBC driver.", driver); } catch (SQLException ex) { DriverManager.println("Cannot register " + driver + " because of " + ex.getMessage() + "."); LOG.error("Cannot register {} as JDBC driver.", driver, ex); } } private static Set deregisterDrivers() { Set deregistered = new HashSet(); Enumeration registered = DriverManager.getDrivers(); while (registered.hasMoreElements()) { deregistered.add(registered.nextElement()); } for (Driver driver : deregistered) { try { DriverManager.deregisterDriver(driver); } catch (SQLException sex) { LOG.debug("Cannot deregister {} from DriverManager.", driver); LOG.trace("Details: ", sex); deregistered.remove(driver); } } LOG.trace("{} driver(s) deregistered.", deregistered.size()); return deregistered; } private static void registerDrivers(final Set deregistered) { for (Driver driver : deregistered) { try { DriverManager.registerDriver(driver); } catch (SQLException sex) { LOG.warn("Cannot register {} again:", driver, sex); } } } /** * Gets the real JDBC URL of the underlying driver. * * @param jdbcURL the jdbc url, e.g. "jdbc:proxy:hsqldb:mem:testdb" * @return the real driver name */ public static String getRealURL(final String jdbcURL) { if (jdbcURL.startsWith(JDBC_URL_PREFIX)) { return "jdbc:" + StringUtils.substring(jdbcURL, JDBC_URL_PREFIX.length()); } else { return jdbcURL; } } /** * Gets the real driver name of the underlying driver. * * @param jdbcURL the jdbc url, e.g. "jdbc:proxy:hsqldb:mem:testdb" * @return the real driver name */ public static String getRealDriverName(final String jdbcURL) { return getDriverName(getRealURL(jdbcURL)); } private static String getDriverName(final String jdbcURL) { String driverName = getKnownDriverFor(jdbcURL); if (driverName == null) { return getDriver(jdbcURL).getClass().getName(); } return driverName; } /** * Gets the real driver. * * @param jdbcURL the jdbc url, e.g. "jdbc:proxy:hsqldb:mem:testdb" * @return the real driver */ public static Driver getRealDriver(final String jdbcURL) { String realURL = getRealURL(jdbcURL); return getDriver(realURL); } private static Driver getDriver(final String url) { try { return DriverManager.getDriver(url); } catch (SQLException ex) { LOG.trace("Cannot get driver from DriverManager.", ex); LOG.debug("Must first load driver for \"{}\" because {}.", url, ex.getMessage()); return loadDriverFor(url); } } private static Driver loadDriverFor(final String jdbcURL) { try { String driverName = getKnownDriverFor(jdbcURL); if (driverName != null) { Class.forName(driverName); LOG.debug("Driver {} for URL \"{}\" loaded.", driverName, jdbcURL); } return DriverManager.getDriver(jdbcURL); } catch (SQLException ex) { throw new IllegalArgumentException("unregistered URL: \"" + jdbcURL + '"', ex); } catch (ClassNotFoundException ex) { throw new IllegalArgumentException("cannot load driver for \"" + jdbcURL + '"', ex); } } /** * Retrieves whether the driver thinks that it can open a connection to the * given URL. Accepted URLs are URLs beginning with: *
    *
  • jdbc:proxy:...
  • *
  • jdbc:jamon:... (if JAMon is in the classpath)
  • *
* * @param url the JDBC URL * @return true, if successful * @see Driver#acceptsURL(String) */ public boolean acceptsURL(final String url) { String prefix = url.toLowerCase(); return StringUtils.startsWith(prefix, JDBC_URL_PREFIX); } /** * Attempts to make a database connection to the given URL. The driver * returns "null" if it realizes it is the wrong kind of driver to * connect to the given URL. This will be common, as when the JDBC driver * manager is asked to connect to a given URL it passes the URL to each * loaded driver in turn. * * @param url the url * @param info the info (e.g. user/password) * @return the connection * @throws SQLException the sQL exception * @see Driver#connect(String, Properties) */ public Connection connect(final String url, final Properties info) throws SQLException { LOG.trace("Connecting to URL \"{}\"...", url); if (!acceptsURL(url)) { LOG.trace("{} does not accept \"{}\" as URL.", this, url); return null; } String realURL = getRealURL(url); Driver realDriver = getDriver(realURL); Connection connection = realDriver.connect(realURL, info); LOG.trace("Connected to real URL \"{}\".", realURL); return ProxyConnection.newInstance(connection); } /** * Gets the major version. * * @return major version */ public int getMajorVersion() { return 1; } /** * Gets the minor version. * * @return the minor version */ public int getMinorVersion() { return 4; } /** * Gets the property info. * * @param url the url * @param info the info * @return the property info * @throws SQLException the SQL exception */ public DriverPropertyInfo[] getPropertyInfo(final String url, final Properties info) throws SQLException { String realURL = getRealURL(url); Driver driver = getDriver(realURL); return driver.getPropertyInfo(realURL, info); } /** * Jdbc compliant. * * @return true, if successful */ public boolean jdbcCompliant() { return true; } /** * Gets the parent logger. This method is needed for the support of Java 5. * * @return the parent logger * @throws SQLFeatureNotSupportedException the SQL feature not supported exception */ public java.util.logging.Logger getParentLogger() throws SQLFeatureNotSupportedException { throw new SQLFeatureNotSupportedException("not yet implemented"); } /** * Better toString implementation which supports logging and debugging. * * @return the string * @see java.lang.Object#toString() */ @Override public String toString() { return this.getClass().getSimpleName() + " " + this.getMajorVersion() + "." + this.getMinorVersion() + " for \"" + JDBC_URL_PREFIX + "...\""; } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy