curcuru 01/03/16 08:59:45
Added: test/java/src/org/apache/qetest/xslwrapper
TransformWrapper.java TransformWrapperFactory.java
TransformWrapperFactory.properties
TransformWrapperHelper.java TraxDOMWrapper.java
TraxFileWrapper.java TraxWrapperUtils.java
Log:
New implementations of XSL processor wrappers, will replace ProcessorWrapper
and subclasses once I'm sure the functionality is equivalent. Much cleaner
design and better timing reporting, better granularity, removed unused code,
etc.
Revision Changes Path
1.1
xml-xalan/test/java/src/org/apache/qetest/xslwrapper/TransformWrapper.java
Index: TransformWrapper.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 [EMAIL PROTECTED]
*
* 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 java.util.Hashtable;
import java.util.Properties;
/**
* Helper interface to wrapper various XSLT processors for testing.
*
* A TransformWrapper wraps a particular 'flavor' of XSLT processing.
* This includes both a particular XSLT implementation, such as
* Xalan or Saxon, as well as a particular method to perform
* processing, like using streams or DOMs to perform transforms.
*
* As an important side effect, this class should return timing
* information about the steps done to perform the transformation.
* Note that exactly what is timed and how it's timed should be
* clearly documented in implementing classes!
*
* This is not a general-purpose wrapper for doing XSLT
* transformations: for that, you might as well use the real
* javax.xml.transform package itself. However this does allow
* many conformance and performance tests to run comparatively
* between different flavors of processors.
*
* TransformWrapper is a bit of an awkward name, but I wanted to
* keep it separate from the pre-existing ProcessorWrapper that
* this replaces so we can ensure stability for Xalan testing
* while updating to this new class.
*
* @author Shane Curcuru
* @version $Id: TransformWrapper.java,v 1.1 2001/03/16 16:59:44 curcuru Exp $
*/
public interface TransformWrapper
{
/**
* Timing constant: this operation did not attempt to time this
* item, or the item is not appropriate for this case.
*
* Currently we return a similar array of longs from every
* timed call, however buildStylesheet() would obviously not
* have entries for xmlread/xmlbuild times. This value will
* be used for any times not used, since a negative number is
* clearly inappropriate for a time duration (until someone
* does some heavy relativistic optimizations).
*/
public static final long TIME_UNUSED = -2L;
/**
* Timing index: overall time to complete operation.
*
* This time, which is always the first long[] array item in
* any timed call, is the overall amount of time taken to
* complete the whole operation, from start to finish. This
* may include time in reading the inputs from disk and
* writing the outputs to disk, as well as any other time
* taken by the processor to complete other portions of the
* task.
*
* In general, this should not include overhead for the wrapper
* itself, and notably will not include time taken up while
* setting parameters or other attributes into the underlying
* processor (which are hopefully minor compared to other items).
*
* Note that other timing indexes may be filled in as
* TIME_UNUSED by calls that don't time anything useful. E.g.
* buildStylesheet will not return data for xml-related times.
*/
public static final int IDX_OVERALL = 0;
/**
* Timing index: time spend reading an XSL file into memory.
*
* This should be the time spent just reading the XSL file from
* disk into memory, to attempt to isolate disk I/O issues.
* Note that implementations should carefully document exactly
* what this operation does: just reads the data into a
* ByteStream, or actually builds a DOM, or whatever.
*/
public static final int IDX_XSLREAD = 1;
/**
* Timing index: time to build the stylesheet.
*
* This should include the time it takes the processor
* implementation to take an XSL source and turn it into
* whatever useable form it wants.
*
* In TrAX, this would normally correspond to the time it
* takes the newTemplates() call to return when handed a
* StreamSource(ByteStream) object. Normally this would
* be a ByteStream already in memory, but some wrappers
* may not allow separating the xslread time (which would
* be reading the file from disk into a ByteStream in memory)
* from this xslbuild time.
*/
public static final int IDX_XSLBUILD = 2;
/**
* Timing index: time spend reading an XML file into memory.
*
* This should be the time spent just reading the XML file from
* disk into memory, to attempt to isolate disk I/O issues.
* Note that implementations should carefully document exactly
* what this operation does: just reads the data into a
* ByteStream, or actually builds a DOM, or whatever.
*/
public static final int IDX_XMLREAD = 3;
/**
* Timing index: time to build the XML document.
*
* This should include the time it takes the processor
* implementation to take an XML source and turn it into
* whatever useable form it wants.
*
* In TrAX, this would normally only correspond to the time
* taken to create a DOMSource from an in-memory ByteStream.
* The Xalan-C version may use this more than the Java version.
*/
public static final int IDX_XMLBUILD = 4;
/**
* Timing index: time to complete the transform from sources.
*
* Normally this should be just the time to complete outputting
* the whole result tree from a transform from in-memory sources.
* Obviously different wrapper implementations will measure
* slightly different things in this field, which needs to be
* clearly documented.
*
* For example, in TrAX, this would correspond to doing a
* transformer.transform(xmlSource, StreamResult(ByteStream))
* where the ByteStream is in memory. A separate time should be
* recorded for resultwrite that actually puts the stream out
* to disk.
*
* Note that some wrappers may not be able to separate the
* transform time from the resultwrite time: for example a
* wrapper that wants to test with new StreamResult(URL).
*/
public static final int IDX_TRANSFORM = 5;
/**
* Timing index: time to write the result tree to disk.
*
* See discussion in IDX_TRANSFORM. This may not always
* be used.
*/
public static final int IDX_RESULTWRITE = 6;
/**
* Timing index: Time from beginning of transform from sources
* until the first bytes of the result tree come out.
*
* Future use. This is for testing pipes and server
* applications, where the user is concerned about latency and
* throughput. This will measure how responsive the processor
* appears to be at first (but not necessarily how long it
* takes to write the whole the result tree).
*/
public static final int IDX_FIRSTLATENCY = 7;
/**
* URL for set/getAttribute: should be an integer to set
* for the output indent of the processor.
*
* This is a common enough attribute that most wrapper
* implementations should be able to support it in a
* straightforward manner.
*/
public static final String ATTRIBUTE_INDENT =
"http://xml.apache.org/xalan/wrapper/indent";
/**
* URL for set/getAttribute: should be an Object to attempt
* to set as a diagnostic log/stream for the processor.
*
* //@todo see if there's a fairly generic way to implement
* this that will get at least some data from all common
* processor implementations: either by using some native
* diagnostics PrintStream the processor provides, or by
* implementing a simple LoggingErrorListener, etc.
*/
public static final String ATTRIBUTE_DIAGNOSTICS =
"http://xml.apache.org/xalan/wrapper/diagnostics";
/**
* Get a general description of this wrapper itself.
*
* @return a general description of this wrapper: roughly how
* it performs transforms (stream/SAX/DOM/etc) and what it times
*/
public String getDescription();
/**
* 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();
/**
* Actually create/initialize an underlying processor or factory.
*
* For TrAX/javax.xml.transform implementations, this creates
* a new TransformerFactory. For Xalan-J 1.x this creates an
* XSLTProcessor. Other implmentations may or may not actually
* do any work in this method.
*
* @param options Hashtable of options, possibly specific to
* that implementation. For future use.
*
* @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;
/**
* Allows the user to ask the wrapper to set specific
* attributes on the underlying implementation.
*
* Attribute names that are recognized by the wrapper will
* be re-mapped to the appropriate API calls to the underlying
* processor. Attribute names that are not recognized by the
* wrapper will be set directly into the underlying processor
* where the processor supports a similar setAttribute API.
*
* //@todo define behavior when the underlying processor throws
* an exception that's not an IllegalArgumentException.
*
* @param name The name of the attribute.
* @param value The value of the attribute.
* @throws IllegalArgumentException thrown if the underlying
* implementation doesn't recognize the attribute.
*
* @see #ATTRIBUTE_INDENT
* @see #ATTRIBUTE_DIAGNOSTICS
*/
public void setAttribute(String name, Object value)
throws IllegalArgumentException;
/**
* Allows the user to retrieve specific attributes on the
* underlying implementation.
*
* Attribute names that are recognized by the wrapper will
* be re-mapped to the appropriate API calls to the underlying
* processor, or will simply return internal state values.
* Attribute names that are not recognized by the
* wrapper will be set directly into the underlying processor
* where the processor supports a similar getAttribute API.
*
* //@todo define behavior when the underlying processor throws
* an exception that's not an IllegalArgumentException.
*
* @param name The name of the attribute.
* @return value The value of the attribute.
* @throws IllegalArgumentException thrown if the underlying
* implementation doesn't recognize the attribute.
*
* @see #ATTRIBUTE_INDENT
* @see #ATTRIBUTE_DIAGNOSTICS
*/
public Object getAttribute(String name) throws IllegalArgumentException;
/**
* 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 converted to URLs as needed for any underlying
* processor implementation.
*
* @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 various parts of
* our operation; [0] is always the total end-to-end time, and
* other array indicies are represented by IDX_* constants
*
* @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;
/**
* 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 various parts of
* our operation; [0] is always the total end-to-end time, and
* other array indicies are represented by constants
*
* @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;
/**
* Reports if a pre-built/pre-compiled stylesheet is ready;
* presumably built by calling buildStylesheet(xslName).
*
* @return true if one is ready; false otherwise
*
* @see #buildStylesheet(String xslName)
*/
public boolean isStylesheetReady();
/**
* 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 various parts of
* our operation; [0] is always the total end-to-end time, and
* other array indicies are represented by constants
*
* @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;
/**
* 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 various parts of
* our operation; [0] is always the total end-to-end time, and
* other array indicies are represented by constants
*
* @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;
/**
* Set a stylesheet parameter for use in later transforms.
*
* This method merely stores the triple for use later in a
* transform operation. Note that the actual mechanisims for
* setting parameters in implementation differ, especially with
* regards to namespaces.
*
* Note that the namespace may not contain the "{" or "}"
* characters, since these would be illegal XML namespaces
* anyways; an IllegalArgumentException will be thrown; also
* the name must not be null.
*
* @param namespace for the parameter, must not contain {}
* @param name of the parameter, must not be null
* @param value of the parameter
*
* @throws IllegalArgumentException thrown if the namespace
* or name appears to be illegal.
*/
public void setParameter(String namespace, String name, Object value)
throws IllegalArgumentException;
/**
* Get a parameter that was set with setParameter.
*
* Only returns parameters set locally, not parameters exposed
* by the underlying processor implementation. Not terribly
* useful but I like providing gets for any sets I define.
*
* @param namespace for the parameter, must not contain {}
* @param name of the parameter, must not be null
*
* @return value of the parameter; null if not found
*/
public Object getParameter(String namespace, String name);
/**
* 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);
}
1.1
xml-xalan/test/java/src/org/apache/qetest/xslwrapper/TransformWrapperFactory.java
Index: TransformWrapperFactory.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 [EMAIL PROTECTED]
*
* 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 java.io.InputStream;
import java.io.IOException;
import java.util.Properties;
/**
* Factory static class for creating TransformWrappers.
*
* Includes a 'wrapperMapper' functionality to simplify specifying
* the 'flavor' of a wrapper to create. This is optional, but will
* allow a user to specify newWrapper("trax.file") and get back an
* instance of an org.apache.qetest.xslwrapper.TraxFileWrapper.
*
* @author Shane Curcuru
* @version $Id: TransformWrapperFactory.java,v 1.1 2001/03/16 16:59:44
curcuru Exp $
*/
public abstract class TransformWrapperFactory
{
/**
* Currently known list of implemented wrappers.
*
* Allows specification of a simple name for each wrapper,
* so clients don't necessarily have to know the FQCN or
* fully qualified classname of their wrapper.</p>
*
* <ul>Where:
* <li>key = String simple name = xalan|trax|etc...</li>
* <li>value = String FQCN of wrapper implementation</li>
* <li>Supports: See TransformWrapperFactory.properties</li>
* </ul>
*/
protected static Properties wrapperMapper = null;
/**
* Static initializer for wrapperMapper.
* Attempts to load TransformWrapperFactory.properties into
* our wrapperMapper.
*/
static
{
wrapperMapper = new Properties();
// Add a default trax flavor, since it's widely used
// This should be overwritten below if the properties
// file can be loaded
wrapperMapper.put("trax",
"org.apache.qetest.xslwrapper.TraxFileWrapper");
try
{
InputStream is =
TransformWrapperFactory.class.getResourceAsStream(
"TransformWrapperFactory.properties");
wrapperMapper.load(is);
is.close();
}
catch (Exception e)
{
System.err.println(
"TransformWrapperFactory.properties.load() threw: "
+ e.toString());
e.printStackTrace();
}
};
/**
* Accessor for our wrapperMapper.
*
* @return Properties block of wrapper implementations
* that we implicitly know about; may be null if we have none
*/
public static final Properties getDescriptions()
{
return wrapperMapper;
}
/**
* Return an instance of a TransformWrapper of requested flavor.
*
* This static factory method creates TransformWrappers for the
* user. Our 'wrapperMapper' functionality allows users to
* either specify short names listed in
* TransformWrapperFactory.properties (which are mapped to the
* appropriate FQCN's) or to directly supply the FQCN of a
* wrapper to create.
*
* @param flavor to create, either a wrapperMapped one or FQCN
*
* @return instance of a wrapper; will throw an
* IllegalArgumentException if we cannot find the asked-for
* wrapper class anywhere
*/
public static final TransformWrapper newWrapper(String flavor)
{
// Attempt to lookup the flavor: if found, use the
// value we got, otherwise default to the same value
String className = wrapperMapper.getProperty(flavor, flavor);
try
{
Class clazz = Class.forName(className);
TransformWrapper wrapper = (TransformWrapper) clazz.newInstance();
return wrapper;
}
catch (Exception e)
{
throw new IllegalArgumentException("newWrapper() threw: " +
e.toString());
}
}
}
1.1
xml-xalan/test/java/src/org/apache/qetest/xslwrapper/TransformWrapperFactory.properties
Index: TransformWrapperFactory.properties
===================================================================
# Used by TransformWrapperFactory.wrapperMapper
# This maps simple 'flavor' names to specific FQCN names
# of actual TransformWrapper implementations, allowing users
# to specify much simpler -flavor arguments
# Default for Xalan2 and TrAX is the TraxFileWrapper, which
# does transforms from StreamSource(URL)
xalan2=org.apache.qetest.xslwrapper.TraxFileWrapper
trax=org.apache.qetest.xslwrapper.TraxFileWrapper
# Other TrAX wrappers use the same TrAX APIs but in
# different models - streams, doms, sax, etc.
trax.file=org.apache.qetest.xslwrapper.TraxFileWrapper
trax.stream=org.apache.qetest.xslwrapper.TraxStreamWrapper
trax.dom=org.apache.qetest.xslwrapper.TraxDOMWrapper
trax.sax=org.apache.qetest.xslwrapper.TraxSAXWrapper
1.1
xml-xalan/test/java/src/org/apache/qetest/xslwrapper/TransformWrapperHelper.java
Index: TransformWrapperHelper.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 [EMAIL PROTECTED]
*
* 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 java.util.Enumeration;
import java.util.Hashtable;
/**
* A few default implementations of TransformWrapper methods.
*
* A TransformWrapperHelper implements a few of the common methods
* from TransformWrapper that don't directly interact with the
* underlying processor. Individual wrapper implementations are
* free to extend this class to get some free code.
*
* @author Shane Curcuru
* @version $Id: TransformWrapperHelper.java,v 1.1 2001/03/16 16:59:44
curcuru Exp $
*/
public abstract class TransformWrapperHelper implements TransformWrapper
{
/** Constant denoting that indent should not be set. */
protected static final int NO_INDENT = -2;
/**
* Current number of spaces to indent, default: NO_INDENT.
* Users call setAttribute(ATTRIBUTE_INDENT, int) to set this.
* If it is set, it will be applied to an underlying processor
* during each transform operation, where supported.
*/
protected int m_indent = NO_INDENT;
/**
* Allows the user to ask the wrapper to set specific
* attributes on the underlying implementation.
*
* Supported attributes in this class include:
* ATTRIBUTE_INDENT
*
* //@todo define behavior for subclasses who want our default
* behavior but also want to throw the exception for
* attributes that are not recognized.
*
* @param name The name of the attribute.
* @param value The value of the attribute.
*
* @throws IllegalArgumentException thrown only if we can't
* parse an int from the value
*
* @see #ATTRIBUTE_INDENT
*/
public void setAttribute(String name, Object value)
throws IllegalArgumentException
{
if (ATTRIBUTE_INDENT.equals(name))
{
try
{
m_indent = (new Integer((String)value)).intValue();
}
catch (Exception e)
{
throw new IllegalArgumentException("setAttribute: bad value:
" + value);
}
}
}
/**
* Allows the user to retrieve specific attributes on the
* underlying implementation.
*
* This class merely returns the indent for ATTRIBUTE_INDENT.
*
* //@todo define behavior for subclasses who want our default
* behavior but also want to throw the exception for
* attributes that are not recognized.
*
* @param name The name of the attribute.
* @return value The value of the attribute.
* @throws IllegalArgumentException not thrown from this class
*
* @see #ATTRIBUTE_INDENT
*/
public Object getAttribute(String name) throws IllegalArgumentException
{
if (ATTRIBUTE_INDENT.equals(name))
{
return new Integer(m_indent);
}
return null;
}
/** If our wrapper has a built stylesheet ready. */
protected boolean m_stylesheetReady = false;
/**
* Reports if a pre-built/pre-compiled stylesheet is ready;
* presumably built by calling buildStylesheet(xslName).
*
* @return true if one is ready; false otherwise
*
* @see #buildStylesheet(String xslName)
*/
public boolean isStylesheetReady()
{
return m_stylesheetReady;
}
/** Set of stylesheet parameters for use in transforms. */
protected Hashtable m_params = null;
/**
* Set a stylesheet parameter for use in later transforms.
*
* This method merely stores the triple for use later in a
* transform operation. Note that the actual mechanisims for
* setting parameters in implementation differ, especially with
* regards to namespaces.
*
* Note that the namespace may not contain the "{" or "}"
* characters, since these would be illegal XML namespaces
* anyways; an IllegalArgumentException will be thrown.
* Note that the name may not begin with the "{"
* character, since it would likely be an illegal XML name
* anyways; an IllegalArgumentException will be thrown.
*
* @param namespace for the parameter
* @param name of the parameter
* @param value of the parameter
*
* @throws IllegalArgumentException thrown if the namespace
* appears to be illegal.
*/
public void setParameter(String namespace, String name, Object value)
throws IllegalArgumentException
{
if (null != namespace)
{
if ((namespace.indexOf("{") > -1)
|| (namespace.indexOf("}") > -1))
throw new IllegalArgumentException(
"setParameter: illegal namespace includes brackets: " +
namespace);
}
if (null != name)
{
if (name.startsWith("{"))
throw new IllegalArgumentException(
"setParameter: illegal name begins with bracket: " +
name);
}
if (null == m_params)
m_params = new Hashtable();
if (null != namespace)
{
m_params.put("{" + namespace + "}" + name, value);
}
else
{
m_params.put(name, value);
}
}
/**
* Get a parameter that was set with setParameter.
*
* Only returns parameters set locally, not parameters exposed
* by the underlying processor implementation. Not terribly useful
* but I always like providing gets for any sets I define.
*
* @param namespace for the parameter
* @param name of the parameter
*
* @param value of the parameter; null if not found
*/
public Object getParameter(String namespace, String name)
{
if (null == m_params)
return null;
if (null != namespace)
{
return m_params.get("{" + namespace + "}" + name);
}
else
{
return m_params.get(name);
}
}
/**
* Apply the parameters that were set with setParameter to
* our underlying processor implementation.
*
* Subclasses may call this to apply all set parameters during
* each transform if they override the applyParameter() method
* to set a single parameter.
*
* This is a convenience method for getting data out of
* m_params that was encoded by our setParameter().
*
* @param passThru to be passed to each applyParameter() method
* call - for TrAX, you might pass a Transformer object.
*/
protected void applyParameters(Object passThru)
{
if (null == m_params)
return;
for (Enumeration enum = m_params.keys();
enum.hasMoreElements();
/* no increment portion */ )
{
String namespace = null;
String name = null;
String key = enum.nextElement().toString();
//@todo compare with TransformerImpl.setParameter's use of a
StringTokenizer(..., "{}"...
// Decode the namespace, if present
if (key.startsWith("{"))
{
int idx = key.indexOf("}");
namespace = key.substring(1, idx);
name = key.substring(idx + 1); //@todo check for out of range?
}
else
{
// namespace stays null
name = key;
}
// Call subclassed worker method for each parameter
applyParameter(passThru, namespace, name, m_params.get(key));
}
}
/**
* Apply a single parameter to our underlying processor
* implementation: must be overridden.
*
* Subclasses must override; this class will throw an
* IllegalStateException since we can't do anything.
*
* @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)
{
throw new
IllegalStateException("TransformWrapperHelper.applyParameter must be
overridden!");
}
/**
* Reset our parameters and wrapper state, and optionally
* force creation of a new underlying processor implementation.
*
* This class clears the indent and any parameters.
* Subclasses are free to call us to get this default behavior
* or not. Note that subclasses must clear m_stylesheetReady
* themselves if needed.
*
* @param newProcessor ignored in this class
*/
public void reset(boolean newProcessor)
{
m_params = null;
m_indent = NO_INDENT;
}
/**
* Worker method to return default array of longs.
*
* Simply returns long[] pre-filled to TIME_UNUSED, suitable
* for returning from various transform API's.
*
* @return long[] = TIME_UNUSED
*/
protected long[] getTimeArray()
{
return new long[]
{
TIME_UNUSED, /* IDX_OVERALL */
TIME_UNUSED, /* IDX_XSLREAD */
TIME_UNUSED, /* IDX_XSLBUILD */
TIME_UNUSED, /* IDX_XMLREAD */
TIME_UNUSED, /* IDX_XMLBUILD */
TIME_UNUSED, /* IDX_TRANSFORM */
TIME_UNUSED, /* IDX_RESULTWRITE */
TIME_UNUSED /* IDX_FIRSTLATENCY */
};
}
}
1.1
xml-xalan/test/java/src/org/apache/qetest/xslwrapper/TraxDOMWrapper.java
Index: TraxDOMWrapper.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 [EMAIL PROTECTED]
*
* 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.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.Templates;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.Source;
import javax.xml.transform.dom.DOMResult;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.xml.sax.InputSource;
import java.util.Hashtable;
import java.util.Properties;
/**
* Implementation of TransformWrapper that uses the TrAX API and
* uses DOMs for it's sources.
*
* This implementation records separate times for xslRead (time to
* parse the xsl and build a DOM) and xslBuild (time to take the
* DOMSource object until it's built the templates); xmlRead (time
* to parse the xml and build a DOM). Note xmlBuild is not timed
* since it's not easily measureable in TrAX.
* The transform time is just the time to create the DOMResult
* object; the resultsWrite is the separate time it takes to
* serialize that to disk.
*
* <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.
*
* //@todo add in checks for factory.getFeature(DOMSource.FEATURE)
*
* @author Shane Curcuru
* @version $Id: TraxDOMWrapper.java,v 1.1 2001/03/16 16:59:44 curcuru Exp $
*/
public class TraxDOMWrapper 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 DOMSource(node)
*/
public String getDescription()
{
return "Uses TrAX to perform transforms from DOMSource(node)";
}
/**
* 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", "dom");
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. For Xalan-J 1.x this creates an
* XSLTProcessor. Other implmentations may or may not actually
* do any work in this method.
*
* @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 converted to URLs as needed for any underlying
* processor implementation.
*
* @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
*
* @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;
DocumentBuilderFactory dfactory =
DocumentBuilderFactory.newInstance();
dfactory.setNamespaceAware(true);
DocumentBuilder docBuilder = dfactory.newDocumentBuilder();
// Timed: read xsl into a DOM
startTime = System.currentTimeMillis();
Node xslNode = docBuilder.parse(new InputSource(xslName));
xslRead = System.currentTimeMillis() - startTime;
// Untimed: create DOMSource and setSystemId
DOMSource xslSource = new DOMSource(xslNode);
xslSource.setSystemId(xslName);
// Timed: build Transformer from DOMSource
startTime = System.currentTimeMillis();
Transformer transformer = factory.newTransformer(xslSource);
xslBuild = System.currentTimeMillis() - startTime;
// Timed: read xml into a DOM
startTime = System.currentTimeMillis();
Node xmlNode = docBuilder.parse(new InputSource(xmlName));
xmlRead = System.currentTimeMillis() - startTime;
// Untimed: create DOMSource and setSystemId
DOMSource xmlSource = new DOMSource(xmlNode);
xmlSource.setSystemId(xmlName);
// Untimed: create DOMResult
Document outNode = docBuilder.newDocument();
DOMResult domResult = new DOMResult(outNode);
// Untimed: Apply any parameters needed
applyParameters(transformer);
// Timed: build xml (so to speak) and transform
startTime = System.currentTimeMillis();
transformer.transform(xmlSource, domResult);
transform = System.currentTimeMillis() - startTime;
// Untimed: prepare serializer with outputProperties
// from the stylesheet
Transformer resultSerializer = factory.newTransformer();
Properties serializationProps = transformer.getOutputProperties();
resultSerializer.setOutputProperties(serializationProps);
// Timed: writeResults from the DOMResult
startTime = System.currentTimeMillis();
resultSerializer.transform(new DOMSource(outNode),
new StreamResult(resultName));
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 only these 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;
DocumentBuilderFactory dfactory =
DocumentBuilderFactory.newInstance();
dfactory.setNamespaceAware(true);
DocumentBuilder docBuilder = dfactory.newDocumentBuilder();
// Timed: read xsl into a DOM
startTime = System.currentTimeMillis();
Node xslNode = docBuilder.parse(new InputSource(xslName));
xslRead = System.currentTimeMillis() - startTime;
// Untimed: create DOMSource and setSystemId
DOMSource xslSource = new DOMSource(xslNode);
xslSource.setSystemId(xslName);
// Timed: build Templates from DOMSource
startTime = System.currentTimeMillis();
builtTemplates = factory.newTemplates(xslSource);
xslBuild = System.currentTimeMillis() - startTime;
m_stylesheetReady = true;
long[] times = getTimeArray();
times[IDX_OVERALL] = xslRead + xslBuild;
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 only these 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 xmlRead = 0;
long transform = 0;
long resultWrite = 0;
// Untimed: get Transformer from Templates
Transformer transformer = builtTemplates.newTransformer();
DocumentBuilderFactory dfactory =
DocumentBuilderFactory.newInstance();
dfactory.setNamespaceAware(true);
DocumentBuilder docBuilder = dfactory.newDocumentBuilder();
// Timed: read xml into a DOM
startTime = System.currentTimeMillis();
Node xmlNode = docBuilder.parse(new InputSource(xmlName));
xmlRead = System.currentTimeMillis() - startTime;
// Untimed: create DOMSource and setSystemId
DOMSource xmlSource = new DOMSource(xmlNode);
xmlSource.setSystemId(xmlName);
// Untimed: create DOMResult
Document outNode = docBuilder.newDocument();
DOMResult domResult = new DOMResult(outNode);
// Untimed: Apply any parameters needed
applyParameters(transformer);
// Timed: build xml (so to speak) and transform
startTime = System.currentTimeMillis();
transformer.transform(xmlSource, domResult);
transform = System.currentTimeMillis() - startTime;
// Untimed: prepare serializer with outputProperties
// from the stylesheet
Transformer resultSerializer = factory.newTransformer();
Properties serializationProps = transformer.getOutputProperties();
resultSerializer.setOutputProperties(serializationProps);
// Timed: writeResults from the DOMResult
startTime = System.currentTimeMillis();
resultSerializer.transform(new DOMSource(outNode),
new StreamResult(resultName));
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,
* and 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[] transformEmbedded(String xmlName, String resultName)
throws Exception
{
long startTime = 0;
long xslRead = 0;
long xslBuild = 0;
long xmlRead = 0;
long transform = 0;
long resultWrite = 0;
DocumentBuilderFactory dfactory =
DocumentBuilderFactory.newInstance();
dfactory.setNamespaceAware(true);
DocumentBuilder docBuilder = dfactory.newDocumentBuilder();
// Timed: read xml into a DOM
startTime = System.currentTimeMillis();
Node xmlNode = docBuilder.parse(new InputSource(xmlName));
xmlRead = System.currentTimeMillis() - startTime;
// Untimed: create DOMSource and setSystemId
DOMSource xmlSource = new DOMSource(xmlNode);
xmlSource.setSystemId(xmlName);
// Timed: readxsl from the xml document
startTime = System.currentTimeMillis();
Source xslSource = factory.getAssociatedStylesheet(xmlSource,
null, null, null);
xslRead = System.currentTimeMillis() - startTime;
// Timed: build Transformer from Source
startTime = System.currentTimeMillis();
Transformer transformer = factory.newTransformer(xslSource);
xslBuild = System.currentTimeMillis() - startTime;
// Untimed: create DOMResult
Document outNode = docBuilder.newDocument();
DOMResult domResult = new DOMResult(outNode);
// Untimed: Apply any parameters needed
applyParameters(transformer);
// Timed: build xml (so to speak) and transform
startTime = System.currentTimeMillis();
transformer.transform(xmlSource, domResult);
transform = System.currentTimeMillis() - startTime;
// Untimed: prepare serializer with outputProperties
// from the stylesheet
Transformer resultSerializer = factory.newTransformer();
Properties serializationProps = transformer.getOutputProperties();
resultSerializer.setOutputProperties(serializationProps);
// Timed: writeResults from the DOMResult
startTime = System.currentTimeMillis();
resultSerializer.transform(new DOMSource(outNode),
new StreamResult(resultName));
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;
}
/**
* 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);
}
}
1.1
xml-xalan/test/java/src/org/apache/qetest/xslwrapper/TraxFileWrapper.java
Index: TraxFileWrapper.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 [EMAIL PROTECTED]
*
* 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.util.Hashtable;
import java.util.Properties;
/**
* Implementation of TransformWrapper that uses the TrAX API and
* uses files for it's sources.
*
* <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.
*
* @author Shane Curcuru
* @version $Id: TraxFileWrapper.java,v 1.1 2001/03/16 16:59:44 curcuru Exp $
*/
public class TraxFileWrapper 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(systemId)";
}
/**
* 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", "dom");
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. For Xalan-J 1.x this creates an
* XSLTProcessor. Other implmentations may or may not actually
* do any work in this method.
*
* @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 converted to URLs as needed for any underlying
* processor implementation.
*
* @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 only these parts of
* our operation: IDX_OVERALL, IDX_XSLBUILD, 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[] transform(String xmlName, String xslName, String resultName)
throws Exception
{
preventFootShooting();
long startTime = 0;
long xslBuild = 0;
long transform = 0;
// Timed: read/build xsl from a URL
startTime = System.currentTimeMillis();
Transformer transformer = factory.newTransformer(new
StreamSource(xslName));
xslBuild = System.currentTimeMillis() - startTime;
// Untimed: Apply any parameters needed
applyParameters(transformer);
// Timed: read/build xml, transform, and write results
startTime = System.currentTimeMillis();
transformer.transform(new StreamSource(xmlName), new
StreamResult(resultName));
transform = System.currentTimeMillis() - startTime;
long[] times = getTimeArray();
times[IDX_OVERALL] = xslBuild + transform;
times[IDX_XSLBUILD] = xslBuild;
times[IDX_TRANSFORM] = transform;
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 only these parts of
* our operation: IDX_OVERALL, 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 xslBuild = 0;
// Timed: read/build xsl from a URL
startTime = System.currentTimeMillis();
builtTemplates = factory.newTemplates(new StreamSource(xslName));
xslBuild = System.currentTimeMillis() - startTime;
m_stylesheetReady = true;
long[] times = getTimeArray();
times[IDX_OVERALL] = xslBuild;
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 only these parts of
* our operation: IDX_OVERALL, IDX_XSLBUILD, 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; 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 transform = 0;
// UNTimed: get Transformer from Templates
Transformer transformer = builtTemplates.newTransformer();
// Untimed: Apply any parameters needed
applyParameters(transformer);
// Timed: read/build xml, transform, and write results
startTime = System.currentTimeMillis();
transformer.transform(new StreamSource(xmlName), new
StreamResult(resultName));
transform = System.currentTimeMillis() - startTime;
long[] times = getTimeArray();
times[IDX_OVERALL] = transform;
times[IDX_TRANSFORM] = transform;
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;
// Timed: readxsl from the xml document
startTime = System.currentTimeMillis();
Source xslSource = factory.getAssociatedStylesheet(new
StreamSource(xmlName),
null, null,
null);
xslRead = System.currentTimeMillis() - startTime;
// Timed: build xsl from a URL
startTime = System.currentTimeMillis();
Transformer transformer = factory.newTransformer(xslSource);
xslBuild = System.currentTimeMillis() - startTime;
// Untimed: Apply any parameters needed
applyParameters(transformer);
// Timed: read/build xml, transform, and write results
startTime = System.currentTimeMillis();
transformer.transform(new StreamSource(xmlName), new
StreamResult(resultName));
transform = System.currentTimeMillis() - startTime;
long[] times = getTimeArray();
times[IDX_OVERALL] = xslRead + xslBuild + transform;
times[IDX_XSLREAD] = xslRead;
times[IDX_XSLBUILD] = xslBuild;
times[IDX_TRANSFORM] = transform;
return times;
}
/**
* 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);
}
}
1.1
xml-xalan/test/java/src/org/apache/qetest/xslwrapper/TraxWrapperUtils.java
Index: TraxWrapperUtils.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 [EMAIL PROTECTED]
*
* 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 java.lang.reflect.Field;
import java.util.Properties;
/**
* Cheap-o utilities for Trax*Wrapper implementations.
*
* @author Shane Curcuru
* @version $Id: TraxWrapperUtils.java,v 1.1 2001/03/16 16:59:44 curcuru Exp $
*/
public abstract class TraxWrapperUtils
{
/**
* Get a generic description of the TrAX related info.
*
* @return Properties block with basic info about any TrAX
* implementing processor, plus specific version information
* about Xalan-J 2.x or Xerces-J 1.x if found
*/
public static Properties getTraxInfo()
{
Properties p = new Properties();
p.put("traxwrapper.api", "trax");
p.put("traxwrapper.language", "java");
try
{
Properties sysProps = System.getProperties();
p.put("traxwrapper.jaxp.transform",
sysProps.getProperty("javax.xml.transform.TransformerFactory", "unset"));
p.put("traxwrapper.jaxp.parser.dom",
sysProps.getProperty("javax.xml.parsers.DocumentBuilderFactory", "unset"));
p.put("traxwrapper.jaxp.parser.sax",
sysProps.getProperty("javax.xml.parsers.SAXParserFactory",
"unset"));
}
// In case we're in an Applet
catch (SecurityException se) { /* no-op, ignore */ }
// Look for some Xalan/Xerces specific version info
try
{
Class clazz =
Class.forName("org.apache.xerces.framework.Version");
// Found 1.x, grab it's version fields
Field f = clazz.getField("fVersion");
p.put("traxwrapper.xerces.version", (String)f.get(null));
}
catch (Exception e1) { /* no-op, ignore */ }
try
{
Class clazz =
Class.forName("org.apache.xalan.processor.XSLProcessorVersion");
Field f = clazz.getField("S_VERSION");
p.put("traxwrapper.xalan.version", (String)f.get(null));
}
catch (Exception e2) { /* no-op, ignore */ }
return p;
}
}
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]