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

import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Date;
import java.sql.Timestamp;
import java.sql.Time;
import java.util.Properties;
import java.util.Vector;
import java.util.StringTokenizer;
import java.lang.IllegalArgumentException;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.NodeList;
import org.w3c.dom.Node;
import java.util.Vector;
import java.util.Enumeration;
import java.math.BigDecimal;
import org.apache.xml.dtm.DTM;
import org.apache.xml.dtm.DTMManager;
import org.apache.xml.dtm.ref.DTMManagerDefault;
import org.apache.xpath.XPathContext;
import org.apache.xalan.extensions.ExpressionContext;
import org.apache.xpath.objects.XBooleanStatic;

import org.w3c.dom.*;
import java.sql.*;
import java.util.*;

/**
 * An XSLT extension that allows a stylesheet to
 * access JDBC data. From the stylesheet perspective,
 * XConnection provides 3 extension functions: new(),
 * query(), and close().
 * Use new() to call one of XConnection constructors, which
 * establishes a JDBC driver connection to a data source and
 * returns an XConnection object.
 * Then use the XConnection object query() method to return a
 * result set in the form of a row-set element.
 * When you have finished working with the row-set, call the
 * XConnection object close() method to terminate the connection.
 */
public class XConnection
{

  /**
   * Flag for DEBUG mode
   */
  private static final boolean DEBUG = false;

  /**
   * The Current Connection Pool in Use. An XConnection can only
   * represent one query at a time, prior to doing some type of query.
   */
  private ConnectionPool m_ConnectionPool = null;

  /**
   * If a default Connection Pool is used. i.e. A connection Pool
   * that is created internally, then do we actually allow pools
   * to be created. Due to the archititure of the Xalan Extensions,
   * there is no notification of when the Extension is being unloaded and
   * as such, there is a good chance that JDBC COnnections are not closed.
   * A finalized is provided to try and catch this situation but since
   * support of finalizers is inconsistant across JVM's this may cause
   * a problem. The robustness of the JDBC Driver is also at issue here.
   * if a controlled shutdown is provided by the driver then default
   * conntectiom pools are OK.
   */
  private boolean m_DefaultPoolingEnabled = false;


  /**
   * As we do queries, we will produce SQL Documents. Any ony may produce
   * one or more SQL Documents so that the current connection information
   * may be easilly reused. This collection will hold a collection of all
   * the documents created. As Documents are closed, they will be removed
   * from the collection and told to free all the used resources.
   */
  private Vector m_OpenSQLDocuments = new Vector();


  /**
   * Let's keep a copy of the ConnectionPoolMgr in
   * alive here so we are keeping the static pool alive
   * We will also use this Pool Manager to register our default pools.
   */
  private ConnectionPoolManager m_PoolMgr = new ConnectionPoolManager();

  /**
   * For PreparedStatements, we need a place to
   * to store the parameters in a vector.
   */
  private Vector m_ParameterList = new Vector();

  /**
   * Allow the SQL Extensions to return null on error. The Error information will
   * be stored in a seperate Error Document that can easily be retrived using the
   * getError() method.
   * %REVIEW% This functionality will probably be buried inside the SQLDocument.
   */
  private SQLErrorDocument m_Error = null;

  /**
   */
  private boolean m_IsDefaultPool = false;

  /**
   * This flag will be used to indicate to the SQLDocument to use
   * Streaming mode. Streeaming Mode will reduce the memory footprint
   * to a fixed amount but will not let you traverse the tree more than
   * once since the Row data will be reused for every Row in the Query.
   */
  private boolean m_IsStreamingEnabled = true;

  /**
   */
  public XConnection( )
  {
  }

  // The original constructors will be kept around for backwards
  // compatibility. Future Stylesheets should use the approaite
  // connect method to receive full error information.
  //
  /**
   * @param exprContext
   * @param ConnPoolName
   */
  public XConnection( ExpressionContext exprContext, String ConnPoolName )
  {
    connect(exprContext, ConnPoolName);
  }

  /**
   * @param exprContext
   * @param driver
   * @param dbURL
   */
  public XConnection( ExpressionContext exprContext, String driver, String dbURL )
  {
    connect(exprContext, driver, dbURL);
  }

