/*
 * 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.xslt;

import org.apache.xpath.*;
import org.apache.xpath.compiler.XPathParser;
import org.apache.xpath.compiler.Compiler;
import org.apache.xalan.xpath.XObject;
import org.apache.xalan.xpath.XString;
import org.apache.xalan.xpath.XNodeSet;
import org.apache.xalan.xpath.XBoolean;
import org.apache.xalan.xpath.XNumber;
import org.apache.xalan.xpath.XNull;

import org.w3c.dom.*;
import org.w3c.dom.traversal.NodeIterator;
import org.xml.sax.ContentHandler;
import org.xml.sax.*;
import org.xml.sax.helpers.*;
import org.xml.sax.ext.*;
import org.xml.sax.helpers.ParserAdapter;
import org.apache.xml.serialize.XMLSerializer;

import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerFactoryConfigurationError;
import javax.xml.transform.Templates;
import javax.xml.transform.Source;
import javax.xml.transform.SourceLocator;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.sax.SAXSource;
import javax.xml.transform.sax.TransformerHandler;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.ErrorListener;

import java.util.*;
import java.net.*;
import java.io.*;
import java.lang.reflect.*;

import org.apache.xalan.templates.Stylesheet;
//import org.apache.xalan.templates.StylesheetRoot;
import org.apache.xalan.xpath.xml.XMLParserLiaison;
import org.apache.xalan.xpath.xml.ProblemListenerDefault;
import org.apache.xalan.xpath.xml.ProblemListener;
import org.apache.xalan.templates.StylesheetComposed;
import org.apache.xalan.transformer.TransformerImpl;
import org.apache.xalan.processor.StylesheetHandler;
import org.apache.xalan.processor.TransformerFactoryImpl;
//import org.apache.xalan.processor.ProcessorStylesheet;
//import org.apache.xalan.xslt.StylesheetSpec;
import org.apache.xalan.trace.*;
import org.apache.xalan.res.XSLTErrorResources;
import org.apache.xalan.res.XSLMessages;
import org.apache.xml.utils.PrefixResolverDefault;
import org.apache.xml.utils.TreeWalker;
import org.apache.xml.utils.QName;
import org.apache.xml.utils.DefaultErrorHandler;
import org.apache.xalan.stree.SourceTreeHandler;


/**
 * <meta name="usage" content="advanced"/>
 * The Xalan workhorse -- Collaborates with the XML parser liaison, the DOM,
 * and the XPath engine, to transform a source tree of nodes into a result tree
 * according to instructions and templates specified by a stylesheet tree.
 * We suggest you use one of the
 * static XSLTProcessorFactory getProcessor() methods to instantiate the processor
 * and return an interface that greatly simplifies the process of manipulating
 * XSLTEngineImpl.
 *
 * <p>The methods <code>process(...)</code> are the primary public entry points.
 * The best way to perform transformations is to use the
 * {@link org.apache.xalan.xslt.XSLTProcessor#process(org.apache.xalan.xslt.XSLTInputSource, org.apache.xalan.xslt.XSLTInputSource, org.apache.xalan.xslt.XSLTResultTarget)} method,
 * but you may use any of process methods defined in XSLTEngineImpl.</p>
 * 
 * <p>Please note that this class is not safe per instance over multiple 
 * threads.  If you are in a multithreaded environment, you should 
 * keep a pool of these objects, or create a new one each time.  In a 
 * multithreaded environment, the right way to do things is to create a 
 * StylesheetRoot via processStylesheet, and then reuse this object 
 * over multiple threads.</p>
 *
 * <p>If you reuse the processor instance, you should call reset() between transformations.</p>
 * @see XSLTProcessorFactory
 * @see XSLTProcessor
 */
public class XSLTEngineImpl implements  XSLTProcessor
{
  //private Processor m_processor;
  private TransformerFactory m_tfactory;
  private TransformerImpl m_transformerImpl;
  private DOM2Helper m_liaison;
  private String m_outputFileName;
  private DocumentHandler m_documentHandler = null;
  private ProblemListenerDefault m_problemListener;
  private Hashtable m_stylesheetParams;
  StylesheetRoot m_stylesheetRoot = null;
  
  Vector m_evalList = null;
  boolean m_needToEval = false;
  
  /*
  * If this is true, then the diag function will
  * be called.
  */
  private boolean m_traceTemplateChildren = false;

  /*
  * If this is true, then the simple tracing of templates
  * will be performed.
  */
  private boolean m_traceTemplates = false;
  
  /*
  * If this is true, then diagnostics of each select
  * will be performed.
  */
  boolean m_traceSelects = false;

  /*
  * A stream to print diagnostics to.
  */
  java.io.PrintWriter m_diagnosticsPrintWriter = null;

  /* For diagnostics */
  Hashtable m_durationsTable = new Hashtable();
  
  /**
   * A XSLMessages instance capable of producing user messages.
   */
  private static XSLMessages m_XSLMessages = new XSLMessages();
  
    
 /**
   * Construct an XSLT processor that uses the default DTM (Document Table Model) liaison
   * and XML parser. As a general rule, you should use XSLTProcessorFactory to create an
   * instance of this class and provide access to the instance via the XSLTProcessor interface.
   *
   * @see XSLTProcessorFactory
   * @see XSLTProcessor
   */
  protected XSLTEngineImpl()
    throws org.xml.sax.SAXException
  {    
    m_tfactory = TransformerFactory.newInstance();
    m_problemListener = new ProblemListenerDefault();    
  }

  /**
   * Construct an XSLT processor that uses the the given parser liaison.
   * As a general rule, you should use XSLTProcessorFactory to create an
   * instance of this class and provide access to the instance via the XSLTProcessor interface.
   *
   * @see XSLTProcessorFactory
   * @see XSLTProcessor
   */
  public XSLTEngineImpl(String liaisonClassName)
    throws SAXException 
  {   
    m_tfactory = TransformerFactory.newInstance();
    m_problemListener = new ProblemListenerDefault();
    
    try 
      {
        m_liaison =  (DOM2Helper)(Class.forName(liaisonClassName).newInstance());
        //org.apache.xpath.XPathContext xctxt = this.getTransformer().getXPathContext();

        //xctxt.setDOMHelper(m_liaison);        
      } 
      catch (ClassNotFoundException e1) 
      {
        throw new SAXException("XML Liaison class " + liaisonClassName +
          " specified but not found", e1);
      } 
      catch (IllegalAccessException e2) 
      {
          throw new SAXException("XML Liaison class " + liaisonClassName +
            " found but cannot be loaded", e2);
      } 
      catch (InstantiationException e3) 
      {
          throw new SAXException("XML Liaison class " + liaisonClassName +
            " loaded but cannot be instantiated (no empty public constructor?)",
            e3);
      } 
      catch (ClassCastException e4) 
      {
          throw new SAXException("XML Liaison class " + liaisonClassName +
            " does not implement DOM2Helper", e4);
      }
   
  }
    
    

  /**
   * Construct an XSL processor that uses the the given parser liaison.
   * As a general rule, you should use XSLTProcessorFactory to create an
   * instance of this class and provide access to the instance via the XSLTProcessor interface.
   *
   * @param XMLParserLiaison A liaison to an XML parser.
   *
   * @see org.apache.xalan.xpath.xml.XMLParserLiaison
   * @see XSLTProcessorFactory
   * @see XSLTProcessor
   */
  public XSLTEngineImpl(XMLParserLiaison parserLiaison)
    throws org.xml.sax.SAXException
  {
    m_tfactory = TransformerFactory.newInstance();
    m_problemListener = new ProblemListenerDefault();
    
    m_liaison =  (DOM2Helper)parserLiaison;
   // org.apache.xpath.XPathContext xctxt = this.getTransformer().getXPathContext();

    //xctxt.setDOMHelper(m_liaison);    
  }

  /**
   * Construct an XSLT processor that can call back to the XML parser, in order to handle
   * included files and the like.
   *
   * @param XMLParserLiaison A liaison to an XML parser.
   *
   * @see org.apache.xalan.xpath.xml.XMLParserLiaison
   * @see XSLTProcessorFactory
   * @see XSLTProcessor
   */
  XSLTEngineImpl(XMLParserLiaison parserLiaison, XPathFactory xpathFactory)    
    throws SAXException
  {   
    m_tfactory = TransformerFactory.newInstance();
    m_problemListener = new ProblemListenerDefault();
    
    m_liaison =  (DOM2Helper)parserLiaison;
   // org.apache.xpath.XPathContext xctxt = this.getTransformer().getXPathContext();

    //xctxt.setDOMHelper(m_liaison);    
  }
 
