You are viewing a plain text version of this content. The canonical link for it is here.
Posted to derby-commits@db.apache.org by ka...@apache.org on 2011/07/11 12:32:41 UTC

svn commit: r1145111 - in /db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/upgradeTests: DriverUnloader.java PhaseChanger.java UpgradeClassLoader.java

Author: kahatlen
Date: Mon Jul 11 10:32:41 2011
New Revision: 1145111

URL: http://svn.apache.org/viewvc?rev=1145111&view=rev
Log:
DERBY-5316: Unload old JDBC drivers when done with them in the upgrade tests

When we're done with an old version in the upgrade test, deregister all
JDBC drivers in the old version's class loader from DriverManager.

Added:
    db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/upgradeTests/DriverUnloader.java   (with props)
Modified:
    db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/upgradeTests/PhaseChanger.java
    db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/upgradeTests/UpgradeClassLoader.java

Added: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/upgradeTests/DriverUnloader.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/upgradeTests/DriverUnloader.java?rev=1145111&view=auto
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/upgradeTests/DriverUnloader.java (added)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/upgradeTests/DriverUnloader.java Mon Jul 11 10:32:41 2011
@@ -0,0 +1,45 @@
+/*
+
+Derby - Class org.apache.derbyTesting.functionTests.tests.upgradeTests.DriverUnloader
+
+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.derbyTesting.functionTests.tests.upgradeTests;
+
+import java.sql.Driver;
+import java.sql.DriverManager;
+import java.sql.SQLException;
+import java.util.Enumeration;
+
+/**
+ * Helper class used by the upgrade tests to unload JDBC drivers loaded in
+ * separate class loaders. This class must live in the same class loader as
+ * the drivers it attempts to unload.
+ */
+public class DriverUnloader {
+    /**
+     * Deregister all JDBC drivers accessible from the class loader in which
+     * this class lives.
+     */
+    public static void unload() throws SQLException {
+        Enumeration e = DriverManager.getDrivers();
+        while (e.hasMoreElements()) {
+            DriverManager.deregisterDriver((Driver) e.nextElement());
+        }
+    }
+}

Propchange: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/upgradeTests/DriverUnloader.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/upgradeTests/PhaseChanger.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/upgradeTests/PhaseChanger.java?rev=1145111&r1=1145110&r2=1145111&view=diff
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/upgradeTests/PhaseChanger.java (original)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/upgradeTests/PhaseChanger.java Mon Jul 11 10:32:41 2011
@@ -20,17 +20,16 @@ limitations under the License.
 */
 package org.apache.derbyTesting.functionTests.tests.upgradeTests;
 
-import java.io.PrintStream;
-import java.security.AccessController;
+import java.lang.reflect.Method;
 import java.sql.SQLException;
 
 import javax.sql.DataSource;
 
-import junit.extensions.TestSetup;
 import junit.framework.Test;
 
 import org.apache.derbyTesting.junit.BaseTestCase;
 import org.apache.derbyTesting.junit.BaseTestSetup;
+import org.apache.derbyTesting.junit.JDBC;
 import org.apache.derbyTesting.junit.JDBCDataSource;
 import org.apache.derbyTesting.junit.TestConfiguration;
 
@@ -121,12 +120,21 @@ final class PhaseChanger extends BaseTes
      * Shutdown the database engine and reset the class loader.
      * @throws SQLException if the engine couldn't be stopped
      */
-    protected void tearDown() throws SQLException
+    protected void tearDown() throws Exception
     {
         if ( trace ) BaseTestCase.traceit(" Test upgrade done.");
         DataSource ds = JDBCDataSource.getDataSource();
         JDBCDataSource.shutEngine(ds);
 
+        // When we're done with the old driver, make sure it's deregistered
+        // from the DriverManager (if running on a platform that has the
+        // DriverManager class). The shutEngine() should also deregister the
+        // driver, but on some versions it doesn't (DERBY-2905, DERBY-5316).
+        if (phase == UpgradeChange.PH_POST_HARD_UPGRADE &&
+                JDBC.vmSupportsJDBC3()) {
+            deregisterDriver();
+        }
+
         if (loader != null)
             UpgradeClassLoader.setThreadLoader(previousLoader);       
         loader = null;
@@ -135,5 +143,19 @@ final class PhaseChanger extends BaseTes
         UpgradeChange.phase.set(null);
         UpgradeChange.oldVersion.set(null);
     }
-    
+
+    /**
+     * Deregister all JDBC drivers in the class loader associated with this
+     * version.
+     */
+    private void deregisterDriver() throws Exception {
+        // DriverManager only allows deregistering of drivers from classes
+        // that live in a class loader that is able to load the driver. So
+        // create an instance of DriverUnloader in the old driver's class
+        // loader.
+        Class unloader = Class.forName(
+                DriverUnloader.class.getName(), true, loader);
+        Method m = unloader.getMethod("unload", (Class[]) null);
+        m.invoke(null, (Object[]) null);
+    }
 }

Modified: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/upgradeTests/UpgradeClassLoader.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/upgradeTests/UpgradeClassLoader.java?rev=1145111&r1=1145110&r2=1145111&view=diff
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/upgradeTests/UpgradeClassLoader.java (original)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/upgradeTests/UpgradeClassLoader.java Mon Jul 11 10:32:41 2011
@@ -20,19 +20,16 @@ limitations under the License.
 */
 package org.apache.derbyTesting.functionTests.tests.upgradeTests;
 
+import java.io.ByteArrayOutputStream;
 import java.io.File;
 import java.io.IOException;
-import java.lang.reflect.Method;
+import java.io.InputStream;
 import java.net.MalformedURLException;
 import java.net.URL;
 import java.net.URLClassLoader;
 import java.security.AccessController;
-import java.util.Properties;
 
-import junit.extensions.TestSetup;
 import junit.framework.Assert;
-import junit.framework.Test;
-import junit.framework.TestSuite;
 
 import org.apache.derbyTesting.junit.BaseTestCase;
 
@@ -237,9 +234,46 @@ public class UpgradeClassLoader
         
         // Specify null for parent class loader to avoid mixing up 
         // jars specified in the system classpath
-        return new URLClassLoader(url, null);       
+        ClassLoader oldVersionLoader = new URLClassLoader(url, null);
+
+        // DERBY-5316: We need to unload the JDBC driver when done with it,
+        // but that can only be done if the DriverUnloader class lives in a
+        // class-loader which is able to load the driver class.
+        return new ClassLoader(oldVersionLoader) {
+            protected Class findClass(String name)
+                    throws ClassNotFoundException {
+                if (name.equals(DriverUnloader.class.getName())) {
+                    try {
+                        byte[] b = fetchDriverUnloaderBytes();
+                        return defineClass(name, b, 0, b.length);
+                    } catch (IOException ioe) {
+                        throw new ClassNotFoundException(name, ioe);
+                    }
+                }
+                throw new ClassNotFoundException(name);
+            }
+        };
+    }
+
+    /**
+     * Get a byte array with the contents of the class file for the
+     * {@code DriverUnloader} class.
+     */
+    private static byte[] fetchDriverUnloaderBytes() throws IOException {
+        InputStream in =
+            DriverUnloader.class.getResourceAsStream("DriverUnloader.class");
+        try {
+            ByteArrayOutputStream out = new ByteArrayOutputStream();
+            byte[] buf = new byte[4096];
+            int len;
+            while ((len = in.read(buf)) > 0) {
+                out.write(buf, 0, len);
+            }
+            return out.toByteArray();
+        } finally {
+            in.close();
+        }
     }
-    
 }