  /**
   * @param exprContext
   * @param list
   */
  public XConnection( ExpressionContext exprContext, NodeList list )
  {
    connect(exprContext, list);
  }

  /**
   * @param exprContext
   * @param driver
   * @param dbURL
   * @param user
   * @param password
   */
  public XConnection( ExpressionContext exprContext, String driver, String dbURL, String user, String password )
  {
    connect(exprContext, driver, dbURL, user, password);
  }

  /**
   * @param exprContext
   * @param driver
   * @param dbURL
   * @param protocolElem
   */
  public XConnection( ExpressionContext exprContext, String driver, String dbURL, Element protocolElem )
  {
    connect(exprContext, driver, dbURL, protocolElem);
  }


  /**
   * Create an XConnection using the name of an existing Connection Pool
   * @param exprContext
   * @param ConnPoolName
   * @return
   */
  public XBooleanStatic connect( ExpressionContext exprContext, String ConnPoolName )
  {
    try
    {
      m_ConnectionPool = m_PoolMgr.getPool(ConnPoolName);

      if (m_ConnectionPool == null)
        throw new java.lang.IllegalArgumentException("Invalid Pool Name");

      m_IsDefaultPool = false;
      return new XBooleanStatic(true);
    }
    catch (Exception e)
    {
      buildErrorDocument(exprContext, e);
      return new XBooleanStatic(false);
    }

  }

  /**
   * Create an XConnection object with just a driver and database URL.
   * @param exprContext
   * @param driver JDBC driver of the form foo.bar.Driver.
   * @param dbURL database URL of the form jdbc:subprotocol:subname.
   * @return
   */
  public XBooleanStatic connect( ExpressionContext exprContext, String driver, String dbURL )
  {
    try
    {
      init(driver, dbURL, new Properties());
      return new XBooleanStatic(true);
    }
    catch(SQLException e)
    {
      buildErrorDocument(exprContext, e);
      return new XBooleanStatic(false);
    }
    catch (Exception e)
    {
      buildErrorDocument(exprContext, e);
      return new XBooleanStatic(false);
    }
  }

  /**
   * @param exprContext
   * @param protocolElem
   * @return
   */
  public XBooleanStatic connect( ExpressionContext exprContext, Element protocolElem )
  {
    try
    {
      initFromElement(protocolElem);
      return new XBooleanStatic(true);
    }
    catch(SQLException e)
    {
      buildErrorDocument(exprContext, e);
      return new XBooleanStatic(false);
    }
    catch (Exception e)
    {
      buildErrorDocument(exprContext, e);
      return new XBooleanStatic(false);
    }
  }

  /**
   * @param exprContext
   * @param list
   * @return
   */
  public XBooleanStatic connect( ExpressionContext exprContext, NodeList list )
  {
    try
    {
      initFromElement( (Element) list.item(0) );
      return new XBooleanStatic(true);
    }
    catch(SQLException e)
    {
      buildErrorDocument(exprContext, e);
      return new XBooleanStatic(false);
    }
    catch (Exception e)
    {
      buildErrorDocument(exprContext, e);
      return new XBooleanStatic(false);
    }
  }

  /**
   * Create an XConnection object with user ID and password.
   * @param exprContext
   * @param driver JDBC driver of the form foo.bar.Driver.
   * @param dbURL database URL of the form jdbc:subprotocol:subname.
   * @param user user ID.
   * @param password connection password.
   * @return
   */
  public XBooleanStatic connect( ExpressionContext exprContext, String driver, String dbURL, String user, String password )
  {
    try
    {
      Properties prop = new Properties();
      prop.put("user", user);
      prop.put("password", password);

      init(driver, dbURL, prop);

      return new XBooleanStatic(true);
    }
    catch(SQLException e)
    {
      buildErrorDocument(exprContext, e);
      return new XBooleanStatic(false);
    }
    catch (Exception e)
    {
      buildErrorDocument(exprContext, e);
      return new XBooleanStatic(false);
    }
  }