  /**
   * 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_transformerImpl != null)
      m_transformerImpl.reset(); 
    m_stylesheetParams = null;
  }
  
 

  /**
   * Transform the source tree to the output in the given
   * result tree target. As a general rule, we recommend you use the
   * {@link org.apache.xalan.xslt.XSLTProcessor#process(org.apache.xalan.xslt.XSLTInputSource, org.apache.xalan.xslt.XSLTInputSource, org.apache.xalan.xslt.XSLTResultTarget)} method.
   * @param inputSource  The input source.
   * @param stylesheetSource  The stylesheet source.  May be null if source has a xml-stylesheet PI.
   * @param outputTarget The output source tree.
   * @exception XSLProcessorException thrown if the active ProblemListener and XMLParserLiaison decide
   * the error condition is severe enough to halt processing.
   */
  public void process( XSLTInputSource inputSource,
                       XSLTInputSource stylesheetSource,
                       XSLTResultTarget outputTarget)
    throws SAXException
  {
    try
    {
      Boolean totalTimeID = new Boolean(true);
      pushTime(totalTimeID);
      Node sourceTree = null;
      if(null != inputSource)
        sourceTree = getSourceTreeFromInput(inputSource);
      Templates templates = null;
      if (m_needToEval)
      {
        Node node = null;
        if (null != stylesheetSource)
        {
          Source ssSource = stylesheetSource.getSourceObject();
          if(ssSource instanceof DOMSource)
          {
            node = ((DOMSource)ssSource).getNode();
          }
        }
        if (null == node)
        {
          node = new DOM2Helper().createDocument() ; 
        }
        for (int i=0; i< m_evalList.size(); i++)
        {
          String name = (String)m_evalList.elementAt(i);
          String expression = (String)m_stylesheetParams.get(name);
          try{
            org.apache.xpath.objects.XObject val = org.apache.xpath.XPathAPI.eval(node, expression);
            
            m_stylesheetParams.put(name, val);
          }
          catch(TransformerException te)
          {}
        }
        m_needToEval = false;
        m_evalList = null;
      }
      if(null != stylesheetSource)
      {
        try{
        templates = m_tfactory.newTemplates(stylesheetSource.getSourceObject());
        }
        catch (TransformerConfigurationException tce)
        {
          throw new SAXException(tce);
        }  
        
      }      
      else if(null != sourceTree)
      {
        String stylesheetURI = null;
        Stack hrefs = new Stack();
        for(Node child=sourceTree.getFirstChild(); null != child; child=child.getNextSibling())
        {
          if(Node.PROCESSING_INSTRUCTION_NODE == child.getNodeType())
          {
            ProcessingInstruction pi = (ProcessingInstruction)child;
            if(pi.getNodeName().equals("xml-stylesheet")
               || pi.getNodeName().equals("xml:stylesheet"))
            {
              boolean isOK = true;
              StringTokenizer tokenizer = new StringTokenizer(pi.getNodeValue(), " \t=");
              while(tokenizer.hasMoreTokens())
              {
                if(tokenizer.nextToken().equals("type"))
                {
                  String typeVal = tokenizer.nextToken();
                  typeVal = typeVal.substring(1, typeVal.length()-1);
                  if(!typeVal.equals("text/xsl"))
                  {
                    isOK = false;
                  }
                }
              }

              if(isOK)
              {
                tokenizer = new StringTokenizer(pi.getNodeValue(), " \t=");
                while(tokenizer.hasMoreTokens())
                {
                  if(tokenizer.nextToken().equals("href"))
                  {
                    stylesheetURI = tokenizer.nextToken();
                    stylesheetURI = stylesheetURI.substring(1, stylesheetURI.length()-1);
                    hrefs.push(stylesheetURI);
                  }
                }                
              }
            }
          }
        } // end for(int i = 0; i < nNodes; i++)
        boolean isRoot = true;
        Stylesheet prevStylesheet = null;
        while(!hrefs.isEmpty())
        {
          Stylesheet stylesheet = getStylesheetFromPIURL((String)hrefs.pop(), sourceTree,
                                                         (null != inputSource)
                                                         ? inputSource.getSystemId() : null,
                                                         isRoot);
          if(false == isRoot)
          {
            prevStylesheet.setImport((StylesheetComposed)stylesheet);
          }
          prevStylesheet = stylesheet;
          isRoot = false;
        }
      }
      else
      {
        error(XSLTErrorResources.ER_NO_INPUT_STYLESHEET); //"Stylesheet input was not specified!");
      }
      
     
      if(null == templates)
      {
        if (m_stylesheetRoot != null)
          templates = m_stylesheetRoot.getObject();
        else
        {  
          error(XSLTErrorResources.ER_FAILED_PROCESS_STYLESHEET); //"Failed to process stylesheet!");
          return;
        }  
      }

      if(null != sourceTree)
      {
        try{
          m_transformerImpl = (TransformerImpl)templates.newTransformer(); 
          if (m_problemListener != null)
            m_transformerImpl.setErrorListener(m_problemListener);
          if (m_liaison != null)
          m_transformerImpl.getXPathContext().setDOMHelper(m_liaison);
   
        }
        catch (TransformerConfigurationException tce)
        {
          throw new SAXException(tce);
        }  
        
        if (m_stylesheetParams != null)
        {
          Enumeration keys = m_stylesheetParams.keys();
          while (keys.hasMoreElements())
          {
            String name = (String)keys.nextElement();
            Object value = m_stylesheetParams.get(name); 
            m_transformerImpl.setParameter(name, null, value);
          } 
        }  
        
        try{
          m_transformerImpl.transform(inputSource.getSourceObject(),
                    outputTarget.getResultObject());
        }
        catch (TransformerException te)
        {
          throw new SAXException(te);
        }  
        if(null != m_diagnosticsPrintWriter)
        {
          displayDuration("Total time", totalTimeID);
        }
      }
    }
    catch(MalformedURLException mue)
    {
      error(XSLTErrorResources.ERROR0000, new Object[] {mue.getMessage()}, mue);
      // throw se;
    }
    catch(FileNotFoundException fnfe)
    {
      error(XSLTErrorResources.ERROR0000, new Object[] {fnfe.getMessage()}, fnfe);
      // throw se;
    }
    catch(IOException ioe)
    {
      error(XSLTErrorResources.ERROR0000, new Object[] {ioe.getMessage()}, ioe);
      // throw se;
    }
    catch(SAXException se)
    {
      error(XSLTErrorResources.ER_SAX_EXCEPTION, se); //"SAX Exception", se);
      // throw se;
    }
  }

  /**
   * Bottleneck the creation of the stylesheet for derivation purposes.
   */
  public StylesheetRoot createStylesheetRoot(String baseIdentifier)
    throws MalformedURLException, FileNotFoundException,
           IOException, SAXException
  {
    try{
      if (baseIdentifier == null)
        return new StylesheetRoot(this, baseIdentifier); 
      
      Source inSource = new XSLTInputSource(baseIdentifier).getSourceObject();
      Templates templates = m_tfactory.newTemplates(inSource);
      StylesheetRoot stylesheet = new StylesheetRoot((org.apache.xalan.templates.StylesheetRoot)templates);      
      return stylesheet;      
    }
    catch (TransformerConfigurationException tce)
    {
      throw new SAXException(tce);
    }
  }

  /**
   * Given a URI to an XSL stylesheet,
   * Compile the stylesheet into an internal representation.
   * This calls reset() before processing if the stylesheet root has been set
   * to non-null.
   * @param xmldocURLString  The URL to the input XML document.
   * @return The compiled stylesheet object.
   * @exception XSLProcessorException thrown if the active ProblemListener and XMLParserLiaison decide
   * the error condition is severe enough to halt processing.
   */
  public StylesheetRoot processStylesheet(XSLTInputSource stylesheetSource)
    throws SAXException
  {
    try{
      if(null != ((TransformerFactoryImpl)m_tfactory).newTemplatesHandler().getTemplates())
        reset();
    }
    catch (TransformerConfigurationException tce)
    {
      throw new SAXException(tce);
    }

    String xslIdentifier = ((null == stylesheetSource) ||
                            (null == stylesheetSource.getSystemId()))
                           ? "Input XSL" : stylesheetSource.getSystemId();

    // In case we have a fragment identifier, go ahead and
    // try and parse the XML here.
    m_stylesheetRoot = null;
    try
    {
      m_stylesheetRoot = createStylesheetRoot(stylesheetSource.getSystemId());
      addTraceListenersToStylesheet();
      StylesheetHandler stylesheetProcessor
        = new StylesheetHandler((TransformerFactoryImpl)m_tfactory); //this, m_stylesheetRoot); 
      Source ssSource = stylesheetSource.getSourceObject();
      if(ssSource instanceof DOMSource)
      {
        if(((DOMSource)ssSource).getNode() instanceof StylesheetRoot)
        {
          m_stylesheetRoot = (StylesheetRoot)((DOMSource)ssSource).getNode();
        }
        else
        {
          TreeWalker tw = new TreeWalker(stylesheetProcessor);
          tw.traverse(((DOMSource)ssSource).getNode());
          m_stylesheetRoot = new StylesheetRoot(stylesheetProcessor.getStylesheetRoot());
        }
      }
      else
      {
        stylesheetProcessor.pushStylesheet(m_stylesheetRoot.getObject());      
        diag("========= Parsing "+xslIdentifier+" ==========");
        pushTime(xslIdentifier);
        //String liaisonClassName = System.getProperty("org.apache.xalan.source.liaison");

        if(null != m_liaison)
        {
         // DOM2Helper liaison =  (DOM2Helper)(Class.forName(liaisonClassName).newInstance());
          m_liaison.parse(SAXSource.sourceToInputSource(ssSource));
        }  
        if(null != m_diagnosticsPrintWriter)
          displayDuration("Parse of "+xslIdentifier, xslIdentifier);
      }
    }
    catch(Exception e)
    {
      error(XSLTErrorResources.ER_COULDNT_PARSE_DOC, new Object[] {xslIdentifier}, e); //"Could not parse "+xslIdentifier+" document!", e);
    }
    return m_stylesheetRoot;
  }

