You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@cocoon.apache.org by re...@apache.org on 2007/04/03 10:10:49 UTC

svn commit: r525076 - in /cocoon/trunk/core/cocoon-core/src: main/java/org/apache/cocoon/components/source/ main/java/org/apache/cocoon/components/source/helpers/ main/java/org/apache/cocoon/components/source/impl/ main/resources/META-INF/cocoon/spring...

Author: reinhard
Date: Tue Apr  3 01:10:48 2007
New Revision: 525076

URL: http://svn.apache.org/viewvc?view=rev&rev=525076
Log:
- Avalon->Spring
- provide an abstract bean definition that can be used by any custom bean definition of caching sources
- move dependency on InspectableSource to repository-impl (where it was before but as I refactored 
  incrementally, it was easier to move things around)

- all unit tests pass but the coverage of the refresher goes to 0 so I'm not sure if
  everything still works as expected

- the refresher is setup via Spring too. This has the disadvantage that an
  "inline configuration" (-> within the bean definition) can't be provided anymore
  
- javadocs still need to reflect my latest changes

Added:
    cocoon/trunk/core/cocoon-core/src/main/resources/META-INF/cocoon/spring/cocoon-core-caching-source.xml   (with props)
Removed:
    cocoon/trunk/core/cocoon-core/src/main/java/org/apache/cocoon/components/source/InspectableSource.java
    cocoon/trunk/core/cocoon-core/src/main/java/org/apache/cocoon/components/source/impl/InspectableTraversableCachingSource.java
Modified:
    cocoon/trunk/core/cocoon-core/src/main/java/org/apache/cocoon/components/source/helpers/DelaySourceRefresher.java
    cocoon/trunk/core/cocoon-core/src/main/java/org/apache/cocoon/components/source/impl/CachingSourceFactory.java
    cocoon/trunk/core/cocoon-core/src/test/java/org/apache/cocoon/components/source/impl/CachingSourceTestCase.java
    cocoon/trunk/core/cocoon-core/src/test/resources/org/apache/cocoon/components/source/impl/CachingSourceTestCase.spring.xml
    cocoon/trunk/core/cocoon-core/src/test/resources/org/apache/cocoon/components/source/impl/CachingSourceTestCase.xtest

Modified: cocoon/trunk/core/cocoon-core/src/main/java/org/apache/cocoon/components/source/helpers/DelaySourceRefresher.java
URL: http://svn.apache.org/viewvc/cocoon/trunk/core/cocoon-core/src/main/java/org/apache/cocoon/components/source/helpers/DelaySourceRefresher.java?view=diff&rev=525076&r1=525075&r2=525076
==============================================================================
--- cocoon/trunk/core/cocoon-core/src/main/java/org/apache/cocoon/components/source/helpers/DelaySourceRefresher.java (original)
+++ cocoon/trunk/core/cocoon-core/src/main/java/org/apache/cocoon/components/source/helpers/DelaySourceRefresher.java Tue Apr  3 01:10:48 2007
@@ -30,24 +30,15 @@
 
 import org.apache.avalon.framework.CascadingException;
 import org.apache.avalon.framework.CascadingRuntimeException;
-import org.apache.avalon.framework.activity.Disposable;
-import org.apache.avalon.framework.configuration.Configurable;
 import org.apache.avalon.framework.configuration.Configuration;
 import org.apache.avalon.framework.configuration.ConfigurationException;
 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.logger.AbstractLogEnabled;
 import org.apache.avalon.framework.parameters.Parameters;
 import org.apache.avalon.framework.service.ServiceException;
 import org.apache.avalon.framework.service.ServiceManager;
-import org.apache.avalon.framework.service.Serviceable;
-import org.apache.avalon.framework.thread.ThreadSafe;
-import org.apache.excalibur.source.Source;
-import org.apache.excalibur.source.SourceException;
-import org.apache.excalibur.source.SourceResolver;
-
 import org.apache.cocoon.Constants;
 import org.apache.cocoon.ProcessingException;
 import org.apache.cocoon.Processor;
@@ -57,6 +48,12 @@
 import org.apache.cocoon.environment.background.BackgroundEnvironment;
 import org.apache.cocoon.environment.internal.EnvironmentHelper;
 import org.apache.cocoon.util.NetUtils;
+import org.apache.cocoon.util.avalon.CLLoggerWrapper;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.excalibur.source.Source;
+import org.apache.excalibur.source.SourceException;
+import org.apache.excalibur.source.SourceResolver;
 
 /**
  * Default implementation of the refresher.
@@ -64,33 +61,29 @@
  * @since 2.1.1
  * @version $Id$
  */