  /**
   * Create an XConnection object with a connection protocol
   * @param exprContext
   * @param driver JDBC driver of the form foo.bar.Driver.
   * @param dbURL database URL of the form jdbc:subprotocol:subname.
   * @param protocolElem list of string tag/value connection arguments,
   * normally including at least "user" and "password".
   * @return
   */
  public XBooleanStatic connect( ExpressionContext exprContext, String driver, String dbURL, Element protocolElem )
  {
    try
    {
      Properties prop = new Properties();

      NamedNodeMap atts = protocolElem.getAttributes();

      for (int i = 0; i < atts.getLength(); i++)
      {
        prop.put(atts.item(i).getNodeName(), atts.item(i).getNodeValue());
      }

      init(driver, dbURL, prop);

      return new XBooleanStatic(true);
    }
    catch(SQLException e)
    {
      buildErrorDocument(exprContext, e);
      return new XBooleanStatic(false);
    }
    catch (Exception e)
    {
      buildErrorDocument(exprContext, e);
      return new XBooleanStatic(false);
    }
  }


  /**
   * Allow the database connection information to be sepcified in
   * the XML tree. The connection information could also be
   * externally originated and passed in as an XSL Parameter.
   * The required XML Format is as follows.
   * A document fragment is needed to specify the connection information
   * the top tag name is not specific for this code, we are only interested
   * in the tags inside.
   * <DBINFO-TAG>
   * Specify the driver name for this connection pool
   * <dbdriver>drivername</dbdriver>
   * Specify the URL for the driver in this connection pool
   * <dburl>url</dburl>
   * Specify the password for this connection pool
   * <password>password</password>
   * Specify the username for this connection pool
   * <user>username</user>
   * You can add extra protocol items including the User Name & Password
   * with the protocol tag. For each extra protocol item, add a new element
   * where the name of the item is specified as the name attribute and
   * and its value as the elements value.
   * <protocol name="name of value">value</protocol>
   * </DBINFO-TAG>
   * @param e
   * @return
   * @throws SQLException
   */
  private void initFromElement( Element e )throws SQLException
  {

    Properties prop = new Properties();
    String driver = "";
    String dbURL = "";
    Node n = e.getFirstChild();

    if (null == n) return; // really need to throw an error

    do
    {
      String nName = n.getNodeName();

      if (nName.equalsIgnoreCase("dbdriver"))
      {
        driver = "";
        Node n1 = n.getFirstChild();
        if (null != n1)
        {
          driver = n1.getNodeValue();
        }
      }

      if (nName.equalsIgnoreCase("dburl"))
      {
        dbURL = "";
        Node n1 = n.getFirstChild();
        if (null != n1)
        {
          dbURL = n1.getNodeValue();
        }
      }

      if (nName.equalsIgnoreCase("password"))
      {
        String s = "";
        Node n1 = n.getFirstChild();
        if (null != n1)
        {
          s = n1.getNodeValue();
        }
        prop.put("password", s);
      }

      if (nName.equalsIgnoreCase("user"))
      {
        String s = "";
        Node n1 = n.getFirstChild();
        if (null != n1)
        {
          s = n1.getNodeValue();
        }
        prop.put("user", s);
      }

      if (nName.equalsIgnoreCase("protocol"))
      {
        String Name = "";

        NamedNodeMap attrs = n.getAttributes();
        Node n1 = attrs.getNamedItem("name");
        if (null != n1)
        {
          String s = "";
          Name = n1.getNodeValue();

          Node n2 = n.getFirstChild();
          if (null != n2) s = n2.getNodeValue();

          prop.put(Name, s);
        }
      }

    } while ( (n = n.getNextSibling()) != null);

    init(driver, dbURL, prop);
  }



