[jboss-svn-commits] JBoss Common SVN: r2761 - in common-core/trunk/src: main/java/org/jboss/util/threadpool and 3 other directories.

jboss-svn-commits at lists.jboss.org jboss-svn-commits at lists.jboss.org
Thu Mar 27 15:59:15 EDT 2008


Author: bstansberry at jboss.com
Date: 2008-03-27 15:59:14 -0400 (Thu, 27 Mar 2008)
New Revision: 2761

Added:
   common-core/trunk/src/main/java/org/jboss/util/loading/ClassLoaderSource.java
   common-core/trunk/src/main/java/org/jboss/util/loading/ConstructorTCCLClassLoaderSource.java
   common-core/trunk/src/main/java/org/jboss/util/loading/MyClassLoaderClassLoaderSource.java
   common-core/trunk/src/test/java/org/jboss/test/util/test/loading/
   common-core/trunk/src/test/java/org/jboss/test/util/test/loading/ClassLoaderSourceTestBase.java
   common-core/trunk/src/test/java/org/jboss/test/util/test/loading/ConstructorTCCLClassLoaderSourceUnitTestCase.java
   common-core/trunk/src/test/java/org/jboss/test/util/test/loading/MyClassLoaderClassLoaderSourceUnitTestCase.java
   common-core/trunk/src/test/java/org/jboss/test/util/test/threadpool/
   common-core/trunk/src/test/java/org/jboss/test/util/test/threadpool/BasicThreadPoolTCCLTestCase.java
Modified:
   common-core/trunk/src/main/java/org/jboss/util/threadpool/BasicThreadPool.java
   common-core/trunk/src/main/java/org/jboss/util/threadpool/BasicThreadPoolMBean.java
Log:
[JBCOMMON-41] BasicThreadPool can manage thread context classloader

Added: common-core/trunk/src/main/java/org/jboss/util/loading/ClassLoaderSource.java
===================================================================
--- common-core/trunk/src/main/java/org/jboss/util/loading/ClassLoaderSource.java	                        (rev 0)
+++ common-core/trunk/src/main/java/org/jboss/util/loading/ClassLoaderSource.java	2008-03-27 19:59:14 UTC (rev 2761)
@@ -0,0 +1,40 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.util.loading;
+
+/**
+ * Interface for objects that provide a reference to a classloader.
+ * 
+ * @see org.jboss.util.threadpool.BasicThreadPool#setClassLoaderSource(ClassLoaderSource)
+ * 
+ * @author Brian Stansberry
+ */
+public interface ClassLoaderSource
+{
+   /**
+    * Gets the classloader provided by this object.
+    * 
+    * @return the classloader, or <code>null</code> if none is available
+    */
+   ClassLoader getClassLoader();
+}

Added: common-core/trunk/src/main/java/org/jboss/util/loading/ConstructorTCCLClassLoaderSource.java
===================================================================
--- common-core/trunk/src/main/java/org/jboss/util/loading/ConstructorTCCLClassLoaderSource.java	                        (rev 0)
+++ common-core/trunk/src/main/java/org/jboss/util/loading/ConstructorTCCLClassLoaderSource.java	2008-03-27 19:59:14 UTC (rev 2761)
@@ -0,0 +1,55 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.util.loading;
+
+import java.lang.ref.WeakReference;
+import java.security.AccessController;
+
+/**
+ * {@link ClassLoaderSource} implementation that returns the 
+ * {@link Thread#getContextClassLoader() thread context classloader (TCCL)}
+ * in effect when this class' constructor is invoked.
+ * 
+ * @author Brian Stansberry
+ */
+public class ConstructorTCCLClassLoaderSource implements ClassLoaderSource
+{
+   private final WeakReference classLoaderRef;
+   
+   public ConstructorTCCLClassLoaderSource()
+   {      
+      ContextClassLoader ccl = (ContextClassLoader) AccessController.doPrivileged(ContextClassLoader.INSTANTIATOR);
+      ClassLoader cl = ccl.getContextClassLoader();
+      
+      if (cl != null)
+         classLoaderRef = new WeakReference(cl);
+      else
+         classLoaderRef = null;
+   }
+   
+   public ClassLoader getClassLoader()
+   {      
+      return classLoaderRef == null ? null : (ClassLoader) classLoaderRef.get();
+   }
+
+}

