unico 2004/03/23 08:28:54
Modified: src/blocks/scratchpad/java/org/apache/cocoon/components/source/impl CachingSourceFactory.java CachingSource.java TraversableCachingSource.java UpdateTarget.java DelayRefresher.java src/blocks/scratchpad/conf delay-refresher.xconf Log: factor common code used by updater, fix asynchronic update for traversables Revision Changes Path 1.7 +6 -12 cocoon-2.1/src/blocks/scratchpad/java/org/apache/cocoon/components/source/impl/CachingSourceFactory.java Index: CachingSourceFactory.java =================================================================== RCS file: /home/cvs/cocoon-2.1/src/blocks/scratchpad/java/org/apache/cocoon/components/source/impl/CachingSourceFactory.java,v retrieving revision 1.6 retrieving revision 1.7 diff -u -r1.6 -r1.7 --- CachingSourceFactory.java 23 Mar 2004 12:47:22 -0000 1.6 +++ CachingSourceFactory.java 23 Mar 2004 16:28:54 -0000 1.7 @@ -271,7 +271,7 @@ while (names.hasNext()) { String name = (String) names.next(); if (name.startsWith("cocoon:")) { - params.setParameter(name.substring("cocoon:".length()),sp.getParameter(name)); + params.setParameter(name.substring("cocoon:".length()), sp.getParameter(name)); sp.removeParameter(name); } } @@ -281,12 +281,12 @@ } } - final String cacheName = params.getParameter("cache-name", null); int expires = params.getParameterAsInteger("cache-expires", -1); if (expires == -1) { expires = this.defaultExpires; params.setParameter("cache-expires", String.valueOf(this.defaultExpires)); } + params.setParameter("cache-role", this.cacheRole); final Source wrappedSource = this.resolver.resolveURI(uri); CachingSource source; @@ -294,29 +294,23 @@ source = new TraversableCachingSource(scheme, location, (TraversableSource) wrappedSource, - cacheName, + params, expires, - parameters, this.async); } else { source = new CachingSource(scheme, location, wrappedSource, - cacheName, + params, expires, - parameters, this.async); } - if (this.async) { - // schedule it with the refresher - this.refresher.refresh(source.getCacheKey(), uri, this.cacheRole, params); - } - // set the required components directly for speed source.cache = this.cache; source.resolver = this.resolver; + source.refresher = this.refresher; ContainerUtil.enableLogging(source, this.getLogger()); try { 1.8 +115 -81 cocoon-2.1/src/blocks/scratchpad/java/org/apache/cocoon/components/source/impl/CachingSource.java Index: CachingSource.java =================================================================== RCS file: /home/cvs/cocoon-2.1/src/blocks/scratchpad/java/org/apache/cocoon/components/source/impl/CachingSource.java,v retrieving revision 1.7 retrieving revision 1.8 diff -u -r1.7 -r1.8 --- CachingSource.java 22 Mar 2004 17:38:25 -0000 1.7 +++ CachingSource.java 23 Mar 2004 16:28:54 -0000 1.8 @@ -20,11 +20,12 @@ import java.io.IOException; import java.io.InputStream; import java.io.Serializable; -import java.net.MalformedURLException; -import java.util.Map; +import java.util.Collection; +import java.util.Iterator; import org.apache.avalon.framework.activity.Initializable; 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; @@ -41,6 +42,7 @@ import org.apache.excalibur.source.SourceNotFoundException; import org.apache.excalibur.source.SourceResolver; import org.apache.excalibur.source.SourceValidity; +import org.apache.excalibur.source.TraversableSource; import org.apache.excalibur.source.impl.validity.ExpiresValidity; import org.apache.excalibur.source.impl.validity.TimeStampValidity; import org.apache.excalibur.xml.sax.XMLizable; @@ -83,6 +85,9 @@ /** The current cache */ protected Cache cache; + /** The refresher for asynchronous updates */ + protected Refresher refresher; + /** The source object for the real content */ protected Source source; @@ -95,9 +100,6 @@ /** The full location string */ final protected String uri; - /** The wrapped source uri */ - final protected String sourceURI; - /** The used protocol */ final protected String protocol; @@ -107,11 +109,8 @@ /** number of seconds before cached object becomes invalid */ final protected int expires; - /** key name extension */ - final protected String cacheName; - - /** additional source parameters */ - final protected Map parameters; + /** Parameters */ + final protected Parameters parameters; /** asynchronic refresh strategy ? */ final protected boolean async; @@ -122,39 +121,24 @@ public CachingSource(final String protocol, final String uri, final Source source, - final String cacheName, - final int expires, - final Map parameters, - final boolean async) { - this(protocol, uri, source.getURI(), cacheName, expires, parameters, async); - this.source = source; - } - - /** - * Construct a new object. - */ - public CachingSource(final String protocol, - final String uri, - final String sourceURI, - final String cacheName, + final Parameters parameters, final int expires, - final Map parameters, final boolean async) { this.protocol = protocol; this.uri = uri; - this.sourceURI = sourceURI; - this.cacheName = cacheName; + this.source = source; this.expires = expires; - this.parameters = parameters; this.async = async; + this.parameters = parameters; - String key = "source:" + sourceURI; + String key = "source:" + source.getURI(); + String cacheName = parameters.getParameter("cache-name", null); if (cacheName != null) { key += ":" + cacheName; } this.cacheKey = new SimpleCacheKey(key, false); } - + /** * Set the ServiceManager. */ @@ -181,6 +165,13 @@ } } } + if (this.async && expires > 0) { + // schedule it with the refresher + this.refresher.refresh(this.cacheKey, + getSourceURI(), + this.parameters.getParameter("cache-role", null), + this.parameters); + } } /** @@ -210,7 +201,7 @@ storeResponse = true; } if (response.getExtra() == null || refresh) { - response.setExtra(readMeta()); + response.setExtra(readMeta(this.source)); this.freshMeta = true; } if (storeResponse) { @@ -239,10 +230,10 @@ storeResponse = true; } if (response.getBinaryResponse() == null || refresh) { - response.setBinaryResponse(readBinaryResponse()); + response.setBinaryResponse(readBinaryResponse(this.source)); if (!this.freshMeta) { /* always refresh meta in this case */ - response.setExtra(readMeta()); + response.setExtra(readMeta(this.source)); } } if (storeResponse) { @@ -273,10 +264,11 @@ storeResponse = true; } if (response.getXMLResponse() == null || refresh) { - response.setXMLResponse(readXMLResponse()); + byte[] binary = response.getBinaryResponse(); + response.setXMLResponse(readXMLResponse(this.source, binary, this.manager)); if (!this.freshMeta) { /* always refresh meta in this case */ - response.setExtra(readMeta()); + response.setExtra(readMeta(this.source)); } } if (storeResponse) { @@ -358,12 +350,7 @@ * @see org.apache.excalibur.source.Source#exists() */ public boolean exists() { - try { - return this.getSource().exists(); - } - catch (IOException e) { - return true; - } + return this.source.exists(); } /** @@ -386,11 +373,7 @@ */ public void refresh() { this.response = null; - try { - getSource().refresh(); - } - catch (IOException ignore) { - } + this.source.refresh(); } // ---------------------------------------------------- XMLizable implementation @@ -426,17 +409,7 @@ * Return the uri of the cached source. */ protected String getSourceURI() { - return this.sourceURI; - } - - /** - * Return the cached source itself. - */ - protected Source getSource() throws MalformedURLException, IOException { - if (this.source == null) { - this.source = resolver.resolveURI(sourceURI, null, parameters); - } - return this.source; + return this.source.getURI(); } /** @@ -461,25 +434,22 @@ * @throws IOException * @throws CascadingIOException */ - protected byte[] readXMLResponse() throws SAXException, IOException, CascadingIOException { + protected static byte[] readXMLResponse(Source source, byte[] binary, ServiceManager manager) + throws SAXException, IOException, CascadingIOException { XMLSerializer serializer = null; XMLizer xmlizer = null; byte[] result = null; try { - serializer = (XMLSerializer) this.manager.lookup(XMLSerializer.ROLE); + serializer = (XMLSerializer) manager.lookup(XMLSerializer.ROLE); - if (this.source instanceof XMLizable) { - ((XMLizable) this.source).toSAX(serializer); + if (source instanceof XMLizable) { + ((XMLizable) source).toSAX(serializer); } else { - byte[] binary = null; - if (this.response != null) { - binary = this.response.getBinaryResponse(); - } if (binary == null) { - binary = readBinaryResponse(); + binary = readBinaryResponse(source); } - final String mimeType = this.source.getMimeType(); + final String mimeType = source.getMimeType(); if (mimeType != null) { xmlizer = (XMLizer) manager.lookup(XMLizer.ROLE); xmlizer.toSAX(new ByteArrayInputStream(binary), @@ -490,10 +460,10 @@ } result = (byte[]) serializer.getSAXFragment(); } catch (ServiceException se) { - throw new CascadingIOException("Missing service dependencyj.", se); + throw new CascadingIOException("Missing service dependency.", se); } finally { - this.manager.release(xmlizer); - this.manager.release(serializer); + manager.release(xmlizer); + manager.release(serializer); } return result; } @@ -505,10 +475,11 @@ * @throws IOException * @throws SourceNotFoundException */ - protected byte[] readBinaryResponse() throws IOException, SourceNotFoundException { + protected static byte[] readBinaryResponse(Source source) + throws IOException, SourceNotFoundException { final ByteArrayOutputStream baos = new ByteArrayOutputStream(); final byte[] buffer = new byte[2048]; - final InputStream inputStream = this.source.getInputStream(); + final InputStream inputStream = source.getInputStream(); int length; while ((length = inputStream.read(buffer)) > -1) { baos.write(buffer, 0, length); @@ -524,14 +495,47 @@ * @return source meta data * @throws IOException */ - protected SourceMeta readMeta() throws IOException { - SourceMeta meta = new SourceMeta(); - long lastModified = getSource().getLastModified(); - if (lastModified <= 0) { - lastModified = System.currentTimeMillis(); + protected static SourceMeta readMeta(Source source) throws IOException { + SourceMeta meta; + + if (source instanceof TraversableSource) { + + final TraversableSourceMeta tmeta = new TraversableSourceMeta(); + final TraversableSource tsource = (TraversableSource) source; + + tmeta.setName(tsource.getName()); + tmeta.setIsCollection(tsource.isCollection()); + + if (tmeta.isCollection()) { + final Collection children = tsource.getChildren(); + if (children != null) { + final String[] names = new String[children.size()]; + final Iterator iter = children.iterator(); + int count = 0; + while(iter.hasNext()) { + TraversableSource child = (TraversableSource) iter.next(); + names[count] = child.getName(); + count++; + } + tmeta.setChildren(names); + } + } + + meta = tmeta; } - meta.setLastModified(lastModified); - meta.setMimeType(getSource().getMimeType()); + else { + meta = new SourceMeta(); + } + + final long lastModified = source.getLastModified(); + if (lastModified > 0) { + meta.setLastModified(lastModified); + } + else { + meta.setLastModified(System.currentTimeMillis()); + } + meta.setMimeType(source.getMimeType()); + return meta; } @@ -568,6 +572,36 @@ m_exists = exists; } + } + + protected static class TraversableSourceMeta extends SourceMeta { + private String m_name; + private boolean m_isCollection; + private String[] m_children; + + protected String getName() { + return m_name; + } + + protected void setName(String name) { + m_name = name; + } + + protected boolean isCollection() { + return m_isCollection; + } + + protected void setIsCollection(boolean isCollection) { + m_isCollection = isCollection; + } + + protected String[] getChildren() { + return m_children; + } + + protected void setChildren(String[] children) { + m_children = children; + } } } 1.3 +26 -140 cocoon-2.1/src/blocks/scratchpad/java/org/apache/cocoon/components/source/impl/TraversableCachingSource.java Index: TraversableCachingSource.java =================================================================== RCS file: /home/cvs/cocoon-2.1/src/blocks/scratchpad/java/org/apache/cocoon/components/source/impl/TraversableCachingSource.java,v retrieving revision 1.2 retrieving revision 1.3 diff -u -r1.2 -r1.3 --- TraversableCachingSource.java 23 Mar 2004 12:46:38 -0000 1.2 +++ TraversableCachingSource.java 23 Mar 2004 16:28:54 -0000 1.3 @@ -16,13 +16,11 @@ package org.apache.cocoon.components.source.impl; import java.io.IOException; -import java.net.MalformedURLException; import java.util.ArrayList; import java.util.Collection; -import java.util.Iterator; -import java.util.Map; import org.apache.avalon.framework.container.ContainerUtil; +import org.apache.avalon.framework.parameters.Parameters; import org.apache.excalibur.source.Source; import org.apache.excalibur.source.SourceException; import org.apache.excalibur.source.TraversableSource; @@ -31,33 +29,17 @@ * Traversable version of [EMAIL PROTECTED] org.apache.cocoon.components.source.impl.CachingSource}. */ public class TraversableCachingSource extends CachingSource implements TraversableSource { - - // the Source children in case of a collection - private TraversableSource[] m_children; - public TraversableCachingSource(String protocol, - String uri, - String sourceURI, - String cacheName, - int expires, - Map parameters, - boolean async) { - super(protocol, uri, sourceURI, cacheName, expires, parameters, async); - } + private TraversableSource tsource; public TraversableCachingSource(String protocol, String location, TraversableSource source, - String cacheName, + Parameters params, int expires, - Map parameters, boolean async) { - super(protocol, location, source, cacheName, expires, parameters, async); - } - - public void dispose() { - super.dispose(); - m_children = null; + super(protocol, location, source, params, expires, async); + this.tsource = source; } // ---------------------------------------------------- TraversableSource implementation @@ -94,8 +76,10 @@ public Source getChild(String name) throws SourceException { + Source child; try { initMetaResponse(false); + child = this.tsource.getChild(name); } catch (SourceException e) { throw e; @@ -108,7 +92,7 @@ throw new SourceException("Source is not a collection"); } - return createChildSource(name); + return createSource(getChildURI(super.uri, name), child); } public Collection getChildren() throws SourceException { @@ -126,18 +110,19 @@ if (!isCollection()) { throw new SourceException("Source is not a collection"); } - + final Collection result = new ArrayList(); - if (m_children != null) { - for (int i = 0; i < m_children.length; i++) { - result.add(createChildSource(m_children[i])); + final TraversableSourceMeta meta = (TraversableSourceMeta) super.response.getExtra(); + final String[] children = meta.getChildren(); + for (int i = 0; i < children.length; i++) { + Source child; + try { + child = this.tsource.getChild(children[i]); } - } - else { - final String[] children = ((TraversableSourceMeta) super.response.getExtra()).getChildren(); - for (int i = 0; i < children.length; i++) { - result.add(createChildSource(children[i])); + catch (IOException e) { + throw new SourceException("Failure getting child", e); } + result.add(createSource(getChildURI(super.uri, children[i]), child)); } return result; @@ -145,104 +130,36 @@ public Source getParent() throws SourceException { + Source parent; try { initMetaResponse(false); + parent = this.tsource.getParent(); } catch (SourceException e) { throw e; } catch (IOException e) { - throw new SourceException("Failure getting child", e); + throw new SourceException("Failure getting parent", e); } - return createSource(getParentURI(super.uri), getParentURI(super.sourceURI)); + return createSource(getParentURI(super.uri), parent); } // ---------------------------------------------------- helper methods - - protected SourceMeta readMeta() throws IOException { - final TraversableSourceMeta meta = new TraversableSourceMeta(); - - final long lastModified = getTraversableSource().getLastModified(); - if (lastModified > 0) { - meta.setLastModified(lastModified); - } - else { - meta.setLastModified(System.currentTimeMillis()); - } - meta.setMimeType(getTraversableSource().getMimeType()); - - meta.setName(getTraversableSource().getName()); - meta.setIsCollection(getTraversableSource().isCollection()); - - if (meta.isCollection()) { - final Collection children = getTraversableSource().getChildren(); - if (children != null) { - m_children = new TraversableSource[children.size()]; - final String[] names = new String[children.size()]; - final Iterator iter = children.iterator(); - int count = 0; - while(iter.hasNext()) { - TraversableSource child = (TraversableSource) iter.next(); - m_children[count] = child; - names[count] = child.getName(); - count++; - } - meta.setChildren(names); - } - } - return meta; - } - - protected TraversableSource getTraversableSource() throws MalformedURLException, IOException { - return (TraversableSource) getSource(); - } - - private TraversableCachingSource createChildSource(TraversableSource childSource) - throws SourceException { - return createSource(childSource, getChildURI(super.uri, childSource.getName())); - } - - private TraversableCachingSource createSource(TraversableSource wrappedSource, String sourceURI) - throws SourceException { - final TraversableCachingSource child = - new TraversableCachingSource(super.protocol, - sourceURI, - wrappedSource, - super.cacheName, - super.expires, - super.parameters, - super.async); - child.cache = super.cache; - child.resolver = super.resolver; - ContainerUtil.enableLogging(child,getLogger()); - try { - ContainerUtil.service(child,super.manager); - ContainerUtil.initialize(child); - } catch (Exception e) { - throw new SourceException("Unable to initialize source.", e); - } - return child; - } - - private TraversableCachingSource createChildSource(String childName) - throws SourceException { - return createSource(getChildURI(super.uri, childName), getChildURI(super.sourceURI, childName)); - } - private TraversableCachingSource createSource(String uri, String sourceURI) + private TraversableCachingSource createSource(String uri, Source wrapped) throws SourceException { final TraversableCachingSource source = new TraversableCachingSource(super.protocol, uri, - sourceURI, - super.cacheName, - super.expires, + (TraversableSource) wrapped, super.parameters, + super.expires, super.async); source.cache = super.cache; source.resolver = super.resolver; + source.refresher = super.refresher; ContainerUtil.enableLogging(source, getLogger()); try { ContainerUtil.service(source, super.manager); @@ -313,35 +230,4 @@ return parentUri + qs; } - protected static class TraversableSourceMeta extends SourceMeta { - - private String m_name; - private boolean m_isCollection; - private String[] m_children; - - protected String getName() { - return m_name; - } - - protected void setName(String name) { - m_name = name; - } - - protected boolean isCollection() { - return m_isCollection; - } - - protected void setIsCollection(boolean isCollection) { - m_isCollection = isCollection; - } - - protected String[] getChildren() { - return m_children; - } - - protected void setChildren(String[] children) { - m_children = children; - } - - } } 1.4 +102 -99 cocoon-2.1/src/blocks/scratchpad/java/org/apache/cocoon/components/source/impl/UpdateTarget.java Index: UpdateTarget.java =================================================================== RCS file: /home/cvs/cocoon-2.1/src/blocks/scratchpad/java/org/apache/cocoon/components/source/impl/UpdateTarget.java,v retrieving revision 1.3 retrieving revision 1.4 diff -u -r1.3 -r1.4 --- UpdateTarget.java 5 Mar 2004 10:07:25 -0000 1.3 +++ UpdateTarget.java 23 Mar 2004 16:28:54 -0000 1.4 @@ -15,155 +15,158 @@ */ package org.apache.cocoon.components.source.impl; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.InputStream; import java.util.Map; -import org.apache.avalon.excalibur.pool.Recyclable; 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.cocoon.caching.Cache; -import org.apache.cocoon.caching.ExtendedCachedResponse; import org.apache.cocoon.caching.SimpleCacheKey; import org.apache.cocoon.components.cron.ConfigurableCronJob; -import org.apache.cocoon.components.sax.XMLSerializer; import org.apache.excalibur.source.Source; import org.apache.excalibur.source.SourceResolver; -import org.apache.excalibur.source.SourceValidity; import org.apache.excalibur.source.impl.validity.ExpiresValidity; -import org.apache.excalibur.xml.sax.SAXParser; -import org.apache.excalibur.xml.sax.XMLizable; -import org.xml.sax.InputSource; /** * A target updating a cache entry. * * This target requires several parameters: - * - uri (String): The uri to cache, every valid protocol can be used, except the Cocoon protocol! - * - cacheRole (String): The role of the cache component to store the content - * - expires (long): The time in seconds the cached content is valid - * - cacheKey (SimpleCacheKey) : The key used to cache the content + * <ul> + * <li> + * <code>uri (String)</code>: + * The uri to cache, every valid protocol can be used, except the Cocoon protocol! + * </li> + * <li> + * <code>cache-role (String)</code>: + * The role of the cache component to store the content + * </li> + * <li> + * <code>cache-expires (long)</code>: + * The time in seconds the cached content is valid + * </li> + * <li> + * <code>fail-safe (boolean)</code> + * Whether to invalidate the cached response when updating it failed. + * </li> + * <li> + * <code>cache-key (SimpleCacheKey)</code>: + * The key used to cache the content + * </li> + * </ul> * * @since 2.1.1 * @author <a href="mailto:[EMAIL PROTECTED]">Carsten Ziegeler</a> * @version CVS $Id$ */ -public class UpdateTarget - extends AbstractLogEnabled - implements Recyclable, Serviceable, ConfigurableCronJob { +public class UpdateTarget extends AbstractLogEnabled +implements Serviceable, ConfigurableCronJob { - protected String uri; + // service dependencies + protected ServiceManager manager; + protected SourceResolver resolver; + // configuration + protected String uri; protected String cacheRole; + protected int expires; + protected boolean failSafe; - protected long expires; + // the key under which to store the CachedResponse in the Cache + protected SimpleCacheKey cacheKey; - protected ServiceManager manager; + + // ---------------------------------------------------- Lifecycle - protected SourceResolver resolver; + public UpdateTarget() { + } - protected SimpleCacheKey cacheKey; + /* (non-Javadoc) + * @see org.apache.avalon.framework.service.Serviceable#service(org.apache.avalon.framework.service.ServiceManager) + */ + public void service(ServiceManager manager) throws ServiceException { + this.manager = manager; + this.resolver = (SourceResolver) this.manager.lookup(SourceResolver.ROLE); + } + + /* (non-Javadoc) + * @see org.apache.cocoon.components.scheduler.ConfigurableTarget#setup(org.apache.avalon.framework.parameters.Parameters, java.util.Map) + */ + public void setup(Parameters pars, Map objects) { + this.uri = pars.getParameter("uri", null); + this.cacheRole = pars.getParameter("cache-role", Cache.ROLE); + this.expires = pars.getParameterAsInteger("cache-expires", 60); + this.failSafe = pars.getParameterAsBoolean("fail-safe", true); + this.cacheKey = (SimpleCacheKey) objects.get("cache-key"); + } + + + // ---------------------------------------------------- CronJob implementation /* (non-Javadoc) * @see org.apache.avalon.cornerstone.services.scheduler.Target#targetTriggered(java.lang.String) */ public void execute(String name) { - if ( this.uri != null ) { - if ( this.getLogger().isInfoEnabled()) { + if (this.uri != null) { + if (this.getLogger().isInfoEnabled()) { this.getLogger().info("Refreshing " + this.uri); } - + Source source = null; Cache cache = null; try { - cache = (Cache)this.manager.lookup(this.cacheRole); - // the content expires, so remove it - cache.remove(cacheKey); + cache = (Cache) this.manager.lookup(this.cacheRole); source = this.resolver.resolveURI(this.uri); - - XMLSerializer serializer = null; - SAXParser parser = null; - byte[] cachedResponse; - byte[] content = null; - try { - serializer = (XMLSerializer)this.manager.lookup(XMLSerializer.ROLE); - if ( source instanceof XMLizable ) { - ((XMLizable)source).toSAX(serializer); - } else { - // resd the content - final ByteArrayOutputStream baos = new ByteArrayOutputStream(); - final byte[] buffer = new byte[2048]; - final InputStream inputStream = source.getInputStream(); - int length; - - while ((length = inputStream.read(buffer)) > -1) { - baos.write(buffer, 0, length); - } - baos.flush(); - inputStream.close(); - - content = baos.toByteArray(); - - parser = (SAXParser)this.manager.lookup(SAXParser.ROLE); + CachedSourceResponse response = (CachedSourceResponse) cache.get(this.cacheKey); + + if (source.exists()) { + + // what is in the cached response? + byte[] binary = null; + byte[] xml = null; + if (response != null) { + binary = response.getBinaryResponse(); + xml = response.getXMLResponse(); + } - final InputSource inputSource = new InputSource(new ByteArrayInputStream(content)); - inputSource.setSystemId(source.getURI()); + // create a new cached response + response = new CachedSourceResponse(new ExpiresValidity(this.expires * 1000)); - parser.parse( inputSource, serializer ); + // only create objects that have previously been used + if (binary != null) { + binary = CachingSource.readBinaryResponse(source); + response.setBinaryResponse(binary); + } + if (xml != null) { + xml = CachingSource.readXMLResponse(source, binary, this.manager); + response.setXMLResponse(xml); } - cachedResponse = (byte[])serializer.getSAXFragment(); - } finally { - this.manager.release(parser); - this.manager.release(serializer); + // meta info is always set + response.setExtra(CachingSource.readMeta(source)); + + cache.store(this.cacheKey, response); + } + else if (response != null) { + cache.remove(this.cacheKey); + } + } catch (Exception e) { + if (!failSafe) { + // the content expires, so remove it + cache.remove(cacheKey); + getLogger().warn("Exception during updating " + this.uri, e); + } + else { + getLogger().warn("Updating of source " + this.uri + " failed. " + + "Cached response (if any) will be stale.", e); } - - SourceValidity val = new ExpiresValidity(this.expires); - ExtendedCachedResponse response = new ExtendedCachedResponse(val, content); - response.setAlternativeResponse(cachedResponse); - cache.store(cacheKey, response); - - } catch (Exception ignore) { - this.getLogger().error("Exception during updating " +this.uri, ignore); } finally { this.resolver.release(source); - this.manager.release( cache ); + this.manager.release(cache); } - } - } - - /* (non-Javadoc) - * @see org.apache.cocoon.components.scheduler.ConfigurableTarget#setup(org.apache.avalon.framework.parameters.Parameters, java.util.Map) - */ - public void setup(Parameters pars, Map objects) { - this.uri = pars.getParameter("uri", null); - this.cacheRole = pars.getParameter("cache-role", Cache.ROLE); - this.expires = pars.getParameterAsLong("cache-expires", 1800); - this.cacheKey = (SimpleCacheKey) objects.get("cache-key"); - } - - /* (non-Javadoc) - * @see org.apache.avalon.excalibur.pool.Recyclable#recycle() - */ - public void recycle() { - this.uri = null; - this.cacheKey = null; - this.expires = 0; - this.cacheRole = null; - } - - /* (non-Javadoc) - * @see org.apache.avalon.framework.service.Serviceable#service(org.apache.avalon.framework.service.ServiceManager) - */ - public void service(ServiceManager manager) throws ServiceException { - this.manager = manager; - this.resolver = (SourceResolver) this.manager.lookup(SourceResolver.ROLE); } } 1.2 +14 -14 cocoon-2.1/src/blocks/scratchpad/java/org/apache/cocoon/components/source/impl/DelayRefresher.java Index: DelayRefresher.java =================================================================== RCS file: /home/cvs/cocoon-2.1/src/blocks/scratchpad/java/org/apache/cocoon/components/source/impl/DelayRefresher.java,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- DelayRefresher.java 22 Mar 2004 17:38:25 -0000 1.1 +++ DelayRefresher.java 23 Mar 2004 16:28:54 -0000 1.2 @@ -62,21 +62,21 @@ public class DelayRefresher extends AbstractLogEnabled implements Contextualizable, Serviceable, Parameterizable, Disposable, ThreadSafe, Refresher, CronJob { - private static final String PARAM_CACHE_ROLE = "cache-role"; - private static final String PARAM_CACHE_EXPIRES = "cache-expires"; - private static final String PARAM_UPDATE_TARGET = "update-target"; - private static final String PARAM_WRITE_INTERVAL = "write-interval"; - private static final String PARAM_WRITE_FILE = "write-file"; + private static final String PARAM_CACHE_ROLE = "cache-role"; + private static final String PARAM_CACHE_EXPIRES = "cache-expires"; + private static final String PARAM_UPDATE_TARGET_ROLE = "update-target-role"; + private static final String PARAM_WRITE_INTERVAL = "write-interval"; + private static final String PARAM_WRITE_FILE = "write-file"; - private static final String DEFAULT_WRITE_FILE = "refresher-targets.xml"; + private static final String DEFAULT_WRITE_FILE = "refresher-targets.xml"; - private static final String CACHE_KEY = "cache-key"; + private static final String CACHE_KEY = "cache-key"; - private static final String TAGNAME_TARGET = "target"; - private static final String ATTR_CACHE = "cache"; - private static final String ATTR_EXPIRES = "expires"; - private static final String ATTR_KEY = "key"; - private static final String ATTR_URI = "uri"; + private static final String TAGNAME_TARGET = "target"; + private static final String ATTR_CACHE = "cache"; + private static final String ATTR_EXPIRES = "expires"; + private static final String ATTR_KEY = "key"; + private static final String ATTR_URI = "uri"; // service dependencies protected ServiceManager manager; @@ -124,7 +124,7 @@ * @see org.apache.avalon.framework.parameters.Parameterizable#parameterize(org.apache.avalon.framework.parameters.Parameters) */ public void parameterize(Parameters parameters) throws ParameterException { - this.updateTarget = parameters.getParameter(PARAM_UPDATE_TARGET, CronJob.ROLE + "/UpdateTarget"); + this.updateTarget = parameters.getParameter(PARAM_UPDATE_TARGET_ROLE, CronJob.ROLE + "/UpdateTarget"); int writeInterval = parameters.getParameterAsInteger(PARAM_WRITE_INTERVAL, 0); if (writeInterval > 0) { this.setupRefreshJobSource(parameters); 1.2 +11 -0 cocoon-2.1/src/blocks/scratchpad/conf/delay-refresher.xconf Index: delay-refresher.xconf =================================================================== RCS file: /home/cvs/cocoon-2.1/src/blocks/scratchpad/conf/delay-refresher.xconf,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- delay-refresher.xconf 22 Mar 2004 17:38:25 -0000 1.1 +++ delay-refresher.xconf 23 Mar 2004 16:28:54 -0000 1.2 @@ -33,6 +33,8 @@ | more than one DelayRefreshers. It represents the file name, relative to | the cocoon working directory of the file the refresher writes its list | of registered target configurations to. + | - 'update-target-role' (org.apache.cocoon.components.cron.CronJob/UpdateTarget) + | The role name of the CronJob to use for updating the Sources. +--> <component role="org.apache.cocoon.components.source.impl.Refresher/Delay" class="org.apache.cocoon.components.source.impl.DelayRefresher" @@ -40,7 +42,16 @@ <!-- <parameter name="write-interval" value="0"/> <parameter name="write-file" value="refresher-targets.xml"/> + <parameter name="update-target-role" value="org.apache.cocoon.components.cron.CronJob/UpdateTarget"/> --> </component> + + <!-- This is the default CronJob for updating the Source files + used by the DelayRefresher. + --> + <component role="org.apache.cocoon.components.cron.CronJob/UpdateTarget" + class="org.apache.cocoon.components.source.impl.UpdateTarget" + logger="core.refresher.update" + /> </xconf>