  /**
   * Initilize is being called because we did not have an
   * existing Connection Pool, so let's see if we created one
   * already or lets create one ourselves.
   * @param driver
   * @param dbURL
   * @param prop
   * @return
   * @throws SQLException
   */
  private void init( String driver, String dbURL, Properties prop )throws SQLException
  {
    Connection con = null;

    if (DEBUG)
      System.out.println("XConnection, Connection Init");

    String user = prop.getProperty("user");
    if (user == null) user = "";

    String passwd = prop.getProperty("password");
    if (passwd == null) passwd = "";


    String poolName = driver + dbURL + user + passwd;
    ConnectionPool cpool = m_PoolMgr.getPool(poolName);

    if (cpool == null)
    {

      if (DEBUG)
      {
        System.out.println("XConnection, Creating Connection");
        System.out.println(" Driver  :" + driver);
        System.out.println(" URL     :" + dbURL);
        System.out.println(" user    :" + user);
        System.out.println(" passwd  :" + passwd);
      }


      DefaultConnectionPool defpool = new DefaultConnectionPool();

      if ((DEBUG) && (defpool == null))
        System.out.println("Failed to Create a Default Connection Pool");

      defpool.setDriver(driver);
      defpool.setURL(dbURL);
      defpool.setProtocol(prop);

      // Only enable pooling in the default pool if we are explicatly
      // told too.
      if (m_DefaultPoolingEnabled) defpool.setPoolEnabled(true);

      m_PoolMgr.registerPool(poolName, defpool);
      m_ConnectionPool = defpool;


    }

    m_IsDefaultPool = true;

    //
    // Let's test to see if we really can connect
    // Just remember to give it back after the test.
    //
    try
    {
      con = m_ConnectionPool.getConnection();
    }
    catch(SQLException e)
    {
      if (con != null)
      {
        m_ConnectionPool.releaseConnectionOnError(con);
        con = null;
      }
      throw e;
    }
    finally
    {
      m_ConnectionPool.releaseConnection(con);
    }
  }


  /**
   * Execute a query statement by instantiating an
   * @param exprContext
   * @param queryString the SQL query.
   * @return XStatement implements NodeIterator.
   * @throws SQLException
   * @link org.apache.xalan.lib.sql.XStatement XStatement}
   * object. The XStatement executes the query, and uses the result set
   * to create a
   * @link org.apache.xalan.lib.sql.RowSet RowSet},
   * a row-set element.
   */
  public DTM query( ExpressionContext exprContext, String queryString )
  {
    Connection con = null;
    Statement stmt = null;
    ResultSet rs = null;

    DTMManagerDefault mgrDefault = null;
    SQLDocument doc = null;

    try
    {
      if (DEBUG) System.out.println("query()");
      if (null == m_ConnectionPool)
      {
        // Build an Error Document, NOT Connected
        return null;
      }

      try
      {
        con = m_ConnectionPool.getConnection();
        stmt = con.createStatement();
        rs = stmt.executeQuery(queryString);
      }
      catch(SQLException e)
      {
        // We have not created a document yet, so lets close the
        // connection ourselves then let the process deal with the
        // error.
        //
        try  { if (null != rs) rs.close(); }
        catch(Exception e1) {}
        try  { if (null != stmt) stmt.close(); }
        catch(Exception e1) { }
        try  {
          if (null != con) m_ConnectionPool.releaseConnectionOnError(con);
        } catch(Exception e1) { }

        // Re throw the error so the process can handle the error
        // normally
        throw e;
      }

      if (DEBUG) System.out.println("..creatingSQLDocument");

      DTMManager mgr =
        ((XPathContext.XPathExpressionContext)exprContext).getDTMManager();
      mgrDefault = (DTMManagerDefault) mgr;
      int dtmIdent = mgrDefault.getFirstFreeDTMID();

      doc =
        new SQLDocument(
          mgr, dtmIdent << DTMManager.IDENT_DTM_NODE_BITS ,
          m_ConnectionPool, con, stmt, rs, m_IsStreamingEnabled);

      if (null != doc)
      {
        if (DEBUG) System.out.println("..returning Document");

        // Register our document
        mgrDefault.addDTM(doc, dtmIdent);

        // also keep a local reference
        m_OpenSQLDocuments.addElement(doc);
        return doc;
      }
      else
      {
        return null;
      }
    }
    catch(SQLException e)
    {
      if ((doc != null) && (mgrDefault != null))
      {
        doc.closeOnError();
        mgrDefault.release(doc, true);
      }
      buildErrorDocument(exprContext, e);
      return null;
    }
    catch (Exception e)
    {
      if ((doc != null) && (mgrDefault != null))
      {
        doc.closeOnError();
        mgrDefault.release(doc, true);
      }

      if (DEBUG) System.out.println("exception in query()");
      buildErrorDocument(exprContext, e);
      return null;
    }
    finally
    {
      if (DEBUG) System.out.println("leaving query()");
    }
  }

