/* 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 org.fcrepo.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);
        }
    }
}
@@ -434,16 +434,51 @@
 tyInfo;%0A
+import java.sql.PreparedStatement;%0A
 import j
@@ -529,35 +529,8 @@
 ion;
-%0Aimport java.sql.Statement;
 %0A%0Aim
@@ -3921,16 +3921,24 @@
         
+Prepared
 Statemen
@@ -3953,13 +3953,14 @@
 onn.
-creat
+prepar
 eSta
@@ -3966,16 +3966,74 @@
 atement(
+%22SELECT COUNT(*) FROM ?%22);%0A            st.setString(1, tbl
 );%0A     
@@ -4074,37 +4074,8 @@
 ery(
-%22SELECT COUNT(*) FROM %22 + tbl
 );%0A 

use PreparedStatements