Author: sylvain
Date: Thu Mar 10 14:47:14 2005
New Revision: 157005

URL: http://svn.apache.org/viewcvs?view=rev&rev=157005
Log:
Refactor per-sitemap classpath: move creation of the classloader in the 
TreeProcessor rather than in the ServiceManager, which allows to update the 
thread's context classloader as we go deep in the sitemap tree.

Added:
    
cocoon/trunk/src/java/org/apache/cocoon/components/classloader/ClassLoaderFactory.java
      - copied, changed from r156985, 
cocoon/trunk/src/core/java/org/apache/cocoon/core/ClassLoaderFactory.java
    
cocoon/trunk/src/java/org/apache/cocoon/components/classloader/DefaultClassLoaderFactory.java
      - copied, changed from r156985, 
cocoon/trunk/src/core/java/org/apache/cocoon/core/DefaultClassLoaderFactory.java
Removed:
    cocoon/trunk/src/core/java/org/apache/cocoon/core/ClassLoaderFactory.java
    
cocoon/trunk/src/core/java/org/apache/cocoon/core/DefaultClassLoaderFactory.java
Modified:
    
cocoon/trunk/src/core/java/org/apache/cocoon/core/container/CoreServiceManager.java
    cocoon/trunk/src/java/org/apache/cocoon/cocoon.roles
    
cocoon/trunk/src/java/org/apache/cocoon/components/container/CocoonServiceManager.java
    
cocoon/trunk/src/java/org/apache/cocoon/components/treeprocessor/ConcreteTreeProcessor.java
    
cocoon/trunk/src/java/org/apache/cocoon/components/treeprocessor/DefaultTreeBuilder.java
    
cocoon/trunk/src/java/org/apache/cocoon/components/treeprocessor/ProcessorComponentInfo.java
    
cocoon/trunk/src/java/org/apache/cocoon/components/treeprocessor/TreeBuilder.java
    
cocoon/trunk/src/java/org/apache/cocoon/components/treeprocessor/TreeProcessor.java
    
cocoon/trunk/src/java/org/apache/cocoon/components/treeprocessor/sitemap/SitemapLanguage.java

Modified: 
cocoon/trunk/src/core/java/org/apache/cocoon/core/container/CoreServiceManager.java
URL: 
http://svn.apache.org/viewcvs/cocoon/trunk/src/core/java/org/apache/cocoon/core/container/CoreServiceManager.java?view=diff&r1=157004&r2=157005
==============================================================================
--- 
cocoon/trunk/src/core/java/org/apache/cocoon/core/container/CoreServiceManager.java
 (original)
+++ 
cocoon/trunk/src/core/java/org/apache/cocoon/core/container/CoreServiceManager.java
 Thu Mar 10 14:47:14 2005
@@ -45,9 +45,7 @@
 import org.apache.cocoon.components.ComponentInfo;
 import org.apache.cocoon.configuration.ConfigurationBuilder;
 import org.apache.cocoon.configuration.Settings;
-import org.apache.cocoon.core.ClassLoaderFactory;
 import org.apache.cocoon.core.Core;
-import org.apache.cocoon.core.DefaultClassLoaderFactory;
 import org.apache.cocoon.core.container.handler.AbstractComponentHandler;
 import org.apache.cocoon.core.container.handler.AliasComponentHandler;
 import org.apache.cocoon.core.container.handler.ComponentHandler;
@@ -108,12 +106,21 @@
     /** The parent ServiceManager */
     protected ServiceManager parentManager;
     