  /**
   * Execute a parameterized query statement by instantiating an
   * @param exprContext
   * @param queryString the SQL query.
   * @return XStatement implements NodeIterator.
   * @throws SQLException
   * @link org.apache.xalan.lib.sql.XStatement XStatement}
   * object. The XStatement executes the query, and uses the result set
   * to create a
   * @link org.apache.xalan.lib.sql.RowSet RowSet},
   * a row-set element.
   */
  public DTM pquery( ExpressionContext exprContext, String queryString )
  {
    Connection con = null;
    PreparedStatement stmt = null;
    ResultSet rs = null;

    try
    {
      int indx;

      try
      {
        con = m_ConnectionPool.getConnection();
        stmt = con.prepareStatement(queryString);
      }
      catch(SQLException e)
      {
        // We have not created a document yet, so lets close the
        // connection ourselves then let the process deal with the
        // error.
        //
        try { if (null != stmt) stmt.close(); }
        catch(Exception e1) { }
        try {
          if (null != con) m_ConnectionPool.releaseConnectionOnError(con);
        }  catch(Exception e1) {}

        // Re throw the error so the process can handle the error
        // normally
        throw e;
      }

      if (DEBUG) System.out.println("..building Prepared Statement");

      try
      {
        Enumeration enum = m_ParameterList.elements();
        indx = 1;
        while (enum.hasMoreElements())
        {
          QueryParameter qp = (QueryParameter) enum.nextElement();
          setParameter(indx, stmt, qp);
          indx++;
        }

        rs = stmt.executeQuery();
      }
      catch(SQLException e)
      {
        // We have not created a document yet, so lets close the
        // connection ourselves then let the process deal with the
        // error.
        //
        try { if (null != rs) rs.close();  }
        catch(Exception e1) {  }
        try { if (null != stmt) stmt.close(); }
        catch(Exception e1) {  }
        try  {
          if (null != con) m_ConnectionPool.releaseConnectionOnError(con);
        } catch(Exception e1) { }

        // Re throw the error so the process can handle the error
        // normally
        throw e;
      }

      if (DEBUG) System.out.println("..creatingSQLDocument");

      DTMManager mgr =
        ((XPathContext.XPathExpressionContext)exprContext).getDTMManager();
      DTMManagerDefault mgrDefault = (DTMManagerDefault) mgr;
      int dtmIdent = mgrDefault.getFirstFreeDTMID();

      SQLDocument doc =
        new SQLDocument(mgr, dtmIdent << DTMManager.IDENT_DTM_NODE_BITS,
        m_ConnectionPool, con, stmt, rs, m_IsStreamingEnabled);

      if (null != doc)
      {
        if (DEBUG) System.out.println("..returning Document");

        // Register our document
        mgrDefault.addDTM(doc, dtmIdent);

        // also keep a local reference
        m_OpenSQLDocuments.addElement(doc);
        return doc;
      }
      else
      {
        // Build Error Doc, BAD Result Set
        return null;
      }
    }
    catch(SQLException e)
    {
      buildErrorDocument(exprContext, e);
      return null;
    }
    catch (Exception e)
    {
      buildErrorDocument(exprContext, e);
      return null;
    }
  }


