blob: 3146fb42d05004084a61dbe4a66e938382127151 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* $Id$
*/
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Properties;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMResult;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.sax.SAXResult;
import javax.xml.transform.sax.SAXSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
import org.xml.sax.InputSource;
import org.xml.sax.helpers.DefaultHandler;
/**
* What it does: this sample creates multiple threads
* and runs them. Each thread will be assigned a particular
* stylesheet. Each thread will run multiple transformations on
* various xml files using its own transformer.
*
* Note: the flavors used by the transformations can be
* configured below by changing SOURCE_FLAVOR and
* RESULT_FLAVOR. XSLTC can also be used by changing
* USE_XSLTC.
*
* Description of files included with the sample:
*
* foo0.xsl and foo1.xsl: foo0.xsl is the stylesheet used
* for transformations by thread #0, foo1.xsl is the stylesheet
* used by thread #1.
*
* foo0.xml and foo1.xml: foo0.xml and foo1.xml are the XML
* files used for the first and second transformations done
* by each thread.
*
* Output will go to *.out files in the TransformThread directory.
*
* @author <a href="mailto:richcao@ca.ibm.com">Richard Cao</a>
*/
public class TransformThread implements Runnable
{
// Flavors
public final static int STREAM = 0;
public final static int SAX = 1;
public final static int DOM = 2;
public final static String[] flavorNames =
new String[] { "Stream", "SAX", "DOM" };
// Configurable options
private static int SOURCE_FLAVOR = STREAM;
// private static int SOURCE_FLAVOR = SAX;
// private static int SOURCE_FLAVOR = DOM;
private static int RESULT_FLAVOR = STREAM;
// private static int RESULT_FLAVOR = SAX;
// private static int RESULT_FLAVOR = DOM;
private static boolean USE_XSLTC = false;
// private static boolean useXSLTC = true;
// Threads
private final static int NUM_THREADS = 2;
private static TransformThread INSTANCES[] = null;
protected Thread m_thread = null;
// Number of transformations per thread
private final static int NUM_TRANSFORMATIONS = 2;
// Files names and extensions
private final static String XML_IN_BASE = "foo";
private final static String XML_EXT = ".xml";
private final static String XSL_IN_BASE = "foo";
private final static String XSL_EXT = ".xsl";
private final static String FILE_OUT_BASE = "foo_";
private final static String FILE_OUT_EXT = ".out";
// Thread identifier
private int m_thrdNum = -1;
private InputStream[] m_inStream = null;
private Source[] m_inSource = null;
private Result[] m_outResult = null;
// One Transformer per thread since Transformers
// are _NOT_ thread-safe
private Transformer m_transformer = null;
/** Constructs the TransformThread object
* @param thrdNum a unique identifier for this object
*/
public TransformThread(int thrdNum)
{
m_thrdNum = thrdNum;
m_inStream = new InputStream[NUM_TRANSFORMATIONS];
m_inSource = new Source[NUM_TRANSFORMATIONS];
m_outResult = new Result[NUM_TRANSFORMATIONS];
try
{
initSource();
initResult();
// ensure xslSourceURI is a valid URI
final String xslSourceFileName = XSL_IN_BASE + m_thrdNum + XSL_EXT;
final String xslSourceURI = (new File(xslSourceFileName)).toURL().toString();
StreamSource xslSource = new StreamSource(xslSourceFileName);
xslSource.setSystemId(xslSourceURI);
// Initialize the tranformer
m_transformer =
TransformerFactory.newInstance().newTransformer(xslSource);
m_thread = new Thread(this);
}
catch (Throwable e)
{
e.printStackTrace();
System.exit(1);
}
}
/** Initialize the results (m_outResult) according
* to RESULT_FLAVOR
*/
private void initResult()
{
try
{
for (int i = 0; i < NUM_TRANSFORMATIONS; i++)
{
switch (RESULT_FLAVOR)
{
case STREAM :
OutputStream outStream =
new FileOutputStream(FILE_OUT_BASE + "thread_"
+ m_thrdNum + "_transformation_" + i + FILE_OUT_EXT);
m_outResult[i] = new StreamResult(outStream);
break;
case SAX :
DefaultHandler defaultHandler = new DefaultHandler();
m_outResult[i] = new SAXResult(defaultHandler);
break;
case DOM :
m_outResult[i] = new DOMResult();
break;
}
}
}
catch (Exception e)
{
e.printStackTrace();
System.exit(1);
}
}
/** Initialize the sources (m_inSource) according
* to SOURCE_FLAVOR
*/
private void initSource()
{
try
{
for (int i = 0; i < NUM_TRANSFORMATIONS; i++)
{
// Ensure we get a valid URI
final String sourceXMLURI = (new File(XML_IN_BASE + i + XML_EXT)).toURL().toString();
// Open for input
m_inStream[i] = new FileInputStream(XML_IN_BASE + i + XML_EXT);
switch (SOURCE_FLAVOR)
{
case STREAM :
m_inSource[i] = new StreamSource(m_inStream[i]);
break;
case SAX :
m_inSource[i] = new SAXSource(new InputSource(m_inStream[i]));
break;
case DOM :
try
{
DocumentBuilderFactory dfactory =
DocumentBuilderFactory.newInstance();
// Must always setNamespaceAware when
// building xsl stylesheets
dfactory.setNamespaceAware(true);
m_inSource[i] =
new DOMSource(dfactory.newDocumentBuilder().parse(m_inStream[i]));
}
catch (Exception e)
{
e.printStackTrace();
}
break;
}
if (m_inSource[i] != null)
{
// If we don't do this, the transformer
// won't know how to resolve relative URLs
// in the stylesheet.
m_inSource[i].setSystemId(sourceXMLURI);
}
}
}
catch (Exception e)
{
e.printStackTrace();
System.exit(1);
}
}
/**
* @see java.lang.Runnable#run()
*/
public void run()
{
try
{
// Perform multiple transformations with the same
// transformer
for (int i = 0; i < NUM_TRANSFORMATIONS; i++)
{
m_transformer.transform(m_inSource[i], m_outResult[i]);
}
}
catch (Exception e)
{
e.printStackTrace();
System.exit(1);
}
}
/** Creates thread instances
*/
private static void initThreads()
{
INSTANCES = new TransformThread[NUM_THREADS];
for (int count = 0; count < NUM_THREADS; count++)
{
INSTANCES[count] = new TransformThread(count);
}
}
/** Sets the appropriate system properties if XSLTC is
* to be used (according to USE_XSLTC)
*/
private static void initSystemProperties()
{
if (USE_XSLTC)
{
// Set the TransformerFactory system property if XSLTC is required
// Note: To make this sample more flexible, load properties from a properties file.
// The setting for the Xalan Transformer is "org.apache.xalan.processor.TransformerFactoryImpl"
String key = "javax.xml.transform.TransformerFactory";
String value = "org.apache.xalan.xsltc.trax.TransformerFactoryImpl";
Properties props = System.getProperties();
props.put(key, value);
System.setProperties(props);
}
}
/**
* Usage:
* java TransformThread
*/
public static void main(String argv[])
{
try
{
initSystemProperties();
initThreads();
for (int count = 0; count < NUM_THREADS; count++)
{
INSTANCES[count].m_thread.start();
}
}
catch (Throwable e)
{
e.printStackTrace();
System.exit(1);
}
}
}