/*
 * The Apache Software License, Version 1.1
 *
 *
 * Copyright (c) 1999 The Apache Software Foundation.  All rights 
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer. 
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. The end-user documentation included with the redistribution,
 *    if any, must include the following acknowledgment:  
 *       "This product includes software developed by the
 *        Apache Software Foundation (http://www.apache.org/)."
 *    Alternately, this acknowledgment may appear in the software itself,
 *    if and wherever such third-party acknowledgments normally appear.
 *
 * 4. The names "Xalan" and "Apache Software Foundation" must
 *    not be used to endorse or promote products derived from this
 *    software without prior written permission. For written 
 *    permission, please contact apache@apache.org.
 *
 * 5. Products derived from this software may not be called "Apache",
 *    nor may "Apache" appear in their name, without prior written
 *    permission of the Apache Software Foundation.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation and was
 * originally based on software copyright (c) 1999, Lotus
 * Development Corporation., http://www.lotus.com.  For more
 * information on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 */
package org.apache.xalan.transformer;

// Java imports
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.StringWriter;
import java.io.UnsupportedEncodingException;
import java.util.Enumeration;
import java.util.NoSuchElementException;
import java.util.Properties;
import java.util.Stack;
import java.util.StringTokenizer;
import java.util.Vector;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.transform.ErrorListener;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.URIResolver;
import javax.xml.transform.dom.DOMResult;
import javax.xml.transform.sax.SAXResult;
import javax.xml.transform.stream.StreamResult;
import org.apache.xalan.processor.TransformerFactoryImpl;
import org.apache.xalan.res.XSLMessages;
import org.apache.xalan.res.XSLTErrorResources;
import org.apache.xalan.serialize.Method;
import org.apache.xalan.serialize.Serializer;
import org.apache.xalan.serialize.SerializerFactory;
import org.apache.xalan.templates.AVT;
import org.apache.xalan.templates.Constants;
import org.apache.xalan.templates.ElemAttributeSet;
import org.apache.xalan.templates.ElemForEach;
import org.apache.xalan.templates.ElemSort;
import org.apache.xalan.templates.ElemTemplate;
import org.apache.xalan.templates.ElemTemplateElement;
import org.apache.xalan.templates.ElemTextLiteral;
import org.apache.xalan.templates.ElemVariable;
import org.apache.xalan.templates.OutputProperties;
import org.apache.xalan.templates.Stylesheet;
import org.apache.xalan.templates.StylesheetComposed;
import org.apache.xalan.templates.StylesheetRoot;
import org.apache.xalan.templates.WhiteSpaceInfo;
import org.apache.xalan.templates.XUnresolvedVariable;
import org.apache.xalan.trace.TraceManager;
import org.apache.xml.dtm.DTM;
import org.apache.xml.dtm.DTMIterator;
import org.apache.xml.dtm.DTMManager;
import org.apache.xml.dtm.DTMWSFilter;
import org.apache.xml.utils.BoolStack;
import org.apache.xml.utils.DOMBuilder;
import org.apache.xml.utils.NodeVector;
import org.apache.xml.utils.ObjectPool;
import org.apache.xml.utils.QName;
import org.apache.xml.utils.SAXSourceLocator;
import org.apache.xml.utils.WrappedRuntimeException;
import org.apache.xpath.Arg;
import org.apache.xpath.DOMHelper;
import org.apache.xpath.VariableStack;
import org.apache.xpath.XPathContext;
import org.apache.xpath.objects.XObject;
import org.w3c.dom.Document;
import org.w3c.dom.DocumentFragment;
import org.w3c.dom.Node;
import org.w3c.dom.Text;
import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;
import org.xml.sax.SAXNotRecognizedException;
import org.xml.sax.SAXNotSupportedException;
import org.xml.sax.SAXParseException;
import org.xml.sax.ext.DeclHandler;
import org.xml.sax.ext.LexicalHandler;

//dml
import org.apache.xpath.ExtensionsProvider;
import org.apache.xalan.extensions.ExtensionsTable;

/**
 * <meta name="usage" content="advanced"/>
 * This class implements the
 * {@link javax.xml.transform.Transformer} interface, and is the core
 * representation of the transformation execution.</p>
 */