  /**
   * Given a URI to an XSL stylesheet,
   * Compile the stylesheet into an internal representation.
   * This calls reset() before processing if the stylesheet root has been set
   * to non-null.
   * @param xmldocURLString  The URL to the input XML document.
   * @return The compiled stylesheet object.
   * @exception XSLProcessorException thrown if the active ProblemListener and XMLParserLiaison decide
   * the error condition is severe enough to halt processing.
   */
  public StylesheetRoot processStylesheet(String xsldocURLString)
    throws SAXException
  {
    try
    {
      XSLTInputSource input = new XSLTInputSource(getURLFromString(xsldocURLString, null).toString());
      return processStylesheet(input);
    }
    catch(SAXException se)
    {
      error(XSLTErrorResources.ER_PROCESSSTYLESHEET_NOT_SUCCESSFUL, se); //"processStylesheet not succesfull!", se);
      return null; // shut up compiler
    }
  }

  /**
   * 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 DocumentHandler.
   */
  public void setStylesheet(StylesheetRoot stylesheetRoot)
  {
    m_stylesheetRoot = stylesheetRoot;
    org.apache.xalan.templates.StylesheetRoot sr = stylesheetRoot.getObject();
    if (m_transformerImpl == null)
      m_transformerImpl = (TransformerImpl)sr.newTransformer();
    m_transformerImpl.setStylesheet(sr);
    if (m_problemListener != null)
      m_transformerImpl.setErrorListener(m_problemListener);
  }

  /**
   * Get the current stylesheet for this processor.
   */
  public StylesheetRoot getStylesheet()    
  {
    return m_stylesheetRoot;
  }

  /**
   * <meta name="usage" content="internal"/>
   * Get the filename of the output document, if it was set.
   * This is for use by multiple output documents, to determine
   * the base directory for the output document.  It needs to
   * be set by the caller.
   */
  public String getOutputFileName()
  {
    return m_outputFileName;
  }

  /**
   * <meta name="usage" content="internal"/>
   * Set the filename of the output document.
   * This is for use by multiple output documents, to determine
   * the base directory for the output document.  It needs to
   * be set by the caller.
   */
  public void setOutputFileName(String filename)
  {
    m_outputFileName = filename;
  }

  

  /**
   * Given an input source, get the source tree.
   */
  public Node getSourceTreeFromInput(XSLTInputSource inputSource)
    throws org.xml.sax.SAXException
  {
    Node sourceTree = null;
    String xmlIdentifier = ((null == inputSource) ||
                            (null == inputSource.getSystemId()))
                           ? "Input XML" : inputSource.getSystemId();
    
    Source iSource = inputSource.getSourceObject(); 

    if(iSource instanceof DOMSource)
    {
      //if(getXMLProcessorLiaison() instanceof org.apache.xalan.xpath.dtm.DTMLiaison)
       // error(XSLTErrorResources.ER_CANT_USE_DTM_FOR_INPUT);

      sourceTree = ((DOMSource)iSource).getNode();
    }
    else
    {
      // In case we have a fragment identifier, go ahead and
      // try and parse the XML here.
      try
      {
        diag("========= Parsing "+xmlIdentifier+" ==========");
        pushTime(xmlIdentifier);
        
        String liaisonClassName = System.getProperty("org.apache.xalan.source.liaison");

        if(null != liaisonClassName)
        {
          DOM2Helper liaison =  (DOM2Helper)(Class.forName(liaisonClassName).newInstance());
          liaison.parse(SAXSource.sourceToInputSource(iSource));
          if(null != m_diagnosticsPrintWriter)
            displayDuration("Parse of "+xmlIdentifier, xmlIdentifier);
          sourceTree = liaison.getDocument();
        }
        else
        {      
          XMLReader reader = XMLReaderFactory.createXMLReader();        
          try
          {
            reader.setFeature("http://xml.org/sax/features/namespace-prefixes", true);
          }
          catch(SAXException se)
          {
          // What can we do?
          // TODO: User diagnostics.
          }
        
          // Get the input content handler, which will handle the 
          // parse events and create the source tree.          
          //StylesheetHandler inputHandler = (StylesheetHandler)m_processor.getTemplatesBuilder();
          //reader.setContentHandler( inputHandler );
          
          SourceTreeHandler handler = new SourceTreeHandler();
          reader.setContentHandler(handler);
          reader.setProperty("http://xml.org/sax/properties/lexical-handler", handler);
        
          // Kick off the parse.  When the ContentHandler gets 
          // the startDocument event, it will call transformNode( node ).
          reader.parse( SAXSource.sourceToInputSource(iSource));
          sourceTree = handler.getRoot();
        }
      }
      catch(Exception e)
      {
        // Unwrap exception
        if((e instanceof SAXException) && (null != ((SAXException)e).getException()))
        {
          // ((SAXException)e).getException().printStackTrace();
          e = ((SAXException)e).getException();
        }
        sourceTree = null; // shutup compiler
        error(XSLTErrorResources.ER_COULDNT_PARSE_DOC, new Object[] {xmlIdentifier}, e); //"Could not parse "+xmlIdentifier+" document!", e);
      }
    }

    return sourceTree;
  }