Added: common-core/trunk/src/main/java/org/jboss/util/loading/MyClassLoaderClassLoaderSource.java
===================================================================
--- common-core/trunk/src/main/java/org/jboss/util/loading/MyClassLoaderClassLoaderSource.java	                        (rev 0)
+++ common-core/trunk/src/main/java/org/jboss/util/loading/MyClassLoaderClassLoaderSource.java	2008-03-27 19:59:14 UTC (rev 2761)
@@ -0,0 +1,39 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.util.loading;
+
+/**
+ * {@link ClassLoaderSource} implementation that returns the ClassLoader
+ * that loaded this class.
+ * 
+ * @author Brian Stansberry
+ */
+public class MyClassLoaderClassLoaderSource implements ClassLoaderSource
+{
+
+   public ClassLoader getClassLoader()
+   {
+      return getClass().getClassLoader();
+   }
+
+}

Modified: common-core/trunk/src/main/java/org/jboss/util/threadpool/BasicThreadPool.java
===================================================================
--- common-core/trunk/src/main/java/org/jboss/util/threadpool/BasicThreadPool.java	2008-03-27 16:24:00 UTC (rev 2760)
+++ common-core/trunk/src/main/java/org/jboss/util/threadpool/BasicThreadPool.java	2008-03-27 19:59:14 UTC (rev 2761)
@@ -21,10 +21,12 @@
   */
 package org.jboss.util.threadpool;
 
+import java.security.AccessController;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Map;
 import java.util.PriorityQueue;
+import java.util.concurrent.BlockingQueue;
 import java.util.concurrent.LinkedBlockingQueue;
 import java.util.concurrent.RejectedExecutionHandler;
 import java.util.concurrent.ThreadFactory;
@@ -35,6 +37,8 @@
 
 import org.jboss.logging.Logger;
 import org.jboss.util.collection.WeakValueHashMap;
+import org.jboss.util.loading.ClassLoaderSource;
+import org.jboss.util.loading.ContextClassLoaderSwitcher;
 
 
 /**
@@ -79,7 +83,12 @@
 
    /** The thread group */
    private ThreadGroup threadGroup;
+   
+   /** Source for the thread contrext classloader to assign to threads */
+   private ClassLoaderSource classLoaderSource;
 
+   private ContextClassLoaderSwitcher classLoaderSwitcher;
+   
    /** The last thread number */
    private AtomicInteger lastThreadNumber = new AtomicInteger(0);
 
@@ -130,10 +139,10 @@
       queue = new LinkedBlockingQueue(1024);
 
       
-      executor = new ThreadPoolExecutor(4, 4, 60, TimeUnit.SECONDS, queue);
+      executor = new RestoreTCCLThreadPoolExecutor(4, 4, 60, TimeUnit.SECONDS, queue);
       executor.setThreadFactory(factory);
       executor.setRejectedExecutionHandler(new ThreadPoolExecutor.AbortPolicy());
-
+      
       poolNumber = lastPoolNumber.incrementAndGet();
       setName(name);
       this.threadGroup = threadGroup;
@@ -400,6 +409,37 @@
          blockingMode = BlockingMode.ABORT;
    }
 
