You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by si...@apache.org on 2012/08/06 22:07:51 UTC

svn commit: r1369963 - in /commons/proper/dbutils/trunk/src: changes/changes.xml main/java/org/apache/commons/dbutils/DbUtils.java

Author: simonetripodi
Date: Mon Aug  6 20:07:51 2012
New Revision: 1369963

URL: http://svn.apache.org/viewvc?rev=1369963&view=rev
Log:
[DBUTILS-96] DbUtils#loadDriver(ClassLoader,String) makes DriverManager throwing 'No suitable driver found for jdbc' if ClassLoader is not the System's one

Modified:
    commons/proper/dbutils/trunk/src/changes/changes.xml
    commons/proper/dbutils/trunk/src/main/java/org/apache/commons/dbutils/DbUtils.java

Modified: commons/proper/dbutils/trunk/src/changes/changes.xml
URL: http://svn.apache.org/viewvc/commons/proper/dbutils/trunk/src/changes/changes.xml?rev=1369963&r1=1369962&r2=1369963&view=diff
==============================================================================
--- commons/proper/dbutils/trunk/src/changes/changes.xml (original)
+++ commons/proper/dbutils/trunk/src/changes/changes.xml Mon Aug  6 20:07:51 2012
@@ -43,6 +43,12 @@ The <action> type attribute can be add,u
     <title>Release Notes</title>
   </properties>
   <body>
+    <release version="1.6" date="201?-??-??" description="Bugfixes">
+      <action dev="simonetripodi" due-to="yuyf" type="fix" issue="DBUTILS-96">
+        DbUtils#loadDriver(ClassLoader,String) makes DriverManager throwing "No suitable driver found for jdbc"
+        if ClassLoader is not the System's one
+      </action>
+    </release>
     <release version="1.5" date="2012-07-20" description="Bugfixes and addition of BeanMapHandler">
       <action dev="simonetripodi" due-to="Benedikt Ritter" type="update" issue="DBUTILS-94">
         Provide test coverage for org.apache.commons.dbutils.DbUtils

Modified: commons/proper/dbutils/trunk/src/main/java/org/apache/commons/dbutils/DbUtils.java
URL: http://svn.apache.org/viewvc/commons/proper/dbutils/trunk/src/main/java/org/apache/commons/dbutils/DbUtils.java?rev=1369963&r1=1369962&r2=1369963&view=diff
==============================================================================
--- commons/proper/dbutils/trunk/src/main/java/org/apache/commons/dbutils/DbUtils.java (original)
+++ commons/proper/dbutils/trunk/src/main/java/org/apache/commons/dbutils/DbUtils.java Mon Aug  6 20:07:51 2012
@@ -16,11 +16,17 @@
  */
 package org.apache.commons.dbutils;
 
+import static java.sql.DriverManager.registerDriver;
+
 import java.io.PrintWriter;
+import java.lang.reflect.Constructor;
 import java.sql.Connection;
+import java.sql.Driver;
+import java.sql.DriverPropertyInfo;
 import java.sql.ResultSet;
 import java.sql.SQLException;
 import java.sql.Statement;
+import java.util.Properties;
 
 /**
  * A collection of JDBC helper methods.  This class is thread safe.
@@ -193,13 +199,30 @@ public final class DbUtils {
      */
     public static boolean loadDriver(ClassLoader classLoader, String driverClassName) {
         try {
-            classLoader.loadClass(driverClassName).newInstance();
-            return true;
+            Class<?> loadedClass = classLoader.loadClass(driverClassName);
 
-        } catch (IllegalAccessException e) {
-            // Constructor is private, OK for DriverManager contract
-            return true;
+            if (!Driver.class.isAssignableFrom(loadedClass)) {
+                return false;
+            }
+
+            @SuppressWarnings("unchecked") // guarded by previous check
+            Class<Driver> driverClass = (Class<Driver>) loadedClass;
+            Constructor<Driver> driverConstructor = driverClass.getConstructor();
+
+            // make Constructor accessible if it is private
+            boolean isConstructorAccessible = driverConstructor.isAccessible();
+            if (!isConstructorAccessible) {
+                driverConstructor.setAccessible(true);
+            }
+
+            try {
+                Driver driver = driverConstructor.newInstance();
+                registerDriver(new DriverProxy(driver));
+            } finally {
+                driverConstructor.setAccessible(isConstructorAccessible);
+            }
 
+            return true;
         } catch (Exception e) {
             return false;
 
@@ -303,4 +326,75 @@ public final class DbUtils {
         }
     }
 
+    /**
+     * Simple {@link Driver} proxy class that proxies a JDBC Driver loaded dynamically.
+     *
+     * @since 1.6
+     */
+    private static final class DriverProxy implements Driver {
+
+        /**
+         * The adapted JDBC Driver loaded dynamically.
+         */
+        private final Driver adapted;
+
+        /**
+         * Creates a new JDBC Driver that adapts a JDBC Driver loaded dynamically.
+         *
+         * @param adapted the adapted JDBC Driver loaded dynamically.
+         */
+        public DriverProxy(Driver adapted) {
+            this.adapted = adapted;
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        @Override
+        public boolean acceptsURL(String url) throws SQLException {
+            return adapted.acceptsURL(url);
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        @Override
+        public Connection connect(String url, Properties info) throws SQLException {
+            return adapted.connect(url, info);
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        @Override
+        public int getMajorVersion() {
+            return adapted.getMajorVersion();
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        @Override
+        public int getMinorVersion() {
+            return adapted.getMinorVersion();
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        @Override
+        public DriverPropertyInfo[] getPropertyInfo(String url, Properties info) throws SQLException {
+            return adapted.getPropertyInfo(url, info);
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        @Override
+        public boolean jdbcCompliant() {
+            return adapted.jdbcCompliant();
+        }
+
+    }
+
 }