You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@cocoon.apache.org by cz...@apache.org on 2006/03/04 21:12:37 UTC

svn commit: r383193 - in /cocoon/trunk/cocoon-core/src: main/java/org/apache/cocoon/components/treeprocessor/ main/java/org/apache/cocoon/components/treeprocessor/sitemap/ main/java/org/apache/cocoon/reading/ test/java/org/apache/cocoon/core/container/

Author: cziegeler
Date: Sat Mar  4 12:12:35 2006
New Revision: 383193

URL: http://svn.apache.org/viewcvs?rev=383193&view=rev
Log:
Combine DefaultTreeBuilder and SitemapLanguage
Remove per sitemap class loading

Removed:
    cocoon/trunk/cocoon-core/src/main/java/org/apache/cocoon/components/treeprocessor/DefaultTreeBuilder.java
Modified:
    cocoon/trunk/cocoon-core/src/main/java/org/apache/cocoon/components/treeprocessor/ConcreteTreeProcessor.java
    cocoon/trunk/cocoon-core/src/main/java/org/apache/cocoon/components/treeprocessor/TreeBuilder.java
    cocoon/trunk/cocoon-core/src/main/java/org/apache/cocoon/components/treeprocessor/TreeProcessor.java
    cocoon/trunk/cocoon-core/src/main/java/org/apache/cocoon/components/treeprocessor/sitemap/SitemapLanguage.java
    cocoon/trunk/cocoon-core/src/main/java/org/apache/cocoon/reading/ImageReader.java
    cocoon/trunk/cocoon-core/src/test/java/org/apache/cocoon/core/container/ContainerTestCase.java

Modified: cocoon/trunk/cocoon-core/src/main/java/org/apache/cocoon/components/treeprocessor/ConcreteTreeProcessor.java
URL: http://svn.apache.org/viewcvs/cocoon/trunk/cocoon-core/src/main/java/org/apache/cocoon/components/treeprocessor/ConcreteTreeProcessor.java?rev=383193&r1=383192&r2=383193&view=diff
==============================================================================
--- cocoon/trunk/cocoon-core/src/main/java/org/apache/cocoon/components/treeprocessor/ConcreteTreeProcessor.java (original)
+++ cocoon/trunk/cocoon-core/src/main/java/org/apache/cocoon/components/treeprocessor/ConcreteTreeProcessor.java Sat Mar  4 12:12:35 2006
@@ -69,9 +69,6 @@
     /** Our ServiceManager */
     private ServiceManager manager;
 
-    /** Our class loader */
-    private ClassLoader classloader;
-
     /** The processor that wraps us */
     private TreeProcessor wrappingProcessor;
 
@@ -104,9 +101,6 @@
     /** Processor attributes */
     protected Map processorAttributes = new HashMap();
 
-    /** no listeners by default */ 
-    private Map classpathListeners = Collections.EMPTY_MAP;
-
     /** Bean Factory for this sitemap. */
     protected ConfigurableBeanFactory beanFactory;
 
@@ -129,19 +123,10 @@
         needsReload = true;
     }
     
-    public void setClasspathListeners(Map classpathListeners) {
-        this.classpathListeners = classpathListeners;
-    }
-    
-    public Map getClasspathListeners() {
-        return this.classpathListeners;
-    }    
-    
     /** Set the processor data, result of the treebuilder job */
     public void setProcessorData(ConfigurableBeanFactory beanFactory,
                                  ServiceManager manager,
-                                 ClassLoader classloader, 
-                                 ProcessingNode rootNode, 
+                                 ProcessingNode rootNode,
                                  List disposableNodes,
                                  List enterSitemapEventListeners,
                                  List leaveSitemapEventListeners) {
@@ -151,7 +136,6 @@
 
         this.beanFactory = beanFactory;
         this.manager = manager;
-        this.classloader = classloader;
         this.rootNode = rootNode;
         this.disposableNodes = disposableNodes;
         this.enterSitemapEventListeners = enterSitemapEventListeners;
@@ -333,10 +317,6 @@
             requestCount++;
         }
 
-        Thread currentThread = Thread.currentThread();
-        ClassLoader oldClassLoader = currentThread.getContextClassLoader();
-        currentThread.setContextClassLoader(this.classloader);
-
         try {
             // invoke listeners
             // only invoke if pipeline is not internally
@@ -384,9 +364,6 @@
                     ((LeaveSitemapEventListener)current.component).leftSitemap(leaveEvent);
                 }
             }
-
-            // Restore classloader
-            currentThread.setContextClassLoader(oldClassLoader);
 
             // Decrement the concurrent request count
             synchronized (this) {

Modified: cocoon/trunk/cocoon-core/src/main/java/org/apache/cocoon/components/treeprocessor/TreeBuilder.java
URL: http://svn.apache.org/viewcvs/cocoon/trunk/cocoon-core/src/main/java/org/apache/cocoon/components/treeprocessor/TreeBuilder.java?rev=383193&r1=383192&r2=383193&view=diff
==============================================================================
--- cocoon/trunk/cocoon-core/src/main/java/org/apache/cocoon/components/treeprocessor/TreeBuilder.java (original)
+++ cocoon/trunk/cocoon-core/src/main/java/org/apache/cocoon/components/treeprocessor/TreeBuilder.java Sat Mar  4 12:12:35 2006
@@ -45,8 +45,6 @@
     
     ServiceManager getServiceManager();
     
-    ClassLoader getBuiltProcessorClassLoader();
-
     ConcreteTreeProcessor getProcessor();
 
     void setProcessor(ConcreteTreeProcessor processor);

Modified: cocoon/trunk/cocoon-core/src/main/java/org/apache/cocoon/components/treeprocessor/TreeProcessor.java
URL: http://svn.apache.org/viewcvs/cocoon/trunk/cocoon-core/src/main/java/org/apache/cocoon/components/treeprocessor/TreeProcessor.java?rev=383193&r1=383192&r2=383193&view=diff
==============================================================================
--- cocoon/trunk/cocoon-core/src/main/java/org/apache/cocoon/components/treeprocessor/TreeProcessor.java (original)
+++ cocoon/trunk/cocoon-core/src/main/java/org/apache/cocoon/components/treeprocessor/TreeProcessor.java Sat Mar  4 12:12:35 2006
@@ -15,13 +15,10 @@
  */
 package org.apache.cocoon.components.treeprocessor;
 
-import java.io.File;
 import java.io.IOException;
 import java.net.URL;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Iterator;
 import java.util.Map;
+
 import org.apache.avalon.framework.activity.Disposable;
 import org.apache.avalon.framework.activity.Initializable;
 import org.apache.avalon.framework.configuration.Configurable;
@@ -40,9 +37,6 @@
 import org.apache.cocoon.ProcessingException;
 import org.apache.cocoon.Processor;
 import org.apache.cocoon.components.ContextHelper;
-import org.apache.cocoon.components.classloader.ClassLoaderFactory;
-import org.apache.cocoon.components.classloader.ReloadingClassLoaderFactory;
-import org.apache.cocoon.components.fam.SitemapMonitor;
 import org.apache.cocoon.components.flow.Interpreter;
 import org.apache.cocoon.components.source.SourceUtil;
 import org.apache.cocoon.components.source.impl.DelayedRefreshSourceWrapper;
@@ -52,16 +46,6 @@
 import org.apache.cocoon.environment.internal.EnvironmentHelper;
 import org.apache.cocoon.sitemap.SitemapExecutor;
 import org.apache.cocoon.sitemap.impl.DefaultExecutor;
-import org.apache.commons.jci.compilers.JavaCompiler;
-import org.apache.commons.jci.compilers.eclipse.EclipseJavaCompiler;
-import org.apache.commons.jci.listeners.CompilingListener;
-import org.apache.commons.jci.listeners.FileChangeListener;
-import org.apache.commons.jci.listeners.NotifyingListener;
-import org.apache.commons.jci.listeners.ReloadingListener;
-import org.apache.commons.jci.listeners.ResourceStoringListener;
-import org.apache.commons.jci.monitor.FilesystemAlterationListener;
-import org.apache.commons.jci.stores.ResourceStore;
-import org.apache.commons.jci.stores.TransactionalResourceStore;
 import org.apache.excalibur.source.Source;
 import org.apache.excalibur.source.SourceResolver;
 import org.apache.regexp.RE;
@@ -104,8 +88,6 @@
     /** Check for reload? */
     protected boolean checkReload;
     
-    protected SitemapMonitor fam;
-    
     /** The source resolver */
     protected SourceResolver resolver;
 
@@ -149,7 +131,6 @@
         this.manager = parent.concreteProcessor.getServiceManager();
 
         this.resolver = (SourceResolver) this.manager.lookup(SourceResolver.ROLE);
-        this.fam = (SitemapMonitor) this.manager.lookup(SitemapMonitor.ROLE);
         this.settings = (Settings) this.manager.lookup(Settings.ROLE);
         this.environmentHelper = new EnvironmentHelper(parent.environmentHelper);
         // Setup environment helper
@@ -186,7 +167,6 @@
     public void service(ServiceManager manager) throws ServiceException {
         this.manager = manager;
         this.resolver = (SourceResolver) this.manager.lookup(SourceResolver.ROLE);
-        this.fam = (SitemapMonitor) this.manager.lookup(SitemapMonitor.ROLE);
         this.settings = (Settings) this.manager.lookup(Settings.ROLE);
     }
 
@@ -274,7 +254,7 @@
         return this.concreteProcessor.buildPipeline(environment);
     }
 