+   public ClassLoaderSource getClassLoaderSource()
+   {
+      return classLoaderSource;
+   }
+
+   public void setClassLoaderSource(ClassLoaderSource classLoaderSource)
+   {
+      if (classLoaderSource == null)
+      {
+         this.classLoaderSource = null;
+         this.classLoaderSwitcher = null;
+      }
+      else if (classLoaderSwitcher == null)
+      {
+         try
+         {
+            this.classLoaderSwitcher = (ContextClassLoaderSwitcher) AccessController.doPrivileged(ContextClassLoaderSwitcher.INSTANTIATOR);
+            this.classLoaderSource = classLoaderSource;
+         }
+         catch (SecurityException e)
+         {
+            log.error("Cannot manage context classloader for pool threads; " +
+                      "Do not have setContextClassLoader permission");
+         }
+      }
+      else
+      {
+         this.classLoaderSource = classLoaderSource;
+      }
+   }
+
    public ThreadPool getInstance()
    {
       return this;
@@ -479,6 +519,15 @@
       }
       return info;
    }
+   
+   protected void setDefaultThreadContextClassLoader(Thread thread)
+   {
+      if (classLoaderSwitcher != null)
+      {
+         ClassLoader cl = classLoaderSource == null ? null : classLoaderSource.getClassLoader();
+         classLoaderSwitcher.setContextClassLoader(thread, cl);
+      }
+   }
 
    // Private -------------------------------------------------------
 
@@ -494,10 +543,38 @@
          String threadName = BasicThreadPool.this.toString() + "-" + lastThreadNumber.incrementAndGet();
          Thread thread = new Thread(threadGroup, runnable, threadName);
          thread.setDaemon(true);
+         BasicThreadPool.this.setDefaultThreadContextClassLoader(thread);
          return thread;
       }
    }
+   
+   private class RestoreTCCLThreadPoolExecutor extends ThreadPoolExecutor
+   {      
+      public RestoreTCCLThreadPoolExecutor(int corePoolSize, int maximumPoolSize, 
+                                           long keepAliveTime, TimeUnit unit,
+                                           BlockingQueue<Runnable> workQueue)
+      {
+         super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue);
+      }
 
+      @Override
+      protected void afterExecute(Runnable r, Throwable t)
+      {
+         try
+         {
+            super.afterExecute(r, t);
+         }
+         finally
+         {
+
+            BasicThreadPool.this.setDefaultThreadContextClassLoader(Thread.currentThread());
+         }
+      }
+      
+      
+      
+   }
+
    /** An encapsulation of a task and its completion timeout
     */ 
    private static class TimeoutInfo implements Comparable

Modified: common-core/trunk/src/main/java/org/jboss/util/threadpool/BasicThreadPoolMBean.java
===================================================================
--- common-core/trunk/src/main/java/org/jboss/util/threadpool/BasicThreadPoolMBean.java	2008-03-27 16:24:00 UTC (rev 2760)
+++ common-core/trunk/src/main/java/org/jboss/util/threadpool/BasicThreadPoolMBean.java	2008-03-27 19:59:14 UTC (rev 2761)
@@ -21,6 +21,8 @@
   */
 package org.jboss.util.threadpool;
 
+import org.jboss.util.loading.ClassLoaderSource;
+
 /**
  * Management interface for the thread pool.
  *
@@ -101,5 +103,33 @@
     */
    void setKeepAliveTime(long time);
 
+   /** 
+    * Gets the source of the classloader that will be set as the 
+    * {@link Thread#getContextClassLoader() thread context classloader}
+    * for pool threads.
+    * 
+    * @return the {@link ClassLoaderSource}. May return <code>null</code>.
+    */
+   ClassLoaderSource getClassLoaderSource();
+
+   /** 
+    * Sets the source of the classloader that will be set as the 
+    * {@link Thread#getContextClassLoader() thread context classloader}
+    * for pool threads. If set, whenever any new pool thread is created, it's
+    * context classloader will be set to the loader provided by this source.
+    * Further, when any thread is returned to the pool, its context classloader
+    * will be reset to the loader provided by this source.
+    * <p> 
+    * If set to <code>null</code> (the default), the pool will not attempt to 
+    * manage the context classloader for pool threads; instead a newly created 
+    * pool thread will inherit its context classloader from whatever thread 
+    * triggered the addition to the pool.  A thread returned to the pool will
+    * not have its context classloader changed from whatever it was.
+    * </p>
+    * 
+    * @param classLoaderSource the {@link ClassLoaderSource}. May be <code>null</code>.
+    */
+   void setClassLoaderSource(ClassLoaderSource classLoaderSource);
+
    // Inner classes -------------------------------------------------
 }