+    /** The classloader to get classes from */
+    protected ClassLoader classloader;
+    
     /** The resolver used to resolve includes. It is lazily loaded in [EMAIL 
PROTECTED] #getSourceResolver()}. */
     private SourceResolver cachedSourceResolver;
 
     /** Create the ServiceManager with a parent ServiceManager */
     public CoreServiceManager( final ServiceManager parent ) {
+        this(parent, null);
+    }
+
+    /** Create the ServiceManager with a parent ServiceManager and a 
ClassLoader */
+    public CoreServiceManager( final ServiceManager parent, final ClassLoader 
classloader ) {
         this.parentManager = parent;
+        this.classloader = classloader;
         
         RoleManager parentRoleManager = null;
         // get role manager and logger manager
@@ -166,32 +173,8 @@
      * @see 
org.apache.avalon.framework.configuration.Configurable#configure(org.apache.avalon.framework.configuration.Configuration)
      */
     public void configure(Configuration configuration) throws 
ConfigurationException {
-        
-        ClassLoader classLoader = null;
-        
-        Configuration classLoaderConfig = configuration.getChild("classpath", 
false);
-        
-        // We have a specific classpath for this manager
-        if (classLoaderConfig != null) {
-            // We need a parent manager to lookup the CL factory
-            if (this.parentManager == null) {
-                throw new ConfigurationException("Cannot set <classpath> on 
root ServiceManager at " +
-                        classLoaderConfig.getLocation());
-            }
-            
-            try {
-                ClassLoaderFactory clFactory = 
(ClassLoaderFactory)this.parentManager.lookup(ClassLoaderFactory.ROLE);
                 
-                // TODO: add classloader to constructor to be able to 
propagate parentManager's CL
-                classLoader = 
clFactory.createClassLoader(Thread.currentThread().getContextClassLoader(), 
classLoaderConfig);
-            } catch (ConfigurationException ce) {
-                throw ce;
-            } catch (Exception e) {
-                throw new ConfigurationException("Cannot setup classloader", 
e);
-            }
-        }
-        
-        this.componentEnv = new ComponentEnvironment(classLoader, getLogger(), 
this.roleManager, this.loggerManager, this.context, this);
+        this.componentEnv = new ComponentEnvironment(this.classloader, 
getLogger(), this.roleManager, this.loggerManager, this.context, this);
         
         // Setup location
         this.location = configuration.getLocation();

Modified: cocoon/trunk/src/java/org/apache/cocoon/cocoon.roles
URL: 
http://svn.apache.org/viewcvs/cocoon/trunk/src/java/org/apache/cocoon/cocoon.roles?view=diff&r1=157004&r2=157005
==============================================================================
--- cocoon/trunk/src/java/org/apache/cocoon/cocoon.roles (original)
+++ cocoon/trunk/src/java/org/apache/cocoon/cocoon.roles Thu Mar 10 14:47:14 
2005
@@ -30,8 +30,8 @@
 
 <role-list>
 
-  <role name="org.apache.cocoon.core.ClassLoaderFactory"
-        default-class="org.apache.cocoon.core.DefaultClassLoaderFactory"/>
+  <role name="org.apache.cocoon.components.classloader.ClassLoaderFactory"
+        
default-class="org.apache.cocoon.components.classloader.DefaultClassLoaderFactory"/>
 
   <role name="org.apache.excalibur.source.SourceFactorySelector"
         shorthand="source-factories"

Copied: 
cocoon/trunk/src/java/org/apache/cocoon/components/classloader/ClassLoaderFactory.java
 (from r156985, 
cocoon/trunk/src/core/java/org/apache/cocoon/core/ClassLoaderFactory.java)
URL: 
http://svn.apache.org/viewcvs/cocoon/trunk/src/java/org/apache/cocoon/components/classloader/ClassLoaderFactory.java?view=diff&rev=157005&p1=cocoon/trunk/src/core/java/org/apache/cocoon/core/ClassLoaderFactory.java&r1=156985&p2=cocoon/trunk/src/java/org/apache/cocoon/components/classloader/ClassLoaderFactory.java&r2=157005
==============================================================================
--- cocoon/trunk/src/core/java/org/apache/cocoon/core/ClassLoaderFactory.java 
(original)
+++ 
cocoon/trunk/src/java/org/apache/cocoon/components/classloader/ClassLoaderFactory.java
 Thu Mar 10 14:47:14 2005
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.cocoon.core;
+package org.apache.cocoon.components.classloader;
 
 import org.apache.avalon.framework.configuration.Configuration;
 import org.apache.avalon.framework.configuration.ConfigurationException;

Copied: 
cocoon/trunk/src/java/org/apache/cocoon/components/classloader/DefaultClassLoaderFactory.java
 (from r156985, 
cocoon/trunk/src/core/java/org/apache/cocoon/core/DefaultClassLoaderFactory.java)
URL: 
http://svn.apache.org/viewcvs/cocoon/trunk/src/java/org/apache/cocoon/components/classloader/DefaultClassLoaderFactory.java?view=diff&rev=157005&p1=cocoon/trunk/src/core/java/org/apache/cocoon/core/DefaultClassLoaderFactory.java&r1=156985&p2=cocoon/trunk/src/java/org/apache/cocoon/components/classloader/DefaultClassLoaderFactory.java&r2=157005
==============================================================================
--- 
cocoon/trunk/src/core/java/org/apache/cocoon/core/DefaultClassLoaderFactory.java
 (original)
+++ 
cocoon/trunk/src/java/org/apache/cocoon/components/classloader/DefaultClassLoaderFactory.java
 Thu Mar 10 14:47:14 2005
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.cocoon.core;
+package org.apache.cocoon.components.classloader;
 
 import java.net.URL;
 import java.net.URLClassLoader;

Modified: 
cocoon/trunk/src/java/org/apache/cocoon/components/container/CocoonServiceManager.java
URL: 
http://svn.apache.org/viewcvs/cocoon/trunk/src/java/org/apache/cocoon/components/container/CocoonServiceManager.java?view=diff&r1=157004&r2=157005
==============================================================================
--- 
cocoon/trunk/src/java/org/apache/cocoon/components/container/CocoonServiceManager.java
 (original)
+++ 
cocoon/trunk/src/java/org/apache/cocoon/components/container/CocoonServiceManager.java
 Thu Mar 10 14:47:14 2005
@@ -43,7 +43,12 @@
 
     /** Create the ServiceManager with a parent ServiceManager */
     public CocoonServiceManager( final ServiceManager parent) {
-        super( parent );
+        this(parent, null);
+    }
+    
+    /** Create the ServiceManager with a parent ServiceManager and a 
ClassLoader */
+    public CocoonServiceManager( final ServiceManager parent, final 
ClassLoader classloader) {
+        super(parent, classloader);
         ProcessorComponentInfo parentInfo = null;
         if (parent != null) {
             try {

Modified: 
cocoon/trunk/src/java/org/apache/cocoon/components/treeprocessor/ConcreteTreeProcessor.java
URL: 
http://svn.apache.org/viewcvs/cocoon/trunk/src/java/org/apache/cocoon/components/treeprocessor/ConcreteTreeProcessor.java?view=diff&r1=157004&r2=157005
==============================================================================
--- 
cocoon/trunk/src/java/org/apache/cocoon/components/treeprocessor/ConcreteTreeProcessor.java
 (original)
+++ 
cocoon/trunk/src/java/org/apache/cocoon/components/treeprocessor/ConcreteTreeProcessor.java
 Thu Mar 10 14:47:14 2005
@@ -44,6 +44,9 @@
 
     /** Our ServiceManager */
     private ServiceManager manager;
+    
+    /** Our class loader */
+    private ClassLoader classloader;
 
     /** The processor that wraps us */
     private TreeProcessor wrappingProcessor;
@@ -75,12 +78,13 @@
     }
     
     /** Set the processor data, result of the treebuilder job */
-    public void setProcessorData(ServiceManager manager, ProcessingNode 
rootNode, List disposableNodes) {
+    public void setProcessorData(ServiceManager manager, ClassLoader 
classloader, ProcessingNode rootNode, List disposableNodes) {
         if (this.rootNode != null) {
             throw new IllegalStateException("setProcessorData() can only be 
called once");
         }
 
         this.manager = manager;
+        this.classloader = classloader;
         this.rootNode = rootNode;
         this.disposableNodes = disposableNodes;
     }
@@ -188,7 +192,11 @@
         synchronized (this) {
             requestCount++;
         }
-
+        
+        Thread currentThread = Thread.currentThread();
+        ClassLoader oldClassLoader = currentThread.getContextClassLoader();
+        currentThread.setContextClassLoader(this.classloader);
+        
         try {
             // and now process
             EnvironmentHelper.enterProcessor(this, this.manager, environment);
@@ -211,6 +219,9 @@
             }
 
         } finally {
+            // Restore classloader
+            currentThread.setContextClassLoader(oldClassLoader);
+
             // Decrement the concurrent request count
             synchronized (this) {
                 requestCount--;

Modified: 
cocoon/trunk/src/java/org/apache/cocoon/components/treeprocessor/DefaultTreeBuilder.java
URL: 
http://svn.apache.org/viewcvs/cocoon/trunk/src/java/org/apache/cocoon/components/treeprocessor/DefaultTreeBuilder.java?view=diff&r1=157004&r2=157005
==============================================================================
--- 
cocoon/trunk/src/java/org/apache/cocoon/components/treeprocessor/DefaultTreeBuilder.java
 (original)
+++ 
cocoon/trunk/src/java/org/apache/cocoon/components/treeprocessor/DefaultTreeBuilder.java
 Thu Mar 10 14:47:14 2005
@@ -92,6 +92,12 @@
      * It is created by [EMAIL PROTECTED] #createServiceManager(Context, 
Configuration)}.
      */
     private ServiceManager itsManager;
+    
+    /**
+     * The classloader for the processor that we are building.
+     * It is created by [EMAIL PROTECTED] #createServiceManager(Context, 
Configuration)}.
+     */
+    protected ClassLoader itsClassLoader;
 
     /**
      * Helper object which sets up components in the context
@@ -208,6 +214,9 @@
      */
     protected ServiceManager createServiceManager(Context context, 
Configuration tree)
     throws Exception {
+        // Useless method as it's redefined in SitemapLanguage
+        // which is the only used incarnation.
+        this.itsClassLoader = Thread.currentThread().getContextClassLoader();
         return this.manager;
     }
 
@@ -230,6 +239,9 @@
         return this.itsManager;
     }
 
+    public ClassLoader getBuiltProcessorClassLoader() {
+        return this.itsClassLoader;
+    }
 
     /**
      * Register a <code>ProcessingNode</code> under a given name.

Modified: 
cocoon/trunk/src/java/org/apache/cocoon/components/treeprocessor/ProcessorComponentInfo.java
URL: 
http://svn.apache.org/viewcvs/cocoon/trunk/src/java/org/apache/cocoon/components/treeprocessor/ProcessorComponentInfo.java?view=diff&r1=157004&r2=157005
==============================================================================
--- 
cocoon/trunk/src/java/org/apache/cocoon/components/treeprocessor/ProcessorComponentInfo.java
 (original)
+++ 
cocoon/trunk/src/java/org/apache/cocoon/components/treeprocessor/ProcessorComponentInfo.java
 Thu Mar 10 14:47:14 2005
@@ -72,9 +72,6 @@
     /** Component info for the parent processor */
     ProcessorComponentInfo parent;
     
-    /** The service manager for this processor */
-    private ServiceManager manager;
-    
     /** Lock that prevents further modification */
     private boolean locked = false;
     

Modified: 
cocoon/trunk/src/java/org/apache/cocoon/components/treeprocessor/TreeBuilder.java
URL: 
http://svn.apache.org/viewcvs/cocoon/trunk/src/java/org/apache/cocoon/components/treeprocessor/TreeBuilder.java?view=diff&r1=157004&r2=157005
==============================================================================
--- 
cocoon/trunk/src/java/org/apache/cocoon/components/treeprocessor/TreeBuilder.java
 (original)
+++ 
cocoon/trunk/src/java/org/apache/cocoon/components/treeprocessor/TreeBuilder.java
 Thu Mar 10 14:47:14 2005
@@ -34,6 +34,8 @@
     void setParentProcessorManager(ServiceManager manager);
     
     ServiceManager getBuiltProcessorManager();
+    
+    ClassLoader getBuiltProcessorClassLoader();
 
     ConcreteTreeProcessor getProcessor();
 

Modified: 
cocoon/trunk/src/java/org/apache/cocoon/components/treeprocessor/TreeProcessor.java
URL: 
http://svn.apache.org/viewcvs/cocoon/trunk/src/java/org/apache/cocoon/components/treeprocessor/TreeProcessor.java?view=diff&r1=157004&r2=157005
==============================================================================
--- 
cocoon/trunk/src/java/org/apache/cocoon/components/treeprocessor/TreeProcessor.java
 (original)
+++ 
cocoon/trunk/src/java/org/apache/cocoon/components/treeprocessor/TreeProcessor.java
 Thu Mar 10 14:47:14 2005
@@ -401,7 +401,10 @@
                 treeBuilder.setParentProcessorManager(this.manager);
 
                 ProcessingNode root = treeBuilder.build(sitemapProgram);
-                
newProcessor.setProcessorData(treeBuilder.getBuiltProcessorManager(), root, 
treeBuilder.getDisposableNodes());
+                newProcessor.setProcessorData(
+                        treeBuilder.getBuiltProcessorManager(),
+                        treeBuilder.getBuiltProcessorClassLoader(),
+                        root, treeBuilder.getDisposableNodes());
             } finally {
                 this.manager.release(treeBuilder);
             }

Modified: 
cocoon/trunk/src/java/org/apache/cocoon/components/treeprocessor/sitemap/SitemapLanguage.java
URL: 
http://svn.apache.org/viewcvs/cocoon/trunk/src/java/org/apache/cocoon/components/treeprocessor/sitemap/SitemapLanguage.java?view=diff&r1=157004&r2=157005
==============================================================================
--- 
cocoon/trunk/src/java/org/apache/cocoon/components/treeprocessor/sitemap/SitemapLanguage.java
 (original)
+++ 
cocoon/trunk/src/java/org/apache/cocoon/components/treeprocessor/sitemap/SitemapLanguage.java
 Thu Mar 10 14:47:14 2005
@@ -31,6 +31,7 @@
 import org.apache.avalon.framework.context.DefaultContext;
 import org.apache.avalon.framework.service.ServiceManager;
 import org.apache.cocoon.Constants;
+import org.apache.cocoon.components.classloader.ClassLoaderFactory;
 import org.apache.cocoon.components.container.CocoonServiceManager;
 import org.apache.cocoon.components.treeprocessor.CategoryNode;
 import org.apache.cocoon.components.treeprocessor.CategoryNodeBuilder;
@@ -71,14 +72,40 @@
             }
             config = new DefaultConfiguration("", "");
         }
-
-        CocoonServiceManager newManager = new 
CocoonServiceManager(this.parentProcessorManager);
-
-        // Go through the component lifecycle
-        newManager.enableLogging(getLogger());
-        newManager.contextualize(context);
-        newManager.configure(config);
-        newManager.initialize();
+        
+        // Create the classloader, if needed.
+        ClassLoader newClassLoader;
+        Configuration classpathConfig = config.getChild("classpath", false);
+        if (classpathConfig == null) {
+            newClassLoader = Thread.currentThread().getContextClassLoader();
+        } else {
+            // Create a new classloader
+            ClassLoaderFactory clFactory = 
(ClassLoaderFactory)this.parentProcessorManager.lookup(ClassLoaderFactory.ROLE);
+            newClassLoader = clFactory.createClassLoader(
+                    Thread.currentThread().getContextClassLoader(),
+                    classpathConfig
+            );
+        }
+        
+        this.itsClassLoader = newClassLoader;
+        
+        // Create the manager within its own classloader
+        Thread currentThread = Thread.currentThread();
+        ClassLoader oldClassLoader = currentThread.getContextClassLoader();
+        currentThread.setContextClassLoader(newClassLoader);
+        CocoonServiceManager newManager;
+        
+        try {
+            newManager = new CocoonServiceManager(this.parentProcessorManager, 
newClassLoader);
+    
+            // Go through the component lifecycle
+            newManager.enableLogging(getLogger());
+            newManager.contextualize(context);
+            newManager.configure(config);
+            newManager.initialize();
+        } finally {
+            currentThread.setContextClassLoader(oldClassLoader);
+        }
 
         return newManager;
     }


Reply via email to