vgritsenko 2002/06/16 15:45:50
Modified: . Tag: cocoon_2_0_3_branch changes.xml
src/java/org/apache/cocoon/components/xslt Tag:
cocoon_2_0_3_branch XSLTProcessor.java
XSLTProcessorImpl.java
src/java/org/apache/cocoon/transformation Tag:
cocoon_2_0_3_branch TraxTransformer.java
Log:
fix bug 3782
Revision Changes Path
No revision
No revision
1.138.2.21 +5 -1 xml-cocoon2/changes.xml
Index: changes.xml
===================================================================
RCS file: /home/cvs/xml-cocoon2/changes.xml,v
retrieving revision 1.138.2.20
retrieving revision 1.138.2.21
diff -u -r1.138.2.20 -r1.138.2.21
--- changes.xml 14 Jun 2002 16:29:22 -0000 1.138.2.20
+++ changes.xml 16 Jun 2002 22:45:49 -0000 1.138.2.21
@@ -39,6 +39,10 @@
<release version="@version@" date="@date@">
+ <action dev="VG" type="fix" fixes-bug="3782">
+ TraxTransformer and XSLTProcessor components now correctly handle
+ dependecies on imported (via xsl:include) XSLT stylesheets.
+ </action>
<action dev="NKB" type="fix">
Removed Java 1.3+ only method (URL.getPath()) from LinkStatusGenerator.
</action>
No revision
No revision
1.6.2.1 +19 -3
xml-cocoon2/src/java/org/apache/cocoon/components/xslt/XSLTProcessor.java
Index: XSLTProcessor.java
===================================================================
RCS file:
/home/cvs/xml-cocoon2/src/java/org/apache/cocoon/components/xslt/XSLTProcessor.java,v
retrieving revision 1.6
retrieving revision 1.6.2.1
diff -u -r1.6 -r1.6.2.1
--- XSLTProcessor.java 22 Feb 2002 07:00:15 -0000 1.6
+++ XSLTProcessor.java 16 Jun 2002 22:45:49 -0000 1.6.2.1
@@ -53,6 +53,7 @@
import org.apache.avalon.framework.component.Component;
import org.apache.avalon.framework.parameters.Parameters;
import org.apache.cocoon.ProcessingException;
+import org.apache.cocoon.caching.CacheValidity;
import org.apache.cocoon.environment.Source;
import org.apache.cocoon.environment.SourceResolver;
import org.xml.sax.XMLFilter;
@@ -64,6 +65,7 @@
* This is the interface of the XSLT processor in Cocoon.
*
* @author <a href="mailto:[EMAIL PROTECTED]">Ovidiu Predescu</a>
+ * @author <a href="mailto:[EMAIL PROTECTED]">Vadim Gritsenko</a>
* @version CVS $Id$
* @version 1.0
* @since July 11, 2001
@@ -84,6 +86,19 @@
*/
void setSourceResolver(SourceResolver resolver);
+ /**
+ * <p>Return a <code>CacheValidity</code> for a given
+ * stylesheet <code>Source</code>. This can be used in a pipeline to
+ * handle caching of a transformation results.
+ *
+ * <p>This method accesses cache of the Templates objects to obtain list
+ * of included stylesheets, which is built when stylesheet is created.
+ *
+ * @param stylesheet a <code>Source</code> value
+ * @return a <code>CacheValidity</code> value
+ */
+ CacheValidity getTransformerValidity(Source stylesheet);
+
/**
* <p>Return a <code>TransformerHandler</code> for a given
* stylesheet <code>Source</code>. This can be used in a pipeline to
@@ -95,8 +110,9 @@
* <code>null</code>, is inserted in the chain SAX events as an XML
* filter during the parsing or the source document.
*
- * <p>This method caches the Source object and performs a reparsing
- * only if this changes.
+ * <p>This method caches the Templates object with meta information
(modification
+ * time and list of included stylesheets) and performs a reparsing only if
this
+ * changes.
*
* @param stylesheet a <code>Source</code> value
* @param filter a <code>XMLFilter</code> value
1.18.2.1 +131 -84
xml-cocoon2/src/java/org/apache/cocoon/components/xslt/XSLTProcessorImpl.java
Index: XSLTProcessorImpl.java
===================================================================
RCS file:
/home/cvs/xml-cocoon2/src/java/org/apache/cocoon/components/xslt/XSLTProcessorImpl.java,v
retrieving revision 1.18
retrieving revision 1.18.2.1
diff -u -r1.18 -r1.18.2.1
--- XSLTProcessorImpl.java 6 Apr 2002 02:37:29 -0000 1.18
+++ XSLTProcessorImpl.java 16 Jun 2002 22:45:49 -0000 1.18.2.1
@@ -51,7 +51,6 @@
package org.apache.cocoon.components.xslt;
import org.apache.avalon.framework.activity.Disposable;
-import org.apache.avalon.framework.component.Component;
import org.apache.avalon.framework.component.ComponentException;
import org.apache.avalon.framework.component.ComponentManager;
import org.apache.avalon.framework.component.Composable;
@@ -62,6 +61,9 @@
import org.apache.cocoon.ResourceNotFoundException;
import org.apache.cocoon.ProcessingException;
+import org.apache.cocoon.caching.CacheValidity;
+import org.apache.cocoon.caching.TimeStampCacheValidity;
+import org.apache.cocoon.caching.AggregatedCacheValidity;
import org.apache.cocoon.components.store.Store;
import org.apache.cocoon.environment.Source;
import org.apache.cocoon.environment.SourceResolver;
@@ -69,10 +71,8 @@
import org.apache.cocoon.util.TraxErrorHandler;
import org.xml.sax.InputSource;
import org.xml.sax.XMLFilter;
-import org.xml.sax.XMLReader;
import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;
-import org.xml.sax.helpers.XMLReaderFactory;
import javax.xml.transform.URIResolver;
import javax.xml.transform.TransformerException;
@@ -80,17 +80,14 @@
import javax.xml.transform.Templates;
import javax.xml.transform.Result;
import javax.xml.transform.Transformer;
-import javax.xml.transform.sax.SAXSource;
import javax.xml.transform.sax.SAXTransformerFactory;
import javax.xml.transform.sax.TemplatesHandler;
import javax.xml.transform.sax.TransformerHandler;
-import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
import java.io.File;
-import java.io.InputStream;
import java.io.IOException;
-import java.io.StringWriter;
-import java.io.Writer;
+import java.util.List;
+import java.util.ArrayList;
/**
* This class defines the implementation of the [EMAIL PROTECTED]
XSLTProcessor}
@@ -146,15 +143,19 @@
/** Is incremental processing turned on? (default for Xalan: no) */
protected boolean incrementalProcessing = false;
+ /** Resolver used to resolve XSL includes */
protected SourceResolver resolver;
+ /** List accumulating included stylesheets */
+ protected List includes;
+
/**
* Compose. Try to get the store
*/
public void compose(ComponentManager manager)
throws ComponentException {
this.manager = manager;
- this.getLogger().debug("XSLTProcessorImpl component initialized.");
+ getLogger().debug("XSLTProcessorImpl component initialized.");
this.store = (Store)manager.lookup(Store.TRANSIENT_CACHE);
}
@@ -199,6 +200,38 @@
}
}
+ public CacheValidity getTransformerValidity(Source stylesheet)
+ {
+ // No lastModified - no validity
+ if (stylesheet.getLastModified() == 0) {
+ return null;
+ }
+
+ // No store - fallback to previous implementation
+ if (!useStore) {
+ return new TimeStampCacheValidity(stylesheet.getLastModified());
+ }
+
+ // Get data from cache
+ String id = stylesheet.getSystemId();
+ Object[] templateAndTimeAndIncludes = (Object[])store.get(id);
+ if (templateAndTimeAndIncludes != null &&
templateAndTimeAndIncludes[2] != null) {
+ // Create aggregated validity
+ List includes = (List)templateAndTimeAndIncludes[2];
+ AggregatedCacheValidity validity = new AggregatedCacheValidity();
+ validity.add(new
TimeStampCacheValidity(stylesheet.getLastModified()));
+ for (int i = includes.size() - 1; i >= 0; i--) {
+ Object[] pair = (Object[])includes.get(i);
+ long time = ((Long)pair[1]).longValue();
+ validity.add(new TimeStampCacheValidity(time));
+ }
+ return validity;
+ } else {
+ // No data - fallback to previous implementation
+ return new TimeStampCacheValidity(stylesheet.getLastModified());
+ }
+ }
+
public TransformerHandler getTransformerHandler(Source stylesheet)
throws ProcessingException {
return getTransformerHandler(stylesheet, null);
@@ -211,25 +244,25 @@
final String id = stylesheet.getSystemId();
Templates templates = getTemplates(stylesheet, id);
if (templates == null) {
- if (this.getLogger().isDebugEnabled()) {
+ if (getLogger().isDebugEnabled()) {
getLogger().debug("Creating new Templates for " + id);
}
-
// Create a Templates ContentHandler to handle parsing of the
// stylesheet.
TemplatesHandler templatesHandler
- = getTransformerFactory().newTemplatesHandler();
+ = getTransformerFactory().newTemplatesHandler();
if (filter != null) {
filter.setContentHandler(templatesHandler);
}
- if (this.getLogger().isDebugEnabled()) {
+ if (getLogger().isDebugEnabled()) {
getLogger().debug("Source = " + stylesheet
- + ", templatesHandler = " + templatesHandler);
+ + ", templatesHandler = " + templatesHandler);
}
// Process the stylesheet.
+ includes = new ArrayList();
stylesheet.toSAX(filter != null ?
(ContentHandler)filter :
(ContentHandler)templatesHandler);
@@ -237,31 +270,14 @@
// the stylesheet) from the TemplatesHandler.
templates = templatesHandler.getTemplates();
putTemplates (templates, stylesheet, id);
+ includes = null;
} else {
- if (this.getLogger().isDebugEnabled()) {
+ if (getLogger().isDebugEnabled()) {
getLogger().debug("Reusing Templates for " + id);
}
}
TransformerHandler handler =
getTransformerFactory().newTransformerHandler(templates);
-
- /* (VG)
- From
http://java.sun.com/j2se/1.4/docs/api/javax/xml/transform/TransformerFactory.html#newTemplates(javax.xml.transform.Source)
- Or
http://xml.apache.org/xalan-j/apidocs/javax/xml/transform/TransformerFactory.html#newTemplates(javax.xml.transform.Source)
-
- "Returns: Templates object capable of being used for
transformation
- purposes, never null."
- if (handler == null) {
- if (this.getLogger().isDebugEnabled()) {
- getLogger().debug("Re-creating new Templates for " + id);
- }
-
- templates = getTransformerFactory().newTemplates(new
SAXSource(stylesheet.getInputSource()));
- putTemplates (templates, stylesheet, id);
- handler =
getTransformerFactory().newTransformerHandler(templates);
- }
- */
-
handler.getTransformer().setErrorListener(new
TraxErrorHandler(getLogger()));
return handler;
} catch (ProcessingException e) {
@@ -284,40 +300,42 @@
Result result)
throws ProcessingException {
try {
- if (this.getLogger().isDebugEnabled()) {
+ if (getLogger().isDebugEnabled()) {
getLogger().debug("XSLTProcessorImpl: transform source = " +
source
+ ", stylesheet = " + stylesheet
+ ", parameters = " + params
+ ", result = " + result);
}
TransformerHandler handler = getTransformerHandler(stylesheet);
- Transformer transformer = handler.getTransformer();
-
if (params != null) {
+ Transformer transformer = handler.getTransformer();
transformer.clearParameters();
String[] names = params.getNames();
for (int i = names.length -1 ; i >= 0; i--) {
transformer.setParameter(names[i],
params.getParameter(names[i]));
}
}
- InputSource is = source.getInputSource();
- InputStream bs = is.getByteStream();
- this.getLogger().debug("XSLTProcessorImpl: starting transform");
- // FIXME (VG): Is it possible to use Source's toSAX method?
- try {
- transformer.transform(new StreamSource(bs,
is.getSystemId()), result);
- } finally {
- bs.close();
- }
- this.getLogger().debug("XSLTProcessorImpl: transform done");
- } catch (Exception e) {
+
+ handler.setResult(result);
+ source.toSAX(handler);
+ getLogger().debug("XSLTProcessorImpl: transform done");
+ } catch (ProcessingException e) {
+ throw e;
+ } catch (ParameterException e) {
throw new ProcessingException("Error in running Transformation",
e);
+ } catch (SAXException e) {
+ if (e.getException() == null) {
+ throw new ProcessingException("Error in running
Transformation", e);
+ } else {
+ getLogger().debug("Got SAXException. Rethrowing cause
exception.", e);
+ throw new ProcessingException("Error in running
Transformation", e.getException());
+ }
}
}
/**
- * Helper for TransformerFactory.
- */
+ * Helper for TransformerFactory.
+ */
private SAXTransformerFactory getTransformerFactory() throws Exception {
if(tfactory == null) {
if (tfactoryClass == null) {
@@ -339,49 +357,78 @@
}
private Templates getTemplates(Source stylesheet, String id)
- throws IOException, ProcessingException {
- if (!useStore)
+ throws ProcessingException, IOException, SAXException {
+ if (!useStore) {
return null;
+ }
- getLogger().debug("XSLTProcessorImpl getTemplates: stylesheet " +
id);
+ if (getLogger().isDebugEnabled()) {
+ getLogger().debug("XSLTProcessorImpl getTemplates: stylesheet "
+ id);
+ }
- Templates templates = null;
- // only stylesheets with a last modification date are stored
- if (stylesheet.getLastModified() != 0) {
- // Stored is an array of the template and the caching time
- if (store.containsKey(id)) {
- Object[] templateAndTime = (Object[])store.get(id);
+ // Only stylesheets with a last modification date are stored
+ if (stylesheet.getLastModified() == 0) {
+ // Remove an old template
+ store.remove(id);
+ return null;
+ }
- if(templateAndTime != null && templateAndTime[1] != null) {
- long storedTime = ((Long)templateAndTime[1]).longValue();
+ // Stored is an array of the templates and the caching time and list
of includes
+ Object[] templateAndTimeAndIncludes = (Object[])store.get(id);
+ if (templateAndTimeAndIncludes == null) {
+ // Templates not found in cache
+ return null;
+ }
- if (storedTime < stylesheet.getLastModified()) {
- store.remove(id);
- } else {
- templates = (Templates)templateAndTime[0];
- }
+ // Check template modification time
+ long storedTime = ((Long)templateAndTimeAndIncludes[1]).longValue();
+ if (storedTime != stylesheet.getLastModified()) {
+ store.remove(id);
+ return null;
+ }
+
+ // Check includes
+ List includes = (List)templateAndTimeAndIncludes[2];
+ if (includes != null) {
+ for (int i = includes.size() - 1; i >= 0; i--) {
+ // Every include stored as pair of source ID and timestamp
+ Object[] pair = (Object[])includes.get(i);
+ Source included = resolver.resolve((String)pair[0]);
+ if (included.getLastModified() !=
((Long)pair[1]).longValue()) {
+ store.remove(id);
+ return null;
}
}
- } else if (store.containsKey(id)) {
- // remove an old template if it exists
- store.remove(id);
}
- return templates;
+
+ // Templates were not modified, return from cache
+ return (Templates)templateAndTimeAndIncludes[0];
}
private void putTemplates (Templates templates, Source stylesheet,
String id)
- throws IOException, ProcessingException {
- if (!useStore)
+ throws IOException {
+ if (!useStore) {
return;
+ }
- // only stylesheets with a last modification date are stored
+ // Only stylesheets with a last modification date are stored
if (stylesheet.getLastModified() != 0) {
+ // Check that included stylesheets are cacheable
+ for (int i = includes.size() - 1; i >= 0; i--) {
+ Object[] pair = (Object[])includes.get(i);
+ if (((Long)pair[1]).longValue() == 0) {
+ return;
+ }
+ }
// Stored is an array of the template and the current time
- Object[] templateAndTime = new Object[2];
- templateAndTime[0] = templates;
- templateAndTime[1] = new Long(stylesheet.getLastModified());
- store.hold(id, templateAndTime);
+ Object[] templateAndTimeAndIncludes = new Object[3];
+ templateAndTimeAndIncludes[0] = templates;
+ templateAndTimeAndIncludes[1] = new
Long(stylesheet.getLastModified());
+ if (includes.size() > 0) {
+ templateAndTimeAndIncludes[2] = includes;
+ }
+ store.hold(id, templateAndTimeAndIncludes);
}
}
@@ -401,9 +448,9 @@
*/
public javax.xml.transform.Source resolve(String href, String base)
throws TransformerException {
- if (this.getLogger().isDebugEnabled()) {
- this.getLogger().debug("resolve(href = " + href +
- ", base = " + base + "); resolver = " +
resolver);
+ if (getLogger().isDebugEnabled()) {
+ getLogger().debug("resolve(href = " + href +
+ ", base = " + base + "); resolver = " +
resolver);
}
Source xslSource = null;
@@ -433,14 +480,14 @@
}
}
- InputSource is = xslSource.getInputSource();
- if (this.getLogger().isDebugEnabled()) {
+ if (getLogger().isDebugEnabled()) {
getLogger().debug("xslSource = " + xslSource
- + ", system id = " + is.getSystemId());
+ + ", system id = " + xslSource.getSystemId());
}
+ InputSource is = xslSource.getInputSource();
+ includes.add(new Object[]{xslSource.getSystemId(), new
Long(xslSource.getLastModified())});
return new StreamSource(is.getByteStream(), is.getSystemId());
-
} catch (ResourceNotFoundException rnfe) {
// to obtain the same behaviour as when the resource is
// transformed by the XSLT Transformer we should return null
here.
No revision
No revision
1.21.2.2 +9 -15
xml-cocoon2/src/java/org/apache/cocoon/transformation/TraxTransformer.java
Index: TraxTransformer.java
===================================================================
RCS file:
/home/cvs/xml-cocoon2/src/java/org/apache/cocoon/transformation/TraxTransformer.java,v
retrieving revision 1.21.2.1
retrieving revision 1.21.2.2
diff -u -r1.21.2.1 -r1.21.2.2
--- TraxTransformer.java 20 Apr 2002 00:04:16 -0000 1.21.2.1
+++ TraxTransformer.java 16 Jun 2002 22:45:49 -0000 1.21.2.2
@@ -63,7 +63,6 @@
import org.apache.cocoon.ProcessingException;
import org.apache.cocoon.caching.CacheValidity;
import org.apache.cocoon.caching.Cacheable;
-import org.apache.cocoon.caching.TimeStampCacheValidity;
import org.apache.cocoon.components.browser.Browser;
import org.apache.cocoon.components.xslt.XSLTProcessor;
import org.apache.cocoon.components.deli.Deli;
@@ -80,8 +79,11 @@
import javax.xml.transform.sax.SAXResult;
import javax.xml.transform.sax.TransformerHandler;
import java.io.IOException;
-import java.text.StringCharacterIterator;
-import java.util.*;
+import java.util.Map;
+import java.util.HashMap;
+import java.util.Set;
+import java.util.Iterator;
+import java.util.Enumeration;
/**
* This Transformer is used to transform this incomming SAX stream using
@@ -160,8 +162,6 @@
public class TraxTransformer extends AbstractTransformer
implements Transformer, Composable, Configurable, Cacheable, Disposable {
- private static final String FILE = "file:";
-
/** The Browser service instance */
private Browser browser = null;
@@ -311,10 +311,8 @@
return HashUtil.hash(this.inputSource.getSystemId());
}
- StringBuffer sb = new StringBuffer();
- sb.append(this.inputSource.getSystemId());
- Set entries = map.entrySet();
- for(Iterator i=entries.iterator(); i.hasNext();){
+ StringBuffer sb = new
StringBuffer(this.inputSource.getSystemId());
+ for(Iterator i = map.entrySet().iterator(); i.hasNext();){
sb.append(';');
Map.Entry entry = (Map.Entry)i.next();
sb.append(entry.getKey());
@@ -339,17 +337,13 @@
* (if parameter added/removed or value changed, key should
* change also), only stylesheet's modified time is included.
*/
- if (this.inputSource.getLastModified() != 0) {
- return new
TimeStampCacheValidity(this.inputSource.getLastModified());
- }
- return null;
+ return xsltProcessor.getTransformerValidity(this.inputSource);
}
/**
* Set the <code>XMLConsumer</code> that will receive XML data.
*/
public void setConsumer(XMLConsumer consumer) {
-
HashMap map = getLogicSheetParameters();
if (map != null) {
Iterator iterator = map.keySet().iterator();
----------------------------------------------------------------------
In case of troubles, e-mail: [EMAIL PROTECTED]
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]