Added: common-core/trunk/src/test/java/org/jboss/test/util/test/loading/ClassLoaderSourceTestBase.java
===================================================================
--- common-core/trunk/src/test/java/org/jboss/test/util/test/loading/ClassLoaderSourceTestBase.java	                        (rev 0)
+++ common-core/trunk/src/test/java/org/jboss/test/util/test/loading/ClassLoaderSourceTestBase.java	2008-03-27 19:59:14 UTC (rev 2761)
@@ -0,0 +1,125 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.test.util.test.loading;
+
+import org.jboss.test.BaseTestCase;
+import org.jboss.util.loading.ClassLoaderSource;
+
+/**
+ * Base class for testing {@link ClassLoaderSource} implementations.
+ * 
+ * @author Brian Stansberry
+ */
+public abstract class ClassLoaderSourceTestBase extends BaseTestCase
+{
+   protected ClassLoader origCl;
+   
+   /**
+    * @param name
+    */
+   public ClassLoaderSourceTestBase(String name)
+   {
+      super(name);
+   }
+   
+   @Override
+   protected void setUp() throws Exception
+   {
+      super.setUp();
+      
+      origCl = Thread.currentThread().getContextClassLoader();
+   }
+   
+   @Override
+   protected void tearDown() throws Exception
+   {
+      try
+      {
+         super.tearDown();
+      }
+      finally
+      {
+         Thread.currentThread().setContextClassLoader(origCl);
+      }
+   }
+   
+   protected abstract ClassLoaderSource createClassLoaderSource();
+   protected abstract ClassLoader getExpectedClassLoader(ClassLoader tccl);
+   
+   /**
+    * Tests that the ClassLoaderSource returns the expected classloader
+    * when the TCCL is null.
+    */
+   public void testNullTCCL()
+   {
+      checkCorrectClassLoaderSource(null);
+   }
+   
+   /**
+    * Tests that the ClassLoaderSource returns the expected classloader
+    * when the TCCL is the basic one in place when this test is executed.
+    */
+   public void testOriginalTCCL()
+   {
+      checkCorrectClassLoaderSource(origCl);
+   }
+   
+   /**
+    * Tests that the ClassLoaderSource returns the expected classloader
+    * when the TCCL is the CLS impl's own classloader.
+    */
+   public void testImplClassLoader()
+   {
+      checkCorrectClassLoaderSource(createClassLoaderSource().getClass().getClassLoader());
+   }
+   
+   /**
+    * Tests that the ClassLoaderSource returns the expected classloader
+    * when the TCCL is a child classloader.
+    */
+   public void testDifferentTCCL()
+   {
+      checkCorrectClassLoaderSource(getExtendedClassLoader());
+   }
+   
+   protected void checkCorrectClassLoaderSource(ClassLoader tccl)
+   {
+      Thread.currentThread().setContextClassLoader(tccl);
+      ClassLoaderSource cls = createClassLoaderSource();
+      assertSame("ClassLoaderSource returned expected cl", getExpectedClassLoader(tccl), cls.getClassLoader());
+   }
+   
+   protected ClassLoader getExtendedClassLoader()
+   {
+      return new ExtendedClassLoader(origCl);
+   }
+   
+   private class ExtendedClassLoader extends ClassLoader
+   {
+      ExtendedClassLoader(ClassLoader parent)
+      {
+         super(parent);
+      }
+   }
+
+}