-    /* (non-Javadoc)
+    /**
      * @see org.apache.cocoon.Processor#getRootProcessor()
      */
     public Processor getRootProcessor() {
@@ -360,181 +340,6 @@
         }
     }
     
-    private JavaCompiler createJavaCompiler(final Configuration config) {
-        // FIXME: extract compiler and compiler configuration from config
-        return new EclipseJavaCompiler();
-    }
-    
-    private ResourceStore createResourceStore(final Configuration storeConfig) throws Exception {
-        final String className = storeConfig.getAttribute("class","org.apache.commons.jci.stores.MemoryResourceStore");
-        final ResourceStore store = (ResourceStore) Class.forName(className).newInstance();
-        if (getLogger().isDebugEnabled()) {
-            getLogger().debug("storing resources in " + store.getClass().getName());
-        }
-        return store;
-    }
-    
-    private FilesystemAlterationListener createCompilingListener(
-            final Configuration dirConfig
-            ) throws Exception {
-        Source src = null;
-        
-        try {
-            src = resolver.resolveURI(dirConfig.getAttribute("src"));
-            final File repository = new File(src.getURI().substring(5));
-
-            if (getLogger().isDebugEnabled()) {
-                getLogger().debug("monitoring src dir " + dirConfig.getAttribute("src"));
-            }
-
-            return new CompilingListener(
-                repository,
-                createJavaCompiler(dirConfig.getChild("compiler")),
-                new TransactionalResourceStore(createResourceStore(dirConfig.getChild("store")))
-              );
-        } finally {
-            resolver.release(src);
-        }
-    }
-
-    private FilesystemAlterationListener createReloadingListener(final Configuration dirConfig) 
-        throws Exception {
-        
-        Source src = null;
-        
-        try {
-            src = resolver.resolveURI(dirConfig.getAttribute("src"));
-            final File repository = new File(src.getURI().substring(5));
-
-            if (getLogger().isDebugEnabled()) {
-                getLogger().debug("monitoring class dir " + dirConfig.getAttribute("src"));
-            }
-
-            return new ReloadingListener(
-                repository,
-                createResourceStore(dirConfig.getChild("store"))
-                );
-        } finally {
-            resolver.release(src);
-        }
-    }
-
-    private FilesystemAlterationListener createFileChangeListener(
-            final Configuration dirConfig
-            ) throws Exception {
-        Source src = null;
-        
-        try {
-            src = resolver.resolveURI(dirConfig.getAttribute("src"));
-            final File repository = new File(src.getURI().substring(5));
-
-            if (getLogger().isDebugEnabled()) {
-                getLogger().debug("monitoring lib dir " + dirConfig.getAttribute("src"));
-            }
-
-            return new FileChangeListener(repository);
-        } finally {
-            resolver.release(src);
-        }
-    }
-
-    
-    private boolean containsListener(Map map, String src, Class clazz) {
-        FilesystemAlterationListener listener = (FilesystemAlterationListener) map.get(src);
-        if (listener == null) {
-            if (getLogger().isDebugEnabled()) {
-                getLogger().debug("no previous listener for " + src);
-            }
-            return false;
-        }
-        if (!listener.getClass().equals(clazz)) {
-            if (getLogger().isDebugEnabled()) {
-                getLogger().debug("previous listener was of a different type");
-            }
-            return false;
-        }
-        
-        return true;
-    }
-    
-    private Map createClasspathListeners(Map oldListeners, Configuration classpathConfig) throws Exception {
-
-        final Configuration[] classDirConfigs = classpathConfig.getChildren("class-dir");        
-        final Configuration[] srcDirConfigs = classpathConfig.getChildren("src-dir");        
-        final Configuration[] libDirConfigs = classpathConfig.getChildren("lib-dir");    
-
-        Map newListeners = new HashMap();
-        
-        for (int i = 0; i < classDirConfigs.length; i++) {
-            final Configuration dirConfig = classDirConfigs[i];
-            final String src = dirConfig.getAttribute("src");
-            if (containsListener(oldListeners, src, ReloadingListener.class)) {
-                if (getLogger().isDebugEnabled()) {
-                    getLogger().debug("keeping ReloadingListener for " + src);
-                }
-                newListeners.put(src, oldListeners.get(src));
-                oldListeners.remove(src);
-            } else {
-                if (getLogger().isDebugEnabled()) {
-                    getLogger().debug("new ReloadingListener for " + src);
-                }
-                newListeners.put(src, createReloadingListener(dirConfig));
-            }
-        }
-
-        for (int i = 0; i < srcDirConfigs.length; i++) {
-            final Configuration dirConfig = srcDirConfigs[i];
-            final String src = dirConfig.getAttribute("src");
-            if (containsListener(oldListeners, src, CompilingListener.class)) {
-                if (getLogger().isDebugEnabled()) {
-                    getLogger().debug("keeping CompilingListener for " + src);
-                }
-                newListeners.put(src, oldListeners.get(src));
-                oldListeners.remove(src);
-            } else {
-                if (getLogger().isDebugEnabled()) {
-                    getLogger().debug("new CompilingListener for " + src);
-                }
-                newListeners.put(src, createCompilingListener(dirConfig));
-            }
-        }
-
-        for (int i = 0; i < libDirConfigs.length; i++) {
-            final Configuration dirConfig = libDirConfigs[i];
-            final String src = dirConfig.getAttribute("src");
-            if (containsListener(oldListeners, src, FileChangeListener.class)) {
-                if (getLogger().isDebugEnabled()) {
-                    getLogger().debug("keeping FileChangeListener for " + src);
-                }
-                newListeners.put(src, oldListeners.get(src));
-                oldListeners.remove(src);
-            } else {
-                if (getLogger().isDebugEnabled()) {
-                    getLogger().debug("new FileChangeListener for " + src);
-                }
-                newListeners.put(src, createFileChangeListener(dirConfig));
-            }
-        }
-             
-        return newListeners;
-    }
-    
-    protected ClassLoader createClassLoader(Configuration classpathConfig)
-    throws Exception {
-        String factoryRole = classpathConfig.getAttribute("factory-role", ClassLoaderFactory.ROLE + "/ReloadingClassLoaderFactory");
-        // Create a new classloader
-        ClassLoaderFactory clFactory = (ClassLoaderFactory)this.manager.lookup(factoryRole);
-        try {
-            return clFactory.createClassLoader(
-                    Thread.currentThread().getContextClassLoader(),
-                    classpathConfig
-            );
-        } finally {
-            this.manager.release(clFactory);
-        }
-    }
-
-    
     private Configuration createSitemapProgram(Source source) throws ProcessingException, SAXException, IOException {
         NamespacedSAXConfigurationHandler handler = new NamespacedSAXConfigurationHandler();
         AnnotationsFilter annotationsFilter = new AnnotationsFilter(handler);
@@ -542,62 +347,6 @@
         return handler.getConfiguration();        
     }
     
