Author: fhanik
Date: Thu Aug  7 20:15:19 2014
New Revision: 1616584

URL: http://svn.apache.org/r1616584
Log:
Fix https://issues.apache.org/bugzilla/show_bug.cgi?id=53853
Dynamic class loading of driver, validator and interceptors can be done from 
libraries on the context class loader. Behavior is partly backwards compatible, 
always try the current loader first, but then attempts the current thread's 
context class loader

Added:
    
tomcat/trunk/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/ClassLoaderUtil.java
   (with props)
Modified:
    tomcat/trunk/modules/jdbc-pool/doc/jdbc-pool.xml
    
tomcat/trunk/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/naming/GenericNamingResourcesFactory.java
    
tomcat/trunk/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/PoolProperties.java
    
tomcat/trunk/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/PooledConnection.java

Modified: tomcat/trunk/modules/jdbc-pool/doc/jdbc-pool.xml
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/modules/jdbc-pool/doc/jdbc-pool.xml?rev=1616584&r1=1616583&r2=1616584&view=diff
==============================================================================
--- tomcat/trunk/modules/jdbc-pool/doc/jdbc-pool.xml (original)
+++ tomcat/trunk/modules/jdbc-pool/doc/jdbc-pool.xml Thu Aug  7 20:15:19 2014
@@ -170,6 +170,22 @@
       </attribute>
     </attributes>
   </subsection>
+  
+  <subsection name="System Properties">
+    <p>System properties are JVM wide, affect all pools created in the JVM</p>
+    <attributes>
+      <attribute 
name="org.apache.tomcat.jdbc.pool.onlyAttemptCurrentClassLoader" 
required="false">
+        <p>(boolean) Controls classloading of dynamic classes, such as 
+           jdbc drivers, interceptors and validators. If set to false, default 
value, 
+           the pool will first attempt to load using the current loader and if 
class loading fails
+           attempt to load using the thread context loader.
+           Set this value to try, if you wish to remain backwards compatible, 
+           Apache Tomcat 8.0.8 and earlier, and only attempt the current 
loader.
+           If not set then the default value is <code>false</code>.)
+        </p>
+      </attribute>
+    </attributes>
+  </subsection>
 
   <subsection name="Common Attributes">
   <p>These attributes are shared between commons-dbcp and tomcat-jdbc-pool, in 
some cases default values are different.</p>

Modified: 
tomcat/trunk/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/naming/GenericNamingResourcesFactory.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/naming/GenericNamingResourcesFactory.java?rev=1616584&r1=1616583&r2=1616584&view=diff
==============================================================================
--- 
tomcat/trunk/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/naming/GenericNamingResourcesFactory.java
 (original)
+++ 
tomcat/trunk/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/naming/GenericNamingResourcesFactory.java
 Thu Aug  7 20:15:19 2014
@@ -31,6 +31,8 @@ import javax.naming.spi.ObjectFactory;
 
 import org.apache.juli.logging.Log;
 import org.apache.juli.logging.LogFactory;