  /**
   * Execute a parameterized query statement by instantiating an
   * @param exprContext
   * @param queryString the SQL query.
   * @param typeInfo
   * @return XStatement implements NodeIterator.
   * @throws SQLException
   * @link org.apache.xalan.lib.sql.XStatement XStatement}
   * object. The XStatement executes the query, and uses the result set
   * to create a
   * @link org.apache.xalan.lib.sql.RowSet RowSet},
   * a row-set element.
   * This method allows for the user to pass in a comma seperated
   * String that represents a list of parameter types. If supplied
   * the parameter types will be used to overload the current types
   * in the current parameter list.
   */
  public DTM pquery( ExpressionContext exprContext, String queryString, String typeInfo )
  {
    Connection con = null;
    PreparedStatement stmt = null;
    ResultSet rs = null;

    try
    {
      int indx;

      // Parse up the parameter types that were defined
      // with the query
      StringTokenizer plist = new StringTokenizer(typeInfo);

      // Override the existing type that is stored in the
      // parameter list. If there are more types than parameters
      // ignore for now, a more meaningfull error should occur
      // when the actual query is executed.
      indx = 0;
      while (plist.hasMoreTokens())
      {
        String value = plist.nextToken();
        QueryParameter qp = (QueryParameter) m_ParameterList.elementAt(indx);
        if ( null != qp )
        {
          qp.setType(value);
        }

        indx++;
      }

      try
      {
        con = m_ConnectionPool.getConnection();
        stmt = con.prepareStatement(queryString);
      }
      catch(SQLException e)
      {
        // We have not created a document yet, so lets close the
        // connection ourselves then let the process deal with the
        // error.
        //
        try { if (null != stmt) stmt.close(); }
        catch(Exception e1) { }
        try {
          if (null != con) m_ConnectionPool.releaseConnectionOnError(con);
        } catch(Exception e1) { }

        // Re throw the error so the process can handle the error
        // normally
        throw e;
      }



      if (DEBUG) System.out.println("..building Prepared Statement");

      try
      {
        Enumeration enum = m_ParameterList.elements();
        indx = 1;
        while (enum.hasMoreElements())
        {
          QueryParameter qp = (QueryParameter) enum.nextElement();
          setParameter(indx, stmt, qp);
          indx++;
        }

        rs = stmt.executeQuery();
      }
      catch(SQLException e)
      {
        // We have not created a document yet, so lets close the
        // connection ourselves then let the process deal with the
        // error.
        //
        try { if (null != rs) rs.close(); }
        catch(Exception e1) { /* Empty */ }
        try { if (null != stmt) stmt.close(); }
        catch(Exception e1) { /* Empty */  }
        try {
          if (null != con) m_ConnectionPool.releaseConnectionOnError(con);
        } catch(Exception e1) { /* Empty */ }

        // Re throw the error so the process can handle the error
        // normally
        throw e;
      }


      if (DEBUG) System.out.println("..creatingSQLDocument");

      DTMManager mgr =
        ((XPathContext.XPathExpressionContext)exprContext).getDTMManager();
      DTMManagerDefault mgrDefault = (DTMManagerDefault) mgr;
      int dtmIdent = mgrDefault.getFirstFreeDTMID();

      SQLDocument doc =
        new SQLDocument(mgr, dtmIdent << DTMManager.IDENT_DTM_NODE_BITS ,
        m_ConnectionPool, con, stmt, rs, m_IsStreamingEnabled);

      if (null != doc)
      {
        if (DEBUG) System.out.println("..returning Document");

        // Register our document
        mgrDefault.addDTM(doc, dtmIdent);

        // also keep a local reference
        m_OpenSQLDocuments.addElement(doc);
        return doc;
      }
      else
      {
        // Build Error Doc, BAD Result Set
        return null;
      }
    }
    catch(SQLException e)
    {
      buildErrorDocument(exprContext, e);
      return null;
    }
    catch (Exception e)
    {
      buildErrorDocument(exprContext, e);
      return null;
    }
  }

  /**
   * Add an untyped value to the parameter list.
   * @param value
   * @return
   */
  public void addParameter( String value )
  {
    addParameterWithType(value, null);
  }

  /**
   * Add a typed parameter to the parameter list.
   * @param value
   * @param Type
   * @return
   */
  public void addParameterWithType( String value, String Type )
  {
    m_ParameterList.addElement( new QueryParameter(value, Type) );
  }


  /**
   * Add a single parameter to the parameter list
   * formatted as an Element
   * @param e
   * @return
   */
  public void addParameterFromElement( Element e )
  {
    NamedNodeMap attrs = e.getAttributes();
    Node Type = attrs.getNamedItem("type");
    Node n1  = e.getFirstChild();
    if (null != n1)
    {
      String value = n1.getNodeValue();
      if (value == null) value = "";
      m_ParameterList.addElement( new QueryParameter(value, Type.getNodeValue()) );
    }
  }


  /**
   * Add a section of parameters to the Parameter List
   * Do each element from the list
   * @param nl
   * @return
   */
  public void addParameterFromElement( NodeList nl )
  {
    //
    // Each child of the NodeList represents a node
    // match from the select= statment. Process each
    // of them as a seperate list.
    // The XML Format is as follows
    //
    // <START-TAG>
    //   <TAG1 type="int">value</TAG1>
    //   <TAGA type="int">value</TAGA>
    //   <TAG2 type="string">value</TAG2>
    // </START-TAG>
    //
    // The XSL to process this is formatted as follows
    // <xsl:param name="plist" select="//START-TAG" />
    // <sql:addParameter( $plist );
    //
    int count = nl.getLength();
    for (int x=0; x<count; x++)
    {
      addParameters( (Element) nl.item(x));
    }
  }

