TransformThread.java Source code

Java tutorial

Introduction

Here is the source code for TransformThread.java

Source

/*
 * 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: TransformThread.java 470245 2006-11-02 06:34:33Z minchau $
 */

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);
        }
    }
}