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


/**
 * <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();
    //m_liaison =  (DOM2Helper)createLiaison();
  }

  /**
   * 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);    
  }
  
  /** 
   * Get a Liaison class
   */
  public XMLParserLiaison createLiaison()
    throws org.xml.sax.SAXException
  {
    return new org.apache.xalan.xpath.xml.XMLParserLiaisonDefault();    
  }
 
  /**
   * 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;
      
      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)
          {
            throw new SAXException(te);
          }
        }
        m_needToEval = false;
        m_evalList = null;
      }
      
      sourceTree = getSourceTreeFromInput(inputSource);
      
      if(null != stylesheetSource)
      {
        try{
        templates = m_tfactory.newTemplates(stylesheetSource.getSourceObject());
        }
        catch (TransformerConfigurationException tce)
        {
          throw new SAXException(tce);
        }  
        
      }      
      else if( null != inputSource)
      { 
        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") && !typeVal.equals("text/xml") && !typeVal.equals("application/xml+xslt"))
                    {
                      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 != templates)
      {
        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(new DOMSource(sourceTree),
                    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);
    }
  }
  
  /**
   * Bottleneck the creation of the stylesheet for derivation purposes.
   */
  StylesheetRoot createStylesheetRoot(String baseIdentifier, XSLTInputSource source)
    throws MalformedURLException, FileNotFoundException,
           IOException, SAXException
  {
    try{
      Source inSource = source.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
    {
      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
        {
          stylesheetProcessor.setSystemId(stylesheetSource.getSystemId());
          TreeWalker tw = new TreeWalker(stylesheetProcessor, new org.apache.xpath.DOM2Helper());
          tw.traverse(((DOMSource)ssSource).getNode());
          m_stylesheetRoot = new StylesheetRoot(stylesheetProcessor.getStylesheetRoot());
        }
      }
      else
      {
				if(null != m_liaison)
        {
         // DOM2Helper liaison =  (DOM2Helper)(Class.forName(liaisonClassName).newInstance());
          m_liaison.parse(SAXSource.sourceToInputSource(ssSource));
					DOMSource source = new DOMSource(m_liaison.getDocument());
					Templates templates = m_tfactory.newTemplates(source);
					m_stylesheetRoot = new StylesheetRoot(
																(org.apache.xalan.templates.StylesheetRoot)templates);																 
        }  
				else
				{
					m_stylesheetRoot = createStylesheetRoot(stylesheetSource.getSystemId(), stylesheetSource);
				}
        addTraceListenersToStylesheet();
        
        
        stylesheetProcessor.pushStylesheet(m_stylesheetRoot.getObject());      
        diag("========= Parsing "+xslIdentifier+" ==========");
        pushTime(xslIdentifier);
        //String liaisonClassName = System.getProperty("org.apache.xalan.source.liaison");

        
        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 != m_liaison)
        {
          //DOM2Helper liaison =  (DOM2Helper)(Class.forName(liaisonClassName).newInstance());
          m_liaison.parse(SAXSource.sourceToInputSource(iSource));
          if(null != m_diagnosticsPrintWriter)
            displayDuration("Parse of "+xmlIdentifier, xmlIdentifier);
          sourceTree = m_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 );
          
         /*TransformerHandlerImpl handler = new TransformerHandlerImpl(getTransformer(), false,
              xmlIdentifier);
          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();
        */  
          org.apache.xml.dtm.DTMManager dtmManager = new org.apache.xml.dtm.ref.DTMManagerDefault();
          org.apache.xml.dtm.DTM dtm = dtmManager.getDTM(inputSource.getSourceObject(), true, null, false, false);
          sourceTree = dtm.getNode(dtm.getDocument());
        }
      }
      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
  {
    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 = new org.apache.xml.dtm.ref.DTMNodeIterator(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 = new org.apache.xml.dtm.ref.DTMNodeIterator(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 = new org.apache.xml.dtm.ref.DTMNodeIterator(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 = new org.apache.xml.dtm.ref.DTMNodeIterator(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, new org.apache.xpath.DOM2Helper());
        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);

			URL xslURL = getURLFromString(xslURLString, xmlBaseIdent);

      XSLTInputSource inputSource = new XSLTInputSource(xslURL.toString());
      
			if(isRoot)
			{				
				if(null != m_liaison)
				{
					try{
						m_liaison.parse(SAXSource.sourceToInputSource(inputSource.getSourceObject()));
						DOMSource source = new DOMSource(m_liaison.getDocument());
						Templates templates = m_tfactory.newTemplates(source);
						m_stylesheetRoot = new StylesheetRoot(
																		(org.apache.xalan.templates.StylesheetRoot)templates);
					}					
					catch (TransformerException tce)
					{
						throw new SAXException(tce);
					}
				}
				else
				{
					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);
      }
      
       
      //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)
  {
    TransformerHandlerImpl handler = new TransformerHandlerImpl(m_transformerImpl, false, null);
    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.object());
  }

  /**
   * 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
