code: /*
   * 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);
      }
    }
  }
  