  /**
   * Get Stylesheet from PI URL
   * 
   * @param xslURLString a valid URI to an XSL stylesheet.
   * @param fragbase Document fragment Node.
   * @param xmlBaseIdent Base URI to resolve stylesheet URL 
   * @param isRoot Flag indicating if root node
   */
  Stylesheet getStylesheetFromPIURL(String xslURLString, Node fragBase,
                                    String xmlBaseIdent, boolean isRoot)
    throws SAXException,
    MalformedURLException,
    FileNotFoundException,
    IOException
  {
    StylesheetRoot m_stylesheetRoot = null;
    Stylesheet stylesheet = null;
    String[] stringHolder =
    {
      null};
    xslURLString = xslURLString.trim();
    int fragIndex = xslURLString.indexOf('#');
    String fragID = null;
    Document stylesheetDoc;
    if(fragIndex == 0)
    {
      diag("Locating stylesheet from fragment identifier...");
      fragID = xslURLString.substring(1);
      
      // Try a bunch of really ugly stuff to find the fragment.
      // What's the right way to do this?

      // Create a XPath parser.
      XPathParser parser = new XPathParser((ErrorListener)m_problemListener.getErrorHandler(), null);
      XPathContext xpathContext = new XPathContext();
      PrefixResolverDefault nsNode = new PrefixResolverDefault(fragBase); //xpathContext.getNamespaceContext();

      NodeIterator nl = null;
      // Create the XPath object.
      try{
      XPath xpath = new XPath(fragID, null, nsNode, XPath.MATCH);
      Compiler compiler = new Compiler();
      // Parse the xpath
      parser.initXPath(compiler, "id("+fragID+")", nsNode);
      org.apache.xpath.objects.XObject xobj = xpath.execute(xpathContext, fragBase, nsNode);

      nl = xobj.nodeset();
      if(nl.nextNode() == null)
      {
        // xobj = Stylesheet.evalXPathStr(getExecContext(), "//*[@id='"+fragID+"']", fragBase, nsNode);
        // Create the XPath object.
        xpath = new XPath(fragID, null, nsNode, XPath.MATCH);

        // Parse the xpath
        parser.initXPath(compiler, "//*[@id='"+fragID+"']", nsNode);
        xobj = xpath.execute(xpathContext, fragBase, nsNode);

        nl = xobj.nodeset();
        if(nl.nextNode() == null)
        {
          // xobj = Stylesheet.evalXPathStr(getExecContext(), "//*[@name='"+fragID+"']", fragBase, nsNode);
          // Create the XPath object.
          xpath = new XPath(fragID, null, nsNode, XPath.MATCH);

          // Parse the xpath
          parser.initXPath(compiler, "//*[@name='"+fragID+"']", nsNode);
          xobj = xpath.execute(xpathContext, fragBase, nsNode);
          nl = xobj.nodeset();
          if(nl.nextNode() == null)
          {
            // Well, hell, maybe it's an XPath...
            // xobj = Stylesheet.evalXPathStr(getExecContext(), fragID, fragBase, nsNode);
            // Create the XPath object.
            //((StylesheetHandler)( m_processor.getTemplatesBuilder())).getLocator()
            xpath = new XPath(fragID, null, nsNode, XPath.MATCH);

            // Parse the xpath
            parser.initXPath(compiler, fragID, nsNode);
            xobj = xpath.execute(xpathContext, fragBase, nsNode);
            nl = xobj.nodeset();
          }
        }
      }
      }
      catch (TransformerException te)
      {
        throw new SAXException(te);
      }
      if(nl.nextNode() == null)
      {
        error(XSLTErrorResources.ER_COULDNT_FIND_FRAGMENT, new Object[] {fragID}); //"Could not find fragment: "+fragID);
      }
      // Use previous because the previous call moved the pointer.
      // or should we use getRoot??
      Node frag = nl.previousNode(); //.item(0);

      if(Node.ELEMENT_NODE == frag.getNodeType())
      {
        pushTime(frag);
        if(isRoot)
        {
          m_stylesheetRoot = createStylesheetRoot(stringHolder[0]);
          stylesheet = m_stylesheetRoot.getObject();
        }
        else
        {
          //stylesheet = new Stylesheet(m_stylesheetRoot);
          // stylesheet = ((StylesheetHandler)(m_processor.getTemplatesBuilder())).getStylesheetRoot();
          try{
            Source source = new XSLTInputSource(fragID).getSourceObject(); 
            Templates templates = m_tfactory.newTemplates(source);
            stylesheet = (org.apache.xalan.templates.StylesheetRoot)templates;
          }
          catch (TransformerConfigurationException tce)
          {
            throw new SAXException(tce);
          }
        }
        addTraceListenersToStylesheet();

        try{
        StylesheetHandler stylesheetProcessor
          = new StylesheetHandler((TransformerFactoryImpl)m_tfactory);
           
        stylesheetProcessor.pushStylesheet(stylesheet);
        TreeWalker tw = new TreeWalker(stylesheetProcessor);
        tw.traverse(frag);

        displayDuration("Setup of "+xslURLString, frag);
        }
        catch (TransformerConfigurationException tce)
        {
          throw new SAXException(tce);
        }
      }
      else
      {
        stylesheetDoc = null;
        error(XSLTErrorResources.ER_NODE_NOT_ELEMENT, new Object[] {fragID}); //"Node pointed to by fragment identifier was not an element: "+fragID);
      }
    }
    else
    {
      // TODO: Use Reader here??
      // hmmm.. for now I'll rely on the XML parser to handle
      // fragment URLs.
      diag(XSLMessages.createMessage(XSLTErrorResources.WG_PARSING_AND_PREPARING, new Object[] {xslURLString})); //"========= Parsing and preparing "+xslURLString+" ==========");
      pushTime(xslURLString);

      if(isRoot)
      {
        m_stylesheetRoot = createStylesheetRoot(xslURLString);
        stylesheet = m_stylesheetRoot.getObject();
      }
      else
      {
        stylesheet = new Stylesheet(m_stylesheetRoot.getObject());
      }
      addTraceListenersToStylesheet();

      try{
      org.apache.xalan.processor.StylesheetHandler stylesheetProcessor
        = new StylesheetHandler((TransformerFactoryImpl)m_tfactory); //this, stylesheet); 
      stylesheetProcessor.pushStylesheet(stylesheet);
         // new StylesheetHandler(this, stylesheet);
      }
      catch (TransformerConfigurationException tce)
      {
        throw new SAXException(tce);
      }
      
      URL xslURL = getURLFromString(xslURLString, xmlBaseIdent);

      XSLTInputSource inputSource = new XSLTInputSource(xslURL.toString());
      String liaisonClassName = System.getProperty("org.apache.xalan.source.liaison");

      if(null != liaisonClassName)
      {
        try{
          DOM2Helper liaison =  (DOM2Helper)(Class.forName(liaisonClassName).newInstance());
          liaison.parse(SAXSource.sourceToInputSource(inputSource.getSourceObject()));
        }
        catch (ClassNotFoundException e1) 
        {
          throw new SAXException("XML Liaison class " + liaisonClassName +
            " specified but not found", e1);
        } 
        catch (IllegalAccessException e2) 
        {
          throw new SAXException("XML Liaison class " + liaisonClassName +
            " found but cannot be loaded", e2);
        } 
        catch (InstantiationException e3) 
        {
          throw new SAXException("XML Liaison class " + liaisonClassName +
            " loaded but cannot be instantiated (no empty public constructor?)",
            e3);
        }
        
        catch (TransformerException tce)
        {
          throw new SAXException(tce);
        }
      }  
      //m_parserLiaison.setDocumentHandler(stylesheetProcessor);
      //m_parserLiaison.parse(inputSource);

      displayDuration("Parsing and init of "+xslURLString, xslURLString);
    }
    return stylesheet;
  }

        
  /**
   * Take a user string and try and parse XML, and also return 
   * the url.
   * @exception XSLProcessorException thrown if the active ProblemListener and XPathContext decide 
   * the error condition is severe enough to halt processing.
   */
  public static URL getURLFromString(String urlString, String base)
    throws SAXException 
  {
    String origURLString = urlString;
    String origBase = base;
    
    // System.out.println("getURLFromString - urlString: "+urlString+", base: "+base);
    Object doc;
    URL url = null;
    int fileStartType = 0;
    try
    {
      
      if(null != base)
      {
        if(base.toLowerCase().startsWith("file:/"))
        {
          fileStartType = 1;
        }
        else if(base.toLowerCase().startsWith("file:"))
        {
          fileStartType = 2;
        }
      }
      
      boolean isAbsoluteURL;
      
      // From http://www.ics.uci.edu/pub/ietf/uri/rfc1630.txt
      // A partial form can be distinguished from an absolute form in that the
      // latter must have a colon and that colon must occur before any slash
      // characters. Systems not requiring partial forms should not use any
      // unencoded slashes in their naming schemes.  If they do, absolute URIs
      // will still work, but confusion may result.
      int indexOfColon = urlString.indexOf(':');
      int indexOfSlash = urlString.indexOf('/');
      if((indexOfColon != -1) && (indexOfSlash != -1) && (indexOfColon < indexOfSlash))
      {
        // The url (or filename, for that matter) is absolute.
        isAbsoluteURL = true;
      }
      else
      {
        isAbsoluteURL = false;
      }
      
      if(isAbsoluteURL || (null == base) || (base.length() == 0))
      {
        try 
        {
          url = new URL(urlString);
        }
        catch (MalformedURLException e) {}
      }
      // The Java URL handling doesn't seem to handle relative file names.
      else if(!((urlString.charAt(0) == '.') || (fileStartType > 0)))
      {
        try 
        {
          URL baseUrl = new URL(base);
          url = new URL(baseUrl, urlString);
        }
        catch (MalformedURLException e) 
        {
        }
      }
      
      if(null == url)
      {
        // Then we're going to try and make a file URL below, so strip 
        // off the protocol header.
        if(urlString.toLowerCase().startsWith("file:/"))
        {
          urlString = urlString.substring(6);
        }
        else if(urlString.toLowerCase().startsWith("file:"))
        {
          urlString = urlString.substring(5);
        }
      }
      
      if((null == url) && ((null == base) || (fileStartType > 0)))
      {
        if(1 == fileStartType)
        {
          if(null != base)
            base = base.substring(6);
          fileStartType = 1;
        }
        else if(2 == fileStartType)
        {
          if(null != base)
            base = base.substring(5);
          fileStartType = 2;
        }
        
        File f = new File(urlString);
        
        if(!f.isAbsolute() && (null != base))
        {
          // String dir = f.isDirectory() ? f.getAbsolutePath() : f.getParent();
          // System.out.println("prebuiltUrlString (1): "+base);
          StringTokenizer tokenizer = new StringTokenizer(base, "\\/");
          String fixedBase = null;
          while(tokenizer.hasMoreTokens())
          {
            String token = tokenizer.nextToken();
            if (null == fixedBase) 
            {
              // Thanks to Rick Maddy for the bug fix for UNIX here.
              if (base.charAt(0) == '\\' || base.charAt(0) == '/') 
              {
                fixedBase = File.separator + token;
              }
              else 
              {
                fixedBase = token;
              }
            }
            else 
            {
              fixedBase+= File.separator + token;
            }
          }
          // System.out.println("rebuiltUrlString (1): "+fixedBase);
          f = new File(fixedBase);
          String dir = f.isDirectory() ? f.getAbsolutePath() : f.getParent();
          // System.out.println("dir: "+dir);
          // System.out.println("urlString: "+urlString);
          // f = new File(dir, urlString);
          // System.out.println("f (1): "+f.toString());
          // urlString = f.getAbsolutePath();
          f = new File(urlString); 
          boolean isAbsolute =  f.isAbsolute() 
                                || (urlString.charAt( 0 ) == '\\')
                                || (urlString.charAt( 0 ) == '/');
          if(!isAbsolute)
          {
            // Getting more and more ugly...
            if(dir.charAt( dir.length()-1 ) != File.separator.charAt(0) && 
               urlString.charAt( 0 ) != File.separator.charAt(0))
            {
              urlString = dir + File.separator + urlString;
            }
            else
            {
              urlString = dir + urlString;
            }

            // System.out.println("prebuiltUrlString (2): "+urlString);
            tokenizer = new StringTokenizer(urlString, "\\/");
            String rebuiltUrlString = null;
            while(tokenizer.hasMoreTokens())
            {
              String token = tokenizer.nextToken();
              if (null == rebuiltUrlString) 
              {
                // Thanks to Rick Maddy for the bug fix for UNIX here.
                if (urlString.charAt(0) == '\\' || urlString.charAt(0) == '/') 
                {
                  rebuiltUrlString = File.separator + token;
                }
                else 
                {
                  rebuiltUrlString = token;
                }
              }
              else 
              {
                rebuiltUrlString+= File.separator + token;
              }
            }
            // System.out.println("rebuiltUrlString (2): "+rebuiltUrlString);
            if(null != rebuiltUrlString)
              urlString = rebuiltUrlString;
          }
          // System.out.println("fileStartType: "+fileStartType);
          if(1 == fileStartType)
          {
            if (urlString.charAt(0) == '/') 
            {
              urlString = "file://"+urlString;
            }
            else
            {
              urlString = "file:/"+urlString;
            }
          }
          else if(2 == fileStartType)
          {
            urlString = "file:"+urlString;
          }
          try 
          {
            // System.out.println("Final before try: "+urlString);
            url = new URL(urlString);
          }
          catch (MalformedURLException e) 
          {
            // System.out.println("Error trying to make URL from "+urlString);
          }
        }
      }
      if(null == url)
      {
        // The sun java VM doesn't do this correctly, but I'll 
        // try it here as a second-to-last resort.
        if((null != origBase) && (origBase.length() > 0))
        {
          try 
          {
            URL baseURL = new URL(origBase);
            // System.out.println("Trying to make URL from "+origBase+" and "+origURLString);
            url = new URL(baseURL, origURLString);
            // System.out.println("Success! New URL is: "+url.toString());
          }
          catch (MalformedURLException e) 
          {
            // System.out.println("Error trying to make URL from "+origBase+" and "+origURLString);
          }
        }
        
        if(null == url)
        {
          try 
          {
            String lastPart;
            if(null != origBase)
            {
              File baseFile = new File(origBase);
              if(baseFile.isDirectory())
              {
                lastPart = new File(baseFile, urlString).getAbsolutePath ();
              }
              else
              {
                String parentDir = baseFile.getParent();
                lastPart = new File(parentDir, urlString).getAbsolutePath ();
              }
            }
            else
            {
              lastPart = new File (urlString).getAbsolutePath ();
            }
            // Hack
            // if((lastPart.charAt(0) == '/') && (lastPart.charAt(2) == ':'))
            //   lastPart = lastPart.substring(1, lastPart.length() - 1);
            
            String fullpath;
            if (lastPart.charAt(0) == '\\' || lastPart.charAt(0) == '/') 
            {
              fullpath = "file://" + lastPart;
            }
            else
            {
              fullpath = "file:" + lastPart;
            }
            url = new URL(fullpath);
          }
          catch (MalformedURLException e2)
          {
            throw new SAXException("Cannot create url for: " + urlString, e2 ); 
              //XSLMessages.createXPATHMessage(XPATHErrorResources.ER_CANNOT_CREATE_URL, new Object[]{urlString}),e2); //"Cannot create url for: " + urlString, e2 );
          }
        }
      }
    }
    catch(SecurityException se)
    {
      try
      {
        url = new URL("http://xml.apache.org/xslt/"+java.lang.Math.random()); // dummy
      }
      catch (MalformedURLException e2)
      {
        // I give up
      }
    }
    // System.out.println("url: "+url.toString());
    return url;
  }