  /**
   * @param elem
   * @return
   */
  private void addParameters( Element elem )
  {
    //
    // Process all of the Child Elements
    // The format is as follows
    //
    //<TAG type ="typeid">value</TAG>
    //<TAG1 type ="typeid">value</TAG1>
    //<TAGA type ="typeid">value</TAGA>
    //
    // The name of the Node is not important just is value
    // and if it contains a type attribute

    Node n = elem.getFirstChild();

    if (null == n) return;

    do
    {
      if (n.getNodeType() == Node.ELEMENT_NODE)
      {
        NamedNodeMap attrs = n.getAttributes();
        Node Type = attrs.getNamedItem("type");
        String TypeStr;

        if (Type == null) TypeStr = "string";
        else TypeStr = Type.getNodeValue();

        Node n1  = n.getFirstChild();
        if (null != n1)
        {
          String value = n1.getNodeValue();
          if (value == null) value = "";


          m_ParameterList.addElement(
            new QueryParameter(value, TypeStr) );
        }
      }
    } while ( (n = n.getNextSibling()) != null);
  }

  /**
   * @return
   */
  public void clearParameters( )
  {
    m_ParameterList.removeAllElements();
  }

  /**
   * There is a problem with some JDBC drivers when a Connection
   * is open and the JVM shutsdown. If there is a problem, there
   * is no way to control the currently open connections in the
   * pool. So for the default connection pool, the actuall pooling
   * mechinsm is disabled by default. The Stylesheet designer can
   * re-enabled pooling to take advantage of connection pools.
   * The connection pool can even be disabled which will close all
   * outstanding connections.
   * @return
   */
  public void enableDefaultConnectionPool( )
  {

    if (DEBUG)
      System.out.println("Enabling Default Connection Pool");

    m_DefaultPoolingEnabled = true;

    if (m_ConnectionPool == null) return;
    if (m_IsDefaultPool) return;

    m_ConnectionPool.setPoolEnabled(true);

  }

  /**
   * See enableDefaultConnectionPool
   * @return
   */
  public void disableDefaultConnectionPool( )
  {
    if (DEBUG)
      System.out.println("Disabling Default Connection Pool");

    m_DefaultPoolingEnabled = false;

    if (m_ConnectionPool == null) return;
    if (!m_IsDefaultPool) return;

    m_ConnectionPool.setPoolEnabled(false);
  }


  /**
   * Control how the SQL Document uses memory. In Streaming Mode,
   * memory consumption is greatly reduces so you can have queries
   * of unlimited size but it will not let you traverse the data
   * more than once.
   * @return
   */
  public void enableStreamingMode( )
  {

    if (DEBUG)
      System.out.println("Enabling Streaming Mode");

    m_IsStreamingEnabled = true;
  }

  /**
   * Control how the SQL Document uses memory. In Streaming Mode,
   * memory consumption is greatly reduces so you can have queries
   * of unlimited size but it will not let you traverse the data
   * more than once.
   * @return
   */
  public void disableStreamingMode( )
  {

    if (DEBUG)
      System.out.println("Disable Streaming Mode");

    m_IsStreamingEnabled = false;
  }

  /**
   * Provide access to the last error that occued. This error
   * may be over written when the next operation occurs.
   * @return
   */
  public DTM getError( )
  {
    return m_Error;
  }

  /**
   * Close the connection to the data source.
   * @return
   * @throws SQLException
   */
  public void close( )throws SQLException
  {

    if (DEBUG)
      System.out.println("Entering XConnection.close");

    //
    // This function is included just for Legacy support
    // If it is really called then we must me using a single
    // document interface, so close all open documents.
    while(m_OpenSQLDocuments.size() != 0)
    {
      SQLDocument d = (SQLDocument) m_OpenSQLDocuments.elementAt(0);
      d.close();
      m_OpenSQLDocuments.removeElementAt(0);
    }

    if (DEBUG)
      System.out.println("Exiting XConnection.close");

  }

