patterntesting.runtime.monitor.db.ProxyDriver Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of patterntesting-rt Show documentation
Show all versions of patterntesting-rt Show documentation
PatternTesting Runtime (patterntesting-rt) is the runtime component for
the PatternTesting framework. It provides the annotations and base classes
for the PatternTesting testing framework (e.g. patterntesting-check,
patterntesting-concurrent or patterntesting-exception) but can be also
used standalone for classpath monitoring or profiling.
It uses AOP and AspectJ to perform this feat.
/*
* $Id: ProxyDriver.java,v 1.1 2014/04/27 19:35:07 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.*;
import java.util.*;
import org.apache.commons.lang.StringUtils;
import org.slf4j.*;
/**
* 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
* @since 1.4.1 (27.03.2014)
* @version $Revision: 1.1 $
*/
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 knownDrivers = new HashMap();
/** Register class as JDBC driver. */
static {
register();
knownDrivers.put("hsqldb", "org.hsqldb.jdbc.JDBCDriver");
knownDrivers.put("sqlserver", "com.microsoft.sqlserver.jdbc.SQLServerDriver");
knownDrivers.put("jturbo", "com.newatlanta.jturbo.driver.Driver");
}
private static String getKnownDriverFor(final String jdbcURL) {
String[] parts = StringUtils.split(jdbcURL + ":x", ':');
return knownDrivers.get(parts[1].toLowerCase());
}
/**
* Registers the driver as JDBC driver.
*/
public static void register() {
Driver driver = new ProxyDriver();
try {
DriverManager.registerDriver(driver);
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);
}
}
/**
* 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 + "...\"";
}
}