You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@xalan.apache.org by cu...@apache.org on 2001/05/22 21:44:04 UTC
cvs commit: xml-xalan/test/java/src/org/apache/qetest/xslwrapper TraxStreamWrapper.java
curcuru 01/05/22 12:44:01
Added: test/java/src/org/apache/qetest/xslwrapper
TraxStreamWrapper.java
Log:
TransformWrapper that uses in-memory byte streams instead of files/URIs
Revision Changes Path
1.1 xml-xalan/test/java/src/org/apache/qetest/xslwrapper/TraxStreamWrapper.java
Index: TraxStreamWrapper.java
===================================================================
/*
* The Apache Software License, Version 1.1
*
*
* Copyright (c) 2001 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution,
* if any, must include the following acknowledgment:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowledgment may appear in the software itself,
* if and wherever such third-party acknowledgments normally appear.
*
* 4. The names "Xalan" and "Apache Software Foundation" must
* not be used to endorse or promote products derived from this
* software without prior written permission. For written
* permission, please contact apache@apache.org.
*
* 5. Products derived from this software may not be called "Apache",
* nor may "Apache" appear in their name, without prior written
* permission of the Apache Software Foundation.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation and was
* originally based on software copyright (c) 1999, Lotus
* Development Corporation., http://www.lotus.com. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*/
package org.apache.qetest.xslwrapper;
import org.apache.qetest.QetestUtils;
import javax.xml.transform.Templates;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.Source;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.Hashtable;
import java.util.Properties;
/**
* Implementation of TransformWrapper that uses the TrAX API and
* uses in-memory streams for it's sources.
*
* <p>This implementation separates the process of reading xml and xsl
* files from disk into byte arrays out from the time processing of
* a new StreamSource(byte[]) takes to build a stylesheet.
* It also separates the time of performing the transformation
* to a StreamResult(byte[]) from the time spent simply sending
* the byte[] through a FileOutputStream to disk.</p>
*
* <p><b>Important!</b> The underlying System property of
* javax.xml.transform.TransformerFactory will determine the actual
* TrAX implementation used. This value will be reported out in
* our getProcessorInfo() method.</p>
*
* <p>//@todo: currently limited to reading in files whose length
* will fit into an int value. The actual file reading routine
* should be updated in several of our methods.</p>
*
* @author Shane Curcuru
* @version $Id: TraxStreamWrapper.java,v 1.1 2001/05/22 19:43:58 curcuru Exp $
*/
public class TraxStreamWrapper extends TransformWrapperHelper
{
/**
* TransformerFactory to use; constructed in newProcessor().
*/
protected TransformerFactory factory = null;
/**
* Templates to use for buildStylesheet().
*/
protected Templates builtTemplates = null;
/**
* Cached copy of newProcessor() Hashtable.
*/
protected Hashtable newProcessorOpts = null;
/**
* Get a general description of this wrapper itself.
*
* @return Uses TrAX to perform transforms from StreamSource(systemId)
*/
public String getDescription()
{
return "Uses TrAX to perform transforms from StreamSource(stream)";
}
/**
* Get a specific description of the wrappered processor.
*
* @return specific description of the underlying processor or
* transformer implementation: this should include both the
* general product name, as well as specific version info. If
* possible, should be implemented without actively creating
* an underlying processor.
*/
public Properties getProcessorInfo()
{
Properties p = TraxWrapperUtils.getTraxInfo();
p.put("traxwrapper.method", "streams");
p.put("traxwrapper.desc", getDescription());
return p;
}
/**
* Actually create/initialize an underlying processor or factory.
*
* For TrAX/javax.xml.transform implementations, this creates
* a new TransformerFactory.
*
* @param options Hashtable of options, unused.
*
* @return (Object)getProcessor() as a side-effect, this will
* be null if there was any problem creating the processor OR
* if the underlying implementation doesn't use this
*
* @throws Exception covers any underlying exceptions thrown
* by the actual implementation
*/
public Object newProcessor(Hashtable options) throws Exception
{
newProcessorOpts = options;
//@todo do we need to do any other cleanup?
reset(false);
factory = TransformerFactory.newInstance();
return (Object)factory;
}
/**
* Transform supplied xmlName file with the stylesheet in the
* xslName file into a resultName file.
*
* Names are assumed to be local path\filename references, and
* will be read as byte streams before being passed to
* underlying StreamSources, etc.
*
* @param xmlName local path\filename of XML file to transform
* @param xslName local path\filename of XSL stylesheet to use
* @param resultName local path\filename to put result in
*
* @return array of longs denoting timing of all parts of
* our operation: IDX_OVERALL, IDX_XSLREAD, IDX_XSLBUILD,
* IDX_XMLREAD, IDX_TRANSFORM, IDX_RESULTWRITE
*
* @throws Exception any underlying exceptions from the
* wrappered processor are simply allowed to propagate; throws
* a RuntimeException if any other problems prevent us from
* actually completing the operation
*/
public long[] transform(String xmlName, String xslName, String resultName)
throws Exception
{
preventFootShooting();
long startTime = 0;
long xslRead = 0;
long xslBuild = 0;
long xmlRead = 0;
long transform = 0;
long resultWrite = 0;
File xslFile = new File(xslName);
int xslLength = new Long(xslFile.length()).intValue(); //@todo warning: possible overflow
byte[] xslBytes = new byte[xslLength];
FileInputStream xslStream = new FileInputStream(xslFile);
// Timed: read xsl into a byte array
startTime = System.currentTimeMillis();
int xslRetVal = xslStream.read(xslBytes);
xslRead = System.currentTimeMillis() - startTime;
// Untimed: create StreamSource and setSystemId
StreamSource xslSource = new StreamSource(new ByteArrayInputStream(xslBytes));
// Note that systemIds must be a legal URI
xslSource.setSystemId(QetestUtils.filenameToURL(xslName));
// Timed: build Transformer from StreamSource
startTime = System.currentTimeMillis();
Transformer transformer = factory.newTransformer(xslSource);
xslBuild = System.currentTimeMillis() - startTime;
File xmlFile = new File(xmlName);
int xmlLength = new Long(xmlFile.length()).intValue(); //@todo warning: possible overflow
byte[] xmlBytes = new byte[xmlLength];
FileInputStream xmlStream = new FileInputStream(xmlFile);
// Timed: read xml into a byte array
startTime = System.currentTimeMillis();
int xmlRetVal = xmlStream.read(xmlBytes);
xmlRead = System.currentTimeMillis() - startTime;
// Untimed: create StreamSource and setSystemId
StreamSource xmlSource = new StreamSource(new ByteArrayInputStream(xmlBytes));
xmlSource.setSystemId(QetestUtils.filenameToURL(xmlName));
// Untimed: create StreamResult
ByteArrayOutputStream outBytes = new ByteArrayOutputStream();
StreamResult byteResult = new StreamResult(outBytes);
// Untimed: Apply any parameters needed
applyParameters(transformer);
// Timed: build xml (so to speak) and transform
startTime = System.currentTimeMillis();
transformer.transform(xmlSource, byteResult);
transform = System.currentTimeMillis() - startTime;
// Timed: writeResults from the byte array
startTime = System.currentTimeMillis();
byte[] writeBytes = outBytes.toByteArray(); // Should this be timed too or not?
FileOutputStream writeStream = new FileOutputStream(resultName);
writeStream.write(writeBytes);
writeStream.close();
resultWrite = System.currentTimeMillis() - startTime;
long[] times = getTimeArray();
times[IDX_OVERALL] = xslRead + xslBuild + xmlRead
+ transform + resultWrite;
times[IDX_XSLREAD] = xslRead;
times[IDX_XSLBUILD] = xslBuild;
times[IDX_XMLREAD] = xmlRead;
times[IDX_TRANSFORM] = transform;
times[IDX_RESULTWRITE] = resultWrite;
return times;
}
/**
* Pre-build/pre-compile a stylesheet.
*
* Although the actual mechanics are implementation-dependent,
* most processors have some method of pre-setting up the data
* needed by the stylesheet itself for later use in transforms.
* In TrAX/javax.xml.transform, this equates to creating a
* Templates object.
*
* Sets isStylesheetReady() to true if it succeeds. Users can
* then call transformWithStylesheet(xmlName, resultName) to
* actually perform a transformation with this pre-built
* stylesheet.
*
* @param xslName local path\filename of XSL stylesheet to use
*
* @return array of longs denoting timing of all parts of
* our operation: IDX_OVERALL, IDX_XSLREAD, IDX_XSLBUILD
*
* @throws Exception any underlying exceptions from the
* wrappered processor are simply allowed to propagate; throws
* a RuntimeException if any other problems prevent us from
* actually completing the operation
*
* @see #transformWithStylesheet(String xmlName, String resultName)
*/
public long[] buildStylesheet(String xslName) throws Exception
{
preventFootShooting();
long startTime = 0;
long xslRead = 0;
long xslBuild = 0;
File xslFile = new File(xslName);
int xslLength = new Long(xslFile.length()).intValue(); //@todo warning: possible overflow
byte[] xslBytes = new byte[xslLength];
FileInputStream xslStream = new FileInputStream(xslFile);
// Timed: read xsl into a byte array
startTime = System.currentTimeMillis();
int xslRetVal = xslStream.read(xslBytes);
xslRead = System.currentTimeMillis() - startTime;
// Untimed: create StreamSource and setSystemId
StreamSource xslSource = new StreamSource(new ByteArrayInputStream(xslBytes));
// Note that systemIds must be a legal URI
xslSource.setSystemId(QetestUtils.filenameToURL(xslName));
// Timed: build Transformer from StreamSource
startTime = System.currentTimeMillis();
builtTemplates = factory.newTemplates(xslSource);
xslBuild = System.currentTimeMillis() - startTime;
// Set internal state that we have a templates ready
// Note: in theory, there's no need to check builtTemplates
// since the newTemplates should never return null
// (it might have thrown an exception, but we don't care)
m_stylesheetReady = true;
long[] times = getTimeArray();
times[IDX_OVERALL] = xslBuild + xslRead;
times[IDX_XSLREAD] = xslRead;
times[IDX_XSLBUILD] = xslBuild;
return times;
}
/**
* Transform supplied xmlName file with a pre-built/pre-compiled
* stylesheet into a resultName file.
*
* User must have called buildStylesheet(xslName) beforehand,
* obviously.
* Names are assumed to be local path\filename references, and
* will be converted to URLs as needed.
*
* @param xmlName local path\filename of XML file to transform
* @param resultName local path\filename to put result in
*
* @return array of longs denoting timing of all parts of
* our operation: IDX_OVERALL,
* IDX_XMLREAD, IDX_TRANSFORM, IDX_RESULTWRITE
*
* @throws Exception any underlying exceptions from the
* wrappered processor are simply allowed to propagate; throws
* a RuntimeException if any other problems prevent us from
* actually completing the operation; throws an
* IllegalStateException if isStylesheetReady() == false.
*
* @see #buildStylesheet(String xslName)
*/
public long[] transformWithStylesheet(String xmlName, String resultName)
throws Exception
{
if (!isStylesheetReady())
throw new IllegalStateException("transformWithStylesheet() when isStylesheetReady() == false");
preventFootShooting();
long startTime = 0;
long xslRead = 0;
long xslBuild = 0;
long xmlRead = 0;
long transform = 0;
long resultWrite = 0;
// UNTimed: get Transformer from Templates
Transformer transformer = builtTemplates.newTransformer();
File xmlFile = new File(xmlName);
int xmlLength = new Long(xmlFile.length()).intValue(); //@todo warning: possible overflow
byte[] xmlBytes = new byte[xmlLength];
FileInputStream xmlStream = new FileInputStream(xmlFile);
// Timed: read xml into a byte array
startTime = System.currentTimeMillis();
int xmlRetVal = xmlStream.read(xmlBytes);
xmlRead = System.currentTimeMillis() - startTime;
// Untimed: create StreamSource and setSystemId
StreamSource xmlSource = new StreamSource(new ByteArrayInputStream(xmlBytes));
xmlSource.setSystemId(QetestUtils.filenameToURL(xmlName));
// Untimed: create StreamResult
ByteArrayOutputStream outBytes = new ByteArrayOutputStream();
StreamResult byteResult = new StreamResult(outBytes);
// Untimed: Apply any parameters needed
applyParameters(transformer);
// Timed: build xml (so to speak) and transform
startTime = System.currentTimeMillis();
transformer.transform(xmlSource, byteResult);
transform = System.currentTimeMillis() - startTime;
// Timed: writeResults from the byte array
startTime = System.currentTimeMillis();
byte[] writeBytes = outBytes.toByteArray(); // Should this be timed too or not?
FileOutputStream writeStream = new FileOutputStream(resultName);
writeStream.write(writeBytes);
writeStream.close();
resultWrite = System.currentTimeMillis() - startTime;
long[] times = getTimeArray();
times[IDX_OVERALL] = xmlRead + transform + resultWrite;
times[IDX_XMLREAD] = xmlRead;
times[IDX_TRANSFORM] = transform;
times[IDX_RESULTWRITE] = resultWrite;
return times;
}
/**
* Transform supplied xmlName file with a stylesheet found in an
* xml-stylesheet PI into a resultName file.
*
* Names are assumed to be local path\filename references, and
* will be converted to URLs as needed. Implementations will
* use whatever facilities exist in their wrappered processor
* to fetch and build the stylesheet to use for the transform.
*
* @param xmlName local path\filename of XML file to transform
* @param resultName local path\filename to put result in
*
* @return array of longs denoting timing of only these parts of
* our operation: IDX_OVERALL, IDX_XSLREAD (time to find XSL
* reference from the xml-stylesheet PI), IDX_XSLBUILD, (time
* to then build the Transformer therefrom), IDX_TRANSFORM
*
* @throws Exception any underlying exceptions from the
* wrappered processor are simply allowed to propagate; throws
* a RuntimeException if any other problems prevent us from
* actually completing the operation
*/
public long[] transformEmbedded(String xmlName, String resultName)
throws Exception
{
preventFootShooting();
long startTime = 0;
long xslRead = 0;
long xslBuild = 0;
long transform = 0;
throw new RuntimeException("transformEmbedded not implemented yet!");
}
/**
* Reset our parameters and wrapper state, and optionally
* force creation of a new underlying processor implementation.
*
* This always clears our built stylesheet and any parameters
* that have been set. If newProcessor is true, also forces a
* re-creation of our underlying processor as if by calling
* newProcessor().
*
* @param newProcessor if we should reset our underlying
* processor implementation as well
*/
public void reset(boolean newProcessor)
{
super.reset(newProcessor); // clears indent and parameters
m_stylesheetReady = false;
builtTemplates = null;
if (newProcessor)
{
try
{
newProcessor(newProcessorOpts);
}
catch (Exception e)
{
//@todo Hmm: what should we do here?
}
}
}
/**
* Apply a single parameter to a Transformer.
*
* Overridden to take a Transformer and call setParameter().
*
* @param passThru to be passed to each applyParameter() method
* call - for TrAX, you might pass a Transformer object.
* @param namespace for the parameter, may be null
* @param name for the parameter, should not be null
* @param value for the parameter, may be null
*/
protected void applyParameter(Object passThru, String namespace,
String name, Object value)
{
try
{
Transformer t = (Transformer)passThru;
// Munge the namespace into the name per
// javax.xml.transform.Transformer.setParameter()
if (null != namespace)
{
name = "{" + namespace + "}" + name;
}
t.setParameter(name, value);
}
catch (Exception e)
{
throw new IllegalArgumentException("applyParameter threw: " + e.toString());
}
}
/**
* Ensure newProcessor has been called when needed.
*
* Prevent users from shooting themselves in the foot by
* calling a transform* API before newProcessor().
*
* (Sorry, I couldn't resist)
*/
public void preventFootShooting() throws Exception
{
if (null == factory)
newProcessor(newProcessorOpts);
}
}
---------------------------------------------------------------------
To unsubscribe, e-mail: xalan-cvs-unsubscribe@xml.apache.org
For additional commands, e-mail: xalan-cvs-help@xml.apache.org