Added: common-core/trunk/src/test/java/org/jboss/test/util/test/loading/ConstructorTCCLClassLoaderSourceUnitTestCase.java
===================================================================
--- common-core/trunk/src/test/java/org/jboss/test/util/test/loading/ConstructorTCCLClassLoaderSourceUnitTestCase.java	                        (rev 0)
+++ common-core/trunk/src/test/java/org/jboss/test/util/test/loading/ConstructorTCCLClassLoaderSourceUnitTestCase.java	2008-03-27 19:59:14 UTC (rev 2761)
@@ -0,0 +1,71 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.test.util.test.loading;
+
+import org.jboss.util.loading.ClassLoaderSource;
+import org.jboss.util.loading.ConstructorTCCLClassLoaderSource;
+import org.jboss.util.loading.MyClassLoaderClassLoaderSource;
+
+/**
+ * Unit tests of {@link ConstructorTCCLClassLoaderSource}.
+ *  
+ * @author Brian Stansberry
+ */
+public class ConstructorTCCLClassLoaderSourceUnitTestCase extends ClassLoaderSourceTestBase
+{
+
+   public ConstructorTCCLClassLoaderSourceUnitTestCase(String name)
+   {
+      super(name);
+   }
+
+   @Override
+   protected ClassLoaderSource createClassLoaderSource()
+   {
+      return new ConstructorTCCLClassLoaderSource();
+   }
+
+   @Override
+   protected ClassLoader getExpectedClassLoader(ClassLoader tccl)
+   {
+      return tccl;
+   }
+   
+   /**
+    * Tests that the ClassLoaderSource does not prevent garbage collection of
+    * the classloader.
+    */
+   public void testGarbageCollectedClassLoader()
+   {
+      ClassLoader cl = getExtendedClassLoader();
+      Thread.currentThread().setContextClassLoader(cl);
+      ClassLoaderSource cls = createClassLoaderSource();
+      Thread.currentThread().setContextClassLoader(origCl);
+      cl = null;
+      
+      System.gc();
+      
+      assertNull("ClassLoader garbage collected", cls.getClassLoader());
+   }
+
+}

Added: common-core/trunk/src/test/java/org/jboss/test/util/test/loading/MyClassLoaderClassLoaderSourceUnitTestCase.java
===================================================================
--- common-core/trunk/src/test/java/org/jboss/test/util/test/loading/MyClassLoaderClassLoaderSourceUnitTestCase.java	                        (rev 0)
+++ common-core/trunk/src/test/java/org/jboss/test/util/test/loading/MyClassLoaderClassLoaderSourceUnitTestCase.java	2008-03-27 19:59:14 UTC (rev 2761)
@@ -0,0 +1,53 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.test.util.test.loading;
+
+import org.jboss.util.loading.ClassLoaderSource;
+import org.jboss.util.loading.MyClassLoaderClassLoaderSource;
+
+/**
+ * Unit tests of {@link MyClassLoaderClassLoaderSource}.
+ *  
+ * @author Brian Stansberry
+ */
+public class MyClassLoaderClassLoaderSourceUnitTestCase extends ClassLoaderSourceTestBase
+{
+
+   public MyClassLoaderClassLoaderSourceUnitTestCase(String name)
+   {
+      super(name);
+   }
+
+   @Override
+   protected ClassLoaderSource createClassLoaderSource()
+   {
+      return new MyClassLoaderClassLoaderSource();
+   }
+
+   @Override
+   protected ClassLoader getExpectedClassLoader(ClassLoader tccl)
+   {
+      return MyClassLoaderClassLoaderSource.class.getClassLoader();
+   }
+
+}

