/* The contents of this file are subject to the license and copyright terms
* detailed in the license directory at the root of the source tree (also
* available online at http://fedora-commons.org/license/).
*/
package fedora.utilities;
import java.io.File;
import java.net.URL;
import java.net.URLClassLoader;
import java.sql.Connection;
import java.sql.Driver;
import java.sql.DriverManager;
import java.sql.DriverPropertyInfo;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;
/**
* Allows one to load a JDBC driver at runtime. java.sql.DriverManager will
* refuse to use a driver not loaded by the system ClassLoader. The workaround
* for this is to use a shim class that implements java.sql.Driver. This shim
* class will do nothing but call the methods of an instance of a JDBC driver
* that is loaded dynamically. This works because DriverShim is loaded by the
* system class loader, and DriverManager doesn't care that it invokes a class
* that wasn't. Note that we must perform the registration on the instance
* ourselves. See the utility method, loadAndRegister and the command-line test
* below. Adapted from http://www.kfu.com/~nsayer/Java/dyn-jdbc.html
*/
public class DriverShim
implements Driver {
/** The JDBC driver we're wrapping. */
private final Driver _driver;
/**
* Constructs a DriverShim over the given driver in order to make it look
* like it came from this classloader.
*/
public DriverShim(Driver d) {
_driver = d;
}
/**
* Loads the driver from the given jar file and registers it with the driver
* manager.
*/
public static final void loadAndRegister(File driverJarFile,
String driverClassName)
throws Exception {
loadAndRegister(new URL("jar:" + driverJarFile.toURI() + "!/"),
driverClassName);
}
public static final void loadAndRegister(URL driverURL,
String driverClassName)
throws Exception {
URLClassLoader urlCL = new URLClassLoader(new URL[] {driverURL});
Driver driver =
(Driver) Class.forName(driverClassName, true, urlCL)
.newInstance();
DriverManager.registerDriver(new DriverShim(driver));
}
//
// Driver implementation
//
/**
* {@inheritDoc}
*/
public boolean acceptsURL(String u) throws SQLException {
return _driver.acceptsURL(u);
}
/**
* {@inheritDoc}
*/
public Connection connect(String u, Properties p) throws SQLException {
return _driver.connect(u, p);
}
/**
* {@inheritDoc}
*/
public int getMajorVersion() {
return _driver.getMajorVersion();
}
/**
* {@inheritDoc}
*/
public int getMinorVersion() {
return _driver.getMinorVersion();
}
/**
* {@inheritDoc}
*/
public DriverPropertyInfo[] getPropertyInfo(String u, Properties p)
throws SQLException {
return _driver.getPropertyInfo(u, p);
}
/**
* {@inheritDoc}
*/
public boolean jdbcCompliant() {
return _driver.jdbcCompliant();
}
/**
* Command-line test. Dynamically loads the driver given at the command
* line, opens a connection, and get the row count of the given table to
* prove it worked. Usage: java -cp . DriverShim someDriver.jar
* org.SomeDriver jdbcURL name pwd tbl
*/
public static void main(String[] args) throws Exception {
if (args.length == 6) {
DriverShim.loadAndRegister(new File(args[0]), args[1]);
Connection conn =
DriverManager.getConnection(args[2], args[3], args[4]);
String tbl = args[5];
Statement st = conn.createStatement();
ResultSet rs = st.executeQuery("SELECT COUNT(*) FROM " + tbl);
rs.next();
System.out.println("The " + tbl + " table has " + rs.getInt(1)
+ " rows.");
rs.close();
st.close();
conn.close();
} else {
System.out.println("Usage: java -cp . DriverShim someDriver.jar"
+ " org.SomeDriver jdbcURL name pwd tbl");
System.exit(1);
}
}
}