-public class DelaySourceRefresher extends AbstractLogEnabled
-                                  implements Contextualizable, Serviceable, Configurable,
-                                             Disposable, ThreadSafe, SourceRefresher {
-
-    private static final String PARAM_WRITE_FILE          = "write-file";
+public class DelaySourceRefresher implements SourceRefresher {
 
+    private Log logger = LogFactory.getLog(getClass());    
+    
+    private static final long DEFAULT_INTERVAL = 0;
+    
 	private static final String DEFAULT_WRITE_FILE        = "refresher-targets.xml";
-
     private static final String TAGNAME_TARGET            = "target";
 	private static final String ATTR_KEY                  = "key";
 	private static final String ATTR_URI                  = "uri";
     private static final String ATTR_INTERVAL             = "interval";
 
-
     protected Context context;
-
-    // service dependencies
-    protected ServiceManager manager;
     protected SourceResolver resolver;
     protected RunnableManager runnable;
+    protected ServiceManager manager;
+    protected Settings settings;
+    protected long writeInterval = DEFAULT_INTERVAL;
+    protected String fileName = DEFAULT_WRITE_FILE;
 
     // the scheduled targets to be persisted and recovered upon restart
     protected Map entries = Collections.synchronizedMap(new HashMap());
 
-    // the cocoon working directory
-    protected File workDir;
-
     /** The source to persist refresher entries into */
     protected File configFile;
 
@@ -99,32 +92,11 @@
 
     protected ConfigurationTask configurationTask;
 
-
-    // ---------------------------------------------------- Lifecycle
-
-	/* (non-Javadoc)
-	 * @see Contextualizable#contextualize(Context)
-	 */
-	public void contextualize(Context context) throws ContextException {
-        this.context = context;
-	}
-
-    /* (non-Javadoc)
-     * @see Serviceable#service(ServiceManager)
-     */
-    public void service(ServiceManager manager) throws ServiceException {
-        this.manager = manager;
-        this.resolver = (SourceResolver) this.manager.lookup(SourceResolver.ROLE);
-        this.runnable = (RunnableManager) this.manager.lookup(RunnableManager.ROLE);
-        this.workDir = new File(((Settings)this.manager.lookup(Settings.ROLE)).getWorkDirectory());
-    }
-
-    public void configure(Configuration configuration) throws ConfigurationException {
-        Parameters parameters = Parameters.fromConfiguration(configuration);
-        long interval = parameters.getParameterAsLong("interval", 0);
-        if (interval > 0) {
-            String fileName = parameters.getParameter(PARAM_WRITE_FILE, DEFAULT_WRITE_FILE);
-            this.configFile = new File(this.workDir, fileName);
+    public void init() throws ConfigurationException {
+        
+        if (writeInterval > 0) {
+            File workDir = new File(this.settings.getWorkDirectory());
+            this.configFile = new File(workDir, fileName);
             if (this.configFile.exists() && !this.configFile.canWrite()) {
                 throw new ConfigurationException("Parameter 'write-source' resolves to not modifiable file: " +
                                                  this.configFile);
@@ -133,36 +105,23 @@
                 throw new ConfigurationException("Can not create parent directory for: " +
                                                  this.configFile);
             }
-            if (getLogger().isDebugEnabled()) {
-                getLogger().debug("Write source location: " + this.configFile);
+            if (logger.isDebugEnabled()) {
+                logger.debug("Write source location: " + this.configFile);
             }
 
             setupRefreshJobs(readRefreshJobConfiguration());
-            startConfigurationTask(interval);
+            startConfigurationTask(writeInterval);
         } else {
-        	if (getLogger().isInfoEnabled()) {
-				getLogger().info("Not writing update targets to file.");
+        	if (logger.isInfoEnabled()) {
+				logger.info("Not writing update targets to file.");
         	}
         }
-
-        // Setup any in-line configured tasks
-        setupRefreshJobs(configuration);
+   
     }
 
-    /* (non-Javadoc)
-     * @see Disposable#dispose()
-     */
-    public void dispose() {
+
+    public void destroy() {
     	stopConfigurationTask();
-        if (this.runnable != null) {
-            this.manager.release(this.runnable);
-            this.runnable = null;
-        }
-        if (this.resolver != null) {
-            this.manager.release(this.resolver);
-            this.resolver = null;
-        }
-        this.manager = null;
     }
 
     // ---------------------------------------------------- SourceRefresher implementation
@@ -187,7 +146,7 @@
         if (task == null) {
             // New source added.
             task = new RefresherTask(key, uri, interval);
-            task.enableLogging(getLogger());
+            task.enableLogging(new CLLoggerWrapper(logger));
             this.entries.put(key, task);
             this.runnable.execute(task, interval, interval);
             this.changed = true;
@@ -225,7 +184,7 @@
                 SourceUtil.toSAX(this.manager, source, source.getMimeType(), b);
             }
         } catch (Exception ignore) {
-            getLogger().warn("Unable to read configuration from " + this.configFile);
+            logger.warn("Unable to read configuration from " + this.configFile);
         } finally {
             if (source != null) {
                 this.resolver.release(source);
@@ -246,8 +205,8 @@
                     try {
                         setupSingleRefreshJob(children[i]);
                     } catch (CascadingException ignore) {
-                        if (getLogger().isDebugEnabled()) {
-                            getLogger().debug("Setting up refresh job, ignoring exception:", ignore);
+                        if (logger.isDebugEnabled()) {
+                            logger.debug("Setting up refresh job, ignoring exception:", ignore);
                         }
                     }
                 }
@@ -275,7 +234,7 @@
      */
     protected void startConfigurationTask(long interval) {
         configurationTask = new ConfigurationTask();
-        configurationTask.enableLogging(getLogger());
+        configurationTask.enableLogging(new CLLoggerWrapper(logger));
         runnable.execute(configurationTask, interval, interval);
     }
 
@@ -320,8 +279,8 @@
                     // Got I/O exception while writing the list.
                     // Will re-try writing the list next time.
                     success = false;
-                    if (getLogger().isDebugEnabled()) {
-                        getLogger().debug("Error writing targets to file.", e);
+                    if (logger.isDebugEnabled()) {
+                        logger.debug("Error writing targets to file.", e);
                     }
                 } finally {
                     if (writer != null) {
@@ -354,8 +313,8 @@
 
         public void run() {
             if (this.uri != null) {
-                if (getLogger().isDebugEnabled()) {
-                    getLogger().debug("Refreshing " + this.uri);
+                if (logger.isDebugEnabled()) {
+                    logger.debug("Refreshing " + this.uri);
                 }
 
                 // Setup Environment
@@ -363,7 +322,7 @@
                 try {
                     org.apache.cocoon.environment.Context ctx =
                             (org.apache.cocoon.environment.Context) context.get(Constants.CONTEXT_ENVIRONMENT_CONTEXT);
-                    env = new BackgroundEnvironment(getLogger(), ctx);
+                    env = new BackgroundEnvironment(new CLLoggerWrapper(logger), ctx);
                 } catch (ContextException e) {
                     throw new CascadingRuntimeException("No context found", e);
                 }
@@ -387,7 +346,7 @@
                         source = resolver.resolveURI(uri);
                         source.refresh();
                     } catch (IOException e) {
-                        getLogger().error("Error refreshing source", e);
+                        logger.error("Error refreshing source", e);
                     } finally {
                         if (source != null) {
                             resolver.release(source);
@@ -425,4 +384,36 @@
             return s.toString();
         }
     }
+    
+    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ set dependencies ~~~~~
+    
+    public void setServiceManager(ServiceManager manager) {
+        this.manager = manager;
+    }
+    
+    public void setSourceResolver(SourceResolver resolver) {
+        this.resolver = resolver;
+    }
+    
+    public void setRunnableManager(RunnableManager runnable) {
+        this.runnable = runnable;
+    }
+    
+    public void setSettings(Settings settings) {
+        this.settings = settings;
+    }
+    
+    public void setWriteFile(String fileName) {
+        this.fileName = fileName;
+    }    
+    
+    public void setWriteInterval(long interval) {
+        this.writeInterval = interval;
+    }
+    
+    public void setAvalonContext(Context context) {
+        this.context = context;
+    }
+
+    
 }

Modified: cocoon/trunk/core/cocoon-core/src/main/java/org/apache/cocoon/components/source/impl/CachingSourceFactory.java
URL: http://svn.apache.org/viewvc/cocoon/trunk/core/cocoon-core/src/main/java/org/apache/cocoon/components/source/impl/CachingSourceFactory.java?view=diff&rev=525076&r1=525075&r2=525076
==============================================================================
--- cocoon/trunk/core/cocoon-core/src/main/java/org/apache/cocoon/components/source/impl/CachingSourceFactory.java (original)
+++ cocoon/trunk/core/cocoon-core/src/main/java/org/apache/cocoon/components/source/impl/CachingSourceFactory.java Tue Apr  3 01:10:48 2007
@@ -21,20 +21,15 @@
 import java.util.Iterator;
 import java.util.Map;
 
-import org.apache.avalon.framework.activity.Disposable;
-import org.apache.avalon.framework.configuration.Configurable;
-import org.apache.avalon.framework.configuration.Configuration;
-import org.apache.avalon.framework.configuration.ConfigurationException;
 import org.apache.avalon.framework.container.ContainerUtil;
-import org.apache.avalon.framework.logger.AbstractLogEnabled;
 import org.apache.avalon.framework.parameters.Parameters;
 import org.apache.avalon.framework.service.ServiceException;
 import org.apache.avalon.framework.service.ServiceManager;
-import org.apache.avalon.framework.service.Serviceable;
-import org.apache.avalon.framework.thread.ThreadSafe;
 import org.apache.cocoon.caching.Cache;
-import org.apache.cocoon.components.source.InspectableSource;
 import org.apache.cocoon.components.source.helpers.SourceRefresher;
+import org.apache.cocoon.util.avalon.CLLoggerWrapper;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
 import org.apache.excalibur.source.Source;
 import org.apache.excalibur.source.SourceException;
 import org.apache.excalibur.source.SourceFactory;
@@ -121,176 +116,41 @@
  * @version $Id$
  * @since 2.1.1
  */
-public class CachingSourceFactory extends AbstractLogEnabled
-                                  implements Serviceable, Configurable, Disposable,
-                                             ThreadSafe, URIAbsolutizer, SourceFactory {
-
-    // ---------------------------------------------------- Constants
-
-    private static final String ASYNC_PARAM = "async";
-    private static final String EVENT_AWARE_PARAM = "event-aware";
-    private static final String CACHE_ROLE_PARAM = "cache-role";
-    private static final String REFRESHER_ROLE_PARAM = "refresher-role";
-    private static final String DEFAULT_EXPIRES_PARAM = "default-expires";
-    private static final String DEFAULT_VALIDITY_STRATEGY = ExpiresCachingSourceValidityStrategy.class.getName();
+public class CachingSourceFactory implements URIAbsolutizer, SourceFactory {
 
-    // ---------------------------------------------------- Instance variables
+    private Log logger = LogFactory.getLog(getClass());        
+    
+    private static final boolean DEFAULT_ASYNC_VALUE = false;
+    
+    private static final int DEFAULT_EXPIRES_VALUE = -1;
 
     /** Protocol prefix / factory name */
-    private String scheme;
+    protected String scheme;
 
     /** Asynchronous ? */
-    private boolean async;
+    protected boolean async = DEFAULT_ASYNC_VALUE;
+    
+    protected int defaultExpires = DEFAULT_EXPIRES_VALUE;
 
-    /** Event aware ? */
-    private boolean eventAware;
+    /** Validity strategy implementation*/
+    protected CachingSourceValidityStrategy validityStrategy;
+    
+    /** The cache */
+    protected Cache cache;
 
-    /** Validity strategy implementation: class name */
-    private String validityStrategyClassName = DEFAULT_VALIDITY_STRATEGY;
+    /** The refresher */
+    protected SourceRefresher refresher;
     
-    /** Validity strategy implementation: class name */
-    private CachingSourceValidityStrategy validityStrategy;
+    /** The Cocoon service manager */
+    protected ServiceManager serviceManager;
     
-    /** The role of the cache */
-    private String cacheRole;
-
-    /** The role of the refresher */
-    private String refresherRole;
-
-    /** Default expires value */
-    private int defaultExpires;
-
-    /** Has the lazy initialization been done? */
-    private volatile boolean isInitialized;
-
-    /** The <code>ServiceManager</code> */
-    protected ServiceManager manager;
-
     /** The {@link SourceResolver} */
     protected SourceResolver resolver;
-
-    /** The refresher */
-    protected SourceRefresher refresher;
-
-    /** The cache */
-    protected Cache cache;
-
-    // ---------------------------------------------------- Lifecycle
-
+    
+    
     public CachingSourceFactory() {
     }
-
-    public void service(ServiceManager manager) {
-        this.manager = manager;
-        // Due to cyclic dependencies we can't lookup the resolver,
-        // the refresher or the cache until after the factory is
-        // initialized.
-    }
-
-    public void configure(Configuration configuration) throws ConfigurationException {
-        this.scheme = configuration.getAttribute("name");
-        Parameters parameters = Parameters.fromConfiguration(configuration);
-
-        // 'async' parameter
-        this.async = parameters.getParameterAsBoolean(ASYNC_PARAM, false);
-
-        // 'event-aware' parameter
-        this.eventAware = parameters.getParameterAsBoolean(EVENT_AWARE_PARAM, false);
-        
-        if(this.eventAware == true) {
-            this.validityStrategyClassName = 
-                "org.apache.cocoon.components.source.impl.EventAwareCachingSourceValidityStrategy";
-        }
-        try {
-            this.validityStrategy = (CachingSourceValidityStrategy) 
-                getClass().getClassLoader().loadClass(this.validityStrategyClassName).newInstance();
-        } catch(Exception cce) {
-            throw new ConfigurationException("Can't create class for '" + 
-                    this.validityStrategyClassName + "'.", cce);
-        }
-
-        // 'cache-role' parameter
-        this.cacheRole = parameters.getParameter(CACHE_ROLE_PARAM, Cache.ROLE);
-
-        // 'refresher-role' parameter
-        if (this.async) {
-            this.refresherRole = parameters.getParameter(REFRESHER_ROLE_PARAM, SourceRefresher.ROLE);
-        }
-
-        this.defaultExpires = parameters.getParameterAsInteger(DEFAULT_EXPIRES_PARAM, -1);
-
-        if (getLogger().isDebugEnabled()) {
-            getLogger().debug("Using cache " + this.cacheRole);
-            if (this.async) {
-                getLogger().debug("Using refresher " + this.refresherRole);
-            }
-        }
-    }
-
-    /**
-     * Lazy initialization of resolver and refresher because of
-     * cyclic dependencies.
-     *
-     * @throws SourceException
-     */
-    private synchronized void lazyInitialize() throws SourceException {
-        if (this.isInitialized) {
-            // another thread finished initialization for us while
-            // we were waiting
-            return;
-        }
-
-        try {
-            this.resolver = (SourceResolver) this.manager.lookup(SourceResolver.ROLE);
-        } catch (ServiceException se) {
-            throw new SourceException("Missing service dependency: " + SourceResolver.ROLE, se);
-        }
-
-        try {
-            this.cache = (Cache) this.manager.lookup(this.cacheRole);
-        } catch (ServiceException se) {
-            throw new SourceException("Missing service dependency: " + this.cacheRole, se);
-        }
-
-        if (this.async) {
-            try {
-                this.refresher = (SourceRefresher) this.manager.lookup(this.refresherRole);
-            } catch (ServiceException se) {
-                throw new SourceException("Missing service dependency: " + this.refresherRole, se);
-            }
-        }
-
-        this.isInitialized = true;
-    }
-
-    /* (non-Javadoc)
-     * @see Disposable#dispose()
-     */
-    public void dispose() {
-        if (this.refresher != null) {
-            this.manager.release(this.refresher);
-            this.refresher = null;
-        }
-        if (this.cache != null) {
-            this.manager.release(this.cache);
-            this.cache = null;
-        }
-        if (this.resolver != null) {
-            this.manager.release(this.resolver);
-            this.resolver = null;
-        }
-        this.manager = null;
-    }
-
-    // ---------------------------------------------------- SourceFactory implementation
-
-    protected String getScheme() {
-        return this.scheme;
-    }
-
-    protected boolean isAsync() {
-        return this.async;
-    }
+    
 
     /**
      * Get a <code>Source</code> object.
@@ -299,13 +159,8 @@
     public Source getSource(final String location, final Map parameters)
     throws MalformedURLException, IOException {
 
-        if (getLogger().isDebugEnabled() ) {
-            getLogger().debug("Creating source " + location);
-        }
-
-        // we must do lazy initialization because of cyclic dependencies
-        if (!this.isInitialized) {
-            lazyInitialize();
+        if (logger.isDebugEnabled() ) {
+            logger.debug("Creating source " + location);
         }
 
         // snip the cache protocol
@@ -343,12 +198,11 @@
             }
         }
 
-        int expires = params.getParameterAsInteger(CachingSource.CACHE_EXPIRES_PARAM, defaultExpires);
-        String cacheName = params.getParameter(CachingSource.CACHE_NAME_PARAM, null);
+        int expires = params.getParameterAsInteger(CachingSource.CACHE_EXPIRES_PARAM, this.defaultExpires);
+        String cacheName = params.getParameter(CachingSource.CACHE_NAME_PARAM, null);        
         boolean fail = params.getParameterAsBoolean(CachingSource.CACHE_FAIL_PARAM, false);
 
-        Source source = this.resolver.resolveURI(uri);
-        return createCachingSource(location, uri, source, expires, cacheName, fail);
+        return createCachingSource(location, uri, this.resolver.resolveURI(uri), expires, cacheName, fail);
     }
 
     /**
@@ -362,51 +216,21 @@
                                                 boolean fail)
     throws SourceException {
 
-        CachingSource source;
-
-        if (wrappedSource instanceof TraversableSource) {
-            if (wrappedSource instanceof InspectableSource) {
-                source = new InspectableTraversableCachingSource(this,
-                                                                 getScheme(),
-                                                                 uri,
-                                                                 wrappedUri,
-                                                                 (InspectableSource) wrappedSource,
-                                                                 expires,
-                                                                 cacheName,
-                                                                 isAsync(),
-                                                                 this.validityStrategy,
-                                                                 fail);
-            } else {
-                source = new TraversableCachingSource(this,
-                                                      getScheme(),
-                                                      uri,
-                                                      wrappedUri,
-                                                      (TraversableSource) wrappedSource,
-                                                      expires,
-                                                      cacheName,
-                                                      isAsync(),
-                                                      this.validityStrategy,
-                                                      fail);
-            }
-        } else {
-            source = new CachingSource(getScheme(),
-                                       uri,
-                                       wrappedUri,
-                                       wrappedSource,
-                                       expires,
-                                       cacheName,
-                                       isAsync(),
-                                       this.validityStrategy,
-                                       fail);
-        }
+        CachingSource source = instantiateSource(
+                        uri,
+                        wrappedUri,
+                        wrappedSource,
+                        expires,
+                        cacheName,
+                        fail);
 
         // set the required components directly for speed
         source.cache = this.cache;
 
-        ContainerUtil.enableLogging(source, getLogger());
+        ContainerUtil.enableLogging(source, new CLLoggerWrapper(logger));
         try {
             // call selected avalon lifecycle interfaces. Mmmh.
-            ContainerUtil.service(source, this.manager);
+            ContainerUtil.service(source, this.serviceManager);
             ContainerUtil.initialize(source);
         } catch (ServiceException e) {
             throw new SourceException("Unable to initialize source.", e);
@@ -419,19 +243,54 @@
             final Parameters params = new Parameters();
             params.setParameter(SourceRefresher.PARAM_CACHE_INTERVAL,
                                 String.valueOf(source.getExpiration()));
+            if(this.refresher == null) {
+                String msg = "Make sure that the SourceRefresher is injected correctly when " + 
+                "you want to use the source asyncronous and with an expires param > 0.";
+                logger.error(msg);
+                throw new SourceException(msg);
+            }
             this.refresher.refresh(source.getCacheKey(), source.getURI(), params);
         }
 
         return source;
     }
+    
+    protected CachingSource instantiateSource(String uri, String wrappedUri, Source wrappedSource, int expires,
+                    String cacheName, boolean fail) {
+
+        if (wrappedSource instanceof TraversableSource) {
+            return new TraversableCachingSource(
+                            this, 
+                            this.scheme, 
+                            uri, 
+                            wrappedUri,
+                            (TraversableSource) wrappedSource, 
+                            expires, 
+                            cacheName, 
+                            this.async,
+                            this.validityStrategy, 
+                            fail);
+        } else {
+            return new CachingSource(
+                            this.scheme, 
+                            uri, 
+                            wrappedUri, 
+                            wrappedSource, 
+                            expires, 
+                            cacheName, 
+                            this.async,
+                            this.validityStrategy, 
+                            fail);
+        }
+    }
 
     /**
      * Release a {@link Source} object.
      */
     public void release(Source source) {
         if (source instanceof CachingSource) {
-            if (getLogger().isDebugEnabled() ) {
-                getLogger().debug("Releasing source " + source.getURI());
+            if (logger.isDebugEnabled() ) {
+                logger.debug("Releasing source " + source.getURI());
             }
             CachingSource caching = (CachingSource) source;
             resolver.release(caching.source);
@@ -439,14 +298,53 @@
         }
     }
 
-    // ---------------------------------------------------- URIAbsolutizer implementation
+    // ---------------------------------------------------- URIAbsolutizer
+    // implementation
 
     /*
-     *  (non-Javadoc)
-     * @see org.apache.excalibur.source.URIAbsolutizer#absolutize(java.lang.String, java.lang.String)
+     * (non-Javadoc)
+     * 
+     * @see org.apache.excalibur.source.URIAbsolutizer#absolutize(java.lang.String,
+     *      java.lang.String)
      */
     public String absolutize(String baseURI, String location) {
         return SourceUtil.absolutize(baseURI, location, true);
     }
 
+    // ---------------------------------------------------- Set dependencies
+    
+    public void setCache(Cache cache) {
+        this.cache = cache;
+    }
+    
+    public void setValidityStrategy(CachingSourceValidityStrategy validityStrategy) {
+        this.validityStrategy = validityStrategy;
+    }   
+    
+    public void setServiceManager(ServiceManager serviceManager) {
+        this.serviceManager = serviceManager;
+    }
+    
+    public void setSourceResolver(SourceResolver resolver) {
+        this.resolver = resolver;
+    }
+    
+    public void setScheme(String scheme) {
+        this.scheme = scheme;
+    }
+ 
+    // optional
+    
+    public void setSourceRefresher(SourceRefresher refresher) {
+        this.refresher = refresher;
+    }
+    
+    public void setAsync(boolean async) {
+        this.async = async;
+    }
+    
+    public void setDefaultExpires(int expires) {
+        this.defaultExpires = expires;
+    }    
+    
 }

Added: cocoon/trunk/core/cocoon-core/src/main/resources/META-INF/cocoon/spring/cocoon-core-caching-source.xml
URL: http://svn.apache.org/viewvc/cocoon/trunk/core/cocoon-core/src/main/resources/META-INF/cocoon/spring/cocoon-core-caching-source.xml?view=auto&rev=525076
==============================================================================
--- cocoon/trunk/core/cocoon-core/src/main/resources/META-INF/cocoon/spring/cocoon-core-caching-source.xml (added)
+++ cocoon/trunk/core/cocoon-core/src/main/resources/META-INF/cocoon/spring/cocoon-core-caching-source.xml Tue Apr  3 01:10:48 2007
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
+<beans xmlns="http://www.springframework.org/schema/beans"
+  xmlns:p="http://www.springframework.org/schema/p"
+  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
+  
+  <!--+
+      | An abstract CachingSource bean definition providing correct dependencies for most
+      | usage scenarios. This avoid code duplication.
+      +-->
+  <bean name="org.apache.excalibur.source.SourceFactory/caching::abstract"
+    class="org.apache.cocoon.components.source.impl.CachingSourceFactory"
+    abstract="true">
+    <property name="cache" ref="org.apache.cocoon.caching.Cache"/>
+    <property name="sourceResolver" ref="org.apache.excalibur.source.SourceResolver"/>
+    <property name="serviceManager" ref="org.apache.avalon.framework.service.ServiceManager"/>
+    <property name="validityStrategy">
+      <bean class="org.apache.cocoon.components.source.impl.ExpiresCachingSourceValidityStrategy"/>        
+    </property>
+  </bean>          
+
+  <bean name="org.apache.excalibur.source.SourceFactory/caching"
+    class="org.apache.cocoon.components.source.impl.CachingSourceFactory"
+    parent="org.apache.excalibur.source.SourceFactory/caching::abstract"
+    p:scheme="caching"/>
+    
+  <bean name="org.apache.cocoon.components.source.helpers.DelaySourceRefresher"
+    class="org.apache.cocoon.components.source.helpers.DelaySourceRefresher"
+    init-method="init" 
+    destroy-method="destroy">
+    <property name="sourceResolver" ref="org.apache.excalibur.source.SourceResolver"/>
+    <property name="serviceManager" ref="org.apache.avalon.framework.service.ServiceManager"/>    
+    <property name="settings" ref="org.apache.cocoon.configuration.Settings"/>    
+    <property name="runnableManager" ref="org.apache.cocoon.components.thread.RunnableManager"/>    
+    <property name="avalonContext" ref="org.apache.avalon.framework.context.Context"/>
+  </bean>       
+  
+  <bean name="org.apache.excalibur.source.SourceFactory/async-caching"
+    class="org.apache.cocoon.components.source.impl.CachingSourceFactory"
+    parent="org.apache.excalibur.source.SourceFactory/caching::abstract"
+    p:scheme="async-caching"
+    p:async="true">
+    <property name="sourceRefresher" ref="org.apache.cocoon.components.source.helpers.DelaySourceRefresher"/>
+  </bean>
+        
+</beans>
\ No newline at end of file

Propchange: cocoon/trunk/core/cocoon-core/src/main/resources/META-INF/cocoon/spring/cocoon-core-caching-source.xml
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cocoon/trunk/core/cocoon-core/src/main/resources/META-INF/cocoon/spring/cocoon-core-caching-source.xml
------------------------------------------------------------------------------
    svn:keywords = Id

Propchange: cocoon/trunk/core/cocoon-core/src/main/resources/META-INF/cocoon/spring/cocoon-core-caching-source.xml
------------------------------------------------------------------------------
    svn:mime-type = text/xml

Modified: cocoon/trunk/core/cocoon-core/src/test/java/org/apache/cocoon/components/source/impl/CachingSourceTestCase.java
URL: http://svn.apache.org/viewvc/cocoon/trunk/core/cocoon-core/src/test/java/org/apache/cocoon/components/source/impl/CachingSourceTestCase.java?view=diff&rev=525076&r1=525075&r2=525076
==============================================================================
--- cocoon/trunk/core/cocoon-core/src/test/java/org/apache/cocoon/components/source/impl/CachingSourceTestCase.java (original)
+++ cocoon/trunk/core/cocoon-core/src/test/java/org/apache/cocoon/components/source/impl/CachingSourceTestCase.java Tue Apr  3 01:10:48 2007
@@ -22,7 +22,7 @@
 
 import org.apache.avalon.framework.context.DefaultContext;
 import org.apache.cocoon.Constants;
-import org.apache.cocoon.core.container.ContainerTestCase;
+import org.apache.cocoon.SitemapComponentTestCase;
 import org.apache.cocoon.environment.mock.MockContext;
 import org.apache.cocoon.xml.LoggingContentHandler;
 import org.apache.cocoon.xml.SaxBuffer;
@@ -32,13 +32,13 @@
 /**
  * TODO describe class
  */
-public class CachingSourceTestCase extends ContainerTestCase {
+public class CachingSourceTestCase extends SitemapComponentTestCase {
 
     private static final String URI = "resource://org/apache/cocoon/components/source/impl/cachingsourcetest.xml?foo=bar";
 
     SourceResolver resolver;
 
-    protected void setUp() throws Exception {
+    public void setUp() throws Exception {
         super.setUp();
         resolver = (SourceResolver) lookup(SourceResolver.ROLE);
     }

Modified: cocoon/trunk/core/cocoon-core/src/test/resources/org/apache/cocoon/components/source/impl/CachingSourceTestCase.spring.xml
URL: http://svn.apache.org/viewvc/cocoon/trunk/core/cocoon-core/src/test/resources/org/apache/cocoon/components/source/impl/CachingSourceTestCase.spring.xml?view=diff&rev=525076&r1=525075&r2=525076
==============================================================================
--- cocoon/trunk/core/cocoon-core/src/test/resources/org/apache/cocoon/components/source/impl/CachingSourceTestCase.spring.xml (original)
+++ cocoon/trunk/core/cocoon-core/src/test/resources/org/apache/cocoon/components/source/impl/CachingSourceTestCase.spring.xml Tue Apr  3 01:10:48 2007
@@ -1,7 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN"
-    "http://www.springframework.org/dtd/spring-beans-2.0.dtd">
-    <!--
+<!--
   Licensed to the Apache Software Foundation (ASF) under one or more
   contributor license agreements.  See the NOTICE file distributed with
   this work for additional information regarding copyright ownership.
@@ -17,10 +15,12 @@
   See the License for the specific language governing permissions and
   limitations under the License.
 -->
-<beans>
-  
-  <bean name="org.apache.cocoon.caching.Cache" class="org.apache.cocoon.caching.impl.CacheImpl">
-    <property name="store" ref="org.apache.excalibur.store.Store"/>
-  </bean>  
+<beans xmlns="http://www.springframework.org/schema/beans"
+  xmlns:p="http://www.springframework.org/schema/p"
+  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
   
+  <import resource="classpath:META-INF/cocoon/spring/cocoon-core-caching-source.xml"/>
+  <import resource="classpath:META-INF/cocoon/spring/cocoon-pipeline-impl-cache.xml"/>
+    
 </beans>

Modified: cocoon/trunk/core/cocoon-core/src/test/resources/org/apache/cocoon/components/source/impl/CachingSourceTestCase.xtest
URL: http://svn.apache.org/viewvc/cocoon/trunk/core/cocoon-core/src/test/resources/org/apache/cocoon/components/source/impl/CachingSourceTestCase.xtest?view=diff&rev=525076&r1=525075&r2=525076
==============================================================================
--- cocoon/trunk/core/cocoon-core/src/test/resources/org/apache/cocoon/components/source/impl/CachingSourceTestCase.xtest (original)
+++ cocoon/trunk/core/cocoon-core/src/test/resources/org/apache/cocoon/components/source/impl/CachingSourceTestCase.xtest Tue Apr  3 01:10:48 2007
@@ -37,11 +37,6 @@
        default-class="org.apache.excalibur.store.impl.StoreJanitorImpl"
   />
 
-  <role name="org.apache.cocoon.components.source.helpers.SourceRefresher"
-        shorthand="delay-refresher"
-        default-class="org.apache.cocoon.components.source.helpers.DelaySourceRefresher"
-  />
-
   <role name="org.apache.excalibur.xml.sax.SAXParser"
         shorthand="xml-parser"
         default-class="org.apache.excalibur.xml.impl.JaxpParser"
@@ -61,23 +56,11 @@
  <components>
 
   <source-factories>
-   <component-instance class="org.apache.cocoon.components.source.impl.CachingSourceFactory" name="caching" logger="core.cachingsource"/>
-   <component-instance class="org.apache.cocoon.components.source.impl.CachingSourceFactory" name="async-caching" logger="core.asynchcachingsource">
-     <parameter name="async" value="true"/>
-   </component-instance>
    <component-instance class="org.apache.cocoon.components.source.impl.XMLizableSourceFactory" name="xml" logger="core.xmlsource"/>
    <component-instance class="org.apache.excalibur.source.impl.FileSourceFactory" name="file" logger="core.filesource"/>
    <component-instance class="org.apache.excalibur.source.impl.ResourceSourceFactory" name="resource" logger="core.resourcesource"/>
    <component-instance class="org.apache.excalibur.source.impl.URLSourceFactory" name="*"/>
   </source-factories>
-
-  <store logger="core.persistentstore">
-    <parameter name="directory" value="cachingsourcetest"/>
-  </store>
-
-  <delay-refresher logger="core.refresher">
-    <parameter name="write-interval" value="10"/>
-  </delay-refresher>
 
   <xmlizer logger="core.xmlizer">
     <parser mime-type="text/xml" role="org.apache.excalibur.xml.sax.SAXParser"/>