Return-Path: Delivered-To: apmail-xml-cocoon-dev-archive@xml.apache.org Received: (qmail 46906 invoked by uid 500); 4 Jul 2001 15:40:42 -0000 Mailing-List: contact cocoon-dev-help@xml.apache.org; run by ezmlm Precedence: bulk list-help: list-unsubscribe: list-post: Reply-To: cocoon-dev@xml.apache.org Delivered-To: mailing list cocoon-dev@xml.apache.org Received: (qmail 46782 invoked from network); 4 Jul 2001 15:40:04 -0000 From: maciejka@tiger.com.pl To: cocoon-dev@xml.apache.org Date: Wed, 4 Jul 2001 17:43:46 +0200 MIME-Version: 1.0 Content-type: Multipart/Mixed; boundary=Message-Boundary-19056 Subject: CachingCIncludeTransformer Reply-to: maciejka@tiger.com.pl Message-ID: <3B4355D2.8417.55083F3@localhost> Priority: normal X-mailer: Pegasus Mail for Win32 (v3.12c) X-Spam-Rating: h31.sny.collab.net 1.6.2 0/1000/N --Message-Boundary-19056 Content-type: text/plain; charset=US-ASCII Content-transfer-encoding: 7BIT Content-description: Mail message body I am attaching code of CachingCIncludeTransformer, IncludeCacheValidity and xml files to try it. Is just a try to attack problem of caching cinclude transformer. Current caching framework design hardly makes it possible. One has to use CacheValidity objects in a hacky way. As ContentAggregator it caches only if includes are files, since sitemap sources always return getLastModified() == 0. Anyone works on caching sitemap includes in ContentAggregator? P.S.: To try it one should change to and add something like: to sitemap.xmap and put x.xml, y.xml, z.xml into webapp dir. Maciek Kaminski maciejka@tiger.com.pl --Message-Boundary-19056 Content-type: text/plain; charset=US-ASCII Content-transfer-encoding: 7BIT Content-description: Text from file 'CachingCIncludeTransformer.java' /***************************************************************************** * Copyright (C) The Apache Software Foundation. All rights reserved. * * ------------------------------------------------------------------------- * * This software is published under the terms of the Apache Software License * * version 1.1, a copy of which has been included with this distribution in * * the LICENSE file. * *****************************************************************************/ package org.apache.cocoon.transformation; import java.io.IOException; import java.util.Map; import org.apache.avalon.excalibur.pool.Recyclable; import org.apache.avalon.framework.component.ComponentException; import org.apache.avalon.framework.component.ComponentManager; import org.apache.avalon.framework.component.Composable; import org.apache.avalon.framework.parameters.Parameters; import org.apache.cocoon.ProcessingException; import org.apache.cocoon.Roles; import org.apache.cocoon.caching.EventCache; import org.apache.cocoon.caching.Cacheable; import org.apache.cocoon.caching.CacheValidity; import org.apache.cocoon.caching.IncludeCacheValidity; import org.apache.cocoon.caching.TimeStampCacheValidity; import org.apache.cocoon.components.parser.Parser; import org.apache.cocoon.environment.Source; import org.apache.cocoon.environment.SourceResolver; import org.apache.cocoon.xml.IncludeXMLConsumer; import org.xml.sax.Attributes; import org.xml.sax.SAXException; import org.xml.sax.helpers.AttributesImpl; import org.apache.cocoon.util.HashUtil; /** * This transformer triggers for the element include in the * namespace "http://apache.org/cocoon/include/1.0". * The src> attribute contains the url which points to * an xml resource which is include instead of the element. * With the attributes element, ns and * prefix it is possible to specify an element * which surrounds the included content. * * @author Carsten Ziegeler * @version CVS $Revision: 1.2 $ $Date: 2001/06/19 13:39:21 $ $Author: cziegeler $ */ public class CachingCIncludeTransformer extends AbstractTransformer implements Recyclable, Composable, Cacheable { public static final String CINCLUDE_NAMESPACE_URI = "http://apache.org/cocoon/include/1.0"; public static final String CINCLUDE_INCLUDE_ELEMENT = "include"; public static final String CINCLUDE_INCLUDE_ELEMENT_SRC_ATTRIBUTE = "src"; public static final String CINCLUDE_INCLUDE_ELEMENT_ELEMENT_ATTRIBUTE = "element"; public static final String CINCLUDE_INCLUDE_ELEMENT_NS_ATTRIBUTE = "ns"; public static final String CINCLUDE_INCLUDE_ELEMENT_PREFIX_ATTRIBUTE = "prefix"; /** The SourceResolver */ protected SourceResolver sourceResolver; /** The current ComponentManager. */ protected ComponentManager manager = null; protected EventCache eventCache; protected IncludeCacheValidity currentCacheValidity; /** * Setup the component. */ public void setup(SourceResolver resolver, Map objectModel, String source, Parameters parameters) throws ProcessingException, SAXException, IOException { this.sourceResolver = resolver; } /** * Composable Interface */ public final void compose(final ComponentManager manager) throws ComponentException { this.manager = manager; this.eventCache = (EventCache)this.manager.lookup(Roles.EVENT_CACHE); } /** * Recycle the component */ public void recycle() { super.recycle(); this.sourceResolver = null; } public void startElement(String uri, String name, String raw, Attributes attr) throws SAXException { if (uri != null && name != null && uri.equals(CINCLUDE_NAMESPACE_URI) && name.equals(CINCLUDE_INCLUDE_ELEMENT)) { this.processCIncludeElement(attr.getValue("",CINCLUDE_INCLUDE_ELEMENT_SRC_ATTRIBUTE), attr.getValue("",CINCLUDE_INCLUDE_ELEMENT_ELEMENT_ATTRIBUTE), attr.getValue("",CINCLUDE_INCLUDE_ELEMENT_NS_ATTRIBUTE), attr.getValue("",CINCLUDE_INCLUDE_ELEMENT_PREFIX_ATTRIBUTE)); } else { super.startElement(uri, name, raw, attr); } } public void endElement(String uri, String name, String raw) throws SAXException { if (uri != null && name != null && uri.equals(CINCLUDE_NAMESPACE_URI) && name.equals(CINCLUDE_INCLUDE_ELEMENT)) { return; } super.endElement(uri, name, raw); } public void endDocument() throws SAXException { super.endDocument(); currentCacheValidity.setIsNew2False(); } protected void processCIncludeElement(String src, String element, String ns, String prefix) throws SAXException { try { currentCacheValidity.add(src, sourceResolver.resolve(src).getLastModified()); } catch (Exception e) { getLogger().error("CachingCIncludeTransformer could not resolve resource", e); throw new SAXException("CachingCIncludeTransformer could not resolve resource", e); } if (element == null) element=""; if (ns == null) ns=""; if (prefix == null) prefix=""; getLogger().debug("Processing CInclude element: src=" + src + ", element=" + element + ", ns=" + ns + ", prefix=" + prefix); if (!"".equals(element)) { AttributesImpl attrs = new AttributesImpl(); if (!ns.equals("")) { super.startPrefixMapping(prefix, ns); } super.startElement(ns, element, (!ns.equals("") && !prefix.equals("") ? prefix+":"+element : element), attrs); } /* Look's more simple and should be faster, but does not work try { this.sourceResolver.resolve(src).stream(this); } catch (Exception e) { getLogger().error("CIncludeTransformer", e); throw new SAXException("CIncludeTransformer could not read resource", e); } */ Parser parser = null; try { IncludeXMLConsumer consumer = new IncludeXMLConsumer(this); parser = (Parser)this.manager.lookup(Roles.PARSER); parser.setConsumer(consumer); parser.parse(this.sourceResolver.resolve(src).getInputSource()); } catch (IOException e) { getLogger().error("CIncludeTransformer", e); throw new SAXException("CIncludeTransformer could not read resource", e); } catch (SAXException e) { getLogger().error("CIncludeTransformer", e); throw(e); } catch (Exception e){ getLogger().error("Could not get parser", e); throw new SAXException("Exception in CIncludeTransformer",e); } finally { if (parser != null) this.manager.release(parser); } if (!"".equals(element)) { super.endElement(ns, element, (!ns.equals("") && !prefix.equals("") ? prefix+":"+element : element)); if (!ns.equals("")) { super.endPrefixMapping(prefix); } } } /** * Generate the unique key. * This key must be unique inside the space of this component. * * @return The generated key hashes the src */ public long generateKey() { return 1; } /** * Generate the validity object. * * @return The generated validity object or null if the * component is currently not cacheable. */ public CacheValidity generateValidity() { try { currentCacheValidity = new IncludeCacheValidity(sourceResolver); return currentCacheValidity; } catch (Exception e) { getLogger().error("CachingCIncludeTransformer: could not generateKey", e); return null; } } } --Message-Boundary-19056 Content-type: text/plain; charset=US-ASCII Content-transfer-encoding: 7BIT Content-description: Text from file 'IncludeCacheValidity.java' package org.apache.cocoon.caching; import java.util.List; import java.util.ArrayList; import java.util.Iterator; import org.apache.cocoon.environment.SourceResolver; public final class IncludeCacheValidity implements CacheValidity { private List sources; private List timeStamps; private boolean isNew; private SourceResolver resolver; public IncludeCacheValidity(SourceResolver resolver) { this.resolver = resolver; sources = new ArrayList(); timeStamps = new ArrayList(); isNew = true; } public boolean isNew() { return isNew; } public void setIsNew2False() { isNew = false; resolver = null; } public void add(String source, long timeStamp) { this.sources.add(source); this.timeStamps.add(new Long(timeStamp)); } public boolean isValid(CacheValidity validity) { if (validity instanceof IncludeCacheValidity) { SourceResolver otherResolver = ((IncludeCacheValidity) validity).resolver; for(Iterator i = sources.iterator(), j = timeStamps.iterator(); i.hasNext();) { String src = ((String)i.next()); long timeStamp = ((Long)j.next()).longValue(); try { if( otherResolver.resolve(src).getLastModified()!= timeStamp ) return false; } catch (Exception e) { return false; } } return true; } return false; } public String toString() { StringBuffer b = new StringBuffer("IncludeCacheValidity: " ); for(Iterator i = sources.iterator(), j = timeStamps.iterator(); i.hasNext();) { b.append("["); b.append(i.next()); b.append(" - "); b.append(j.next()); b.append("]"); if(i.hasNext()) b.append(", "); } return b.toString(); } } --Message-Boundary-19056 Content-type: text/plain; charset=US-ASCII Content-transfer-encoding: 7BIT Content-description: Text from file 'x.xml' --Message-Boundary-19056 Content-type: text/plain; charset=US-ASCII Content-transfer-encoding: 7BIT Content-description: Text from file 'y.xml' --Message-Boundary-19056 Content-type: text/plain; charset=US-ASCII Content-transfer-encoding: 7BIT Content-description: Text from file 'z.xml' --Message-Boundary-19056 Content-Type: text/plain; charset=us-ascii --------------------------------------------------------------------- To unsubscribe, e-mail: cocoon-dev-unsubscribe@xml.apache.org For additional commands, email: cocoon-dev-help@xml.apache.org --Message-Boundary-19056--