public class TransformerImpl extends Transformer
        implements Runnable, DTMWSFilter, ExtensionsProvider
{

  // Synch object to gaurd against setting values from the TrAX interface 
  // or reentry while the transform is going on.

  /** NEEDSDOC Field m_reentryGuard          */
  private Boolean m_reentryGuard = new Boolean(true);

  /**
   * This is null unless we own the stream.
   */
  private java.io.FileOutputStream m_outputStream = null;

  /**
   * True if the parser events should be on the main thread,
   * false if not.  Experemental.  Can not be set right now.
   */
  private boolean m_parserEventsOnMain = true;

  /** The thread that the transformer is running on. */
  private Thread m_transformThread;

  /** The base URL of the source tree. */
  private String m_urlOfSource = null;

  /** The Result object at the start of the transform, if any. */
  private Result m_outputTarget = null;

  /**
   * The output format object set by the user.  May be null.
   */
  private OutputProperties m_outputFormat;

  /** The output serializer */
  private Serializer m_serializer;

  /**
   * The content handler for the source input tree.
   */
  ContentHandler m_inputContentHandler;

  /**
   * The content handler for the result tree.
   */
  private ContentHandler m_outputContentHandler = null;

  //  /*
  //   * Use member variable to store param variables as they're
  //   * being created, use member variable so we don't
  //   * have to create a new vector every time.
  //   */
  //  private Vector m_newVars = new Vector();

  /** The JAXP Document Builder, mainly to create Result Tree Fragments. */
  DocumentBuilder m_docBuilder = null;

  /**
   * A pool of ResultTreeHandlers, for serialization of a subtree to text.
   *  Please note that each of these also holds onto a Text Serializer.  
   */
  private ObjectPool m_textResultHandlerObjectPool =
    new ObjectPool("org.apache.xalan.transformer.ResultTreeHandler");

  /**
   * Related to m_textResultHandlerObjectPool, this is a pool of
   * StringWriters, which are passed to the Text Serializers.
   * (I'm not sure if this is really needed any more.  -sb)      
   */
  private ObjectPool m_stringWriterObjectPool =
    new ObjectPool("java.io.StringWriter");

  /**
   * A static text format object, which can be used over and
   * over to create the text serializers.    
   */
  private OutputProperties m_textformat = new OutputProperties(Method.Text);

  // Commenteded out in response to problem reported by 
  // Nicola Brown <Nicola.Brown@jacobsrimell.com>
  //  /**
  //   * Flag to let us know if an exception should be reported inside the 
  //   * postExceptionFromThread method.  This is needed if the transform is 
  //   * being generated from SAX events, and thus there is no central place 
  //   * to report the exception from.  (An exception is usually picked up in 
  //   * the main thread from the transform thread in {@link #transform(Source source)} 
  //   * from {@link #getExceptionThrown()}. )
  //   */
  //  private boolean m_reportInPostExceptionFromThread = false;

  /**
   * A node vector used as a stack to track the current
   * ElemTemplateElement.  Needed for the
   * org.apache.xalan.transformer.TransformState interface,
   * so a tool can discover the calling template. Note the use of an array 
   * for this limits the recursion depth to 4K.
   */
  ElemTemplateElement[] m_currentTemplateElements 
      = new ElemTemplateElement[XPathContext.RECURSIONLIMIT];
  
  /** The top of the currentTemplateElements stack. */
  int m_currentTemplateElementsTop = 0;

  /**
   * A node vector used as a stack to track the current
   * ElemTemplate that was matched.
   * Needed for the
   * org.apache.xalan.transformer.TransformState interface,
   * so a tool can discover the matched template
   */
  Stack m_currentMatchTemplates = new Stack();

  /**
   * A node vector used as a stack to track the current
   * node that was matched.
   * Needed for the
   * org.apache.xalan.transformer.TransformState interface,
   * so a tool can discover the matched
   * node. 
   */
  NodeVector m_currentMatchedNodes = new NodeVector();

  /**
   * The root of a linked set of stylesheets.
   */
  private StylesheetRoot m_stylesheetRoot = null;

  /**
   * If this is set to true, do not warn about pattern
   * match conflicts.
   */
  private boolean m_quietConflictWarnings = true;

  /**
   * The liason to the XML parser, so the XSL processor
   * can handle included files, and the like, and do the
   * initial parse of the XSL document.
   */
  private XPathContext m_xcontext;

  /**
   * Object to guard agains infinite recursion when
   * doing queries.
   */
  private StackGuard m_stackGuard = new StackGuard();

  /**
   * Output handler to bottleneck SAX events.
   */
  private ResultTreeHandler m_resultTreeHandler;

  /** The key manager, which manages xsl:keys. */
  private KeyManager m_keyManager = new KeyManager();

  /**
   * Stack for the purposes of flagging infinite recursion with
   * attribute sets.
   */
  Stack m_attrSetStack = null;

  /**
   * The table of counters for xsl:number support.
   * @see ElemNumber
   */
  CountersTable m_countersTable = null;

  /**
   * Is > 0 when we're processing a for-each.
   */
  BoolStack m_currentTemplateRuleIsNull = new BoolStack();

  /**
   * The message manager, which manages error messages, warning
   * messages, and other types of message events.   
   */
  private MsgMgr m_msgMgr;

  /**
   * This is a compile-time flag to turn off calling
   * of trace listeners. Set this to false for optimization purposes.
   */
  public static boolean S_DEBUG = false;

  /**
   * The SAX error handler, where errors and warnings are sent.
   */
  private ErrorListener m_errorHandler =
    new org.apache.xml.utils.DefaultErrorHandler();

  /**
   * The trace manager.
   */
  private TraceManager m_traceManager = new TraceManager(this);

  /**
   * If the transform thread throws an exception, the exception needs to
   * be stashed away so that the main thread can pass it on to the
   * client. 
   */
  private Exception m_exceptionThrown = null;

  /**
   * The InputSource for the source tree, which is needed if the
   * parse thread is not the main thread, in order for the parse
   * thread's run method to get to the input source.
   * (Delete this if reversing threads is outlawed. -sb)    
   */
  private Source m_xmlSource;

  /**
   * This is needed for support of setSourceTreeDocForThread(Node doc),
   * which must be called in order for the transform thread's run
   * method to obtain the root of the source tree to be transformed.     
   */
  private int m_doc;

  /**
   * If the the transform is on the secondary thread, we
   * need to know when it is done, so we can return.
   */
  private boolean m_isTransformDone = false;

  /** Flag to to tell if the tranformer needs to be reset. */
  private boolean m_hasBeenReset = false;

  /** NEEDSDOC Field m_shouldReset          */
  private boolean m_shouldReset = true;

  /**
   * NEEDSDOC Method setShouldReset 
   *
   *
   * NEEDSDOC @param shouldReset
   */
  public void setShouldReset(boolean shouldReset)
  {
    m_shouldReset = shouldReset;
  }

  /**
   * A stack of current template modes.
   */
  private Stack m_modes = new Stack();

  //==========================================================
  // SECTION: Constructor
  //==========================================================

  /**
   * Construct a TransformerImpl.
   *
   * @param stylesheet The root of the stylesheet tree.
   */
  public TransformerImpl(StylesheetRoot stylesheet)
   // throws javax.xml.transform.TransformerException    
  {
    setStylesheet(stylesheet);
    setXPathContext(new XPathContext(this));
    getXPathContext().setNamespaceContext(stylesheet);
  }
  
  // ================ ExtensionsTable ===================

  /**
   * The table of ExtensionHandlers.
   */
  private ExtensionsTable m_extensionsTable = null;

  /**
   * Get the extensions table object.
   *
   * @return The extensions table.
   */
  public ExtensionsTable getExtensionsTable()
  {
    return m_extensionsTable;
  }

  /**
   * If the stylesheet contains extensions, set the extensions table object.
   *
   *
   * @param sroot The stylesheet.
   * @throws javax.xml.transform.TransformerException
   */
  void setExtensionsTable(StylesheetRoot sroot)
       throws javax.xml.transform.TransformerException
  {
    try
    {
      if (sroot.getExtensions() != null)
        m_extensionsTable = new ExtensionsTable(sroot);
    }
    catch (javax.xml.transform.TransformerException te)
    {te.printStackTrace();}
  }
  
  //== Implementation of the XPath ExtensionsProvider interface.
  
  public boolean functionAvailable(String ns, String funcName)
          throws javax.xml.transform.TransformerException
  {
    return getExtensionsTable().functionAvailable(ns, funcName);
  }
  
  public boolean elementAvailable(String ns, String elemName)
          throws javax.xml.transform.TransformerException
  {
    return getExtensionsTable().elementAvailable(ns, elemName);   
  }
   
  public Object extFunction(String ns, String funcName, 
                            Vector argVec, Object methodKey)
            throws javax.xml.transform.TransformerException
  {//System.out.println("TransImpl.extFunction() " + ns + " " + funcName +" " + getExtensionsTable());
    return getExtensionsTable().extFunction(ns, funcName, 
                                        argVec, methodKey,
                                        getXPathContext().getExpressionContext());   
  }
  
  //=========================

  /**
   * Reset the state.  This needs to be called after a process() call
   * is invoked, if the processor is to be used again.
   */
  public void reset()
  {

    if (!m_hasBeenReset && m_shouldReset)
    {
      m_hasBeenReset = true;

      if (this.m_outputStream != null)
      {
        try
        {
          m_outputStream.close();
        }
        catch (java.io.IOException ioe){}
      }

      m_outputStream = null;

      // I need to look more carefully at which of these really
      // needs to be reset.
      m_countersTable = null;
      m_stackGuard = new StackGuard();

      m_xcontext.reset();
      
      m_xcontext.getVarStack().reset();
      resetUserParameters();
      

      int n = m_currentTemplateElements.length;
      for (int i = 0; i < n; i++) 
      {
        m_currentTemplateElements[i] = null;
      }
      m_currentTemplateElementsTop = 0;
      
      m_currentMatchTemplates.removeAllElements();
      m_currentMatchedNodes.removeAllElements();

      m_resultTreeHandler = null;
      m_outputTarget = null;
      m_keyManager = new KeyManager();
      m_attrSetStack = null;
      m_countersTable = null;
      m_currentTemplateRuleIsNull = new BoolStack();
      m_xmlSource = null;
      m_doc = DTM.NULL;
      m_isTransformDone = false;
      m_transformThread = null;

      // m_inputContentHandler = null;
      // For now, reset the document cache each time.
      m_xcontext.getSourceTreeManager().reset();
    }

    //    m_reportInPostExceptionFromThread = false;
  }

  /**
   * <code>getProperty</code> returns the current setting of the
   * property described by the <code>property</code> argument.
   *
   * %REVIEW% Obsolete now that source_location is handled in the TransformerFactory?
   *
   * @param property a <code>String</code> value
   * @return a <code>boolean</code> value
   */
  public boolean getProperty(String property)
  {
    return false;
  }

  /**
   * Set a runtime property for this <code>TransformerImpl</code>.
   *
   * %REVIEW% Obsolete now that source_location is handled in the TransformerFactory?
   *
   * @param property a <code>String</code> value
   * @param value an <code>Object</code> value
   */
  public void setProperty(String property, Object value)
  {
  }

  // ========= Transformer Interface Implementation ==========

  /**
   * <meta name="usage" content="experimental"/>
   * Get true if the parser events should be on the main thread,
   * false if not.  Experimental.  Can not be set right now.
   *
   * @return true if the parser events should be on the main thread,
   * false if not.
   */
  public boolean isParserEventsOnMain()
  {
    return m_parserEventsOnMain;
  }

  /**
   * <meta name="usage" content="internal"/>
   * Get the thread that the transform process is on.
   *
   * @return The thread that the transform process is on, or null.
   */
  public Thread getTransformThread()
  {
    return m_transformThread;
  }

  /**
   * <meta name="usage" content="internal"/>
   * Get the thread that the transform process is on.
   *
   * @param t The transform thread, may be null.
   */
  public void setTransformThread(Thread t)
  {
    m_transformThread = t;
  }

  /** NEEDSDOC Field m_hasTransformThreadErrorCatcher          */
  private boolean m_hasTransformThreadErrorCatcher = false;

  /**
   * Return true if the transform was initiated from the transform method,
   * otherwise it was probably done from a pure parse events.
   *
   * NEEDSDOC ($objectName$) @return
   */
  public boolean hasTransformThreadErrorCatcher()
  {
    return m_hasTransformThreadErrorCatcher;
  }
        
        /**
   * Process the source tree to SAX parse events.
   * @param source  The input for the source tree.
   *
   * @throws TransformerException
   */
  public void transform(Source source) throws TransformerException
  {
                transform(source, true); 
        }

  /**
   * Process the source tree to SAX parse events.
   * @param source  The input for the source tree.
   * @param shouldRelease  Flag indicating whether to release DTMManager.
   *
   * @throws TransformerException
   */
  public void transform(Source source, boolean shouldRelease) throws TransformerException
  {

    try
    {
      String base = source.getSystemId();
      
      // If no systemID of the source, use the base of the stylesheet.
      if(null == base)
      {
        base = m_stylesheetRoot.getBaseIdentifier();
      }

      // As a last resort, use the current user dir.
      if(null == base)
      {
        String currentDir = "";
        try {
          currentDir = System.getProperty("user.dir");
        }
        catch (SecurityException se) {}// user.dir not accessible from applet
              
        if (currentDir.startsWith(java.io.File.separator))
          base = "file://" + currentDir;
        else
          base = "file:///" + currentDir;
        
        base = base + java.io.File.separatorChar
               + source.getClass().getName();
      }
      setBaseURLOfSource(base);
      DTMManager mgr = m_xcontext.getDTMManager();
      DTM dtm = mgr.getDTM(source, false, this, true, true);
      dtm.setDocumentBaseURI(base);
      
      boolean hardDelete = true;  // %REVIEW% I have to think about this. -sb

      try
      {
      	// NOTE: This will work because this is _NOT_ a shared DTM, and thus has
      	// only a single Document node. If it could ever be an RTF or other
      	// shared DTM, look at dtm.getDocumentRoot(nodeHandle).
        this.transformNode(dtm.getDocument());
      }
      finally
      {
        if (shouldRelease)
          mgr.release(dtm, hardDelete);
      }

      // Kick off the parse.  When the ContentHandler gets 
      // the startDocument event, it will call transformNode( node ).
      // reader.parse( xmlSource );
      // This has to be done to catch exceptions thrown from 
      // the transform thread spawned by the STree handler.
      Exception e = getExceptionThrown();

      if (null != e)
      {
        if (e instanceof javax.xml.transform.TransformerException)
        {
          throw (javax.xml.transform.TransformerException) e;
        }
        else if (e instanceof org.apache.xml.utils.WrappedRuntimeException)
        {
          fatalError(
              ((org.apache.xml.utils.WrappedRuntimeException) e).getException());
        }
        else
        {
          throw new javax.xml.transform.TransformerException(e);
        }
      }
      else if (null != m_resultTreeHandler)
      {
        m_resultTreeHandler.endDocument();
      }
    }
    catch (org.apache.xml.utils.WrappedRuntimeException wre)
    {
      Throwable throwable = wre.getException();

      while (throwable
             instanceof org.apache.xml.utils.WrappedRuntimeException)
      {
        throwable =
          ((org.apache.xml.utils.WrappedRuntimeException) throwable).getException();
      }

      fatalError(throwable);
    }

    // Patch attributed to David Eisenberg <david@catcode.com>
    catch (org.xml.sax.SAXParseException spe)
    {
      fatalError(spe);
    }
    catch (org.xml.sax.SAXException se)
    {
      m_errorHandler.fatalError(new TransformerException(se));
    }
    finally
    {
      m_hasTransformThreadErrorCatcher = false;

      // This looks to be redundent to the one done in TransformNode.
      reset();
    }
  }
  
  private void fatalError(Throwable throwable) throws TransformerException
  {
    if (throwable instanceof org.xml.sax.SAXParseException)
      m_errorHandler.fatalError(new TransformerException(throwable.getMessage(),new SAXSourceLocator((org.xml.sax.SAXParseException)throwable)));
    else
      m_errorHandler.fatalError(new TransformerException(throwable));
    
  }

  /**
   * Get the base URL of the source.
   *
   * @return The base URL of the source tree, or null.
   */
  public String getBaseURLOfSource()
  {
    return m_urlOfSource;
  }

  /**
   * Get the base URL of the source.
   *
   *
   * NEEDSDOC @param base
   * @return The base URL of the source tree, or null.
   */
  public void setBaseURLOfSource(String base)
  {
    m_urlOfSource = base;
  }

  /**
   * Get the original output target.
   *
   * @return The Result object used to kick of the transform or null.
   */
  public Result getOutputTarget()
  {
    return m_outputTarget;
  }

  /**
   * Set the original output target.  This is useful when using a SAX transform and
   * supplying a ContentHandler or when the URI of the output target should
   * not be the same as the systemID of the original output target.
   *
   *
   * NEEDSDOC @param outputTarget
   */
  public void setOutputTarget(Result outputTarget)
  {
    m_outputTarget = outputTarget;
  }

  /**
   * Get an output property that is in effect for the
   * transformation.  The property specified may be a property
   * that was set with setOutputProperty, or it may be a
   * property specified in the stylesheet.
   *
   * @param name A non-null String that specifies an output
   * property name, which may be namespace qualified.
   *
   * NEEDSDOC @param qnameString
   *
   * @return The string value of the output property, or null
   * if no property was found.
   *
   * @throws IllegalArgumentException If the property is not supported.
   *
   * @see javax.xml.transform.OutputKeys
   */
  public String getOutputProperty(String qnameString)
          throws IllegalArgumentException
  {

    String value = null;
    OutputProperties props = getOutputFormat();

    value = props.getProperty(qnameString);

    if (null == value)
    {
      if (!props.isLegalPropertyKey(qnameString))
        throw new IllegalArgumentException(XSLMessages.createMessage(XSLTErrorResources.ER_OUTPUT_PROPERTY_NOT_RECOGNIZED, new Object[]{qnameString})); //"output property not recognized: "
                                           //+ qnameString);
    }

    return value;
  }

  /**
   * Get the value of a property, without using the default properties.  This
   * can be used to test if a property has been explicitly set by the stylesheet
   * or user.
   *
   * @param name The property name, which is a fully-qualified URI.
   *
   * NEEDSDOC @param qnameString
   *
   * @return The value of the property, or null if not found.
   *
   * @throws IllegalArgumentException If the property is not supported,
   * and is not namespaced.
   */
  public String getOutputPropertyNoDefault(String qnameString)
          throws IllegalArgumentException
  {

    String value = null;
    OutputProperties props = getOutputFormat();

    value = (String) props.getProperties().get(qnameString);

    if (null == value)
    {
      if (!props.isLegalPropertyKey(qnameString))
        throw new IllegalArgumentException(XSLMessages.createMessage(XSLTErrorResources.ER_OUTPUT_PROPERTY_NOT_RECOGNIZED, new Object[]{qnameString})); //"output property not recognized: "
                                          // + qnameString);
    }

    return value;
  }

  /**
   * Set the value of a property.  Recognized properties are:
   *
   * <p>"http://xml.apache.org/xslt/sourcebase" - the base URL for the
   * source, which is needed when pure SAX ContentHandler transformation
   * is to be done.</p>
   *
   * @param name The property name, which is a fully-qualified URI.
   * @param value The requested value for the property.
   * @throws IllegalArgumentException if the property name is not legal.
   */
  public void setOutputProperty(String name, String value)
          throws IllegalArgumentException
  {

    synchronized (m_reentryGuard)
    {

      // Get the output format that was set by the user, otherwise get the 
      // output format from the stylesheet.
      if (null == m_outputFormat)
      {
        m_outputFormat =
          (OutputProperties) getStylesheet().getOutputComposed().clone();
      }

      if (!m_outputFormat.isLegalPropertyKey(name))
        throw new IllegalArgumentException(XSLMessages.createMessage(XSLTErrorResources.ER_OUTPUT_PROPERTY_NOT_RECOGNIZED, new Object[]{name})); //"output property not recognized: "
                                           //+ name);

      m_outputFormat.setProperty(name, value);
    }
  }

  /**
   * Set the output properties for the transformation.  These
   * properties will override properties set in the templates
   * with xsl:output.
   *
   * <p>If argument to this function is null, any properties
   * previously set will be removed.</p>
   *
   * @param oformat A set of output properties that will be
   * used to override any of the same properties in effect
   * for the transformation.
   */
  public void setOutputProperties(Properties oformat)
  {

    synchronized (m_reentryGuard)
    {
      if (null != oformat)
      {

        // See if an *explicit* method was set.
        String method = (String) oformat.get(OutputKeys.METHOD);

        if (null != method)
          m_outputFormat = new OutputProperties(method);
        else if(m_outputFormat==null)
          m_outputFormat = new OutputProperties();
      }

      if (null != oformat)
      {
        m_outputFormat.copyFrom(oformat);
      }

      // copyFrom does not set properties that have been already set, so 
      // this must be called after, which is a bit in the reverse from 
      // what one might think.
      m_outputFormat.copyFrom(m_stylesheetRoot.getOutputProperties());
    }
  }

  /**
   * Get a copy of the output properties for the transformation.  These
   * properties will override properties set in the templates
   * with xsl:output.
   *
   * <p>Note that mutation of the Properties object returned will not
   * effect the properties that the transformation contains.</p>
   *
   * @returns A copy of the set of output properties in effect
   * for the next transformation.
   *
   * NEEDSDOC ($objectName$) @return
   */
  public Properties getOutputProperties()
  {
    return (Properties) getOutputFormat().getProperties().clone();
  }

  /**
   * Create a result ContentHandler from a Result object, based
   * on the current OutputProperties.
   *
   * @param outputTarget Where the transform result should go,
   * should not be null.
   *
   * @return A valid ContentHandler that will create the
   * result tree when it is fed SAX events.
   *
   * @throws TransformerException
   */
  public ContentHandler createResultContentHandler(Result outputTarget)
          throws TransformerException
  {
    return createResultContentHandler(outputTarget, getOutputFormat());
  }

  /**
   * Create a ContentHandler from a Result object and an OutputProperties.
   *
   * @param outputTarget Where the transform result should go,
   * should not be null.
   * @param format The OutputProperties object that will contain
   * instructions on how to serialize the output.
   *
   * @return A valid ContentHandler that will create the
   * result tree when it is fed SAX events.
   *
   * @throws TransformerException
   */
  public ContentHandler createResultContentHandler(
          Result outputTarget, OutputProperties format)
            throws TransformerException
  {

    ContentHandler handler = null;

    // If the Result object contains a Node, then create 
    // a ContentHandler that will add nodes to the input node.
    org.w3c.dom.Node outputNode = null;

    if (outputTarget instanceof DOMResult)
    {
      outputNode = ((DOMResult) outputTarget).getNode();

      org.w3c.dom.Document doc;
      short type;

      if (null != outputNode)
      {
        type = outputNode.getNodeType();
        doc = (org.w3c.dom.Node.DOCUMENT_NODE == type)
              ? (org.w3c.dom.Document) outputNode
              : outputNode.getOwnerDocument();
      }
      else
      {
        doc = org.apache.xpath.DOMHelper.createDocument();
        outputNode = doc;
        type = outputNode.getNodeType();

        ((DOMResult) outputTarget).setNode(outputNode);
      }

      handler =
        (org.w3c.dom.Node.DOCUMENT_FRAGMENT_NODE == type)
        ? new DOMBuilder(doc, (org.w3c.dom.DocumentFragment) outputNode)
        : new DOMBuilder(doc, outputNode);
    }
    else if (outputTarget instanceof SAXResult)
    {
      handler = ((SAXResult) outputTarget).getHandler();

      if (null == handler)
        throw new IllegalArgumentException(
          "handler can not be null for a SAXResult");
    }

    // Otherwise, create a ContentHandler that will serialize the 
    // result tree to either a stream or a writer.
    else if (outputTarget instanceof StreamResult)
    {
      StreamResult sresult = (StreamResult) outputTarget;
      String method = format.getProperty(OutputKeys.METHOD);

      try
      {
        Serializer serializer =
          SerializerFactory.getSerializer(format.getProperties());

        if (null != sresult.getWriter())
          serializer.setWriter(sresult.getWriter());
        else if (null != sresult.getOutputStream())
          serializer.setOutputStream(sresult.getOutputStream());
        else if (null != sresult.getSystemId())
        {
          String fileURL = sresult.getSystemId();

          if (fileURL.startsWith("file:///"))
          {
            if (fileURL.substring(8).indexOf(":") >0)
              fileURL = fileURL.substring(8);
            else 
              fileURL = fileURL.substring(7);
          }

          m_outputStream = new java.io.FileOutputStream(fileURL);

          serializer.setOutputStream(m_outputStream);
        }
        else
          throw new TransformerException(XSLMessages.createMessage(XSLTErrorResources.ER_NO_OUTPUT_SPECIFIED, null)); //"No output specified!");

        handler = serializer.asContentHandler();

        this.setSerializer(serializer);
      }
      catch (UnsupportedEncodingException uee)
      {
        throw new TransformerException(uee);
      }
      catch (IOException ioe)
      {
        throw new TransformerException(ioe);
      }
    }
    else
    {
      throw new TransformerException(XSLMessages.createMessage(XSLTErrorResources.ER_CANNOT_TRANSFORM_TO_RESULT_TYPE, new Object[]{outputTarget.getClass().getName()})); //"Can't transform to a Result of type "
                                     //+ outputTarget.getClass().getName()
                                     //+ "!");
    }

    return handler;
  }
        
        /**
   * Process the source tree to the output result.
   * @param xmlSource  The input for the source tree.
   * @param outputTarget The output source target.
   *
   * @throws TransformerException
   */
  public void transform(Source xmlSource, Result outputTarget)
          throws TransformerException
  {
                transform(xmlSource, outputTarget, true);
        }

  /**
   * Process the source tree to the output result.
   * @param xmlSource  The input for the source tree.
   * @param outputTarget The output source target.
   * @param shouldRelease  Flag indicating whether to release DTMManager. 
   *
   * @throws TransformerException
   */
  public void transform(Source xmlSource, Result outputTarget, boolean shouldRelease)
          throws TransformerException
  {

    synchronized (m_reentryGuard)
    {
      ContentHandler handler = createResultContentHandler(outputTarget);

      m_outputTarget = outputTarget;

      this.setContentHandler(handler);
      transform(xmlSource, shouldRelease);
    }
  }

  /**
   * Process the source node to the output result, if the
   * processor supports the "http://xml.org/trax/features/dom/input"
   * feature.
   * %REVIEW% Do we need a Node version of this?
   * @param node  The input source node, which can be any valid DTM node.
   * @param outputTarget The output source target.
   *
   * @throws TransformerException
   */
  public void transformNode(int node, Result outputTarget)
          throws TransformerException
  {
    

    ContentHandler handler = createResultContentHandler(outputTarget);

    m_outputTarget = outputTarget;

    this.setContentHandler(handler);
    transformNode(node);
  }

  /**
   * Process the source node to the output result, if the
   * processor supports the "http://xml.org/trax/features/dom/input"
   * feature.
   * %REVIEW% Do we need a Node version of this?
   * @param node  The input source node, which can be any valid DTM node.
   * @param outputTarget The output source target.
   *
   * @throws TransformerException
   */
  public void transformNode(int node) throws TransformerException
  {
    //dml
    setExtensionsTable(getStylesheet());
    // Make sure we're not writing to the same output content handler.
    synchronized (m_outputContentHandler)
    {
      m_hasBeenReset = false;
      
      XPathContext xctxt = getXPathContext();
      DTM dtm = xctxt.getDTM(node);

      try
      {
        pushGlobalVars(node);

        // ==========
        // Give the top-level templates a chance to pass information into 
        // the context (this is mainly for setting up tables for extensions).
        StylesheetRoot stylesheet = this.getStylesheet();
        int n = stylesheet.getGlobalImportCount();

        for (int i = 0; i < n; i++)
        {
          StylesheetComposed imported = stylesheet.getGlobalImport(i);
          int includedCount = imported.getIncludeCountComposed();

          for (int j = -1; j < includedCount; j++)
          {
            Stylesheet included = imported.getIncludeComposed(j);

            included.runtimeInit(this);

            for (ElemTemplateElement child = included.getFirstChildElem();
                    child != null; child = child.getNextSiblingElem())
            {
              child.runtimeInit(this);
            }
          }
        }
        // ===========        
        // System.out.println("Calling applyTemplateToNode - "+Thread.currentThread().getName());
        DTMIterator dtmIter = new org.apache.xpath.axes.SelfIteratorNoPredicate();
        dtmIter.setRoot(node, xctxt);
        xctxt.pushContextNodeList(dtmIter);
        try
        {
          this.applyTemplateToNode(null, null, node);
        }
        finally
        {
          xctxt.popContextNodeList();
        }
        // m_stylesheetRoot.getStartRule().execute(this);

        // System.out.println("Done with applyTemplateToNode - "+Thread.currentThread().getName());
        if (null != m_resultTreeHandler)
        {
          m_resultTreeHandler.endDocument();
        }
      }
      catch (Exception se)
      {

        // System.out.println(Thread.currentThread().getName()+" threw an exception! "
        //                   +se.getMessage());
        // If an exception was thrown, we need to make sure that any waiting 
        // handlers can terminate, which I guess is best done by sending 
        // an endDocument.
        
        // SAXSourceLocator
        while(se instanceof org.apache.xml.utils.WrappedRuntimeException)
        {
          Exception e = ((org.apache.xml.utils.WrappedRuntimeException)se).getException();
          if(null != e)
            se = e;
        }
        
        if (null != m_resultTreeHandler)
        {
          try
          {
            if(se instanceof org.xml.sax.SAXParseException)
              m_resultTreeHandler.fatalError((org.xml.sax.SAXParseException)se);
            else if(se instanceof TransformerException)
            {
              TransformerException te = ((TransformerException)se);
              SAXSourceLocator sl = new SAXSourceLocator( te.getLocator() );
              m_resultTreeHandler.fatalError(new org.xml.sax.SAXParseException(te.getMessage(), sl, te)); 
            }
            else
            {
              m_resultTreeHandler.fatalError(new org.xml.sax.SAXParseException(se.getMessage(), new SAXSourceLocator(), se)); 
            }             
          }
          catch (Exception e){}
        }        
        
        if(se instanceof TransformerException)
        {
          m_errorHandler.fatalError((TransformerException)se);
        }
        else if(se instanceof org.xml.sax.SAXParseException)
        {
          m_errorHandler.fatalError(new TransformerException(se.getMessage(), 
                      new SAXSourceLocator((org.xml.sax.SAXParseException)se), 
                      se));
        }
        else
        {
          m_errorHandler.fatalError(new TransformerException(se));
        }
        
      }
      finally
      {
        this.reset();
      }
    }
  }

  /**
   * Get a SAX2 ContentHandler for the input.
   *
   * @return A valid ContentHandler, which should never be null, as
   * long as getFeature("http://xml.org/trax/features/sax/input")
   * returns true.
   */
  public ContentHandler getInputContentHandler()
  {
    return getInputContentHandler(false);
  }

  /**
   * Get a SAX2 ContentHandler for the input.
   *
   * @param doDocFrag true if a DocumentFragment should be created as
   * the root, rather than a Document.
   *
   * @return A valid ContentHandler, which should never be null, as
   * long as getFeature("http://xml.org/trax/features/sax/input")
   * returns true.
   */
  public ContentHandler getInputContentHandler(boolean doDocFrag)
  {

    if (null == m_inputContentHandler)
    {

      //      if(null == m_urlOfSource && null != m_stylesheetRoot)
      //        m_urlOfSource = m_stylesheetRoot.getBaseIdentifier();
      m_inputContentHandler = new TransformerHandlerImpl(this, doDocFrag,
              m_urlOfSource);
    }

    return m_inputContentHandler;
  }

  /**
   * Get a SAX2 DeclHandler for the input.
   * @return A valid DeclHandler, which should never be null, as
   * long as getFeature("http://xml.org/trax/features/sax/input")
   * returns true.
   */
  public DeclHandler getInputDeclHandler()
  {

    if (m_inputContentHandler instanceof DeclHandler)
      return (DeclHandler) m_inputContentHandler;
    else
      return null;
  }

  /**
   * Get a SAX2 LexicalHandler for the input.
   * @return A valid LexicalHandler, which should never be null, as
   * long as getFeature("http://xml.org/trax/features/sax/input")
   * returns true.
   */
  public LexicalHandler getInputLexicalHandler()
  {

    if (m_inputContentHandler instanceof LexicalHandler)
      return (LexicalHandler) m_inputContentHandler;
    else
      return null;
  }

  /**
   * Set the output properties for the transformation.  These
   * properties will override properties set in the templates
   * with xsl:output.
   *
   * @param oformat A valid OutputProperties object (which will
   * not be mutated), or null.
   */
  public void setOutputFormat(OutputProperties oformat)
  {
    m_outputFormat = oformat;
  }

  /**
   * Get the output properties used for the transformation.
   *
   * @return the output format that was set by the user,
   * otherwise the output format from the stylesheet.
   */
  public OutputProperties getOutputFormat()
  {

    // Get the output format that was set by the user, otherwise get the 
    // output format from the stylesheet.
    OutputProperties format = (null == m_outputFormat)
                              ? getStylesheet().getOutputComposed()
                              : m_outputFormat;

    return format;
  }

  /**
   * <meta name="usage" content="internal"/>
   * Get the current serializer in use, which may well not
   * be the main serializer (for instance, this may well be
   * a text serializer for string creation from templates).
   *
   * @return The current serializer, or null if there is none.
   */
  public Serializer getSerializer()
  {
    return m_serializer;
  }

  /**
   * <meta name="usage" content="internal"/>
   * Set the current serializer.
   *
   * @param s The current serializer, or null.
   */
  public void setSerializer(Serializer s)
  {
    m_serializer = s;
  }
  
  /**
   * Set a parameter for the templates.
   * 
   * @param name The name of the parameter.
   * @param namespace The namespace of the parameter.
   * @param value The value object.  This can be any valid Java object
   * -- it's up to the processor to provide the proper
   * coersion to the object, or simply pass it on for use
   * in extensions.
   */
  public void setParameter(String name, String namespace, Object value)
  {

    VariableStack varstack = getXPathContext().getVarStack();
    QName qname = new QName(namespace, name);
    XObject xobject = XObject.create(value, getXPathContext());
    
    StylesheetRoot sroot = m_stylesheetRoot;
    Vector vars = sroot.getVariablesAndParamsComposed();
    int i = vars.size();
    while (--i >= 0)
    {
      ElemVariable variable = (ElemVariable)vars.elementAt(i);
      if(variable.getXSLToken() == Constants.ELEMNAME_PARAMVARIABLE && 
         variable.getName().equals(qname))
      {
          varstack.setGlobalVariable(i, xobject);
      }
    }
  }

  /** NEEDSDOC Field m_userParams          */
  Vector m_userParams;

  /**
   * Set a parameter for the transformation.
   *
   * @param name The name of the parameter,
   *             which may have a namespace URI.
   * @param value The value object.  This can be any valid Java object
   * -- it's up to the processor to provide the proper
   * coersion to the object, or simply pass it on for use
   * in extensions.
   */
  public void setParameter(String name, Object value)
  {

    StringTokenizer tokenizer = new StringTokenizer(name, "{}", false);

    try
    {

      // The first string might be the namespace, or it might be 
      // the local name, if the namespace is null.
      String s1 = tokenizer.nextToken();
      String s2 = tokenizer.hasMoreTokens() ? tokenizer.nextToken() : null;

      if (null == m_userParams)
        m_userParams = new Vector();

      if (null == s2)
      {
        replaceOrPushUserParam(new QName(s1), XObject.create(value, getXPathContext()));
        setParameter(s1, null, value);
      }
      else
      {
        replaceOrPushUserParam(new QName(s1, s2), XObject.create(value, getXPathContext()));
        setParameter(s2, s1, value);
      }
    }
    catch (java.util.NoSuchElementException nsee)
    {

      // Should throw some sort of an error.
    }
  }

  /**
   * NEEDSDOC Method replaceOrPushUserParam 
   *
   *
   * NEEDSDOC @param qname
   * NEEDSDOC @param xval
   */
  private void replaceOrPushUserParam(QName qname, XObject xval)
  {

    int n = m_userParams.size();

    for (int i = n - 1; i >= 0; i--)
    {
      Arg arg = (Arg) m_userParams.elementAt(i);

      if (arg.getQName().equals(qname))
      {
        m_userParams.setElementAt(new Arg(qname, xval, true), i);

        return;
      }
    }

    m_userParams.addElement(new Arg(qname, xval, true));
  }

  /**
   * Get a parameter that was explicitly set with setParameter
   * or setParameters.
   *
   *
   * NEEDSDOC @param name
   * @return A parameter that has been set with setParameter
   * or setParameters,
   * *not* all the xsl:params on the stylesheet (which require
   * a transformation Source to be evaluated).
   */
  public Object getParameter(String name)
  {

    try
    {

      // VariableStack varstack = getXPathContext().getVarStack();
      // The first string might be the namespace, or it might be 
      // the local name, if the namespace is null.
      QName qname = QName.getQNameFromString(name);

      if (null == m_userParams)
        return null;

      int n = m_userParams.size();

      for (int i = n - 1; i >= 0; i--)
      {
        Arg arg = (Arg) m_userParams.elementAt(i);

        if (arg.getQName().equals(qname))
        {
          return arg.getVal().object();
        }
      }

      return null;
    }
    catch (java.util.NoSuchElementException nsee)
    {

      // Should throw some sort of an error.
      return null;
    }
  }
  
  /**
   * Reset parameters that the user specified for the transformation.
   * Called during transformer.reset() after we have cleared the 
   * variable stack. We need to make sure that user params are
   * reset so that the transformer object can be reused. 
   */
  private void resetUserParameters()
  {

    try
    {
      
      if (null == m_userParams)
        return;

      int n = m_userParams.size();
      for (int i = n - 1; i >= 0; i--)
      {
        Arg arg = (Arg) m_userParams.elementAt(i);
        QName name = arg.getQName();
        // The first string might be the namespace, or it might be 
        // the local name, if the namespace is null.
        String s1 = name.getNamespace();
        String s2 = name.getLocalPart();

        setParameter(s2, s1, arg.getVal().object());
        
      }
      
    }
    catch (java.util.NoSuchElementException nsee)
    {
      // Should throw some sort of an error.
      
    }
  }

  /**
   * Set a bag of parameters for the transformation. Note that
   * these will not be additive, they will replace the existing
   * set of parameters.
   *
   * @param name The name of the parameter,
   *             which may have a namespace URI.
   * @param value The value object.  This can be any valid Java object
   * -- it's up to the processor to provide the proper
   * coersion to the object, or simply pass it on for use
   * in extensions.
   *
   * NEEDSDOC @param params
   */
  public void setParameters(Properties params)
  {

    clearParameters();

    Enumeration names = params.propertyNames();

    while (names.hasMoreElements())
    {
      String name = params.getProperty((String) names.nextElement());
      StringTokenizer tokenizer = new StringTokenizer(name, "{}", false);

      try
      {

        // The first string might be the namespace, or it might be 
        // the local name, if the namespace is null.
        String s1 = tokenizer.nextToken();
        String s2 = tokenizer.hasMoreTokens() ? tokenizer.nextToken() : null;

        if (null == s2)
          setParameter(s1, null, params.getProperty(name));
        else
          setParameter(s2, s1, params.getProperty(name));
      }
      catch (java.util.NoSuchElementException nsee)
      {

        // Should throw some sort of an error.
      }
    }
  }

  /**
   * Reset the parameters to a null list.
   */
  public void clearParameters()
  {

    synchronized (m_reentryGuard)
    {
      VariableStack varstack = new VariableStack();

      m_xcontext.setVarStack(varstack);

      m_userParams = null;
    }
  }


  /**
   * Internal -- push the global variables from the Stylesheet onto
   * the context's runtime variable stack.
   * <p>If we encounter a variable
   * that is already defined in the variable stack, we ignore it.  This
   * is because the second variable definition will be at a lower import
   * precedence.  Presumably, global"variables at the same import precedence
   * with the same name will have been caught during the recompose process.
   * <p>However, if we encounter a parameter that is already defined in the
   * variable stack, we need to see if this is a parameter whose value was
   * supplied by a setParameter call.  If so, we need to "receive" the one
   * already in the stack, ignoring this one.  If it is just an earlier
   * xsl:param or xsl:variable definition, we ignore it using the same
   * reasoning as explained above for the variable.
   *
   * @param contextNode The root of the source tree, can't be null.
   *
   * @throws TransformerException
   */
  protected void pushGlobalVars(int contextNode) throws TransformerException
  {

    XPathContext xctxt = m_xcontext;
    VariableStack vs = xctxt.getVarStack();
    StylesheetRoot sr = getStylesheet();
    Vector vars = sr.getVariablesAndParamsComposed();
    
    int i = vars.size();
    vs.link(i);

    while (--i >= 0)
    {
      ElemVariable v = (ElemVariable) vars.elementAt(i);

      // XObject xobj = v.getValue(this, contextNode);
      XObject xobj = new XUnresolvedVariable(v, contextNode, this,
                                     vs.getStackFrame(), 0, true);
      
      if(null == vs.elementAt(i))                               
        vs.setGlobalVariable(i, xobj);
    }

  }

  /**
   * Set an object that will be used to resolve URIs used in
   * document(), etc.
   * @param resolver An object that implements the URIResolver interface,
   * or null.
   */
  public void setURIResolver(URIResolver resolver)
  {

    synchronized (m_reentryGuard)
    {
      m_xcontext.getSourceTreeManager().setURIResolver(resolver);
    }
  }

  /**
   * Get an object that will be used to resolve URIs used in
   * document(), etc.
   *
   * @return An object that implements the URIResolver interface,
   * or null.
   */
  public URIResolver getURIResolver()
  {
    return m_xcontext.getSourceTreeManager().getURIResolver();
  }

  // ======== End Transformer Implementation ========  

  /**
   * Set the content event handler.
   *
   * @param resolver The new content handler.
   *
   * NEEDSDOC @param handler
   * @throws java.lang.NullPointerException If the handler
   *            is null.
   * @see org.xml.sax.XMLReader#setContentHandler
   */
  public void setContentHandler(ContentHandler handler)
  {

    if (handler == null)
    {
      throw new NullPointerException(XSLMessages.createMessage(XSLTErrorResources.ER_NULL_CONTENT_HANDLER, null)); //"Null content handler");
    }
    else
    {
      m_outputContentHandler = handler;

      if (null == m_resultTreeHandler)
        m_resultTreeHandler = new ResultTreeHandler(this, handler);
      else
        m_resultTreeHandler.setContentHandler(handler);
    }
  }

  /**
   * Get the content event handler.
   *
   * @return The current content handler, or null if none was set.
   * @see org.xml.sax.XMLReader#getContentHandler
   */
  public ContentHandler getContentHandler()
  {
    return m_outputContentHandler;
  }

  /**
   * <meta name="usage" content="advanced"/>
   * Given a stylesheet element, create a result tree fragment from it's
   * contents. The fragment will be built within the shared RTF DTM system
   * used as a variable stack.
   * @param templateParent The template element that holds the fragment.
   * @return the NodeHandle for the root node of the resulting RTF.
   *
   * @throws TransformerException
   */
  public int transformToRTF(ElemTemplateElement templateParent)
          throws TransformerException
  {
    // Retrieve a DTM to contain the RTF. At this writing, this may be a
    // multi-document DTM (SAX2RTFDTM).
    DTM dtmFrag = m_xcontext.getRTFDTM();
    return transformToRTF(templateParent,dtmFrag);
  }
  
  /**
   * <meta name="usage" content="advanced"/>
   * Given a stylesheet element, create a result tree fragment from it's
   * contents. The fragment will also use the shared DTM system, but will
   * obtain its space from the global variable pool rather than the dynamic
   * variable stack. This allows late binding of XUnresolvedVariables without
   * the risk that their content will be discarded when the variable stack
   * is popped.
   * 
   * @param templateParent The template element that holds the fragment.
   * @return the NodeHandle for the root node of the resulting RTF.
   *
   * @throws TransformerException
   */
  public int transformToGlobalRTF(ElemTemplateElement templateParent)
          throws TransformerException
  {
    // Retrieve a DTM to contain the RTF. At this writing, this may be a
    // multi-document DTM (SAX2RTFDTM).
    DTM dtmFrag = m_xcontext.getGlobalRTFDTM();
    return transformToRTF(templateParent,dtmFrag);
  }
  
  /**
   * <meta name="usage" content="advanced"/>
   * Given a stylesheet element, create a result tree fragment from it's
   * contents.
   * @param templateParent The template element that holds the fragment.
   * @param dtmFrag The DTM to write the RTF into
   * @return the NodeHandle for the root node of the resulting RTF.
   *
   * @throws TransformerException
   */
  private int transformToRTF(ElemTemplateElement templateParent,DTM dtmFrag)
          throws TransformerException
  {

    XPathContext xctxt = m_xcontext;
    
    ContentHandler rtfHandler = dtmFrag.getContentHandler();

    // Obtain the ResultTreeFrag's root node.
    // NOTE: In SAX2RTFDTM, this value isn't available until after
    // the startDocument has been issued, so assignment has been moved
    // down a bit in the code.
    int resultFragment; // not yet reliably = dtmFrag.getDocument();

    // Save the current result tree handler.
    ResultTreeHandler savedRTreeHandler = this.m_resultTreeHandler;

    // And make a new handler for the RTF.
    m_resultTreeHandler = new ResultTreeHandler(this, rtfHandler);

    ResultTreeHandler rth = m_resultTreeHandler;

    try
    {
      rth.startDocument();
      
      // startDocument is "bottlenecked" in RTH. We need it acted upon immediately,
      // to set the DTM's state as in-progress, so that if the xsl:variable's body causes
      // further RTF activity we can keep that from bashing this DTM.
      rth.flushPending(); 
 
      try
      {

        // Do the transformation of the child elements.
        executeChildTemplates(templateParent, true);

        // Make sure everything is flushed!
        rth.flushPending();
        
        // Get the document ID. May not exist until the RTH has not only
        // received, but flushed, the startDocument, and may be invalid
        // again after the document has been closed (still debating that)
        // ... so waiting until just before the end seems simplest/safest. 
	resultFragment = dtmFrag.getDocument();      
      }
      finally
      {
        rth.endDocument();
      }
    }
    catch (org.xml.sax.SAXException se)
    {
      throw new TransformerException(se);
    }
    finally
    {

      // Restore the previous result tree handler.
      this.m_resultTreeHandler = savedRTreeHandler;
    }

    return resultFragment;
  }

  /**
   * <meta name="usage" content="internal"/>
   * Get the StringWriter pool, so that StringWriter
   * objects may be reused.
   *
   * @return The string writer pool, not null.
   */
  public ObjectPool getStringWriterPool()
  {
    return m_stringWriterObjectPool;
  }

  /**
   * <meta name="usage" content="advanced"/>
   * Take the contents of a template element, process it, and
   * convert it to a string.
   *
   * @param elem The parent element whose children will be output
   * as a string.
   * @param transformer The XSLT transformer instance.
   * @param sourceNode The current source node context.
   * @param mode The current xslt mode.
   *
   * @return The stringized result of executing the elements children.
   *
   * @throws TransformerException
   */
  public String transformToString(ElemTemplateElement elem)
          throws TransformerException
  {
    ElemTemplateElement firstChild = elem.getFirstChildElem();
    if(null == firstChild)
      return "";
    if(elem.hasTextLitOnly() && org.apache.xalan.processor.TransformerFactoryImpl.m_optimize)
    {
      return ((ElemTextLiteral)firstChild).getNodeValue();
    }

    // Save the current result tree handler.
    ResultTreeHandler savedRTreeHandler = this.m_resultTreeHandler;

    // Create a Serializer object that will handle the SAX events 
    // and build the ResultTreeFrag nodes.
    StringWriter sw = (StringWriter) m_stringWriterObjectPool.getInstance();

    m_resultTreeHandler =
      (ResultTreeHandler) m_textResultHandlerObjectPool.getInstance();

    Serializer serializer = m_resultTreeHandler.getSerializer();

    try
    {
      if (null == serializer)
      {
        serializer =
          SerializerFactory.getSerializer(m_textformat.getProperties());

        m_resultTreeHandler.setSerializer(serializer);
        serializer.setWriter(sw);

        ContentHandler shandler = serializer.asContentHandler();

        m_resultTreeHandler.init(this, shandler);
      }
      else
      {

        // Leave Commented.  -sb
        // serializer.setWriter(sw);
        // serializer.setOutputFormat(m_textformat);
        // ContentHandler shandler = serializer.asContentHandler();
        // m_resultTreeHandler.setContentHandler(shandler);
      }
    }
    catch (IOException ioe)
    {
      throw new TransformerException(ioe);
    }

    String result;

    try
    {
      this.m_resultTreeHandler.startDocument();

      // Do the transformation of the child elements.
      executeChildTemplates(elem, true);
      this.m_resultTreeHandler.endDocument();

      result = sw.toString();
    }
    catch (org.xml.sax.SAXException se)
    {
      throw new TransformerException(se);
    }
    finally
    {
      sw.getBuffer().setLength(0);

      try
      {
        sw.close();
      }
      catch (Exception ioe){}

      m_stringWriterObjectPool.freeInstance(sw);
      m_textResultHandlerObjectPool.freeInstance(m_resultTreeHandler);
      m_resultTreeHandler.reset();

      // Restore the previous result tree handler.
      m_resultTreeHandler = savedRTreeHandler;
    }

    return result;
  }

  /**
   * <meta name="usage" content="advanced"/>
   * Given an element and mode, find the corresponding
   * template and process the contents.
   *
   * @param xslInstruction The calling element.
   * @param template The template to use if xsl:for-each, or null.
   * @param child The source context node.
   * @param mode The current mode, may be null.
   * @throws TransformerException
   * @return true if applied a template, false if not.
   */
  public boolean applyTemplateToNode(ElemTemplateElement xslInstruction,  // xsl:apply-templates or xsl:for-each
                                     ElemTemplate template, int child)
                                             throws TransformerException
  {

    DTM dtm = m_xcontext.getDTM(child);
    short nodeType = dtm.getNodeType(child);
    boolean isDefaultTextRule = false;

    if (null == template)
    {
      int maxImportLevel, endImportLevel=0;
      boolean isApplyImports = ((xslInstruction == null)
                                ? false
                                : xslInstruction.getXSLToken()
                                  == Constants.ELEMNAME_APPLY_IMPORTS);

      if (isApplyImports)
      {
        maxImportLevel =
          xslInstruction.getStylesheetComposed().getImportCountComposed() - 1;
        endImportLevel =
          xslInstruction.getStylesheetComposed().getEndImportCountComposed();
      }
      else
      {
        maxImportLevel = -1;
      }

      // If we're trying an xsl:apply-imports at the top level (ie there are no
      // imported stylesheets), we need to indicate that there is no matching template.
      // The above logic will calculate a maxImportLevel of -1 which indicates
      // that we should find any template.  This is because a value of -1 for
      // maxImportLevel has a special meaning.  But we don't want that.
      // We want to match -no- templates. See bugzilla bug 1170.
      if (isApplyImports && (maxImportLevel == -1))
      {
        template = null;
      }
      else
      {

        // Find the XSL template that is the best match for the 
        // element.        
        XPathContext xctxt = m_xcontext;

        try
        {
          xctxt.pushNamespaceContext(xslInstruction);

          QName mode = this.getMode();
          
          if (isApplyImports)
            template = m_stylesheetRoot.getTemplateComposed(xctxt, child, mode,
                  maxImportLevel, endImportLevel, m_quietConflictWarnings, dtm);
          else
            template = m_stylesheetRoot.getTemplateComposed(xctxt, child, mode,
                  m_quietConflictWarnings, dtm);
          
        }
        finally
        {
          xctxt.popNamespaceContext();
        }
      }

      // If that didn't locate a node, fall back to a default template rule.
      // See http://www.w3.org/TR/xslt#built-in-rule.
      if (null == template)
      {
        switch (nodeType)
        {
        case DTM.DOCUMENT_FRAGMENT_NODE :
        case DTM.ELEMENT_NODE :
          template = m_stylesheetRoot.getDefaultRule();
          break;
        case DTM.CDATA_SECTION_NODE :
        case DTM.TEXT_NODE :
        case DTM.ATTRIBUTE_NODE :
          template = m_stylesheetRoot.getDefaultTextRule();
          isDefaultTextRule = true;
          break;
        case DTM.DOCUMENT_NODE :
          template = m_stylesheetRoot.getDefaultRootRule();
          break;
        default :

          // No default rules for processing instructions and the like.
          return false;
        }
      }
    }

    // If we are processing the default text rule, then just clone 
    // the value directly to the result tree.
    try
    {
      pushElemTemplateElement(template);
      m_xcontext.pushCurrentNode(child);
      pushPairCurrentMatched(template, child);
      
      // Fix copy copy29 test.
      DTMIterator cnl = new org.apache.xpath.NodeSetDTM(child, m_xcontext.getDTMManager());
      m_xcontext.pushContextNodeList(cnl);

      if (isDefaultTextRule)
      {
        switch (nodeType)
        {
        case DTM.CDATA_SECTION_NODE :
        case DTM.TEXT_NODE :
          ClonerToResultTree.cloneToResultTree(child, nodeType, 
                                        dtm, getResultTreeHandler(), false);
          break;
        case DTM.ATTRIBUTE_NODE :
          dtm.dispatchCharactersEvents(child, getResultTreeHandler(), false);
          break;
        }
      }
      else
      {

        // Fire a trace event for the template.
         
        if (TransformerImpl.S_DEBUG)
          getTraceManager().fireTraceEvent(template);
        // And execute the child templates.
        // 9/11/00: If template has been compiled, hand off to it
        // since much (most? all?) of the processing has been inlined.
        // (It would be nice if there was a single entry point that
        // worked for both... but the interpretive system works by
        // having the Tranformer execute the children, while the
        // compiled obviously has to run its own code. It's
        // also unclear that "execute" is really the right name for
        // that entry point.)
        m_xcontext.setSAXLocator(template);
        // m_xcontext.getVarStack().link();
        m_xcontext.getVarStack().link(template.m_frameSize);
        executeChildTemplates(template, true);
        
        if (TransformerImpl.S_DEBUG)
          getTraceManager().fireTraceEndEvent(template);
      }
    }
    catch (org.xml.sax.SAXException se)
    {
      throw new TransformerException(se);
    }
    finally
    {
      m_xcontext.getVarStack().unlink();
      m_xcontext.popCurrentNode();
      m_xcontext.popContextNodeList();
      popCurrentMatched();
      popElemTemplateElement();
    }

    return true;
  }
  
  
  /**
   * <meta name="usage" content="advanced"/>
   * Execute each of the children of a template element.  This method
   * is only for extension use.
   *
   * @param elem The ElemTemplateElement that contains the children
   * that should execute.
   * @param sourceNode The current context node.
   * NEEDSDOC @param context
   * @param mode The current mode.
   * @param handler The ContentHandler to where the result events
   * should be fed.
   *
   * @throws TransformerException
   */
  public void executeChildTemplates(
          ElemTemplateElement elem, org.w3c.dom.Node context, QName mode, ContentHandler handler)
            throws TransformerException
  {

    XPathContext xctxt = m_xcontext;

    try
    {
      if(null != mode)
        pushMode(mode);
      xctxt.pushCurrentNode(xctxt.getDTMHandleFromNode(context));
      executeChildTemplates(elem, handler);
    }
    finally
    {
      xctxt.popCurrentNode();
      
      // I'm not sure where or why this was here.  It is clearly in 
      // error though, without a corresponding pushMode().
      if (null != mode)
        popMode();
    }
  }

  /**
   * <meta name="usage" content="advanced"/>
   * Execute each of the children of a template element.
   *
   * @param elem The ElemTemplateElement that contains the children
   * that should execute.
   * @param handler The ContentHandler to where the result events
   * should be fed.
   *
   * @throws TransformerException
   */
  public void executeChildTemplates(
          ElemTemplateElement elem, ContentHandler handler)
            throws TransformerException
  {

    ResultTreeHandler rth = this.getResultTreeHandler();

    // These may well not be the same!  In this case when calling 
    // the Redirect extension, it has already set the ContentHandler
    // in the Transformer.
    ContentHandler savedRTHHandler = rth.getContentHandler();
    ContentHandler savedHandler = this.getContentHandler();

    try
    {
      getResultTreeHandler().flushPending();
      this.setContentHandler(handler);

      // %REVIEW% Make sure current node is being pushed.
      executeChildTemplates(elem, true);
    }
    catch (org.xml.sax.SAXException se)
    {
      throw new TransformerException(se);
    }
    finally
    {
      this.setContentHandler(savedHandler);

      // This fixes a bug where the ResultTreeHandler's ContentHandler
      // was being reset to the wrong ContentHandler.
      rth.setContentHandler(savedRTHHandler);
    }
  }

  /**
   * <meta name="usage" content="advanced"/>
   * Execute each of the children of a template element.
   *
   * @param transformer The XSLT transformer instance.
   *
   * @param elem The ElemTemplateElement that contains the children
   * that should execute.
   * @param sourceNode The current context node.
   * @param mode The current mode.
   * @param shouldAddAttrs true if xsl:attributes should be executed.
   *
   * @throws TransformerException
   */
  public void executeChildTemplates(
          ElemTemplateElement elem, boolean shouldAddAttrs)
            throws TransformerException
  {

    // Does this element have any children?
    ElemTemplateElement t = elem.getFirstChildElem();

    if (null == t)
      return;      
    
    if(elem.hasTextLitOnly() && org.apache.xalan.processor.TransformerFactoryImpl.m_optimize)
    {      
      char[] chars = ((ElemTextLiteral)t).getChars();
      try
      {
        // Have to push stuff on for tooling...
        this.pushElemTemplateElement(t);
        m_resultTreeHandler.characters(chars, 0, chars.length);
      }
      catch(SAXException se)
      {
        throw new TransformerException(se);
      }
      finally
      {
        this.popElemTemplateElement();
      }
      return;
    }

//    // Check for infinite loops if we have to.
//    boolean check = (m_stackGuard.m_recursionLimit > -1);
//
//    if (check)
//      getStackGuard().push(elem, xctxt.getCurrentNode());

    XPathContext xctxt = m_xcontext;
    xctxt.pushSAXLocatorNull();
    int currentTemplateElementsTop = m_currentTemplateElementsTop;
    m_currentTemplateElementsTop++;

    try
    {
      // Loop through the children of the template, calling execute on 
      // each of them.
      for (; t != null; t = t.getNextSiblingElem())
      {
        if (!shouldAddAttrs
                && t.getXSLToken() == Constants.ELEMNAME_ATTRIBUTE)
          continue;

        xctxt.setSAXLocator(t);
        m_currentTemplateElements[currentTemplateElementsTop] = t;
        t.execute(this);
      }
    }
    catch(RuntimeException re)
    {
    	TransformerException te = new TransformerException(re);
    	te.setLocator(t);
    	throw te;
    }
    finally
    {
      m_currentTemplateElementsTop--;
      xctxt.popSAXLocator();
    }

    // Check for infinite loops if we have to
//    if (check)
//      getStackGuard().pop();
  }

  /**
   * <meta name="usage" content="advanced"/>
   * Get the keys for the xsl:sort elements.
   * Note: Should this go into ElemForEach?
   *
   * @param foreach Valid ElemForEach element, not null.
   * @param sourceNodeContext The current node context in the source tree,
   * needed to evaluate the Attribute Value Templates.
   *
   * @return A Vector of NodeSortKeys, or null.
   *
   * @throws TransformerException
   */
  public Vector processSortKeys(ElemForEach foreach, int sourceNodeContext)
          throws TransformerException
  {

    Vector keys = null;
    XPathContext xctxt = m_xcontext;
    int nElems = foreach.getSortElemCount();

    if (nElems > 0)
      keys = new Vector();

    // March backwards, collecting the sort keys.
    for (int i = 0; i < nElems; i++)
    {
      ElemSort sort = foreach.getSortElem(i);
      
      if (TransformerImpl.S_DEBUG)
        getTraceManager().fireTraceEvent(sort);
     
      String langString =
        (null != sort.getLang())
        ? sort.getLang().evaluate(xctxt, sourceNodeContext, foreach) : null;
      String dataTypeString = sort.getDataType().evaluate(xctxt,
                                sourceNodeContext, foreach);

      if (dataTypeString.indexOf(":") >= 0)
        System.out.println(
          "TODO: Need to write the hooks for QNAME sort data type");
      else if (!(dataTypeString.equalsIgnoreCase(Constants.ATTRVAL_DATATYPE_TEXT))
               &&!(dataTypeString.equalsIgnoreCase(
                 Constants.ATTRVAL_DATATYPE_NUMBER)))
        foreach.error(XSLTErrorResources.ER_ILLEGAL_ATTRIBUTE_VALUE,
                      new Object[]{ Constants.ATTRNAME_DATATYPE,
                                    dataTypeString });

      boolean treatAsNumbers =
        ((null != dataTypeString) && dataTypeString.equals(
        Constants.ATTRVAL_DATATYPE_NUMBER)) ? true : false;
      String orderString = sort.getOrder().evaluate(xctxt, sourceNodeContext,
                             foreach);

      if (!(orderString.equalsIgnoreCase(Constants.ATTRVAL_ORDER_ASCENDING))
              &&!(orderString.equalsIgnoreCase(
                Constants.ATTRVAL_ORDER_DESCENDING)))
        foreach.error(XSLTErrorResources.ER_ILLEGAL_ATTRIBUTE_VALUE,
                      new Object[]{ Constants.ATTRNAME_ORDER,
                                    orderString });

      boolean descending =
        ((null != orderString) && orderString.equals(
        Constants.ATTRVAL_ORDER_DESCENDING)) ? true : false;
      AVT caseOrder = sort.getCaseOrder();
      boolean caseOrderUpper;

      if (null != caseOrder)
      {
        String caseOrderString = caseOrder.evaluate(xctxt, sourceNodeContext,
                                                    foreach);

        if (!(caseOrderString.equalsIgnoreCase(Constants.ATTRVAL_CASEORDER_UPPER))
                &&!(caseOrderString.equalsIgnoreCase(
                  Constants.ATTRVAL_CASEORDER_LOWER)))
          foreach.error(XSLTErrorResources.ER_ILLEGAL_ATTRIBUTE_VALUE,
                        new Object[]{ Constants.ATTRNAME_CASEORDER,
                                      caseOrderString });

        caseOrderUpper =
          ((null != caseOrderString) && caseOrderString.equals(
          Constants.ATTRVAL_CASEORDER_UPPER)) ? true : false;
      }
      else
      {
        caseOrderUpper = false;
      }

      keys.addElement(new NodeSortKey(this, sort.getSelect(), treatAsNumbers,
                                      descending, langString, caseOrderUpper,
                                      foreach));
      if (TransformerImpl.S_DEBUG)
        getTraceManager().fireTraceEndEvent(sort);
     }

    return keys;
  }

  //==========================================================
  // SECTION: TransformState implementation
  //==========================================================
  
  /**
   * Get the stack of ElemTemplateElements.
   * 
   * @return A copy of stack that contains the xsl element instructions, 
   * the earliest called in index zero, and the latest called in index size()-1.
   */
  public Vector getElementCallstack()
  {
  	Vector elems = new Vector();
  	int nStackSize = m_currentTemplateElementsTop;
  	for(int i = 0; i < nStackSize; i++)
  	{
  		ElemTemplateElement elem = m_currentTemplateElements[i];
  		if(null != elem)
  		{
  			elems.addElement(elem);
  		}
  	}
  	return elems;
  }

  /**
   * Push the current template element.
   *
   * @param elem The current ElemTemplateElement (may be null, and then
   * set via setCurrentElement).
   */
  public void pushElemTemplateElement(ElemTemplateElement elem)
  {
    m_currentTemplateElements[m_currentTemplateElementsTop++] = elem;
  }

  /**
   * Pop the current template element.
   */
  public void popElemTemplateElement()
  {
    m_currentTemplateElementsTop--;
  }

  /**
   * Set the top of the current template elements
   * stack.
   *
   * @param e The current ElemTemplateElement about to
   * be executed.
   */
  public void setCurrentElement(ElemTemplateElement e)
  {
    m_currentTemplateElements[m_currentTemplateElementsTop-1] = e;
  }

  /**
   * Retrieves the current ElemTemplateElement that is
   * being executed.
   *
   * @return The current ElemTemplateElement that is executing,
   * should not normally be null.
   */
  public ElemTemplateElement getCurrentElement()
  {
    return (m_currentTemplateElementsTop > 0) ? 
        m_currentTemplateElements[m_currentTemplateElementsTop-1] : null;
  }

  /**
   * This method retrieves the current context node
   * in the source tree.
   *
   * @return The current context node (should never be null?).
   */
  public int getCurrentNode()
  {
    return m_xcontext.getCurrentNode();
  }
  
  /**
   * Get the call stack of xsl:template elements.
   * 
   * @return A copy of stack that contains the xsl:template 
   * (ElemTemplate) instructions, the earliest called in index 
   * zero, and the latest called in index size()-1.
   */
  public Vector getTemplateCallstack()
  {
  	Vector elems = new Vector();
  	int nStackSize = m_currentTemplateElementsTop;
  	for(int i = 0; i < nStackSize; i++)
  	{
  		ElemTemplateElement elem = m_currentTemplateElements[i];
  		if(null != elem && (elem.getXSLToken() != Constants.ELEMNAME_TEMPLATE))
  		{
  			elems.addElement(elem);
  		}
  	}
  	return elems;
  }


  /**
   * This method retrieves the xsl:template
   * that is in effect, which may be a matched template
   * or a named template.
   *
   * <p>Please note that the ElemTemplate returned may
   * be a default template, and thus may not have a template
   * defined in the stylesheet.</p>
   *
   * @return The current xsl:template, should not be null.
   */
  public ElemTemplate getCurrentTemplate()
  {

    ElemTemplateElement elem = getCurrentElement();

    while ((null != elem)
           && (elem.getXSLToken() != Constants.ELEMNAME_TEMPLATE))
    {
      elem = elem.getParentElem();
    }

    return (ElemTemplate) elem;
  }

  /**
   * Push both the current xsl:template or xsl:for-each onto the
   * stack, along with the child node that was matched.
   * (Note: should this only be used for xsl:templates?? -sb)
   *
   * @param template xsl:template or xsl:for-each.
   * @param child The child that was matched.
   */
  public void pushPairCurrentMatched(ElemTemplateElement template, int child)
  {
    m_currentMatchTemplates.push(template);
    m_currentMatchedNodes.push(child);
  }

  /**
   * Pop the elements that were pushed via pushPairCurrentMatched.
   */
  public void popCurrentMatched()
  {
    m_currentMatchTemplates.pop();
    m_currentMatchedNodes.pop();
  }

  /**
   * This method retrieves the xsl:template
   * that was matched.  Note that this may not be
   * the same thing as the current template (which
   * may be from getCurrentElement()), since a named
   * template may be in effect.
   *
   * @return The pushed template that was pushed via pushPairCurrentMatched.
   */
  public ElemTemplate getMatchedTemplate()
  {
    return (ElemTemplate) m_currentMatchTemplates.peek();
  }

  /**
   * Retrieves the node in the source tree that matched
   * the template obtained via getMatchedTemplate().
   *
   * @return The matched node that corresponds to the
   * match attribute of the current xsl:template.
   */
  public int getMatchedNode()
  {
    return m_currentMatchedNodes.peepTail();
  }

  /**
   * Get the current context node list.
   *
   * @return A reset clone of the context node list.
   */
  public DTMIterator getContextNodeList()
  {

    try
    {
      DTMIterator cnl = m_xcontext.getContextNodeList();

      return (cnl == null) ? null : (DTMIterator) cnl.cloneWithReset();
    }
    catch (CloneNotSupportedException cnse)
    {

      // should never happen.
      return null;
    }
  }

  /**
   * Get the TrAX Transformer object in effect.
   *
   * @return This object.
   */
  public Transformer getTransformer()
  {
    return this;
  }

  //==========================================================
  // SECTION: Accessor Functions
  //==========================================================

  /**
   * Set the stylesheet for this processor.  If this is set, then the
   * process calls that take only the input .xml will use
   * this instead of looking for a stylesheet PI.  Also,
   * setting the stylesheet is needed if you are going
   * to use the processor as a SAX ContentHandler.
   *
   * @param stylesheetRoot A non-null StylesheetRoot object,
   * or null if you wish to clear the stylesheet reference.
   */
  public void setStylesheet(StylesheetRoot stylesheetRoot)
  {
    m_stylesheetRoot = stylesheetRoot;
  }

  /**
   * Get the current stylesheet for this processor.
   *
   * @return The stylesheet that is associated with this
   * transformer.
   */
  public final StylesheetRoot getStylesheet()
  {
    return m_stylesheetRoot;
  }

  /**
   * Get quietConflictWarnings property. If the quietConflictWarnings
   * property is set to true, warnings about pattern conflicts won't be
   * printed to the diagnostics stream.
   *
   * @return True if this transformer should not report
   * template match conflicts.
   */
  public boolean getQuietConflictWarnings()
  {
    return m_quietConflictWarnings;
  }

  /**
   * If the quietConflictWarnings property is set to
   * true, warnings about pattern conflicts won't be
   * printed to the diagnostics stream.
   * False by default.
   * (Currently setting this property will have no effect.)
   *
   * @param b true if conflict warnings should be suppressed.
   */
  public void setQuietConflictWarnings(boolean b)
  {
    m_quietConflictWarnings = b;
  }

  /**
   * <meta name="usage" content="internal"/>
   * Set the execution context for XPath.
   *
   * @param xcontext A non-null reference to the XPathContext
   * associated with this transformer.
   */
  public void setXPathContext(XPathContext xcontext)
  {
    m_xcontext = xcontext;
  }

  /**
   * Get the XPath context associated with this transformer.
   *
   * @return The XPathContext reference, never null.
   */
  public final XPathContext getXPathContext()
  {
    return m_xcontext;
  }

  /**
   * <meta name="usage" content="internal"/>
   * Get the object used to guard the stack from
   * recursion.
   *
   * @return The StackGuard object, which should never be null.
   */
  public StackGuard getStackGuard()
  {
    return m_stackGuard;
  }

  /**
   * Get the recursion limit.
   * Used for infinite loop check. If the value is -1, do not
   * check for infinite loops. Anyone who wants to enable that
   * check should change the value of this variable to be the
   * level of recursion that they want to check. Be careful setting
   * this variable, if the number is too low, it may report an
   * infinite loop situation, when there is none.
   * Post version 1.0.0, we'll make this a runtime feature.
   *
   * @return The limit on recursion, or -1 if no check is to be made.
   */
  public int getRecursionLimit()
  {
    return m_stackGuard.getRecursionLimit();
  }

  /**
   * Set the recursion limit.
   * Used for infinite loop check. If the value is -1, do not
   * check for infinite loops. Anyone who wants to enable that
   * check should change the value of this variable to be the
   * level of recursion that they want to check. Be careful setting
   * this variable, if the number is too low, it may report an
   * infinite loop situation, when there is none.
   * Post version 1.0.0, we'll make this a runtime feature.
   *
   * @param limit A number that represents the limit of recursion,
   * or -1 if no checking is to be done.
   */
  public void setRecursionLimit(int limit)
  {
    m_stackGuard.setRecursionLimit(limit);
  }

  /**
   * Get the ResultTreeHandler object.
   *
   * @return The current ResultTreeHandler, which may not
   * be the main result tree manager.
   */
  public ResultTreeHandler getResultTreeHandler()
  {
    return m_resultTreeHandler;
  }

  /**
   * Get the KeyManager object.
   *
   * @return A reference to the KeyManager object, which should
   * never be null.
   */
  public KeyManager getKeyManager()
  {
    return m_keyManager;
  }

  /**
   * Check to see if this is a recursive attribute definition.
   *
   * @param attrSet A non-null ElemAttributeSet reference.
   *
   * @return true if the attribute set is recursive.
   */
  public boolean isRecursiveAttrSet(ElemAttributeSet attrSet)
  {

    if (null == m_attrSetStack)
    {
      m_attrSetStack = new Stack();
    }

    if (!m_attrSetStack.empty())
    {
      int loc = m_attrSetStack.search(attrSet);

      if (loc > -1)
      {
        return true;
      }
    }

    return false;
  }

  /**
   * Push an executing attribute set, so we can check for
   * recursive attribute definitions.
   *
   * @param attrSet A non-null ElemAttributeSet reference.
   */
  public void pushElemAttributeSet(ElemAttributeSet attrSet)
  {
    m_attrSetStack.push(attrSet);
  }

  /**
   * Pop the current executing attribute set.
   */
  public void popElemAttributeSet()
  {
    m_attrSetStack.pop();
  }

  /**
   * Get the table of counters, for optimized xsl:number support.
   *
   * @return The CountersTable, never null.
   */
  public CountersTable getCountersTable()
  {

    if (null == m_countersTable)
      m_countersTable = new CountersTable();

    return m_countersTable;
  }

  /**
   * Tell if the current template rule is null, i.e. if we are
   * directly within an apply-templates.  Used for xsl:apply-imports.
   *
   * @return True if the current template rule is null.
   */
  public boolean currentTemplateRuleIsNull()
  {
    return ((!m_currentTemplateRuleIsNull.isEmpty())
            && (m_currentTemplateRuleIsNull.peek() == true));
  }

  /**
   * Push true if the current template rule is null, false
   * otherwise.
   *
   * @param b True if the we are executing an xsl:for-each
   * (or xsl:call-template?).
   */
  public void pushCurrentTemplateRuleIsNull(boolean b)
  {
    m_currentTemplateRuleIsNull.push(b);
  }

  /**
   * Push true if the current template rule is null, false
   * otherwise.
   */
  public void popCurrentTemplateRuleIsNull()
  {
    m_currentTemplateRuleIsNull.pop();
  }

  /**
   * Return the message manager.
   *
   * @return The message manager, never null.
   */
  public MsgMgr getMsgMgr()
  {

    if (null == m_msgMgr)
      m_msgMgr = new MsgMgr(this);

    return m_msgMgr;
  }

  /**
   * Set the error event listener.
   *
   * @param listener The new error listener.
   * @throws IllegalArgumentException if
   */
  public void setErrorListener(ErrorListener listener)
          throws IllegalArgumentException
  {

    synchronized (m_reentryGuard)
    {
      if (listener == null)
        throw new IllegalArgumentException(XSLMessages.createMessage(XSLTErrorResources.ER_NULL_ERROR_HANDLER, null)); //"Null error handler");

      m_errorHandler = listener;
    }
  }

  /**
   * Get the current error event handler.
   *
   * @return The current error handler, which should never be null.
   */
  public ErrorListener getErrorListener()
  {
    return m_errorHandler;
  }

  /**
   * Get an instance of the trace manager for this transformation.
   * This object can be used to set trace listeners on various
   * events during the transformation.
   *
   * @return A reference to the TraceManager, never null.
   */
  public TraceManager getTraceManager()
  {
    return m_traceManager;
  }

  /**
   * Look up the value of a feature.
   *
   * <p>The feature name is any fully-qualified URI.  It is
   * possible for an TransformerFactory to recognize a feature name but
   * to be unable to return its value; this is especially true
   * in the case of an adapter for a SAX1 Parser, which has
   * no way of knowing whether the underlying parser is
   * validating, for example.</p>
   *
   * <h3>Open issues:</h3>
   * <dl>
   *    <dt><h4>Should getFeature be changed to hasFeature?</h4></dt>
   *    <dd>Keith Visco writes: Should getFeature be changed to hasFeature?
   *        It returns a boolean which indicated whether the "state"
   *        of feature is "true or false". I assume this means whether
   *        or not a feature is supported? I know SAX is using "getFeature",
   *        but to me "hasFeature" is cleaner.</dd>
   * </dl>
   *
   * @param name The feature name, which is a fully-qualified
   *        URI.
   * @return The current state of the feature (true or false).
   * @throws org.xml.sax.SAXNotRecognizedException When the
   *            TransformerFactory does not recognize the feature name.
   * @throws org.xml.sax.SAXNotSupportedException When the
   *            TransformerFactory recognizes the feature name but
   *            cannot determine its value at this time.
   *
   * @throws SAXNotRecognizedException
   * @throws SAXNotSupportedException
   */
  public boolean getFeature(String name)
          throws SAXNotRecognizedException, SAXNotSupportedException
  {

    if ("http://xml.org/trax/features/sax/input".equals(name))
      return true;
    else if ("http://xml.org/trax/features/dom/input".equals(name))
      return true;

    throw new SAXNotRecognizedException(name);
  }

  // %TODO% Doc

  /**
   * NEEDSDOC Method getMode 
   *
   *
   * NEEDSDOC (getMode) @return
   */
  public QName getMode()
  {
    return m_modes.isEmpty() ? null : (QName) m_modes.peek();
  }

  // %TODO% Doc

  /**
   * NEEDSDOC Method pushMode 
   *
   *
   * NEEDSDOC @param mode
   */
  public void pushMode(QName mode)
  {
    m_modes.push(mode);
  }

  // %TODO% Doc

  /**
   * NEEDSDOC Method popMode 
   *
   */
  public void popMode()
  {
    m_modes.pop();
  }

  ////////////////////////
  // Implement Runnable //  
  ////////////////////////

  /**
   * Base thread controler for xalan. Must be overriden with
   * a derived class to support thread pooling.
   *
   * All thread-related stuff is in this class.
   * 
   * <p><em>WARNING!</em>  This class will probably move since the DTM 
   * CoroutineSAXParser depends on it.  This class should move 
   * to the CoroutineSAXParser.  You can use it, but be aware 
   * that your code will have to change when the move occurs.</p>
   */
  public static class ThreadControler
  {

    /**
     * Will get a thread from the pool, execute the task
     *  and return the thread to the pool.
     *
     *  The return value is used only to wait for completion
     *
     *
     * NEEDSDOC @param task
     * @param priority if >0 the task will run with the given priority
     *  ( doesn't seem to be used in xalan, since it's allways the default )
     * @returns The thread that is running the task, can be used
     *          to wait for completion
     *
     * NEEDSDOC ($objectName$) @return
     */
    public Thread run(Runnable task, int priority)
    {

      Thread t = new Thread(task);

      t.start();

      //       if( priority > 0 )
      //      t.setPriority( priority );
      return t;
    }

    /**
     *  Wait until the task is completed on the worker
     *  thread.
     *
     * NEEDSDOC @param worker
     * NEEDSDOC @param task
     *
     * @throws InterruptedException
     */
    public void waitThread(Thread worker, Runnable task)
            throws InterruptedException
    {

      // This should wait until the transformThread is considered not alive.
      worker.join();
    }
  }

  /** NEEDSDOC Field tpool          */
  static ThreadControler tpool = new ThreadControler();

  /**
   * Change the ThreadControler that will be used to
   *  manage the transform threads.
   *
   * NEEDSDOC @param tp
   */
  public static void setThreadControler(ThreadControler tp)
  {
    tpool = tp;
  }

  /**
   * Called by SourceTreeHandler to start the transformation
   *  in a separate thread
   *
   * NEEDSDOC @param priority
   */
  public void runTransformThread(int priority)
  {

    // used in SourceTreeHandler
    Thread t = tpool.run(this, priority);

    this.setTransformThread(t);
  }

  /**
   * Called by this.transform() if isParserEventsOnMain()==false.
   *  Similar with runTransformThread(), but no priority is set
   *  and setTransformThread is not set.
   */
  public void runTransformThread()
  {
    tpool.run(this, -1);
  }
  
  /**
   * Called by CoRoutineSAXParser. Launches the CoroutineSAXParser
   * in a thread, and prepares it to invoke the parser from that thread
   * upon request. 
   *  
   */
  public static void runTransformThread(Runnable runnable)
  {
    tpool.run(runnable, -1);
  }

  /**
   * Used by SourceTreeHandler to wait until the transform
   *   completes
   *
   * @throws SAXException
   */
  public void waitTransformThread() throws SAXException
  {

    // This is called to make sure the task is done.
    // It is possible that the thread has been reused -
    // but for a different transformation. ( what if we 
    // recycle the transformer ? Not a problem since this is
    // still in use. )
    Thread transformThread = this.getTransformThread();

    if (null != transformThread)
    {
      try
      {
        tpool.waitThread(transformThread, this);

        if (!this.hasTransformThreadErrorCatcher())
        {
          Exception e = this.getExceptionThrown();

          if (null != e)
          {
            e.printStackTrace();
            throw new org.xml.sax.SAXException(e);
          }
        }

        this.setTransformThread(null);
      }
      catch (InterruptedException ie){}
    }
  }

  /**
   * Get the exception thrown by the secondary thread (normally
   * the transform thread).
   *
   * @return The thrown exception, or null if no exception was
   * thrown.
   */
  public Exception getExceptionThrown()
  {
    return m_exceptionThrown;
  }

  /**
   * Set the exception thrown by the secondary thread (normally
   * the transform thread).
   *
   * @param e The thrown exception, or null if no exception was
   * thrown.
   */
  public void setExceptionThrown(Exception e)
  {
    m_exceptionThrown = e;
  }

  /**
   * This is just a way to set the document for run().
   *
   * @param doc A non-null reference to the root of the
   * tree to be transformed.
   */
  public void setSourceTreeDocForThread(int doc)
  {
    m_doc = doc;
  }

  /**
   * Set the input source for the source tree, which is needed if the
   * parse thread is not the main thread, in order for the parse
   * thread's run method to get to the input source.
   *
   * @param source The input source for the source tree.
   */
  public void setXMLSource(Source source)
  {
    m_xmlSource = source;
  }

  /**
   * Tell if the transform method is completed.
   *
   * @return True if transformNode has completed, or
   * an exception was thrown.
   */
  public boolean isTransformDone()
  {

    synchronized (this)
    {
      return m_isTransformDone;
    }
  }

  /**
   * Set if the transform method is completed.
   *
   * @param done True if transformNode has completed, or
   * an exception was thrown.
   */
  public void setIsTransformDone(boolean done)
  {

    synchronized (this)
    {
      m_isTransformDone = done;
    }
  }

  /**
   * From a secondary thread, post the exception, so that
   * it can be picked up from the main thread.
   *
   * @param e The exception that was thrown.
   */
  void postExceptionFromThread(Exception e)
  {

    // Commented out in response to problem reported by Nicola Brown <Nicola.Brown@jacobsrimell.com>
    //    if(m_reportInPostExceptionFromThread)
    //    {
    //      // Consider re-throwing the exception if this flag is set.
    //      e.printStackTrace();
    //    }
    // %REVIEW Need DTM equivelent?    
    //    if (m_inputContentHandler instanceof SourceTreeHandler)
    //    {
    //      SourceTreeHandler sth = (SourceTreeHandler) m_inputContentHandler;
    //
    //      sth.setExceptionThrown(e);
    //    }
    ContentHandler ch = getContentHandler();

    //    if(ch instanceof SourceTreeHandler)
    //    {
    //      SourceTreeHandler sth = (SourceTreeHandler) ch;
    //      ((TransformerImpl)(sth.getTransformer())).postExceptionFromThread(e);
    //    }
    m_isTransformDone = true;
    m_exceptionThrown = e;
    ;  // should have already been reported via the error handler?

    synchronized (this)
    {

      // See message from me on 3/27/2001 to Patrick Moore.
      //      String msg = e.getMessage();
      // System.out.println(e.getMessage());
      // Is this really needed?  -sb
      notifyAll();

      //      if (null == msg)
      //      {
      //
      //        // m_throwNewError = false;
      //        e.printStackTrace();
      //      }
      // throw new org.apache.xml.utils.WrappedRuntimeException(e);
    }
  }

  /**
   * Run the transform thread.
   */
  public void run()
  {

    m_hasBeenReset = false;

    try
    {

      // int n = ((SourceTreeHandler)getInputContentHandler()).getDTMRoot();
      // transformNode(n);
      try
      {
        m_isTransformDone = false;
        
        // Should no longer be needed...
//          if(m_inputContentHandler instanceof TransformerHandlerImpl)
//          {
//            TransformerHandlerImpl thi = (TransformerHandlerImpl)m_inputContentHandler;
//            thi.waitForInitialEvents();
//          }

        transformNode(m_doc);
        
      }
      catch (Exception e)
      {
        // e.printStackTrace();

        // Strange that the other catch won't catch this...
        if (null != m_transformThread)
          postExceptionFromThread(e);   // Assume we're on the main thread
        else 
          throw new RuntimeException(e.getMessage());
      }
      finally
      {
        m_isTransformDone = true;

        if (m_inputContentHandler instanceof TransformerHandlerImpl)
        {
          ((TransformerHandlerImpl) m_inputContentHandler).clearCoRoutine();
        }

        //        synchronized (this)
        //        {
        //          notifyAll();
        //        }
      }
    }
    catch (Exception e)
    {

      // e.printStackTrace();
      if (null != m_transformThread)
        postExceptionFromThread(e);
      else 
        throw new RuntimeException(e.getMessage());         // Assume we're on the main thread.
    }
  }

  // Fragment re-execution interfaces for a tool.

  /**
   * This will get a snapshot of the current executing context 
   *
   *
   * @return TransformerSnapshot object, snapshot of executing context
   */
  public TransformSnapshot getSnapshot()
  {
    return new TransformSnapshotImpl(this);
  }

  /**
   * This will execute the following XSLT instructions
   * from the snapshot point, after the stylesheet execution
   * context has been reset from the snapshot point. 
   *
   * @param ts The snapshot of where to start execution
   *
   * @throws TransformerException
   */
  public void executeFromSnapshot(TransformSnapshot ts)
          throws TransformerException
  {

    ElemTemplateElement template = getMatchedTemplate();
    int child = getMatchedNode();

    pushElemTemplateElement(template);  //needed??
    m_xcontext.pushCurrentNode(child);  //needed??
    this.executeChildTemplates(template, true);  // getResultTreeHandler());
  }

  /**
   * This will reset the stylesheet execution context
   * from the snapshot point.
   *
   * @param ts The snapshot of where to start execution
   */
  public void resetToStylesheet(TransformSnapshot ts)
  {
    ((TransformSnapshotImpl) ts).apply(this);
  }

  /**
   * NEEDSDOC Method stopTransformation 
   *
   */
  public void stopTransformation(){}

  /**
   * Test whether whitespace-only text nodes are visible in the logical
   * view of <code>DTM</code>. Normally, this function
   * will be called by the implementation of <code>DTM</code>;
   * it is not normally called directly from
   * user code.
   *
   * @param elementHandle int Handle of the element.
   * @return one of NOTSTRIP, STRIP, or INHERIT.
   */
  public short getShouldStripSpace(int elementHandle, DTM dtm)
  {

    try
    {
      org.apache.xalan.templates.WhiteSpaceInfo info =
        m_stylesheetRoot.getWhiteSpaceInfo(m_xcontext, elementHandle, dtm);

      if (null == info)
      {
        return DTMWSFilter.INHERIT;
      }
      else
      {

        // System.out.println("getShouldStripSpace: "+info.getShouldStripSpace());
        return info.getShouldStripSpace()
               ? DTMWSFilter.STRIP : DTMWSFilter.NOTSTRIP;
      }
    }
    catch (TransformerException se)
    {
      return DTMWSFilter.INHERIT;
    }
  }
}  // end TransformerImpl class