   /**
   * Add a trace listener for the purposes of debugging and diagnosis.
   * @param tl Trace listener to be added.
   */
  void addTraceListenersToStylesheet()
    throws SAXException
  {
    /*try
    {
      TraceManager tm = m_transformerImpl.getTraceManager();
      if(tm.hasTraceListeners)
      {
        int nListeners = tm.size();
        for(int i = 0; i < nListeners; i++)
        {
          TraceListener tl = (TraceListener)m_traceListeners.elementAt(i);
          if(null != m_stylesheetRoot)
            m_stylesheetRoot.addTraceListener(tl);
        }
      }
    }
    catch(TooManyListenersException tmle)
    {
      throw new SAXException(XSLMessages.createMessage(XSLTErrorResources.ER_TOO_MANY_LISTENERS, null),tmle ); //"addTraceListenersToStylesheet - TooManyListenersException", tmle);
    }*/
  }
  
  /**
   * Warn the user of an problem.
   * This is public for access by extensions.
   * @exception XSLProcessorException thrown if the active ProblemListener and XMLParserLiaison decide
   * the error condition is severe enough to halt processing.
   */
  public void message(String msg)
    throws SAXException
  {
    message(null, null, msg);
  }



  /**
   * Warn the user of an problem.
   * This is public for access by extensions.
   * @exception XSLProcessorException thrown if the active ProblemListener and XMLParserLiaison decide
   * the error condition is severe enough to halt processing.
   */
  public void message(Node styleNode, Node sourceNode, String msg)
    throws SAXException
  {
    m_problemListener.message(msg);
  }

  /**
   * <meta name="usage" content="internal"/>
   * Warn the user of an problem.
   * @exception XSLProcessorException thrown if the active ProblemListener and XMLParserLiaison decide
   * the error condition is severe enough to halt processing.
   */
  public void warn(int msg)
    throws SAXException
  {
    warn(null, null, msg, null);
  }

  /**
   * <meta name="usage" content="internal"/>
   * Warn the user of an problem.
   * @exception XSLProcessorException thrown if the active ProblemListener and XMLParserLiaison decide
   * the error condition is severe enough to halt processing.
   */
  public void warn(int msg, Object[] args)
    throws SAXException
  {
    warn(null, null, msg, args);
  }

  /**
   * <meta name="usage" content="internal"/>
   * Warn the user of an problem.
   * @exception XSLProcessorException thrown if the active ProblemListener and XMLParserLiaison decide
   * the error condition is severe enough to halt processing.
   */
  public void warn(Node styleNode, Node sourceNode, int msg)
    throws SAXException
  {
    warn(styleNode, sourceNode, msg, null);
  }

  /**
   * <meta name="usage" content="internal"/>
   * Warn the user of an problem.
   * @exception XSLProcessorException thrown if the active ProblemListener and XMLParserLiaison decide
   * the error condition is severe enough to halt processing.
   */
  public void warn(Node styleNode, Node sourceNode, int msg, Object args[])
    throws SAXException
  {
    Exception e = null;
    String fmsg = m_XSLMessages.createWarning(msg, args);
    SourceLocator locator = null;
    try{
     locator = ((StylesheetHandler)(((TransformerFactoryImpl)this.m_tfactory).newTemplatesHandler())).getLocator();
    }
    catch (TransformerConfigurationException tce)
    {
    }
    
    DefaultErrorHandler handler;
    if (m_problemListener == null)
      handler = (DefaultErrorHandler)m_tfactory.getErrorListener();
    else
      handler = (DefaultErrorHandler)m_problemListener.getErrorHandler();
    TransformerException te = (null == e) ? new TransformerException(fmsg, locator) :
                                          new TransformerException(fmsg, locator, e);
    if(null != handler)
    {
      try{
      handler.warning(te);
      }
      catch (TransformerException te2)
      {
        throw new SAXException(te2);
      } 
    }
    else
      throw new SAXException(te);
  }

  /**
   * <meta name="usage" content="internal"/>
   * Tell the user of an error, and probably throw an
   * exception.
   * @exception XSLProcessorException thrown if the active ProblemListener and XMLParserLiaison decide
   * the error condition is severe enough to halt processing.
   */
  public void error(String msg)
    throws SAXException
  {
    Exception e = null;
    SourceLocator locator = null;
    try{
    locator = ((StylesheetHandler)(((TransformerFactoryImpl)this.m_tfactory).newTemplatesHandler())).getLocator();
    }
    catch (TransformerConfigurationException tce)
    {
    }
    DefaultErrorHandler handler;
    if (m_problemListener == null)
      handler = (DefaultErrorHandler)m_tfactory.getErrorListener();
    else
      handler = (DefaultErrorHandler)m_problemListener.getErrorHandler();
    TransformerException te = (null == e) ? new TransformerException(msg, locator) :
                                          new TransformerException(msg, locator, e);
    if(null != handler)
    {  
      try{
      handler.fatalError(te);
    }
      catch (TransformerException te2)
      {
        throw new SAXException(te2);
      } 
    }
    else
      throw new SAXException(te);
  }

  /**
   * <meta name="usage" content="internal"/>
   * Tell the user of an error, and probably throw an
   * exception.
   * @exception XSLProcessorException thrown if the active ProblemListener and XMLParserLiaison decide
   * the error condition is severe enough to halt processing.
   */
  public void error(int msg)
    throws SAXException
  {
    error(null, null, msg, null);
  }

  /**
   * <meta name="usage" content="internal"/>
   * Tell the user of an error, and probably throw an
   * exception.
   * @exception XSLProcessorException thrown if the active ProblemListener and XMLParserLiaison decide
   * the error condition is severe enough to halt processing.
   */
  public void error(int msg, Object[] args)
    throws SAXException
  {
    error(null, null, msg, args);
  }

  /**
   * <meta name="usage" content="internal"/>
   * Tell the user of an error, and probably throw an
   * exception.
   * @exception XSLProcessorException thrown if the active ProblemListener and XMLParserLiaison decide
   * the error condition is severe enough to halt processing.
   */
  public void error(int msg, Exception e)
    throws SAXException
  {
    error(msg, null, e);
  }

