You are viewing a plain text version of this content. The canonical link for it is here.
Posted to docs@cocoon.apache.org by do...@cocoon.apache.org on 2004/07/14 01:28:49 UTC
[Cocoon Wiki] New: XfolioOpenOfficeGeneration
Date: 2004-07-13T16:28:48
Editor: GlorieuxFrédéric <fr...@ajlsm.com>
Wiki: Cocoon Wiki
Page: XfolioOpenOfficeGeneration
URL: http://wiki.apache.org/cocoon/XfolioOpenOfficeGeneration
no comment
New Page:
= Abstract =
XfolioOpenOffice generation, one more time.
The issue is discussed in more than one place (sometimes by me)
this is my last cocoon solution to have a flat oo xml file,
with _caching_ !
= Status =
It works for me, in hope this helps others.
For Cocoon 2.1.5
Could be proposed as a commit in default cocoon ?
= Usage =
See [xfolio.xmap]
{{{
<map:match pattern="**.oo">
<map:generate type="xsp" src="actions/oo.xsp">
<map:parameter name="sxw" value="{context-attr:xfolio.efolder}{1}.sxw"/>
</map:generate>
<map:serialize type="xml"/>
</map:match>
}}}
= How it works ? =
I need an OpenOffice generator, not only to provide an HTML view or some other transformation,
but also to extract metadata on vast amount of documents. I read all I can about OpenOffice generation and search for the best solution which should be
* easy
* fast
* cacheable
== Forget ==
* default src="jar:myzip!myentry.xml" seems to load the file entry in memory,
but never remember the changes (isnt'it the goal to load a class from a jar one type ?)
== Forrest ==
The best I found for now come from Forrest, using the new zip protocol from cocoon, able to resolve things like src="zip://content.xml@{folder}/test.sxw". This is a part of the trick. The problem of their solution is to use a cinclude transformer, which is not cacheable. I mean, you need to regenerate your aggregation each time it is requested. This is not a big problem in Forrest context (essentially generate a site), but on a real life server...
Their solution looks like that
{{{
<map:generate src="transform/cocoon/dummy.xml"/>
<map:transform src="transform/cocoon/sxw2oo.xsl">
<map:parameter name="src" value="{context-attr:xfolio.efolder}{1}.sxw"/>
</map:transform>
<map:transform type="cinclude"/>
<map:serialize type="xml"/>
}}}
The dummy.xml is only there because you need something to begin with pure cocoon.
The job is done by the XSL, to write something like that.
{{{
<office:document xmlns:**>
<c:include select="/*/*">
<xsl:attribute name="src">zip://meta.xml@<xsl:value-of select="$src"/></xsl:attribute>
</c:include>
<c:include select="/*/*">
<xsl:attribute name="src">zip://content.xml@<xsl:value-of select="$src"/></xsl:attribute>
</c:include>
</office:document>
}}}
Problem are
* an Xpath include is expensive (all document need to be loaded as DOM)
* Cinclude (like Xinclude) haven't seem to be cacheable for me
You may say, try a {{<map:agreggate/>}}... I tried, and produce so much problems
of validation that I stopped.
== oo.xsp ==
The attached xsp do quite the same job as the excellent Forrest solution,
with these differences
* the generator is controlled and know the files on which check changes :
the sxw, essentially (and also the xsp, for debug)
* performances
* direct pipe cost ~10 ms
* xinclude cost ~160ms
* cinclude ~320ms
* oo.xsp generator cost ~200ms on first call, but is _cached_ (~40 ms on second call)
= References =
== useful ==
* [http://cvs.apache.org/viewcvs.cgi/*checkout*/xml-forrest/src/core/context/forrest.xmap Forrest Open Office]
* [http://wiki.apache.org/cocoon/XSPCachingWithCocoonHEAD XSPCaching]
* [http://cvs.apache.org/viewcvs.cgi/*checkout*/cocoon-2.1/src/webapp/samples/xsp/xsp/Attic/cacheable.xsp]
* [http://cvs.apache.org/viewcvs.cgi/*checkout*/cocoon-2.1/src/java/org/apache/cocoon/transformation/XIncludeTransformer.java XIncludeTransformer.java]
* [http://cvs.apache.org/viewcvs.cgi/*checkout*/cocoon-2.1/src/java/org/apache/cocoon/components/source/impl/ZipSourceFactory.html ZipSourceFactory.java]
* [http://cvs.apache.org/viewcvs.cgi/*checkout*/cocoon-2.1/src/java/org/apache/cocoon/generation/FileGenerator.html ZipSourceFactory.java]
== bad examples ==
* [http://wiki.apache.org/cocoon/JarProtocolExample JarProtocolExample]
* [http://wiki.apache.org/cocoon/OpenOfficeGeneration OpenOfficeGeneration]
= Rights =
(c) 2003, 2004 xfolio.org, ajlsm.com, strabon.org
Licence : GPL [http://www.gnu.org/copyleft/gpl.html]
* created: 2003-07-10
'''FIXME: is it possible to update an attachement ?'''
= the code =
{{{
<xsp:page xmlns:xsp="http://apache.org/xsp">
<xsp:structure>
<xsp:include>org.apache.excalibur.source.Source</xsp:include>
<xsp:include>org.apache.excalibur.source.SourceException</xsp:include>
<xsp:include>org.apache.excalibur.source.SourceValidity</xsp:include>
<xsp:include>org.apache.cocoon.components.source.SourceUtil</xsp:include>
<xsp:include>org.apache.avalon.framework.parameters.ParameterException</xsp:include>
<xsp:include>org.apache.excalibur.source.impl.validity.ExpiresValidity</xsp:include>
<xsp:include>org.apache.excalibur.source.impl.validity.FileTimeStampValidity</xsp:include>
<xsp:include>org.apache.excalibur.source.impl.validity.AggregatedValidity</xsp:include>
<xsp:include>org.apache.cocoon.environment.SourceResolver</xsp:include>
<xsp:include>java.io.Serializable</xsp:include>
<xsp:include>java.util.Map</xsp:include>
<xsp:include>org.apache.avalon.framework.parameters.Parameters</xsp:include>
<xsp:include>org.apache.cocoon.xml.IncludeXMLConsumer</xsp:include>
</xsp:structure>
<xsp:logic>
// artificial slowdown to make the effects of the cache visible
final int DELAY_SECS = 2;
/** The input source */
protected Source sxwSource;
protected Source xspSource;
/**
* From org.apache.cocoon.generation.FileGenerator
*
* Setup the file generator.
* Try to get the last modification date of the source for caching.
*/
public void setup(SourceResolver resolver, Map objectModel, String src, Parameters par)
throws ProcessingException, SAXException, IOException {
super.setup(resolver, objectModel, src, par);
String sxw="";
try {
sxw = (String)parameters.getParameter("sxw");
this.sxwSource = super.resolver.resolveURI(sxw);
} catch (SourceException se) {
throw SourceUtil.handle("oo.xsp, failed resolution sxw='" + sxw +"'.", se );
} catch (ParameterException pe) {
throw new ProcessingException ("oo.xsp, sxw param not found" , pe);
}
try {
this.xspSource = super.resolver.resolveURI(src);
} catch (SourceException se) {
throw SourceUtil.handle("oo.xsp, failed resolution xsp='" + src + "'.", se);
}
}
/**
* Recycle this component.
* All instance variables are set to <code>null</code>.
*/
public void recycle() {
if (null != this.sxwSource) {
super.resolver.release(this.sxwSource);
this.sxwSource = null;
}
if (this.xspSource != null) {
super.resolver.release(this.xspSource);
this.xspSource = null;
}
super.recycle();
}
/**
* Generate the unique key for the cache.
*
* This key must be unique inside the space of this XSP page, it is used
* to find the page contents in the cache (if getValidity says that the
* contents are still valid).
*
* This method will be invoked before the getValidity() method.
*
* @return The generated key or null if the component
* is currently not cacheable.
*/
public java.io.Serializable getKey() {
String key=(this.sxwSource != null)?this.sxwSource.getURI():null;
return key;
}
/**
* Generate the validity object, tells the cache how long to
* keep contents having this key around.
*
* Before this method can be invoked the getKey() method
* will be invoked.
*
* In our case, validity combine the xsp file and the sxw file.
*
* @return The generated validity object or null if the
* component is currently not cacheable.
*/
public SourceValidity getValidity() {
AggregatedValidity out=new AggregatedValidity();
if (this.sxwSource != null) out.add(this.sxwSource.getValidity());
if (this.xspSource != null) out.add(this.xspSource.getValidity());
return out;
}
</xsp:logic>
<office:document xmlns:office="http://openoffice.org/2000/office" xmlns:style="http://openoffice.org/2000/style" xmlns:text="http://openoffice.org/2000/text" xmlns:table="http://openoffice.org/2000/table" xmlns:draw="http://openoffice.org/2000/drawing" xmlns:fo="http://www.w3.org/1999/XSL/Format" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:meta="http://openoffice.org/2000/meta" xmlns:number="http://openoffice.org/2000/datastyle" xmlns:svg="http://www.w3.org/2000/svg" xmlns:chart="http://openoffice.org/2000/chart" xmlns:dr3d="http://openoffice.org/2000/dr3d" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:form="http://openoffice.org/2000/form" xmlns:script="http://openoffice.org/2000/script" xmlns:config="http://openoffice.org/2001/config" office:class="text" office:version="1.0">
<xsp:logic>
<![CDATA[
/*
This debug commodity makes you sure that something is cached
(DELAY_SECS if create, less if cached)
// slowdown page generation.
try {
Thread.sleep(DELAY_SECS * 1000L);
} catch (InterruptedException ie) {
// Not much that can be done...
}
*/
// from org.apache.cocoon.transformation.XIncludeTransformer
SourceUtil.toSAX(super.resolver.resolveURI("zip://meta.xml@"+this.sxwSource.getURI()), new IncludeXMLConsumer(this.contentHandler));
SourceUtil.toSAX(super.resolver.resolveURI("zip://content.xml@"+this.sxwSource.getURI()), new IncludeXMLConsumer(this.contentHandler));
/*
an xpointer may be nicer (to conform to ooxmlflat), but much more
expensive, because it needs a complete DOM in memory
*/
]]>
</xsp:logic>
</office:document>
</xsp:page>
}}}