antonio 2004/06/26 01:41:18
Modified: . status.xml src/java/org/apache/cocoon/generation JXTemplateGenerator.java Log: [PATCH] Caching JXTemplateGenerator Submitted by: Leszek Gawron Revision Changes Path 1.372 +4 -1 cocoon-2.1/status.xml Index: status.xml =================================================================== RCS file: /home/cvs/cocoon-2.1/status.xml,v retrieving revision 1.371 retrieving revision 1.372 diff -u -r1.371 -r1.372 --- status.xml 23 Jun 2004 19:14:34 -0000 1.371 +++ status.xml 26 Jun 2004 08:41:18 -0000 1.372 @@ -204,6 +204,9 @@ <changes> <release version="@version@" date="@date@"> + <action dev="AG" type="fix" fixes-bug="29752" due-to="Leszek Gawron"> + Apply patch: Caching JXTemplateGenerator. + </action> <action dev="VG" type="update"> ResourceReader can now take configuration elements, parameters are deprecated. 1.47 +70 -14 cocoon-2.1/src/java/org/apache/cocoon/generation/JXTemplateGenerator.java Index: JXTemplateGenerator.java =================================================================== RCS file: /home/cvs/cocoon-2.1/src/java/org/apache/cocoon/generation/JXTemplateGenerator.java,v retrieving revision 1.46 retrieving revision 1.47 diff -u -r1.46 -r1.47 --- JXTemplateGenerator.java 26 Jun 2004 07:31:18 -0000 1.46 +++ JXTemplateGenerator.java 26 Jun 2004 08:41:18 -0000 1.47 @@ -20,6 +20,7 @@ import java.io.IOException; import java.io.PrintStream; import java.io.PrintWriter; +import java.io.Serializable; import java.io.StringReader; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; @@ -43,6 +44,7 @@ import org.apache.avalon.framework.service.ServiceManager; import org.apache.avalon.framework.service.ServiceException; import org.apache.cocoon.ProcessingException; +import org.apache.cocoon.caching.CacheableProcessingComponent; import org.apache.cocoon.components.flow.FlowHelper; import org.apache.cocoon.components.flow.WebContinuation; import org.apache.cocoon.components.flow.javascript.fom.FOM_JavaScriptFlowHelper; @@ -115,7 +117,7 @@ * * @version CVS $Id$ */ -public class JXTemplateGenerator extends ServiceableGenerator { +public class JXTemplateGenerator extends ServiceableGenerator implements CacheableProcessingComponent { private static final JXPathContextFactory jxpathContextFactory = JXPathContextFactory.newInstance(); @@ -711,7 +713,8 @@ final static String PARAMETER = "parameter"; final static String FORMAT_NUMBER = "formatNumber"; final static String FORMAT_DATE = "formatDate"; - + final static String CACHE_KEY = "cache-key"; + final static String VALIDITY = "cache-validity"; /** * Compile a single Jexl expr (contained in ${}) or XPath expression @@ -1116,9 +1119,11 @@ static class StartDocument extends Event { StartDocument(Locator location) { super(location); + templateProperties = new HashMap(); } SourceValidity compileTime; EndDocument endDocument; // null if document fragment + Map templateProperties; } static class EndDocument extends Event { @@ -2182,8 +2187,18 @@ public void startElement(String namespaceURI, String localName, String qname, Attributes attrs) throws SAXException { Event newEvent = null; + AttributesImpl elementAttributes = new AttributesImpl( attrs ); + int attributeCount = elementAttributes.getLength(); + for (int i = 0; i < attributeCount; i++) { + String attributeURI = elementAttributes.getURI(i); + if (StringUtils.equals(attributeURI, NS)) { + getStartEvent().templateProperties.put(elementAttributes.getLocalName(i), + compileExpr(elementAttributes.getValue(i), null, locator)); + elementAttributes.removeAttribute(i--); + } + } StartElement startElement = new StartElement(locator, namespaceURI, - localName, qname, attrs); + localName, qname, elementAttributes); if (NS.equals(namespaceURI)) { if (localName.equals(FOR_EACH)) { String items = attrs.getValue("items"); @@ -2596,8 +2611,10 @@ "Error during resolving of '" + src + "'.", se); } final String uri = inputSource.getURI(); + boolean regenerate = false; + StartDocument startEvent = null; synchronized (cache) { - StartDocument startEvent = (StartDocument)cache.get(uri); + startEvent = (StartDocument)cache.get(uri); if (startEvent != null) { int valid = SourceValidity.UNKNOWN; if (startEvent.compileTime != null) { @@ -2609,7 +2626,19 @@ } if (valid != SourceValidity.VALID) { cache.remove(uri); + regenerate = true; } + } else { + regenerate = true; + } + } + if (regenerate) { + Parser parser = new Parser(); + SourceUtil.parse(this.manager, this.inputSource, parser); + startEvent = parser.getStartEvent(); + startEvent.compileTime = this.inputSource.getValidity(); + synchronized (cache) { + cache.put(uri, startEvent); } } } @@ -2726,15 +2755,6 @@ synchronized (cache) { startEvent = (StartDocument)cache.get(cacheKey); } - if (startEvent == null) { - Parser parser = new Parser(); - SourceUtil.parse(this.manager, this.inputSource, parser); - startEvent = parser.getStartEvent(); - startEvent.compileTime = this.inputSource.getValidity(); - synchronized (cache) { - cache.put(cacheKey, startEvent); - } - } performGeneration(this.xmlConsumer, globalJexlContext, jxpathContext, null, startEvent, null); } @@ -3693,4 +3713,40 @@ ev = ev.next; } } + /* (non-Javadoc) + * @see org.apache.cocoon.caching.CacheableProcessingComponent#getKey() + */ + public Serializable getKey() { + JXTExpression cacheKeyExpr = (JXTExpression)getCurrentTemplateProperty(CACHE_KEY); + try { + return (Serializable) getValue(cacheKeyExpr, globalJexlContext, jxpathContext); + } catch (Exception e) { + getLogger().error("error evaluating cache key", e); + return null; + } + } + + /* (non-Javadoc) + * @see org.apache.cocoon.caching.CacheableProcessingComponent#getValidity() + */ + public SourceValidity getValidity() { + JXTExpression validityExpr = (JXTExpression)getCurrentTemplateProperty(VALIDITY); + try { + return (SourceValidity) getValue(validityExpr, globalJexlContext, jxpathContext); + } catch (Exception e) { + getLogger().error( "error evaluating cache key", e ); + return null; + } + } + + private Object getCurrentTemplateProperty(String propertyName) { + final String uri = inputSource.getURI(); + StartDocument startEvent; + synchronized (cache) { + startEvent = (StartDocument)cache.get(uri); + } + if (startEvent == null) + return null; + return startEvent.templateProperties.get(propertyName); + } }