Author: hlship
Date: Tue Mar  6 15:35:00 2007
New Revision: 515362

URL: http://svn.apache.org/viewvc?view=rev&rev=515362
Log:
TAPESTRY-1316: Address class loader issues inside JBoss

Modified:
    
tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/services/ClassFactoryClassPool.java
    tapestry/tapestry5/tapestry-project/trunk/src/site/apt/jboss.apt

Modified: 
tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/services/ClassFactoryClassPool.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/services/ClassFactoryClassPool.java?view=diff&rev=515362&r1=515361&r2=515362
==============================================================================
--- 
tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/services/ClassFactoryClassPool.java
 (original)
+++ 
tapestry/tapestry5/tapestry-ioc/trunk/src/main/java/org/apache/tapestry/ioc/internal/services/ClassFactoryClassPool.java
 Tue Mar  6 15:35:00 2007
@@ -15,8 +15,10 @@
 package org.apache.tapestry.ioc.internal.services;
 
 import static org.apache.tapestry.ioc.internal.util.CollectionFactory.newSet;
+import static org.apache.tapestry.ioc.internal.util.CollectionFactory.newMap;
 
 import java.util.Set;
+import java.util.Map;
 
 import javassist.ClassPath;
 import javassist.ClassPool;
@@ -31,14 +33,12 @@
  */
 public class ClassFactoryClassPool extends ClassPool
 {
-    private ClassLoader _loader;
-
-    private ClassPath _priorClassPath;
-
     /**
      * Used to identify which class loaders have already been integrated into 
the pool.
      */
-    private Set<ClassLoader> _loaders = newSet();
+    private final Set<ClassLoader> _allLoaders = newSet();
+
+    private final Map<ClassLoader, ClassPath> _leafLoaders = newMap();
 
     public ClassFactoryClassPool(ClassLoader contextClassLoader)
     {
@@ -50,9 +50,6 @@
     /**
      * Convienience method for adding to the ClassPath for a particular class 
loader.
      * <p>
-     * TODO: This code assumes that ClassLoaders are structured as a "line" 
not a proper "tree".
-     * That is, if the ClassLoader hiearchy actually does have branches, 
rather than a straight line
-     * from root to leaf, it may not work.
      * 
      * @param loader
      *            the class loader to add (derived from a loaded class, and 
may be null for some
@@ -60,28 +57,34 @@
      */
     public synchronized void addClassLoaderIfNeeded(ClassLoader loader)
     {
-        if (loader == null || loader == _loader || _loaders.contains(loader)) 
return;
+        Set<ClassLoader> leaves = _leafLoaders.keySet();
+        if (loader == null || leaves.contains(loader) || 
_allLoaders.contains(loader)) return;
 
-        ClassPath path = new LoaderClassPath(loader);
+        // Work out if this loader is a child of a loader we have already.
+        ClassLoader existingLeaf = loader;
+        while (existingLeaf != null && !leaves.contains(existingLeaf))
+        {
+            existingLeaf = existingLeaf.getParent();
+        }
 
-        if (_priorClassPath != null) removeClassPath(_priorClassPath);
+        if (existingLeaf != null)
+        {
+            // The new loader is a child of an existing leaf.
+            // So we remove the old leaf before we add the new loader
+            ClassPath priorPath = _leafLoaders.get(existingLeaf);
+            removeClassPath(priorPath);
+            _leafLoaders.remove(existingLeaf);
+        }
 
+        ClassPath path = new LoaderClassPath(loader);
+        _leafLoaders.put(loader, path);
         insertClassPath(path);
 
-        _priorClassPath = path;
-
         ClassLoader l = loader;
         while (l != null)
         {
-            _loaders.add(l);
+            _allLoaders.add(l);
             l = l.getParent();
         }
-
-        _loader = loader;
-    }
-
-    public synchronized ClassLoader getLoader()
-    {
-        return _loader;
     }
 }

Modified: tapestry/tapestry5/tapestry-project/trunk/src/site/apt/jboss.apt
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/tapestry-project/trunk/src/site/apt/jboss.apt?view=diff&rev=515362&r1=515361&r2=515362
==============================================================================
--- tapestry/tapestry5/tapestry-project/trunk/src/site/apt/jboss.apt (original)
+++ tapestry/tapestry5/tapestry-project/trunk/src/site/apt/jboss.apt Tue Mar  6 
15:35:00 2007
@@ -5,25 +5,7 @@
 Deployment Notes: JBoss
 
   JBoss's default servlet container is {{{tomcat.html}Tomcat}}, so deployment 
notes for Tomcat apply to JBoss as well.
-  
-  JBoss has a very odd class loader structure that causes havoc with many 
frameworks, including Tapestry 5. The way to get around it is to edit the 
configuration file
-  <JBoss 
root>/server/default/deploy/jbossweb-tomcat55.sar/META-INF/jboss-service.xml 
and turn on the UseJBossWebLoader attribute:
-  
-+----+
-      <!-- A flag indicating if the JBoss Loader should be used. This loader
-           uses a unified class loader as the class loader rather than the 
tomcat
-           specific class loader.
-           The default is false to ensure that wars have isolated class loading
-           for duplicate jars and jsp files.
-      -->
-      <attribute name="UseJBossWebLoader">true</attribute>
-+----+     
-  
-  This is not a very good solution, as it affects all web applications within 
the server, potentially causing other problems. Hopefully a better solution will
-  be discoverred in the future. And perhaps a time traveller will venture back 
in time with that information and save me a lot of headaches yesterday.
-  
-  Tapestry has been tested with JBoss 4.0.5, which uses Tomcat 5.5.20.
-  
+      
 * Logging
 
   TODO: Discuss logging configuration for JBoss.     


Reply via email to