  /**
   * Close the connection to the data source. Only close the connections
   * for a single document.
   * @param sqldoc
   * @return
   * @throws SQLException
   */
  public void close( SQLDocument sqldoc )throws SQLException
  {
    if (DEBUG)
      System.out.println("Entering XConnection.close");

    int size = m_OpenSQLDocuments.size();

    for(int x=0; x<size; x++)
    {
      SQLDocument d = (SQLDocument) m_OpenSQLDocuments.elementAt(x);
      if (d == sqldoc)
      {
        d.close();
        m_OpenSQLDocuments.removeElementAt(x);
      }
    }
  }

  /**
   * Set the parameter for a Prepared Statement
   * @param pos
   * @param stmt
   * @param p
   * @return
   * @throws SQLException
   */
  public void setParameter( int pos, PreparedStatement stmt, QueryParameter p )throws SQLException
  {
    String type = p.getType();
    if (type.equalsIgnoreCase("string"))
    {
      stmt.setString(pos, p.getValue());
    }

    if (type.equalsIgnoreCase("bigdecimal"))
    {
      stmt.setBigDecimal(pos, new BigDecimal(p.getValue()));
    }

    if (type.equalsIgnoreCase("boolean"))
    {
      Integer i = new Integer( p.getValue() );
      boolean b = ((i.intValue() != 0) ? false : true);
      stmt.setBoolean(pos, b);
    }

    if (type.equalsIgnoreCase("bytes"))
    {
      stmt.setBytes(pos, p.getValue().getBytes());
    }

    if (type.equalsIgnoreCase("date"))
    {
      stmt.setDate(pos, Date.valueOf(p.getValue()));
    }

    if (type.equalsIgnoreCase("double"))
    {
      Double d = new Double(p.getValue());
      stmt.setDouble(pos, d.doubleValue() );
    }

    if (type.equalsIgnoreCase("float"))
    {
      Float f = new Float(p.getValue());
      stmt.setFloat(pos, f.floatValue());
    }

    if (type.equalsIgnoreCase("long"))
    {
      Long l = new Long(p.getValue());
      stmt.setLong(pos, l.longValue());
    }

    if (type.equalsIgnoreCase("short"))
    {
      Short s = new Short(p.getValue());
      stmt.setShort(pos, s.shortValue());
    }

    if (type.equalsIgnoreCase("time"))
    {
      stmt.setTime(pos, Time.valueOf(p.getValue()) );
    }

    if (type.equalsIgnoreCase("timestamp"))
    {

      stmt.setTimestamp(pos, Timestamp.valueOf(p.getValue()) );
    }

  }

  /**
   * @param exprContext
   * @param excp
   * @return
   */
  private void buildErrorDocument( ExpressionContext exprContext, SQLException excp )
  {
    try
    {
      DTMManager mgr =
        ((XPathContext.XPathExpressionContext)exprContext).getDTMManager();
      DTMManagerDefault mgrDefault = (DTMManagerDefault) mgr;
      int dtmIdent = mgrDefault.getFirstFreeDTMID();

      m_Error = new SQLErrorDocument(mgr, dtmIdent << DTMManager.IDENT_DTM_NODE_BITS, excp);

      // Register our document
      mgrDefault.addDTM(m_Error, dtmIdent);

    }
    catch(Exception e)
    {
      m_Error = null;
    }
  }

  /**
   * @param exprContext
   * @param excp
   * @return
   */
  private void buildErrorDocument( ExpressionContext exprContext, Exception excp )
  {
    try
    {
      DTMManager mgr =
        ((XPathContext.XPathExpressionContext)exprContext).getDTMManager();
      DTMManagerDefault mgrDefault = (DTMManagerDefault) mgr;
      int dtmIdent = mgrDefault.getFirstFreeDTMID();

      m_Error = new SQLErrorDocument(mgr, dtmIdent<<DTMManager.IDENT_DTM_NODE_BITS, excp);

      // Register our document
      mgrDefault.addDTM(m_Error, dtmIdent);

    }
    catch(Exception e)
    {
      m_Error = null;
    }
  }

  /**
   * @return
   */
  protected void finalize( )
  {
    if (DEBUG) System.out.println("In XConnection, finalize");
    try
    {
      close();
    }
    catch(Exception e)
    {
      // Empty We are final Anyway
    }
  }

}