-    private void subscribeListeners(Map listerens, ConcreteTreeProcessor processor) {
-        if (getLogger().isDebugEnabled()) {
-            getLogger().debug("setting up listeners " + listerens);
-        }
-        for (final Iterator it = listerens.values().iterator(); it.hasNext();) {
-            final NotifyingListener newListener = (NotifyingListener) it.next();
-            
-            newListener.setNotificationListener(processor);
-            
-            fam.subscribe(newListener);
-        }        
-    }
-
-    private void unsubscribeListeners(Map listerens) {
-        if (listerens != null && listerens.size() > 0) {
-            if (getLogger().isDebugEnabled()) {
-                getLogger().debug("unsubscribing " + listerens + " from fam");
-            }
-            for (final Iterator it = listerens.values().iterator(); it.hasNext();) {
-                final FilesystemAlterationListener oldListener = (FilesystemAlterationListener) it.next();
-                fam.unsubscribe(oldListener);
-            }
-        }        
-    }
-    
-    private void waitForInitialCompilation(Map listeners) throws Exception {
-        if (listeners.size() > 0) {
-            // wait for the new ones to complete for the first time                
-            for (final Iterator it = listeners.values().iterator(); it.hasNext();) {
-                final NotifyingListener newListener = (NotifyingListener) it.next();
-                if (getLogger().isDebugEnabled()) {
-                    getLogger().debug("waiting for initial compilation");
-                }
-                newListener.waitForFirstCheck();
-            }
-        }        
-    }
-    
-    private void provideClasses(Map listeners, ClassLoader classloader) {
-        for (final Iterator it = listeners.values().iterator(); it.hasNext();) {
-            final NotifyingListener newListener = (NotifyingListener) it.next();
-
-            if (newListener instanceof ResourceStoringListener) {
-                ResourceStoringListener l = (ResourceStoringListener)newListener;
-                if (classloader instanceof ReloadingClassLoaderFactory.DefaultClassLoader) {
-                    if (getLogger().isDebugEnabled()) {
-                        getLogger().debug("adding store " + l.getStore() + " to classloader");
-                    }
-                    ReloadingClassLoaderFactory.DefaultClassLoader cl = (ReloadingClassLoaderFactory.DefaultClassLoader) classloader;
-                    cl.addResourceStore(l.getStore());
-                }
-            }                
-        }        
-    }
-
-    
     /**
      * Build the concrete processor (i.e. loads the sitemap). Should be called
      * only by setupProcessor();
@@ -615,14 +364,11 @@
         long newLastModified;
         ConcreteTreeProcessor newProcessor;
         ConcreteTreeProcessor oldProcessor = this.concreteProcessor;
-        Map oldListeners = Collections.EMPTY_MAP;
-        Map newListeners = Collections.EMPTY_MAP;
                 
         if (oldProcessor != null) {
             if (getLogger().isDebugEnabled()) {
                 getLogger().debug("found a previous ConcreteTreeProcessor");
             }            
-            oldListeners = oldProcessor.getClasspathListeners();                    
         } else {
             if (getLogger().isDebugEnabled()) {
                 getLogger().debug("first version of the ConcreteTreeProcessor");
@@ -650,37 +396,6 @@
 
             newProcessor = createConcreteTreeProcessor();
 
-            // setup sitemap specific classloader
-            // (RP) Should we really support sitemap specific classloader when the global 
-            //      BlocksClassloader is in place?
-            Configuration classpathConfig = sitemapProgram.getChild("components").getChild("classpath", false);
-            if (classpathConfig != null) {
-                if (getLogger().isDebugEnabled()) {
-                    getLogger().debug("ConcreteTreeProcessor has a special classpath");
-                }
-                
-                // create a reloading classloader and make it the context classloader
-                ClassLoader classloader = createClassLoader(classpathConfig);
-                Thread.currentThread().setContextClassLoader(classloader);
-                
-                // create the listeners for all classpath entries (lib, classes, src)
-                newListeners = createClasspathListeners(oldListeners, classpathConfig);
-                
-                // store the listeners in the the concreteTreeProcessor instance
-                newProcessor.setClasspathListeners(newListeners);
-                
-                // subscribe all listeners to filesystem altering monitor (FAM)
-                subscribeListeners(newListeners, newProcessor);
-                
-                // use the information about the listeners to create the classpath
-                provideClasses(newListeners, classloader);
-            }
-
-            unsubscribeListeners(oldListeners);
-            
-            waitForInitialCompilation(newListeners);
-            
-
             // Get the treebuilder that can handle this version of the sitemap.
             TreeBuilder treeBuilder = getTreeBuilder(sitemapProgram);
             try {
@@ -690,7 +405,6 @@
                 newProcessor.setProcessorData(
                         treeBuilder.getBeanFactory(),
                         treeBuilder.getServiceManager(),
-                        treeBuilder.getBuiltProcessorClassLoader(),
                         root,
                         treeBuilder.getDisposableNodes(),
                         treeBuilder.getEnterSitemapEventListeners(),
@@ -749,7 +463,6 @@
                 this.resolver.release(this.source.getSource());
                 this.source = null;
             }
-            this.manager.release(this.fam);
             this.manager.release(this.resolver);
             this.manager.release(this.settings);
             this.resolver = null;

Modified: cocoon/trunk/cocoon-core/src/main/java/org/apache/cocoon/components/treeprocessor/sitemap/SitemapLanguage.java
URL: http://svn.apache.org/viewcvs/cocoon/trunk/cocoon-core/src/main/java/org/apache/cocoon/components/treeprocessor/sitemap/SitemapLanguage.java?rev=383193&r1=383192&r2=383193&view=diff
==============================================================================
--- cocoon/trunk/cocoon-core/src/main/java/org/apache/cocoon/components/treeprocessor/sitemap/SitemapLanguage.java (original)
+++ cocoon/trunk/cocoon-core/src/main/java/org/apache/cocoon/components/treeprocessor/sitemap/SitemapLanguage.java Sat Mar  4 12:12:35 2006
@@ -15,31 +15,54 @@
  */
 package org.apache.cocoon.components.treeprocessor.sitemap;
 
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Iterator;
+import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
 import javax.servlet.ServletConfig;
 
+import org.apache.avalon.excalibur.pool.Recyclable;
+import org.apache.avalon.framework.activity.Disposable;
+import org.apache.avalon.framework.activity.Initializable;
+import org.apache.avalon.framework.configuration.AbstractConfiguration;
 import org.apache.avalon.framework.configuration.Configuration;
 import org.apache.avalon.framework.configuration.ConfigurationException;
 import org.apache.avalon.framework.configuration.DefaultConfiguration;
+import org.apache.avalon.framework.configuration.SAXConfigurationHandler;
 import org.apache.avalon.framework.context.Context;
+import org.apache.avalon.framework.context.ContextException;
+import org.apache.avalon.framework.context.Contextualizable;
 import org.apache.avalon.framework.context.DefaultContext;
+import org.apache.avalon.framework.logger.AbstractLogEnabled;
 import org.apache.avalon.framework.logger.Logger;
+import org.apache.avalon.framework.service.ServiceException;
 import org.apache.avalon.framework.service.ServiceManager;
+import org.apache.avalon.framework.service.ServiceSelector;
+import org.apache.avalon.framework.service.Serviceable;
 import org.apache.cocoon.Constants;
 import org.apache.cocoon.components.ContextHelper;
 import org.apache.cocoon.components.LifecycleHelper;
+import org.apache.cocoon.components.source.SourceUtil;
+import org.apache.cocoon.components.treeprocessor.AbstractProcessingNode;
 import org.apache.cocoon.components.treeprocessor.CategoryNode;
 import org.apache.cocoon.components.treeprocessor.CategoryNodeBuilder;
-import org.apache.cocoon.components.treeprocessor.DefaultTreeBuilder;
+import org.apache.cocoon.components.treeprocessor.ConcreteTreeProcessor;
+import org.apache.cocoon.components.treeprocessor.LinkedProcessingNodeBuilder;
+import org.apache.cocoon.components.treeprocessor.ParameterizableProcessingNode;
+import org.apache.cocoon.components.treeprocessor.ProcessingNode;
+import org.apache.cocoon.components.treeprocessor.ProcessingNodeBuilder;
+import org.apache.cocoon.components.treeprocessor.ProcessorComponentInfo;
+import org.apache.cocoon.components.treeprocessor.StandaloneServiceSelector;
 import org.apache.cocoon.components.treeprocessor.TreeBuilder;
+import org.apache.cocoon.components.treeprocessor.variables.VariableResolver;
+import org.apache.cocoon.components.treeprocessor.variables.VariableResolverFactory;
 import org.apache.cocoon.core.Settings;
 import org.apache.cocoon.core.container.spring.BeanFactoryUtil;
 import org.apache.cocoon.core.container.spring.AvalonEnvironment;
@@ -56,8 +79,14 @@
 import org.apache.cocoon.sitemap.LeaveSitemapEventListener;
 import org.apache.cocoon.sitemap.PatternException;
 import org.apache.cocoon.sitemap.SitemapListener;