  /**
   * <meta name="usage" content="internal"/>
   * Tell the user of an error, and probably throw an
   * exception.
   * @exception XSLProcessorException thrown if the active ProblemListener and XMLParserLiaison decide
   * the error condition is severe enough to halt processing.
   */
  public void error(int msg, Object args[], Exception e)
    throws SAXException
  {
    String fmsg = m_XSLMessages.createMessage(msg, args);
    SourceLocator locator = null;
    try{
      locator = ((StylesheetHandler)(((TransformerFactoryImpl)this.m_tfactory).newTemplatesHandler())).getLocator();
    }
    catch (TransformerConfigurationException tce)
    {
    }
    DefaultErrorHandler handler;
    if (m_problemListener == null)
      handler = (DefaultErrorHandler)m_tfactory.getErrorListener();
    else
      handler = (DefaultErrorHandler)m_problemListener.getErrorHandler();
    TransformerException te = (null == e) ? new TransformerException(fmsg, locator) :
                                          new TransformerException(fmsg, locator, e);
    if(null != handler)
    {
      try{
      handler.fatalError(te);
    }
      catch (TransformerException te2)
      {
        throw new SAXException(te2);
      } 
    }
    else
      throw new SAXException(te);
  }

  /**
    * <meta name="usage" content="internal"/>
  * Tell the user of an error, and probably throw an
   * exception.
   * @exception XSLProcessorException thrown if the active ProblemListener and XMLParserLiaison decide
   * the error condition is severe enough to halt processing.
   */
  public void error(Node styleNode, Node sourceNode, int msg)
    throws SAXException
  {
    error(styleNode, sourceNode, msg, null);
  }

  /**
   * <meta name="usage" content="internal"/>
   * Tell the user of an error, and probably throw an
   * exception.
   * @exception XSLProcessorException thrown if the active ProblemListener and XMLParserLiaison decide
   * the error condition is severe enough to halt processing.
   */
  public void error(Node styleNode, Node sourceNode, int msg, Object args[])
    throws SAXException
  {
    Exception e = null;
    String fmsg = m_XSLMessages.createMessage(msg, args);
    SourceLocator locator = null;
    try{
     locator = ((StylesheetHandler)(((TransformerFactoryImpl)this.m_tfactory).newTemplatesHandler())).getLocator();
    }
    catch (TransformerConfigurationException tce)
    {
    }
    DefaultErrorHandler handler;
    if (m_problemListener == null)
      handler = (DefaultErrorHandler)m_tfactory.getErrorListener();
    else
      handler = (DefaultErrorHandler)m_problemListener.getErrorHandler();
    TransformerException te = (null == e) ? new TransformerException(fmsg, locator) :
                                          new TransformerException(fmsg, locator, e);
    if(null != handler)
    {  
      try{
       handler.fatalError(te);
      }
      catch (TransformerException te2)
      {
        throw new SAXException(te2);
      }
    }
    else
      throw new SAXException(te);
    
   
  }
  
  /**
   * Mark the time, so that displayDuration can later
   * display the elapse.
   */
  void pushTime(Object key)
  {
    if(null != key)
    {
      m_durationsTable.put(key, new Long(System.currentTimeMillis()));
    }
  }

  /**
   * Returns the duration since pushTime was called,
   * in milliseconds.
   */
  long popDuration(Object key)
  {
    long millisecondsDuration = 0;
    if(null != key)
    {
      long start = ((Long)m_durationsTable.get(key)).longValue();
      long stop = System.currentTimeMillis();
      millisecondsDuration = stop - start;
      m_durationsTable.remove(key);
    }
    return millisecondsDuration;
  }
  
   /**
   * Display the duration since pushTime was called.
   */
  protected void displayDuration(String info, Object key)
  {
    long millisecondsDuration = 0;
    if(null != key)
    {
      long start = ((Long)m_durationsTable.get(key)).longValue();
      long stop = System.currentTimeMillis();
      millisecondsDuration = stop - start;
      if(null != m_diagnosticsPrintWriter)
      {
        m_diagnosticsPrintWriter.println(info + " took " + millisecondsDuration + " milliseconds");
      }
      m_durationsTable.remove(key);
    }
  }
  
  /**
   * If this is set, diagnostics will be
   * written to the m_diagnosticsPrintWriter stream. If
   * the value is null, then diagnostics will be turned
   * off.
   */
  public void setDiagnosticsOutput(java.io.OutputStream out)
  {
    setDiagnosticsOutput(new PrintWriter(out));
  }

  /**
   * If this is set, diagnostics will be
   * written to the m_diagnosticsPrintWriter stream. If
   * the value is null, then diagnostics will be turned
   * off.
   */
  public void setDiagnosticsOutput(java.io.PrintWriter pw)
  {
    m_diagnosticsPrintWriter = pw;
   /* if(getProblemListener() instanceof ProblemListenerDefault)
    {
      ((ProblemListenerDefault)getProblemListener()).setDiagnosticsOutput(pw);
    }*/
  }

  /**
   * Bottleneck output of diagnostics.
   */
  protected void diag(String s)
  {
    if(null != m_diagnosticsPrintWriter)
    {
      m_diagnosticsPrintWriter.println(s);
    }
  }

  /**
   * If this is set to true, simple traces of
   * template calls are made.
   */
  public void setTraceTemplates(boolean b)
  {
    m_traceTemplates = b;
  }

  /**
   * If this is set to true, simple traces of
   * template calls are made.
   */
  public void setTraceSelect(boolean b)
  {
    m_traceSelects = b;
  }

  /**
   * If this is set to true, debug diagnostics about
   * template children as they are being constructed
   * will be written to the m_diagnosticsPrintWriter
   * stream.  diagnoseTemplateChildren is false by
   * default.
   */
  public void setTraceTemplateChildren(boolean b)
  {
    m_traceTemplateChildren = b;
  }
  
  //
  // Lexical handler interface
  //

    /**
     * Report the start of DTD declarations, if any.
     *
     * <p>Any declarations are assumed to be in the internal subset
     * unless otherwise indicated by a {@link #startEntity startEntity}
     * event.</p>
     *
     * <p>Note that the start/endDTD events will appear within
     * the start/endDocument events from ContentHandler and
     * before the first startElement event.</p>
     *
     * @param name The document type name.
     * @param publicId The declared public identifier for the
     *        external DTD subset, or null if none was declared.
     * @param systemId The declared system identifier for the
     *        external DTD subset, or null if none was declared.
     * @exception SAXException The application may raise an
     *            exception.
     * @see #endDTD
     * @see #startEntity
     */
    public void startDTD (String name, String publicId, String systemId)
	throws SAXException
    {
      if (m_transformerImpl != null && m_transformerImpl.getInputLexicalHandler() != null)
        m_transformerImpl.getInputLexicalHandler().startDTD(name, publicId, systemId);
    }


    /**
     * Report the end of DTD declarations.
     *
     * @exception SAXException The application may raise an exception.
     * @see #startDTD
     */
    public void endDTD ()
	throws SAXException
    {
      if (m_transformerImpl != null && m_transformerImpl.getInputLexicalHandler() != null)
        m_transformerImpl.getInputLexicalHandler().endDTD();
    }
    
    public void startEntity (String name)
	throws SAXException
    {
      if (m_transformerImpl != null && m_transformerImpl.getInputLexicalHandler() != null)
        m_transformerImpl.getInputLexicalHandler().startEntity (name);
    }


    /**
     * Report the end of an entity.
     *
     * @param name The name of the entity that is ending.
     * @exception SAXException The application may raise an exception.
     * @see #startEntity
     */
    public void endEntity (String name)
	throws SAXException
      {
      if (m_transformerImpl != null && m_transformerImpl.getInputLexicalHandler() != null)
        m_transformerImpl.getInputLexicalHandler().endEntity (name);
    }


    /**
     * Report the start of a CDATA section.
     *
     * <p>The contents of the CDATA section will be reported through
     * the regular {@link org.xml.sax.ContentHandler#characters
     * characters} event.</p>
     *
     * @exception SAXException The application may raise an exception.
     * @see #endCDATA
     */
    public  void startCDATA ()
	throws SAXException
    { 
      if (m_transformerImpl != null && m_transformerImpl.getInputLexicalHandler() != null)
        m_transformerImpl.getInputLexicalHandler().startCDATA();
    }


    /**
     * Report the end of a CDATA section.
     *
     * @exception SAXException The application may raise an exception.
     * @see #startCDATA
     */
    public void endCDATA ()
	throws SAXException
    {
      if (m_transformerImpl != null && m_transformerImpl.getInputLexicalHandler() != null)
        m_transformerImpl.getInputLexicalHandler().endCDATA();
    }


    /**
     * Report an XML comment anywhere in the document.
     *
     * <p>This callback will be used for comments inside or outside the
     * document element, including comments in the external DTD
     * subset (if read).</p>
     *
     * @param ch An array holding the characters in the comment.
     * @param start The starting position in the array.
     * @param length The number of characters to use from the array.
     * @exception SAXException The application may raise an exception.
     */
    public  void comment (char ch[], int start, int length)
	throws SAXException
      {
      if (m_transformerImpl != null && m_transformerImpl.getInputLexicalHandler() != null)
        m_transformerImpl.getInputLexicalHandler().comment (ch, start, length);
    }
    
    // DocumentHandler interface
    
