
/*
 * Copyright (C) 2011 Archie L. Cobbs. All rights reserved.
 *
 * $Id$
 */

package org.dellroad.stuff.servlet;

import java.sql.Driver;
import java.sql.DriverManager;
import java.util.Enumeration;

import javax.servlet.ServletContextEvent;

import org.dellroad.stuff.spring.ThreadLocalContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.util.IntrospectorCleanupListener;

/**
 * Clears references that can cause container memory leaks on Web container class unloading.
 *
 * @see <a href="http://opensource.atlassian.com/confluence/spring/pages/viewpage.action?pageId=2669">Spring Wiki Discussion of
 *      ClassLoader Memory Leaks</a>
 * @since 1.0.49
 */
public class ContextCleanupListener extends IntrospectorCleanupListener {

    protected final Logger log = LoggerFactory.getLogger(getClass());

    /**
     * Unregisters any JDBC drivers registered under the current class loader after
     * first invoking the superclass version of this method.
     *
     * <p>
     * Also resets the {@link ThreadLocalContext} singleton instance
     * so Tomcat won't complain about the lingering ThreadLocal variables.
     * </p>
     */
    @Override
    public void contextDestroyed(ServletContextEvent event) {
        try {
            super.contextDestroyed(event);

            // Unregister JDBC drivers
            for (Enumeration<Driver> e = DriverManager.getDrivers(); e.hasMoreElements(); ) {
                Driver driver = e.nextElement();
                if (driver.getClass().getClassLoader() == getClass().getClassLoader()) {
                    DriverManager.deregisterDriver(driver);
                }
            }

            // Reset the ThreadLocalContext singleton instance to make Tomcat happy
            ThreadLocalContext.setInstance(new ThreadLocalContext());
        } catch (Throwable e) {
            log.error("exception cleaning up servlet context", e);
        }
    }
}

@@ -680,16 +680,63 @@
 aks%3C/a%3E%0A
+ * @see http://bugs.mysql.com/bug.php?id=65909%0A
  * @sinc
@@ -1359,24 +1359,472 @@
 ed(event);%0A%0A
+            // Get my class loader%0A            final ClassLoader thisClassLoader = this.getClass().getClassLoader();%0A%0A            // Work around MySQL bug http://bugs.mysql.com/bug.php?id=65909%0A            try %7B%0A                Class.forName(%22com.mysql.jdbc.AbandonedConnectionCleanupThread%22, false,%0A                  thisClassLoader).getMethod(%22shutdown%22).invoke(null);%0A            %7D catch (Exception e) %7B%0A                // ignore%0A            %7D%0A%0A
             
@@ -1956,24 +1956,30 @@
             
+final 
 Driver drive
@@ -2057,30 +2057,20 @@
 er() == 
-getClass().get
+this
 ClassLoa
@@ -2076,13 +2076,9 @@
 ader
-()) %7B
+)
 %0A   
@@ -2138,26 +2138,8 @@
 r);%0A
-                %7D%0A
     

Add workaround for MySQL bug http://bugs.mysql.com/bug.php?id=65909.