+import org.apache.cocoon.sitemap.SitemapParameters;
 import org.apache.cocoon.util.ClassUtils;
 import org.apache.cocoon.util.StringUtils;
+import org.apache.cocoon.util.location.Location;
+import org.apache.cocoon.util.location.LocationImpl;
+import org.apache.cocoon.util.location.LocationUtils;
+import org.apache.excalibur.source.Source;
+import org.apache.excalibur.source.SourceResolver;
 import org.apache.regexp.RE;
 import org.springframework.beans.BeansException;
 import org.springframework.beans.factory.BeanCreationException;
@@ -67,94 +96,613 @@
 
 /**
  * The tree builder for the sitemap language.
- *
+ * 
  * @version $Id$
  */
 public class SitemapLanguage
-    extends DefaultTreeBuilder
-    implements BeanFactoryAware {
-
-    /** Spring application context. */
-    protected ConfigurableBeanFactory beanFactory;
+    extends AbstractLogEnabled
+    implements TreeBuilder, Contextualizable, Serviceable, Recyclable, BeanFactoryAware {
 
     // Regexp's for splitting expressions
     private static final String COMMA_SPLIT_REGEXP = "[\\s]*,[\\s]*";
+
     private static final String EQUALS_SPLIT_REGEXP = "[\\s]*=[\\s]*";
 
-//    protected ClassLoader createClassLoader(Configuration config)
-//    throws Exception {
-//        ClassLoader newClassLoader;
-//        Configuration classpathConfig = config.getChild("classpath", false);
-//        if (classpathConfig == null) {
-//            return Thread.currentThread().getContextClassLoader();
-//        }
-//        
-//        String factoryRole = config.getAttribute("factory-role", ClassLoaderFactory.ROLE + "/ReloadingClassLoaderFactory");
-//        // Create a new classloader
-//        ClassLoaderFactory clFactory = (ClassLoaderFactory)this.parentProcessorManager.lookup(factoryRole);
-//        try {
-//            return clFactory.createClassLoader(
-//                    Thread.currentThread().getContextClassLoader(),
-//                    classpathConfig
-//            );
-//        } finally {
-//            this.parentProcessorManager.release(clFactory);
-//        }
-//    }
-    
+    protected Map attributes = new HashMap();
+
+    /** Spring application context. */
+    protected ConfigurableBeanFactory beanFactory;
+
+
+    // ----- lifecycle-related objects ------
+
+    /**
+     * This component's avalon context
+     */
+    private Context context;
+
+    /**
+     * This component's service manager
+     */
+    private ServiceManager manager;
+
+    // -------------------------------------
+
+    /**
+     * The tree processor that we are building.
+     */
+    protected ConcreteTreeProcessor processor;
+
+    /**
+     * The namespace of configuration for the processor that we are building.
+     */
+    protected String itsNamespace;
+
+    /**
+     * The context for the processor that we are building It is created by
+     * {@link #createContext(Configuration)}.
+     */
+    private Context itsContext;
+
+    /**
+     * The service manager for the processor that we are building. It is created
+     * by {@link #createServiceManager(ClassLoader, Context, Configuration)}.
+     */
+    private ServiceManager itsManager;
+
+    private ConfigurableBeanFactory itsBeanFactory;
+
+    /**
+     * Helper object which sets up components in the context of the processor
+     * that we are building.
+     */
+    private LifecycleHelper itsLifecycle;
+
+    /**
+     * Selector for ProcessingNodeBuilders which is set up in the context of the
+     * processor that we are building.
+     */
+    private ServiceSelector itsBuilders;
+
+    /**
+     * The sitemap component information grabbed while building itsMaanger
+     */
+    protected ProcessorComponentInfo itsComponentInfo;
+
+    /** Optional event listeners for the enter sitemap event */
+    protected List enterSitemapEventListeners = new ArrayList();
+
+    /** Optional event listeners for the leave sitemap event */
+    protected List leaveSitemapEventListeners = new ArrayList();
+
+    // -------------------------------------
+
+    /** Nodes gone through setupNode() that implement Initializable */
+    private List initializableNodes = new ArrayList();
+
+    /** Nodes gone through setupNode() that implement Disposable */
+    private List disposableNodes = new ArrayList();
+
+    /**
+     * NodeBuilders created by createNodeBuilder() that implement
+     * LinkedProcessingNodeBuilder
+     */
+    private List linkedBuilders = new ArrayList();
+
+    /** Are we in a state that allows to get registered nodes ? */
+    private boolean canGetNode = false;
+
+    /** Nodes registered using registerNode() */
+    private Map registeredNodes = new HashMap();
+
+    /**
+     * @see org.apache.avalon.framework.context.Contextualizable#contextualize(org.apache.avalon.framework.context.Context)
+     */
+    public void contextualize(Context context) throws ContextException {
+        this.context = context;
+    }
+
+    /**
+     * @see org.apache.avalon.framework.service.Serviceable#service(org.apache.avalon.framework.service.ServiceManager)
+     */
+    public void service(ServiceManager manager) throws ServiceException {
+        this.manager = manager;
+    }
+
+    /**
+     * Get the location of the treebuilder config file. Can be overridden for
+     * other versions.
+     * 
+     * @return The location of the treebuilder config file
+     */
+    protected String getBuilderConfigURL() {
+        return "resource://org/apache/cocoon/components/treeprocessor/sitemap-language.xml";
+    }
+
+    /**
+     * @see org.apache.cocoon.components.treeprocessor.TreeBuilder#setAttribute(java.lang.String,
+     *      java.lang.Object)
+     */
+    public void setAttribute(String name, Object value) {
+        this.attributes.put(name, value);
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.cocoon.components.treeprocessor.TreeBuilder#getAttribute(java.lang.String)
+     */
+    public Object getAttribute(String name) {
+        return this.attributes.get(name);
+    }
+
+    /**
+     * @see org.apache.cocoon.components.treeprocessor.TreeBuilder#setProcessor(ConcreteTreeProcessor)
+     */
+    public void setProcessor(ConcreteTreeProcessor processor) {
+        this.processor = processor;
+    }
+
+    /**
+     * @see org.apache.cocoon.components.treeprocessor.TreeBuilder#getProcessor()
+     */
+    public ConcreteTreeProcessor getProcessor() {
+        return this.processor;
+    }
+
+    /**
+     * @see org.apache.cocoon.components.treeprocessor.TreeBuilder#getBeanFactory()
+     */
+    public ConfigurableBeanFactory getBeanFactory() {
+        return this.itsBeanFactory;
+    }
+
+    public ServiceManager getServiceManager() {
+        return this.itsManager;
+    }
+
+    /**
+     * @see org.apache.cocoon.components.treeprocessor.TreeBuilder#getEnterSitemapEventListeners()
+     */
+    public List getEnterSitemapEventListeners() {
+        // we make a copy here, so we can clear(recylce) the list after the
+        // sitemap is build
+        return (List) ((ArrayList) this.enterSitemapEventListeners).clone();
+    }
+
+    /**
+     * @see org.apache.cocoon.components.treeprocessor.TreeBuilder#getLeaveSitemapEventListeners()
+     */
+    public List getLeaveSitemapEventListeners() {
+        // we make a copy here, so we can clear(recylce) the list after the
+        // sitemap is build
+        return (List) ((ArrayList) this.leaveSitemapEventListeners).clone();
+    }
+
+    /**
+     * @see org.apache.cocoon.components.treeprocessor.TreeBuilder#registerNode(java.lang.String,
+     *      org.apache.cocoon.components.treeprocessor.ProcessingNode)
+     */
+    public boolean registerNode(String name, ProcessingNode node) {
+        if (this.registeredNodes.containsKey(name)) {
+            return false;
+        }
+        this.registeredNodes.put(name, node);
+        return true;
+    }
+
+    public ProcessingNode getRegisteredNode(String name) {
+        if (this.canGetNode) {
+            return (ProcessingNode) this.registeredNodes.get(name);
+        }
+        throw new IllegalArgumentException("Categories are only available during buildNode()");
+    }
+
+    public ProcessingNodeBuilder createNodeBuilder(Configuration config) throws Exception {
+        // FIXME : check namespace
+        String nodeName = config.getName();
+
+        if (getLogger().isDebugEnabled()) {
+            getLogger().debug("Creating node builder for " + nodeName);
+        }
+
+        ProcessingNodeBuilder builder;
+        try {
+            builder = (ProcessingNodeBuilder) this.itsBuilders.select(nodeName);
+        } catch (ServiceException ce) {
+            // Is it because this element is unknown ?
+            if (this.itsBuilders.isSelectable(nodeName)) {
+                // No : rethrow
+                throw ce;
+            }
+            // Throw a more meaningful exception
+            String msg = "Unknown element '" + nodeName + "' at " + config.getLocation();
+            throw new ConfigurationException(msg);
+        }
+
+        builder.setBuilder(this);
+
+        if (builder instanceof LinkedProcessingNodeBuilder) {
+            this.linkedBuilders.add(builder);
+        }
+
+        return builder;
+    }
+
+    /**
+     * Create the tree once component manager and node builders have been set
+     * up. Can be overriden by subclasses to perform pre/post tree creation
+     * operations.
+     */
+    protected ProcessingNode createTree(Configuration tree) throws Exception {
+        // Create a node builder from the top-level element
+        ProcessingNodeBuilder rootBuilder = createNodeBuilder(tree);
+
+        // Build the whole tree (with an empty buildModel)
+        return rootBuilder.buildNode(tree);
+    }
+
+    /**
+     * Resolve links : call <code>linkNode()</code> on all
+     * <code>LinkedProcessingNodeBuilder</code>s. Can be overriden by
+     * subclasses to perform pre/post resolution operations.
+     *
+     * Before linking nodes, lookup the view category node used in
+     * {@link #getViewNodes(Collection)}.
+     */
+    protected void linkNodes() throws Exception {
+        // Get the views category node
+        this.viewsNode = CategoryNodeBuilder.getCategoryNode(this, "views");
+
+        // Resolve links
+        Iterator iter = this.linkedBuilders.iterator();
+        while (iter.hasNext()) {
+            ((LinkedProcessingNodeBuilder) iter.next()).linkNode();
+        }
+    }
+
     /**
-     * Build a component manager with the contents of the &lt;map:components&gt; element
-     * of the tree.
+     * Get the namespace URI that builders should use to find their nodes.
      */
-    protected ConfigurableBeanFactory createBeanFactory(ClassLoader   classloader,
-                                                        Context       context,
+    public String getNamespace() {
+        return this.itsNamespace;
+    }
+
+    /**
+     * Build a processing tree from a <code>Configuration</code>.
+     */
+    public ProcessingNode build(Configuration tree) throws Exception {
+        // The namespace used in the whole sitemap is the one of the root
+        // element
+        this.itsNamespace = tree.getNamespace();
+
+        Configuration componentConfig = tree.getChild("components", false);
+
+        if (componentConfig == null) {
+            if (getLogger().isDebugEnabled()) {
+                getLogger().debug("Sitemap has no components definition at " + tree.getLocation());
+            }
+            // componentConfig = new DefaultConfiguration("", "");
+        }
+
+        // Context and manager and classloader for the sitemap we build
+        this.itsContext = createContext(tree);
+
+        // Only create an sitemap internal component manager if there really is
+        // a configuration
+        // FIXME: Internal configurations doesn't work in a non bean factory
+        // environment
+        if (componentConfig != null) {
+            this.itsBeanFactory = this.createBeanFactory(this.itsContext, componentConfig);
+            this.itsManager = (ServiceManager) this.itsBeanFactory.getBean(ServiceManager.class
+                    .getName());
+        } else {
+            this.itsManager = manager;
+        }
+        this.itsComponentInfo = (ProcessorComponentInfo) this.itsManager
+                .lookup(ProcessorComponentInfo.ROLE);
+        // Create a helper object to setup components
+        this.itsLifecycle = new LifecycleHelper(getLogger(), this.itsContext, this.itsManager, null /* configuration */);
+
+        // Create & initialize the NodeBuilder selector.
+        {
+            StandaloneServiceSelector selector = new StandaloneServiceSelector();
+
+            // Load the builder config file
+            SourceResolver resolver = (SourceResolver) this.manager.lookup(SourceResolver.ROLE);
+            String url = getBuilderConfigURL();
+            Configuration config;
+            try {
+                Source src = resolver.resolveURI(url);
+                try {
+                    SAXConfigurationHandler handler = new SAXConfigurationHandler();
+                    SourceUtil.toSAX(this.manager, src, null, handler);
+                    config = handler.getConfiguration();
+                } finally {
+                    resolver.release(src);
+                }
+            } catch (Exception e) {
+                throw new ConfigurationException("Could not load TreeBuilder configuration from "
+                        + url, e);
+            } finally {
+                this.manager.release(resolver);
+            }
+            LifecycleHelper.setupComponent(selector, getLogger(), this.itsContext, this.itsManager,
+                    config.getChild("nodes", false), true);
+            this.itsBuilders = selector;
+        }
+
+        // Calls to getRegisteredNode() are forbidden
+        this.canGetNode = false;
+
+        // Collect all disposable variable resolvers
+        VariableResolverFactory.setDisposableCollector(this.disposableNodes);
+
+        ProcessingNode result = createTree(tree);
+
+        // Calls to getRegisteredNode() are now allowed
+        this.canGetNode = true;
+
+        linkNodes();
+
+        // Initialize all Initializable nodes
+        Iterator iter = this.initializableNodes.iterator();
+        while (iter.hasNext()) {
+            ((Initializable) iter.next()).initialize();
+        }
+
+        // And that's all !
+        return result;
+    }
+
+    /**
+     * Return the list of <code>ProcessingNodes</code> part of this tree that
+     * are <code>Disposable</code>. Care should be taken to properly dispose
+     * them before trashing the processing tree.
+     */
+    public List getDisposableNodes() {
+        return this.disposableNodes;
+    }
+
+    /**
+     * Setup a <code>ProcessingNode</code> by setting its location, calling
+     * all the lifecycle interfaces it implements and giving it the parameter
+     * map if it's a <code>ParameterizableNode</code>.
+     * <p>
+     * As a convenience, the node is returned by this method to allow constructs
+     * like <code>return treeBuilder.setupNode(new MyNode(), config)</code>.
+     */
+    public ProcessingNode setupNode(ProcessingNode node, Configuration config) throws Exception {
+        Location location = getLocation(config);
+        if (node instanceof AbstractProcessingNode) {
+            ((AbstractProcessingNode) node).setLocation(location);
+            ((AbstractProcessingNode) node).setSitemapExecutor(this.processor.getSitemapExecutor());
+        }
+
+        this.itsLifecycle.setupComponent(node, false);
+
+        if (node instanceof ParameterizableProcessingNode) {
+            Map params = getParameters(config, location);
+            ((ParameterizableProcessingNode) node).setParameters(params);
+        }
+
+        if (node instanceof Initializable) {
+            this.initializableNodes.add(node);
+        }
+
+        if (node instanceof Disposable) {
+            this.disposableNodes.add(node);
+        }
+
+        return node;
+    }
+
+    protected LocationImpl getLocation(Configuration config) {
+        String prefix = "";
+
+        if (config instanceof AbstractConfiguration) {
+            // FIXME: AbstractConfiguration has a _protected_ getPrefix()
+            // method.
+            // So make some reasonable guess on the prefix until it becomes
+            // public
+            String namespace = null;
+            try {
+                namespace = ((AbstractConfiguration) config).getNamespace();
+            } catch (ConfigurationException e) {
+                // ignore
+            }
+            if ("http://apache.org/cocoon/sitemap/1.0".equals(namespace)) {
+                prefix = "map";
+            }
+        }
+
+        StringBuffer desc = new StringBuffer().append('<');
+        if (prefix.length() > 0) {
+            desc.append(prefix).append(':').append(config.getName());
+        } else {
+            desc.append(config.getName());
+        }
+        String type = config.getAttribute("type", null);
+        if (type != null) {
+            desc.append(" type=\"").append(type).append('"');
+        }
+        desc.append('>');
+
+        Location rawLoc = LocationUtils.getLocation(config);
+        return new LocationImpl(desc.toString(), rawLoc.getURI(), rawLoc.getLineNumber(), rawLoc
+                .getColumnNumber());
+    }
+
+    /**
+     * Get &lt;xxx:parameter&gt; elements as a <code>Map</code> of </code>ListOfMapResolver</code>s,
+     * that can be turned into parameters using <code>ListOfMapResolver.buildParameters()</code>.
+     * 
+     * @return the Map of ListOfMapResolver, or <code>null</code> if there are
+     *         no parameters.
+     */
+    protected Map getParameters(Configuration config, Location location)
+            throws ConfigurationException {
+
+        Configuration[] children = config.getChildren("parameter");
+
+        if (children.length == 0) {
+            // Parameters are only the component's location
+            // TODO Optimize this
+            return new SitemapParameters.LocatedHashMap(location, 0);
+        }
+
+        Map params = new SitemapParameters.LocatedHashMap(location, children.length + 1);
+        for (int i = 0; i < children.length; i++) {
+            Configuration child = children[i];
+            if (true) { // FIXME : check namespace
+                String name = child.getAttribute("name");
+                String value = child.getAttribute("value");
+                try {
+                    params.put(resolve(name), resolve(value));
+                } catch (PatternException pe) {
+                    String msg = "Invalid pattern '" + value + "' at " + child.getLocation();
+                    throw new ConfigurationException(msg, pe);
+                }
+            }
+        }
+
+        return params;
+    }
+
+    /**
+     * Get the type for a statement : it returns the 'type' attribute if
+     * present, and otherwhise the default type defined for this role in the
+     * components declarations.
+     * 
+     * @throws ConfigurationException
+     *             if the type could not be found.
+     */
+    public String getTypeForStatement(Configuration statement, String role)
+            throws ConfigurationException {
+
+        // Get the component type for the statement
+        String type = statement.getAttribute("type", null);
+        if (type == null) {
+            type = this.itsComponentInfo.getDefaultType(role);
+        }
+
+        if (type == null) {
+            throw new ConfigurationException("No default type exists for 'map:"
+                    + statement.getName() + "' at " + statement.getLocation());
+        }
+
+        // Check that this type actually exists
+        ServiceSelector selector = null;
+        try {
+            selector = (ServiceSelector) this.itsManager.lookup(role + "Selector");
+        } catch (ServiceException e) {
+            throw new ConfigurationException("Cannot get service selector for 'map:"
+                    + statement.getName() + "' at " + statement.getLocation(), e);
+        }
+
+        if (!selector.isSelectable(type)) {
+            throw new ConfigurationException("Type '" + type + "' does not exist for 'map:"
+                    + statement.getName() + "' at " + statement.getLocation());
+        }
+
+        this.itsManager.release(selector);
+
+        return type;
+    }
+
+    /**
+     * Resolve expression using its manager
+     */
+    protected VariableResolver resolve(String expression) throws PatternException {
+        return VariableResolverFactory.getResolver(expression, this.itsManager);
+    }
+
+    public void recycle() {
+        // Reset all data created during the build
+        this.attributes.clear();
+        this.canGetNode = false;
+        this.disposableNodes = new ArrayList(); // Must not be cleared as it's
+                                                // used for processor disposal
+        this.initializableNodes.clear();
+        this.linkedBuilders.clear();
+        this.processor = null; // Set in setProcessor()
+
+        this.itsNamespace = null; // Set in build()
+        LifecycleHelper.dispose(this.itsBuilders);
+        this.itsBuilders = null; // Set in build()
+        this.itsLifecycle = null; // Set in build()
+        this.itsManager = null; // Set in build()
+        this.itsContext = null; // Set in build()
+
+        this.registeredNodes.clear();
+        this.initializableNodes.clear();
+        this.linkedBuilders.clear();
+        this.canGetNode = false;
+        this.registeredNodes.clear();
+
+        VariableResolverFactory.setDisposableCollector(null);
+        this.enterSitemapEventListeners.clear();
+        this.leaveSitemapEventListeners.clear();
+
+        // Go back to initial state
+        this.labelViews.clear();
+        this.viewsNode = null;
+        this.isBuildingView = false;
+        this.isBuildingErrorHandler = false;
+    }
+
+    /**
+     * Build a component manager with the contents of the &lt;map:components&gt;
+     * element of the tree.
+     */
+    protected ConfigurableBeanFactory createBeanFactory(Context context,
                                                         Configuration config)
     throws Exception {
-
-        // Create the classloader, if needed.
         ServiceManager newManager;
-        
+
         // before we pass the configuration we have to strip the
-        // additional configuration parts, like classpath etc. as these
+        // additional configuration parts, like listeners etc. as these
         // are not configurations for the service manager
-        final DefaultConfiguration c = new DefaultConfiguration(config.getName(), 
-                                                                config.getLocation(),
-                                                                config.getNamespace(),
-                                                                "");
+        final DefaultConfiguration c = new DefaultConfiguration(config.getName(), config
+                .getLocation(), config.getNamespace(), "");
         c.addAll(config);
-        c.removeChild(config.getChild("classpath"));
         c.removeChild(config.getChild("listeners"));
 
         // setup spring container
         // first, get the correct parent
         ConfigurableBeanFactory parentContext = this.beanFactory;
         final Request request = ContextHelper.getRequest(context);
-        if ( request.getAttribute(CocoonBeanFactory.BEAN_FACTORY_REQUEST_ATTRIBUTE) != null ) {
-            parentContext = (ConfigurableBeanFactory)request.getAttribute(CocoonBeanFactory.BEAN_FACTORY_REQUEST_ATTRIBUTE);
+        if (request.getAttribute(CocoonBeanFactory.BEAN_FACTORY_REQUEST_ATTRIBUTE) != null) {
+            parentContext = (ConfigurableBeanFactory) request
+                    .getAttribute(CocoonBeanFactory.BEAN_FACTORY_REQUEST_ATTRIBUTE);
         }
 
         final AvalonEnvironment ae = new AvalonEnvironment();
         ae.context = context;
         ae.logger = this.getLogger();
-        ae.servletContext = ((ServletConfig)context.get(CocoonServlet.CONTEXT_SERVLET_CONFIG)).getServletContext();
-        ae.settings = (Settings)this.beanFactory.getBean(Settings.ROLE);
-        final ConfigurationInfo parentConfigInfo = (ConfigurationInfo)parentContext.getBean(ConfigurationInfo.class.getName());
+        ae.servletContext = ((ServletConfig) context.get(CocoonServlet.CONTEXT_SERVLET_CONFIG))
+                .getServletContext();
+        ae.settings = (Settings) this.beanFactory.getBean(Settings.ROLE);
+        final ConfigurationInfo parentConfigInfo = (ConfigurationInfo) parentContext
+                .getBean(ConfigurationInfo.class.getName());
         final ConfigurationInfo ci = ConfigReader.readConfiguration(c, parentConfigInfo, ae);
 
-        final ConfigurableBeanFactory sitemapContext = 
-            BeanFactoryUtil.createBeanFactory(ae, ci, parentContext, false);
+        final ConfigurableBeanFactory sitemapContext = BeanFactoryUtil.createBeanFactory(ae, ci,
+                parentContext, false);
         newManager = (ServiceManager) sitemapContext.getBean(ServiceManager.class.getName());
-        Logger sitemapLogger = (Logger)sitemapContext.getBean(Logger.class.getName());
+        Logger sitemapLogger = (Logger) sitemapContext.getBean(Logger.class.getName());
 
         // and finally the listeners
         final Configuration listenersWrapper = config.getChild("listeners", false);
-        if ( listenersWrapper != null ) {
-            final Configuration[] listeners = listenersWrapper.getChildren("listener");                
-            for(int i = 0; i < listeners.length; i++) {
+        if (listenersWrapper != null) {
+            final Configuration[] listeners = listenersWrapper.getChildren("listener");
+            for (int i = 0; i < listeners.length; i++) {
                 final Configuration current = listeners[i];
-                final TreeBuilder.EventComponent listener = this.createListener(newManager, sitemapLogger, context, current);
-                if ( !(listener.component instanceof SitemapListener) ) {
-                    throw new ConfigurationException("Listener must implement the SitemapListener interface.");
+                final TreeBuilder.EventComponent listener = this.createListener(newManager,
+                        sitemapLogger, context, current);
+                if (!(listener.component instanceof SitemapListener)) {
+                    throw new ConfigurationException(
+                            "Listener must implement the SitemapListener interface.");
                 }
                 this.addListener(listener);
             }
@@ -167,13 +715,10 @@
      * Create a listener
      */
     protected TreeBuilder.EventComponent createListener(ServiceManager manager,
-                                                        Logger sitemapLogger,
-                                                        Context context,
-                                                        Configuration config) 
-    throws Exception {
+            Logger sitemapLogger, Context context, Configuration config) throws Exception {
         // role or class?
         final String role = config.getAttribute("role", null);
-        if ( role != null ) {
+        if (role != null) {
             return new TreeBuilder.EventComponent(manager.lookup(role), true);
         }
         final String className = config.getAttribute("class");
@@ -188,9 +733,9 @@
      * Add a listener
      */
     protected void addListener(TreeBuilder.EventComponent listener) {
-        if ( listener.component instanceof EnterSitemapEventListener ) {
+        if (listener.component instanceof EnterSitemapEventListener) {
             this.enterSitemapEventListeners.add(listener);
-        } else if ( listener.component instanceof LeaveSitemapEventListener ) {
+        } else if (listener.component instanceof LeaveSitemapEventListener) {
             this.leaveSitemapEventListeners.add(listener);
         }
     }
@@ -200,17 +745,18 @@
      */
     protected Context createContext(Configuration tree) throws Exception {
         // Create sub-context for this sitemap
-        DefaultContext newContext = new DefaultContext(super.createContext(tree));
+        DefaultContext newContext = new DefaultContext(this.context);
         Environment env = EnvironmentHelper.getCurrentEnvironment();
         newContext.put(Constants.CONTEXT_ENV_URI, env.getURI());
         newContext.put(Constants.CONTEXT_ENV_PREFIX, env.getURIPrefix());
         // FIXME How to get rid of EnvironmentHelper?
-        newContext.put(Constants.CONTEXT_ENV_HELPER, getProcessor().getWrappingProcessor().getEnvironmentHelper());
+        newContext.put(Constants.CONTEXT_ENV_HELPER, getProcessor().getWrappingProcessor()
+                .getEnvironmentHelper());
 
         return newContext;
     }
 
-    //---- Views management
+    // ---- Views management
 
     /** Collection of view names for each label */
     private Map labelViews = new HashMap();
@@ -225,30 +771,20 @@
     private boolean isBuildingErrorHandler = false;
 
     /**
-     * Pseudo-label for views <code>from-position="first"</code> (i.e. generator).
+     * Pseudo-label for views <code>from-position="first"</code> (i.e.
+     * generator).
      */
     public static final String FIRST_POS_LABEL = "!first!";
 
     /**
-     * Pseudo-label for views <code>from-position="last"</code> (i.e. serializer).
+     * Pseudo-label for views <code>from-position="last"</code> (i.e.
+     * serializer).
      */
     public static final String LAST_POS_LABEL = "!last!";
 
-    /* (non-Javadoc)
-     * @see org.apache.avalon.excalibur.pool.Recyclable#recycle()
-     */
-    public void recycle() {
-        super.recycle();
-
-        // Go back to initial state
-        this.labelViews.clear();
-        this.viewsNode = null;
-        this.isBuildingView = false;
-        this.isBuildingErrorHandler = false;
-    }
-
     /**
-     * Set to <code>true</code> while building the internals of a &lt;map:view&gt;
+     * Set to <code>true</code> while building the internals of a
+     * &lt;map:view&gt;
      */
     public void setBuildingView(boolean building) {
         this.isBuildingView = building;
@@ -262,7 +798,8 @@
     }
 
     /**
-     * Set to <code>true</code> while building the internals of a &lt;map:handle-errors&gt;
+     * Set to <code>true</code> while building the internals of a
+     * &lt;map:handle-errors&gt;
      */
     public void setBuildingErrorHandler(boolean building) {
         this.isBuildingErrorHandler = building;
@@ -276,17 +813,19 @@
     }
 
     /**
-     * Add a view for a label. This is used to register all views that start from
-     * a given label.
-     *
-     * @param label the label (or pseudo-label) for the view
-     * @param view the view name
+     * Add a view for a label. This is used to register all views that start
+     * from a given label.
+     * 
+     * @param label
+     *            the label (or pseudo-label) for the view
+     * @param view
+     *            the view name
      */
     public void addViewForLabel(String label, String view) {
         if (getLogger().isDebugEnabled()) {
             getLogger().debug("views:addViewForLabel(" + label + ", " + view + ")");
         }
-        Set views = (Set)this.labelViews.get(label);
+        Set views = (Set) this.labelViews.get(label);
         if (views == null) {
             views = new HashSet();
             this.labelViews.put(label, views);
@@ -296,22 +835,28 @@
     }
 
     /**
-     * Get the names of views for a given statement. If the cocoon view exists in the returned
-     * collection, the statement can directly branch to the view-handling node.
-     *
-     * @param role the component role (e.g. <code>Generator.ROLE</code>)
-     * @param hint the component hint, i.e. the 'type' attribute
-     * @param statement the sitemap statement
+     * Get the names of views for a given statement. If the cocoon view exists
+     * in the returned collection, the statement can directly branch to the
+     * view-handling node.
+     * 
+     * @param role
+     *            the component role (e.g. <code>Generator.ROLE</code>)
+     * @param hint
+     *            the component hint, i.e. the 'type' attribute
+     * @param statement
+     *            the sitemap statement
      * @return the view names for this statement
      */
-    public Collection getViewsForStatement(String role, String hint, Configuration statement) throws Exception {
+    public Collection getViewsForStatement(String role, String hint, Configuration statement)
+            throws Exception {
 
         String statementLabels = statement.getAttribute("label", null);
 
         if (this.isBuildingView) {
             // Labels are forbidden inside view definition
             if (statementLabels != null) {
-                String msg = "Cannot put a 'label' attribute inside view definition at " + statement.getLocation();
+                String msg = "Cannot put a 'label' attribute inside view definition at "
+                        + statement.getLocation();
                 throw new ConfigurationException(msg);
             }
 
@@ -352,14 +897,14 @@
 
         // Iterate on all labels for this statement
         Iterator labelIter = labels.iterator();
-        while(labelIter.hasNext()) {
+        while (labelIter.hasNext()) {
 
             // Iterate on all views for this labek
-            Collection coll = (Collection)this.labelViews.get(labelIter.next());
+            Collection coll = (Collection) this.labelViews.get(labelIter.next());
             if (coll != null) {
                 Iterator viewIter = coll.iterator();
-                while(viewIter.hasNext()) {
-                    String viewName = (String)viewIter.next();
+                while (viewIter.hasNext()) {
+                    String viewName = (String) viewIter.next();
 
                     views.add(viewName);
                 }
@@ -371,14 +916,15 @@
             views = null;
 
             if (getLogger().isDebugEnabled()) {
-                getLogger().debug(statement.getName() + " has no views at " + statement.getLocation());
+                getLogger().debug(
+                        statement.getName() + " has no views at " + statement.getLocation());
             }
         } else {
             if (getLogger().isDebugEnabled()) {
                 // Dump matching views
                 StringBuffer buf = new StringBuffer(statement.getName() + " will match views [");
                 Iterator iter = views.iterator();
-                while(iter.hasNext()) {
+                while (iter.hasNext()) {
                     buf.append(iter.next()).append(" ");
                 }
                 buf.append("] at ").append(statement.getLocation());
@@ -391,20 +937,11 @@
     }
 
     /**
-     * Before linking nodes, lookup the view category node used in {@link #getViewNodes(Collection)}.
-     */
-    protected void linkNodes() throws Exception {
-        // Get the views category node
-        this.viewsNode = CategoryNodeBuilder.getCategoryNode(this, "views");
-
-        super.linkNodes();
-    }
-
-    /**
-     * Get the {view name, view node} map for a collection of view names.
-     * This allows to resolve view nodes at build time, thus avoiding runtime lookup.
-     *
-     * @param viewNames the view names
+     * Get the {view name, view node} map for a collection of view names. This
+     * allows to resolve view nodes at build time, thus avoiding runtime lookup.
+     * 
+     * @param viewNames
+     *            the view names
      * @return association of names to views
      */
     public Map getViewNodes(Collection viewNames) throws Exception {
@@ -419,8 +956,8 @@
         Map result = new HashMap();
 
         Iterator iter = viewNames.iterator();
-        while(iter.hasNext()) {
-            String viewName = (String)iter.next();
+        while (iter.hasNext()) {
+            String viewName = (String) iter.next();
             result.put(viewName, viewsNode.getNodeByName(viewName));
         }
 
@@ -429,31 +966,38 @@
 
     /**
      * Extract pipeline-hints from the given statement (if any exist)
-     *
-     * @param role the component role (e.g. <code>Generator.ROLE</code>)
-     * @param hint the component hint, i.e. the 'type' attribute
-     * @param statement the sitemap statement
-     * @return the hint params <code>Map</code> for this statement, or null
-     *         if none exist
+     * 
+     * @param role
+     *            the component role (e.g. <code>Generator.ROLE</code>)
+     * @param hint
+     *            the component hint, i.e. the 'type' attribute
+     * @param statement
+     *            the sitemap statement
+     * @return the hint params <code>Map</code> for this statement, or null if
+     *         none exist
      */
-    public Map getHintsForStatement(String role, String hint, Configuration statement) throws Exception {
+    public Map getHintsForStatement(String role, String hint, Configuration statement)
+            throws Exception {
         // This method implemets the hintParam Syntax as follows:
-        //     A hints attribute has one or more comma separated hints
-        //     hints-attr :: hint [ ',' hint ]*
-        //     A hint is a name and an optional (string) value
-        //     If there is no value, it is considered as boolean string "true"
-        //     hint :: literal [ '=' litteral ]
-        //     literal :: <a character string where the chars ',' and '=' are not permitted>
+        // A hints attribute has one or more comma separated hints
+        // hints-attr :: hint [ ',' hint ]*
+        // A hint is a name and an optional (string) value
+        // If there is no value, it is considered as boolean string "true"
+        // hint :: literal [ '=' litteral ]
+        // literal :: <a character string where the chars ',' and '=' are not
+        // permitted>
         //
-        //  A ConfigurationException is thrown if there is a problem "parsing"
-        //  the hint.
+        // A ConfigurationException is thrown if there is a problem "parsing"
+        // the hint.
 
         String statementHintParams = statement.getAttribute("pipeline-hints", null);
         String componentHintParams = null;
         String hintParams = null;
 
-        // firstly, determine if any pipeline-hints are defined at the component level
-        // if so, inherit these pipeline-hints (these hints can be overriden by local pipeline-hints)
+        // firstly, determine if any pipeline-hints are defined at the component
+        // level
+        // if so, inherit these pipeline-hints (these hints can be overriden by
+        // local pipeline-hints)
         componentHintParams = this.itsComponentInfo.getPipelineHint(role, hint);
 
         if (componentHintParams != null) {
@@ -477,32 +1021,34 @@
         RE commaSplit = new RE(COMMA_SPLIT_REGEXP);
         RE equalsSplit = new RE(EQUALS_SPLIT_REGEXP);
 
-        String[]  expressions = commaSplit.split(hintParams.trim());
+        String[] expressions = commaSplit.split(hintParams.trim());
 
         if (getLogger().isDebugEnabled()) {
             getLogger().debug("pipeline-hints: (aggregate-hint) " + hintParams);
         }
 
-        for (int i=0; i<expressions.length;i++) {
-            String [] nameValuePair = equalsSplit.split(expressions[i]);
+        for (int i = 0; i < expressions.length; i++) {
+            String[] nameValuePair = equalsSplit.split(expressions[i]);
 
             try {
                 if (nameValuePair.length < 2) {
                     if (getLogger().isDebugEnabled()) {
-                        getLogger().debug("pipeline-hints: (name) " + nameValuePair[0]
-                                       + "\npipeline-hints: (value) [implicit] true");
+                        getLogger().debug(
+                                "pipeline-hints: (name) " + nameValuePair[0]
+                                        + "\npipeline-hints: (value) [implicit] true");
                     }
 
                     params.put(resolve(nameValuePair[0]), resolve("true"));
                 } else {
                     if (getLogger().isDebugEnabled()) {
-                        getLogger().debug("pipeline-hints: (name) " + nameValuePair[0]
-                                          + "\npipeline-hints: (value) " + nameValuePair[1]);
+                        getLogger().debug(
+                                "pipeline-hints: (name) " + nameValuePair[0]
+                                        + "\npipeline-hints: (value) " + nameValuePair[1]);
                     }
 
                     params.put(resolve(nameValuePair[0]), resolve(nameValuePair[1]));
                 }
-            } catch(PatternException pe) {
+            } catch (PatternException pe) {
                 String msg = "Invalid pattern '" + hintParams + "' at " + statement.getLocation();
                 getLogger().error(msg, pe);
                 throw new ConfigurationException(msg, pe);
@@ -511,7 +1057,7 @@
 
         return params;
     }
-    
+
     /**
      * Get the mime-type for a component (either a serializer or a reader)
      *
@@ -539,9 +1085,11 @@
      * @see org.springframework.beans.factory.BeanFactoryAware#setBeanFactory(org.springframework.beans.factory.BeanFactory)
      */
     public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
-        if ( ! (beanFactory instanceof ConfigurableBeanFactory) ) {
-            throw new BeanCreationException("Bean factory for tree processor must be an instance of " + ConfigurableBeanFactory.class.getName());            
+        if (!(beanFactory instanceof ConfigurableBeanFactory)) {
+            throw new BeanCreationException(
+                    "Bean factory for tree processor must be an instance of "
+                            + ConfigurableBeanFactory.class.getName());
         }
-        this.beanFactory = (ConfigurableBeanFactory)beanFactory;
+        this.beanFactory = (ConfigurableBeanFactory) beanFactory;
     }
 }

Modified: cocoon/trunk/cocoon-core/src/main/java/org/apache/cocoon/reading/ImageReader.java
URL: http://svn.apache.org/viewcvs/cocoon/trunk/cocoon-core/src/main/java/org/apache/cocoon/reading/ImageReader.java?rev=383193&r1=383192&r2=383193&view=diff
==============================================================================
--- cocoon/trunk/cocoon-core/src/main/java/org/apache/cocoon/reading/ImageReader.java (original)
+++ cocoon/trunk/cocoon-core/src/main/java/org/apache/cocoon/reading/ImageReader.java Sat Mar  4 12:12:35 2006
@@ -37,9 +37,7 @@
 
 import com.sun.image.codec.jpeg.ImageFormatException;
 import com.sun.image.codec.jpeg.JPEGCodec;
-import com.sun.image.codec.jpeg.JPEGDecodeParam;
 import com.sun.image.codec.jpeg.JPEGEncodeParam;
-import com.sun.image.codec.jpeg.JPEGImageDecoder;
 import com.sun.image.codec.jpeg.JPEGImageEncoder;
 
 /**

Modified: cocoon/trunk/cocoon-core/src/test/java/org/apache/cocoon/core/container/ContainerTestCase.java
URL: http://svn.apache.org/viewcvs/cocoon/trunk/cocoon-core/src/test/java/org/apache/cocoon/core/container/ContainerTestCase.java?rev=383193&r1=383192&r2=383193&view=diff
==============================================================================
--- cocoon/trunk/cocoon-core/src/test/java/org/apache/cocoon/core/container/ContainerTestCase.java (original)
+++ cocoon/trunk/cocoon-core/src/test/java/org/apache/cocoon/core/container/ContainerTestCase.java Sat Mar  4 12:12:35 2006
@@ -34,7 +34,6 @@
 import org.apache.avalon.framework.parameters.Parameters;
 import org.apache.avalon.framework.service.ServiceException;
 import org.apache.avalon.framework.service.ServiceManager;
-import org.apache.cocoon.core.Core;
 import org.apache.cocoon.core.MutableSettings;
 import org.apache.cocoon.core.container.spring.BeanFactoryUtil;
 import org.apache.cocoon.core.container.spring.AvalonEnvironment;
@@ -287,18 +286,17 @@
         avalonEnv.logger = this.logger;
         avalonEnv.context = this.context;
         avalonEnv.settings = new MutableSettings();
-        avalonEnv.core = new Core(avalonEnv.context);
         avalonEnv.servletContext = new MockContext();
 
         this.rootContext = BeanFactoryUtil.createRootApplicationContext(avalonEnv);
         // read roles
         ConfigurationInfo rolesInfo = ConfigReader.readConfiguration(confRM, null, avalonEnv);
-        ConfigurableBeanFactory rolesContext = BeanFactoryUtil.createApplicationContext(avalonEnv, rolesInfo, rootContext, true);
+        ConfigurableBeanFactory rolesContext = BeanFactoryUtil.createBeanFactory(avalonEnv, rolesInfo, rootContext, true);
 
         // read components
         ConfigurationInfo componentsInfo = ConfigReader.readConfiguration(confCM, rolesInfo, avalonEnv);
         this.addComponents( componentsInfo );
-        ConfigurableBeanFactory componentsContext = BeanFactoryUtil.createApplicationContext(avalonEnv, componentsInfo, rolesContext, false);
+        ConfigurableBeanFactory componentsContext = BeanFactoryUtil.createBeanFactory(avalonEnv, componentsInfo, rolesContext, false);
 
         this.manager = (ServiceManager)componentsContext.getBean(ServiceManager.class.getName());
     }