        /**
     * Receive an object for locating the origin of SAX document events.
     *
     * <p>SAX parsers are strongly encouraged (though not absolutely
     * required) to supply a locator: if it does so, it must supply
     * the locator to the application by invoking this method before
     * invoking any of the other methods in the DocumentHandler
     * interface.</p>
     *
     * <p>The locator allows the application to determine the end
     * position of any document-related event, even if the parser is
     * not reporting an error.  Typically, the application will
     * use this information for reporting its own errors (such as
     * character content that does not match an application's
     * business rules).  The information returned by the locator
     * is probably not sufficient for use with a search engine.</p>
     *
     * <p>Note that the locator will return correct information only
     * during the invocation of the events in this interface.  The
     * application should not attempt to use it at any other time.</p>
     *
     * @param locator An object that can return the location of
     *                any SAX document event.
     * @see org.xml.sax.Locator
     */
    public void setDocumentLocator (Locator locator)
    {}
    
    
    /**
     * Receive notification of the beginning of a document.
     *
     * <p>The SAX parser will invoke this method only once, before any
     * other methods in this interface or in DTDHandler (except for
     * setDocumentLocator).</p>
     *
     * @exception org.xml.sax.SAXException Any SAX exception, possibly
     *            wrapping another exception.
     */
    public void startDocument ()
	throws SAXException
    {
      if (m_documentHandler != null)
        m_documentHandler.startDocument();
      else if (m_transformerImpl != null)
        m_transformerImpl.getInputContentHandler().startDocument();
      //m_transformerImpl.getResultTreeHandler().startDocument();
      
    }
    
    
    /**
     * Receive notification of the end of a document.
     *
     * <p>The SAX parser will invoke this method only once, and it will
     * be the last method invoked during the parse.  The parser shall
     * not invoke this method until it has either abandoned parsing
     * (because of an unrecoverable error) or reached the end of
     * input.</p>
     *
     * @exception org.xml.sax.SAXException Any SAX exception, possibly
     *            wrapping another exception.
     */
    public void endDocument ()
	throws SAXException
    {
      if (m_documentHandler != null)
        m_documentHandler.endDocument();
      else if (m_transformerImpl != null)
        m_transformerImpl.getInputContentHandler().endDocument();
      //m_transformerImpl.getResultTreeHandler().endDocument();
    }
    
    
    /**
     * Receive notification of the beginning of an element.
     *
     * <p>The Parser will invoke this method at the beginning of every
     * element in the XML document; there will be a corresponding
     * endElement() event for every startElement() event (even when the
     * element is empty). All of the element's content will be
     * reported, in order, before the corresponding endElement()
     * event.</p>
     *
     * <p>If the element name has a namespace prefix, the prefix will
     * still be attached.  Note that the attribute list provided will
     * contain only attributes with explicit values (specified or
     * defaulted): #IMPLIED attributes will be omitted.</p>
     *
     * @param name The element type name.
     * @param atts The attributes attached to the element, if any.
     * @exception org.xml.sax.SAXException Any SAX exception, possibly
     *            wrapping another exception.
     * @see #endElement
     * @see org.xml.sax.AttributeList 
     */
    public void startElement (String name, AttributeList atts)
	throws SAXException
    {
      if (m_documentHandler == null)       
      { 
        m_documentHandler = new ParserAdapter(new org.apache.xerces.parsers.SAXParser());
        if (m_transformerImpl != null)
        {  
          ((ParserAdapter)m_documentHandler).setContentHandler(m_transformerImpl.getInputContentHandler());
        }
        /* else if (m_transformerImpl != null)
        {
        int index = name.indexOf(":");
        if (index < 0 )
        m_transformerImpl.getInputContentHandler().startElement(null, name, name, (Attributes)atts);
        //getResultTreeHandler().startElement(null, name, name, (Attributes)atts);
        else
        m_transformerImpl.getInputContentHandler().startElement(name.substring(0,index), name.substring(index+1), name, (Attributes)atts);        
        //m_transformerImpl.getResultTreeHandler().startElement(name.substring(0,index), name.substring(index+1), name, (Attributes)atts);
        */ 
      } 
      m_documentHandler.startElement(name, atts);
    }   
    
    /**
     * Receive notification of the end of an element.
     *
     * <p>The SAX parser will invoke this method at the end of every
     * element in the XML document; there will be a corresponding
     * startElement() event for every endElement() event (even when the
     * element is empty).</p>
     *
     * <p>If the element name has a namespace prefix, the prefix will
     * still be attached to the name.</p>
     *
     * @param name The element type name
     * @exception org.xml.sax.SAXException Any SAX exception, possibly
     *            wrapping another exception.
     */
    public void endElement (String name)
	throws SAXException
    {
      if (m_documentHandler == null)        
      {         
        m_documentHandler = new ParserAdapter(new org.apache.xerces.parsers.SAXParser());
        if (m_transformerImpl != null)
        {
          ((ParserAdapter)m_documentHandler).setContentHandler(m_transformerImpl.getInputContentHandler());
        }
     /* else if (m_transformerImpl != null)
      {
        int index = name.indexOf(":");
        if (index < 0 )
          m_transformerImpl.getInputContentHandler().endElement(null, name, name);
          //m_transformerImpl.getResultTreeHandler().endElement(null, name, name);        
        else
          m_transformerImpl.getInputContentHandler().endElement(name.substring(0,index), name.substring(index+1), name);
          //m_transformerImpl.getResultTreeHandler().endElement(name.substring(0,index), name.substring(index+1), name);
        */
      } 
      m_documentHandler.endElement(name);      
    }     
    
    
    /**
     * Receive notification of character data.
     *
     * <p>The Parser will call this method to report each chunk of
     * character data.  SAX parsers may return all contiguous character
     * data in a single chunk, or they may split it into several
     * chunks; however, all of the characters in any single event
     * must come from the same external entity, so that the Locator
     * provides useful information.</p>
     *
     * <p>The application must not attempt to read from the array
     * outside of the specified range.</p>
     *
     * <p>Note that some parsers will report whitespace using the
     * ignorableWhitespace() method rather than this one (validating
     * parsers must do so).</p>
     *
     * @param ch The characters from the XML document.
     * @param start The start position in the array.
     * @param length The number of characters to read from the array.
     * @exception org.xml.sax.SAXException Any SAX exception, possibly
     *            wrapping another exception.
     * @see #ignorableWhitespace 
     * @see org.xml.sax.Locator
     */
    public void characters (char ch[], int start, int length)
	throws SAXException
    {
      if (m_documentHandler != null)
        m_documentHandler.characters(ch, start, length);
      else if (m_transformerImpl != null)
      m_transformerImpl.getInputContentHandler().characters(ch, start, length);
      //m_transformerImpl.getResultTreeHandler().characters(ch, start, length);
    }  
    
    
    /**
     * Receive notification of ignorable whitespace in element content.
     *
     * <p>Validating Parsers must use this method to report each chunk
     * of ignorable whitespace (see the W3C XML 1.0 recommendation,
     * section 2.10): non-validating parsers may also use this method
     * if they are capable of parsing and using content models.</p>
     *
     * <p>SAX parsers may return all contiguous whitespace in a single
     * chunk, or they may split it into several chunks; however, all of
     * the characters in any single event must come from the same
     * external entity, so that the Locator provides useful
     * information.</p>
     *
     * <p>The application must not attempt to read from the array
     * outside of the specified range.</p>
     *
     * @param ch The characters from the XML document.
     * @param start The start position in the array.
     * @param length The number of characters to read from the array.
     * @exception org.xml.sax.SAXException Any SAX exception, possibly
     *            wrapping another exception.
     * @see #characters
     */
    public void ignorableWhitespace (char ch[], int start, int length)
	throws SAXException
    {
      if (m_documentHandler != null)
        m_documentHandler.ignorableWhitespace(ch, start, length);
      else if (m_transformerImpl != null)
      m_transformerImpl.getInputContentHandler().ignorableWhitespace(ch, start, length);
      //m_transformerImpl.getResultTreeHandler().ignorableWhitespace(ch, start, length);
    }
    
    
    /**
     * Receive notification of a processing instruction.
     *
     * <p>The Parser will invoke this method once for each processing
     * instruction found: note that processing instructions may occur
     * before or after the main document element.</p>
     *
     * <p>A SAX parser should never report an XML declaration (XML 1.0,
     * section 2.8) or a text declaration (XML 1.0, section 4.3.1)
     * using this method.</p>
     *
     * @param target The processing instruction target.
     * @param data The processing instruction data, or null if
     *        none was supplied.
     * @exception org.xml.sax.SAXException Any SAX exception, possibly
     *            wrapping another exception.
     */
    public  void processingInstruction (String target, String data)
	throws SAXException
    {
      if (m_documentHandler != null)
        m_documentHandler.processingInstruction(target, data);
      else if (m_transformerImpl != null)
      m_transformerImpl.getInputContentHandler().processingInstruction(target, data);
      //m_transformerImpl.getResultTreeHandler().processingInstruction(target, data);
    }
    
    // Implement XSLTProcessor
    
    /**
   * Set the output stream. Required when the XSLTProcessor is being used
   * as a SAX DocumentHandler.
   */
  public void setOutputStream(java.io.OutputStream os)
  {
    SourceTreeHandler handler = new SourceTreeHandler(m_transformerImpl);
    handler.setResult(new StreamResult(os));   
  }
  
  /**
   * Convenience function to create an XString.
   * @param s A valid string.
   * @return An XString object.
   */
  public XString createXString(String s)
  {
    return new XString(s);
  }