+import org.apache.tomcat.jdbc.pool.ClassLoaderUtil;
+
 /**
  * Simple way of configuring generic resources by using reflection.
  * Example usage:
@@ -57,7 +59,12 @@ public class GenericNamingResourcesFacto
         Enumeration<RefAddr> refs = ref.getAll();
 
         String type = ref.getClassName();
-        Object o = Class.forName(type).newInstance();
+        Object o = 
+            ClassLoaderUtil.loadClass(
+                type,
+                GenericNamingResourcesFactory.class.getClassLoader(),
+                Thread.currentThread().getContextClassLoader())
+            .newInstance();
 
         while (refs.hasMoreElements()) {
             RefAddr addr = refs.nextElement();

Added: 
tomcat/trunk/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/ClassLoaderUtil.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/ClassLoaderUtil.java?rev=1616584&view=auto
==============================================================================
--- 
tomcat/trunk/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/ClassLoaderUtil.java
 (added)
+++ 
tomcat/trunk/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/ClassLoaderUtil.java
 Thu Aug  7 20:15:19 2014
@@ -0,0 +1,61 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.tomcat.jdbc.pool;
+
+
+import org.apache.juli.logging.Log;
+import org.apache.juli.logging.LogFactory;
+
+public class ClassLoaderUtil {
+    private static final Log log = LogFactory.getLog(ClassLoaderUtil.class);
+    
+    private static final boolean onlyAttemptFirstLoader = 
+        
Boolean.getBoolean(System.getProperty("org.apache.tomcat.jdbc.pool.onlyAttemptCurrentClassLoader",
 "false")); 
+    
+    public static Class loadClass(String className, ClassLoader... 
classLoaders) throws ClassNotFoundException {
+        ClassNotFoundException last = null;
+        StringBuffer errorMsg = null;
+        for (ClassLoader cl : classLoaders) {
+            try {
+                if (cl!=null) {
+                    if (log.isDebugEnabled()) {
+                        log.debug("Attempting to load class["+className+"] 
from "+cl);
+                    }
+                    return Class.forName(className, true, cl);
+                } else {
+                    throw new ClassNotFoundException("Classloader is null");
+                }
+            } catch (ClassNotFoundException x) {
+                last = x;
+                if (errorMsg==null) {
+                    errorMsg = new StringBuffer();
+                } else {
+                    errorMsg.append(";");
+                }
+                errorMsg.append("ClassLoader:");
+                errorMsg.append(cl.toString());
+            }
+            if (onlyAttemptFirstLoader) {
+                break;
+            }
+        }
+        throw new ClassNotFoundException("Unable to load class:"+className+" 
from "+errorMsg, last);
+    }
+
+
+
+}

Propchange: 
tomcat/trunk/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/ClassLoaderUtil.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: 
tomcat/trunk/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/PoolProperties.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/PoolProperties.java?rev=1616584&r1=1616583&r2=1616584&view=diff
==============================================================================
--- 
tomcat/trunk/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/PoolProperties.java
 (original)
+++ 
tomcat/trunk/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/PoolProperties.java
 Thu Aug  7 20:15:19 2014
@@ -767,7 +767,11 @@ public class PoolProperties implements P
 
         try {
             @SuppressWarnings("unchecked")
-            Class<Validator> validatorClass = 
(Class<Validator>)Class.forName(className);
+            Class<Validator> validatorClass = 
(Class<Validator>)ClassLoaderUtil.loadClass(
+                className,
+                PoolProperties.class.getClassLoader(),
+                Thread.currentThread().getContextClassLoader()
+            );
             validator = validatorClass.newInstance();
         } catch (ClassNotFoundException e) {
             log.warn("The class "+className+" cannot be found.", e);
@@ -957,12 +961,20 @@ public class PoolProperties implements P
                     if (log.isDebugEnabled()) {
                         log.debug("Loading interceptor 
class:"+PoolConfiguration.PKG_PREFIX+getClassName());
                     }
-                    clazz = 
Class.forName(PoolConfiguration.PKG_PREFIX+getClassName(), true, 
this.getClass().getClassLoader());
+                    clazz = ClassLoaderUtil.loadClass(
+                        PoolConfiguration.PKG_PREFIX+getClassName(), 
+                        this.getClass().getClassLoader(),
+                        Thread.currentThread().getContextClassLoader()
+                    );
                 } else {
                     if (log.isDebugEnabled()) {
                         log.debug("Loading interceptor class:"+getClassName());
                     }
-                    clazz = Class.forName(getClassName(), true, 
this.getClass().getClassLoader());
+                    clazz = ClassLoaderUtil.loadClass(
+                        getClassName(), 
+                        this.getClass().getClassLoader(),
+                        Thread.currentThread().getContextClassLoader()
+                    );
                 }
             }
             return (Class<? extends JdbcInterceptor>)clazz;

Modified: 
tomcat/trunk/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/PooledConnection.java
URL: 
http://svn.apache.org/viewvc/tomcat/trunk/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/PooledConnection.java?rev=1616584&r1=1616583&r2=1616584&view=diff
==============================================================================
--- 
tomcat/trunk/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/PooledConnection.java
 (original)
+++ 
tomcat/trunk/modules/jdbc-pool/src/main/java/org/apache/tomcat/jdbc/pool/PooledConnection.java
 Thu Aug  7 20:15:19 2014
@@ -247,8 +247,12 @@ public class PooledConnection {
                     //rely on DriverManager
                     log.warn("Not loading a JDBC driver as driverClassName 
property is null.");
                 } else {
-                    driver = (java.sql.Driver) 
Class.forName(poolProperties.getDriverClassName(),
-                            true, 
PooledConnection.class.getClassLoader()).newInstance();
+                    driver = (java.sql.Driver) 
+                        ClassLoaderUtil.loadClass(
+                            poolProperties.getDriverClassName(),
+                            PooledConnection.class.getClassLoader(),
+                            Thread.currentThread().getContextClassLoader()
+                        ).newInstance();
                 }
             }
         } catch (java.lang.Exception cn) {



---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org
For additional commands, e-mail: dev-h...@tomcat.apache.org

Reply via email to