Added: common-core/trunk/src/test/java/org/jboss/test/util/test/threadpool/BasicThreadPoolTCCLTestCase.java
===================================================================
--- common-core/trunk/src/test/java/org/jboss/test/util/test/threadpool/BasicThreadPoolTCCLTestCase.java	                        (rev 0)
+++ common-core/trunk/src/test/java/org/jboss/test/util/test/threadpool/BasicThreadPoolTCCLTestCase.java	2008-03-27 19:59:14 UTC (rev 2761)
@@ -0,0 +1,174 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.test.util.test.threadpool;
+
+import org.jboss.test.BaseTestCase;
+import org.jboss.util.loading.ClassLoaderSource;
+import org.jboss.util.threadpool.BasicThreadPool;
+
+/**
+ * Tests thread context classloader management by BasicThreadPool.
+ * 
+ * @author Brian Stansberry
+ */
+public class BasicThreadPoolTCCLTestCase extends BaseTestCase
+{
+   protected ClassLoader origCl;
+   
+   /**
+    * @param name
+    */
+   public BasicThreadPoolTCCLTestCase(String name)
+   {
+      super(name);
+   }
+   
+   @Override
+   protected void setUp() throws Exception
+   {
+      super.setUp();
+      
+      origCl = Thread.currentThread().getContextClassLoader();
+   }
+   
+   @Override
+   protected void tearDown() throws Exception
+   {
+      try
+      {
+         super.tearDown();
+      }
+      finally
+      {
+         Thread.currentThread().setContextClassLoader(origCl);
+      }
+   }
+   
+   public void testNullClassLoaderSource() throws Exception
+   {
+      ClassLoader existing = origCl == null ? getExtendedClassLoader() : origCl;
+      Thread.currentThread().setContextClassLoader(existing);
+      runClassLoaderSourceTest(null, existing);
+      
+      Thread.currentThread().setContextClassLoader(null);
+      runClassLoaderSourceTest(null, null);      
+   }
+   
+   public void testConfiguredClassLoaderSource() throws Exception
+   {
+      ClassLoaderSource source = new TestClassLoaderSource();
+      runClassLoaderSourceTest(source, source.getClassLoader());
+   }
+   
+   private void runClassLoaderSourceTest(ClassLoaderSource source, ClassLoader expected) throws Exception
+   {
+      ThreadGroup group = new ThreadGroup("Test");
+      BasicThreadPool pool = new BasicThreadPool("Test", group);
+      // Only one thread so we can use it twice to confirm 
+      // it gets cleaned after the first task
+      pool.setMaximumPoolSize(1);
+      pool.setClassLoaderSource(source);
+      
+      Task task = new Task();
+      pool.run(task);
+      
+      // Wait for task completion
+      synchronized (task)
+      {
+         if (!task.done)
+         {
+            task.wait();
+         }
+      }
+      
+//      ClassLoader expected = source == null ? null : source.getClassLoader();
+      assertEquals(expected, task.incomingCl);
+      
+      Task task2 = new Task();
+      pool.run(task2);
+      
+      // Wait for task completion
+      synchronized (task2)
+      {
+         if (!task2.done)
+         {
+            task2.wait();
+         }
+      }
+      
+      assertSame(expected, task.incomingCl);
+      
+      assertEquals("Pool size limited", 1, pool.getPoolSize());
+   }
+   
+   private ClassLoader getExtendedClassLoader()
+   {
+      return new ExtendedClassLoader(origCl);
+   }
+   
+   private class ExtendedClassLoader extends ClassLoader
+   {
+      ExtendedClassLoader(ClassLoader parent)
+      {
+         super(parent);
+      }
+   }
+   
+   private class Task implements Runnable
+   {
+      private ClassLoader incomingCl;
+      private boolean done;
+      
+      public void run()
+      {
+         incomingCl = Thread.currentThread().getContextClassLoader();
+         
+         // Deliberately pollute the TCCL
+         ClassLoader leakedCl = BasicThreadPoolTCCLTestCase.this.getExtendedClassLoader();
+         Thread.currentThread().setContextClassLoader(leakedCl);
+         
+         // Wake up the test thread
+         synchronized (this)
+         {
+            done = true;         
+            notifyAll();
+         }
+      }    
+   }
+   
+   private class TestClassLoaderSource implements ClassLoaderSource
+   {
+      private ClassLoader cl;
+      
+      TestClassLoaderSource()
+      {
+         cl = BasicThreadPoolTCCLTestCase.this.getExtendedClassLoader();
+      }
+
+      public ClassLoader getClassLoader()
+      {
+         return cl;
+      }
+   }
+
+}




More information about the jboss-svn-commits mailing list