  /**
   * Convenience function to create an XObject.
   * @param o Any java object.
   * @return An XObject object.
   */
  public XObject createXObject(Object o)
  {
    return new XObject(o);
  }

  /**
   * Convenience function to create an XNumber.
   * @param d Any double number.
   * @return An XNumber object.
   */
  public XNumber createXNumber(double d)
  {
    return new XNumber(d);
  }

  /**
   * Convenience function to create an XBoolean.
   * @param b boolean value.
   * @return An XBoolean object.
   */
  public XBoolean createXBoolean(boolean b)
  {
    return new XBoolean(b);
  }

  /**
   * Convenience function to create an XNodeSet.
   * @param nl A NodeList object.
   * @return An XNodeSet object.
   */
  public XNodeSet createXNodeSet(NodeList nl)
  {
    return new XNodeSet(nl);
  }

  /**
   * Convenience function to create an XNodeSet from a node.
   * @param n A DOM node.
   * @return An XNodeSet object.
   */
  public XNodeSet createXNodeSet(Node n)
  {
    return new XNodeSet(n);
  }

  /**
   * Convenience function to create an XNull.
   * @return An XNull object.
   */
  public XNull createXNull()
  {
    return new XNull();
  }
  
  /**
   * Get the XMLParserLiaison that this processor uses.
   */
  public XMLParserLiaison getXMLProcessorLiaison()
  {
    return (XMLParserLiaison)m_liaison;
  }

  /**
   * Get the preferred stylesheet for the XSLTInputSource XML document,
   * as identified by the xml-stylesheet PI, and matching the media and
   * charset criteria. See <a href="http://www.w3.org/TR/xml-stylesheet/">
   * Associating Style Sheets with XML documents</a>.
   * Does not yet handle the LINK REL="stylesheet" syntax.
   *
   * @param media The media attribute to be matched.  May be null, in which
   *              case the prefered stylesheet will be used (i.e., alternate = no).
   * @param title The value of the title attribute to match.  May be null.
   * @param charset The value of the charset attribute to match.  May be null.
   * @returns StylesheetSpec extends XSLTInputSource extedns SAX InputSource; the return value
   * can be passed to the processStylesheet method.
   */
  public StylesheetSpec getAssociatedStylesheet(XSLTInputSource source,
                                                      String media,
                                                      String charset)
    throws SAXException
  {
    /*InputSource[]in = m_processor.getAssociatedStylesheets(source, media, null, charset);
    if (in.length >0)
      return (StylesheetSpec)in[0];
    else 
      return null; */
    try{
    Source s = m_tfactory.getAssociatedStylesheet(source.getSourceObject(), media, null, charset);
    return (StylesheetSpec)s; 
    }
    catch (TransformerConfigurationException tce) 
    {
      throw new SAXException(tce); 
    }
  }

  /**
   * Get a list of stylesheet specifications for the XSLTInputSource XML document,
   * as identified by the xml-stylesheet PI, and matching the media and
   * charset criteria. See <a href="http://www.w3.org/TR/xml-stylesheet/">
   * Associating Style Sheets with XML documents</a>.
   * Does not yet handle the LINK REL="stylesheet" syntax.
   *
   * @param media The media attribute to be matched.  May be null, in which
   *              case the prefered stylesheet will be used (i.e., alternate = no).
   * @param title The value of the title attribute to match.  May be null.
   * @param charset The value of the charset attribute to match.  May be null.
   * @returns list of StylesheetSpecs (extend XSLTInputSources extend SAX InputSources; a
   * list member may be passsed to the processStylesheet method.
   */
  public Vector getAssociatedStylesheets(XSLTInputSource source,
                                                      String media,
                                                      String charset)
    throws SAXException
  {
    try{
      Source s = m_tfactory.getAssociatedStylesheet(source.getSourceObject(), media, null, charset);
      Vector v = new Vector();
      //for (int i = 0; i< in.length; i++)
      v.addElement((StylesheetSpec)s);
      return v;
    }
    catch (TransformerConfigurationException tce)
    {
      throw new SAXException(tce);
    }                                              
  }
  
  /**
   * Submit a top-level stylesheet parameter.  This value can
   * be evaluated in the stylesheet via xsl:param-variable.
   * @param key The name of the param.
   * @param value An XObject that will be used.
   */
  public void setStylesheetParam(String key, XObject value)
  {
    setParameter(key, value);
  }

  /**
   * Set a top-level stylesheet parameter.  This value can
   * be evaluated via xsl:param-variable.  Note that the value
   * passed is an expression, and not a string.  This means that
   * setStylesheetParam("foo", "hello"); will look for the
   * element "hello".  If you want to pass a string, you'll
   * need to put quotes around it:
   * setStylesheetParam("foo", "'hello'"); will look for the
   * @param key The name of the param.
   * @param expression An expression that will be evaluated.
   */
  public void setStylesheetParam(String key, String expression)
  {    
    if (m_evalList == null)
      m_evalList = new Vector();
    if (!m_evalList.contains(key))
      m_evalList.addElement(key);
    setParameter(key, expression);
    m_needToEval = true;
  }
  
  /**
   * Set a top-level stylesheet parameter.  This value can
   * be evaluated via xsl:param-variable.  Note that the value
   * passed is an expression, and not a string.  This means that
   * setStylesheetParam("foo", "hello"); will look for the
   * element "hello".  If you want to pass a string, you'll
   * need to put quotes around it:
   * setStylesheetParam("foo", "'hello'"); will look for the
   * @param key The name of the param.
   * @param expression An expression that will be evaluated.
   */
  public void setParameter(String key,  Object value)
  {
    if (m_stylesheetParams == null)
      m_stylesheetParams = new Hashtable();
    m_stylesheetParams.put(key, value); 
  }

  /**
   * Get the current FormatterListener (SAX DocumentHandler), or null if none has been set.
   */
  public DocumentHandler getFormatterListener()
  {
    return m_documentHandler;
    
  }

  /**
   * Set the FormatterListener (the SAX DocumentHandler).
   */
  public void setFormatterListener(DocumentHandler flistener)
  {
    m_documentHandler = flistener;
  }

  /**
   * Get the current SAX DocumentHandler (the same object as the FormatterListener), or null if none has been set.
   */
  public DocumentHandler getDocumentHandler()
  {
    return m_documentHandler;
  }

  /**
   * Set the current SAX DocumentHandler (the same
   * object as the FormatterListener).
   */
  public void setDocumentHandler(DocumentHandler listener)
  {
    if (listener instanceof ParserAdapter)      
      m_transformerImpl.setContentHandler(((ParserAdapter)listener).getContentHandler());
    else if (listener instanceof XSLTEngineImpl)
      m_transformerImpl.setContentHandler(((XSLTEngineImpl)listener).getTransformer().getContentHandler());
    else if (listener instanceof XMLSerializer)
    {
      try{
        m_transformerImpl.setContentHandler(((XMLSerializer)listener).asContentHandler());
      }
      catch (IOException ioe)
      {}
    }
    m_documentHandler = listener;
  }

  /**
   * Add a trace listener for the purposes of debugging and diagnosis.
   * @param tl Trace listener to be added.
   */
  public void addTraceListener(TraceListener tl)
    throws TooManyListenersException
  {
    if (m_transformerImpl != null)
      m_transformerImpl.getTraceManager().addTraceListener(tl);
  }
  
  /**
   * If set to true (the default), pattern conflict warnings are not printed to the diagnostics stream.
   * @param b true if conflict warnings should be suppressed.
   */
  public void setQuietConflictWarnings(boolean b)
  {
    if (m_transformerImpl != null)
      m_transformerImpl.setQuietConflictWarnings(b);
  }

  /**
   * Remove a trace listener.
   * @param tl Trace listener to be removed.
   */
  public void removeTraceListener(TraceListener tl)
  {
    if (m_transformerImpl != null)
      m_transformerImpl.getTraceManager().removeTraceListener(tl);
  }
  
  /**
   * Set the problem listener property.
   * The XSL class can have a single listener to be informed
   * of errors and warnings. The problem listener normally controls whether an exception
   * is thrown or not (or the problem listeners can throw its own RuntimeException).
   * @param l A ProblemListener interface.
   */
  public void setProblemListener(ProblemListener l)
  {
    if (l instanceof ProblemListenerDefault)
      m_problemListener = (ProblemListenerDefault)l;
    else
      m_problemListener = new ProblemListenerDefault(l); 
    if (m_transformerImpl != null)
      m_transformerImpl.setErrorListener(m_problemListener);
    m_tfactory.setErrorListener(m_problemListener);
  }

  /**
   * Get the problem listener property.
   * The XSL class can have a single listener to be informed
   * of errors and warnings. The problem listener normally controls whether an exception
   * is thrown or not (or the problem listener can throw its own RuntimeException).
   * @return A ProblemListener interface.
   */
  public ProblemListener getProblemListener()
  {
    if (m_problemListener.getProblemListener() != null)
      return m_problemListener.getProblemListener();
    else
      return m_problemListener;
  }
  
  public TransformerImpl getTransformer()
  {
    return m_transformerImpl;  
    //return (StylesheetProcessor)m_processor;
  }  

  public TransformerFactoryImpl getTransformerFactory()
  {
    return (TransformerFactoryImpl)m_tfactory;    
  } 

  
} // end XSLTEngineImpl class
