/*
 * The contents of this file are subject to the Mozilla Public License Version 1.1
 * (the "License"); you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at <http://www.mozilla.org/MPL/>.
 * 
 * Software distributed under the License is distributed on an "AS IS" basis, WITHOUT
 * WARRANTY OF ANY KIND, either express or implied. See the License for the specific
 * language governing rights and limitations under the License.
 * 
 * The Original Code is the Venice Web Communities System.
 * 
 * The Initial Developer of the Original Code is Eric J. Bowersox <erbo@silcom.com>,
 * for Silverwrist Design Studios.  Portions created by Eric J. Bowersox are
 * Copyright (C) 2002 Eric J. Bowersox/Silverwrist Design Studios.  All Rights Reserved.
 * 
 * Contributor(s): 
 */
package com.silverwrist.dynamo.db;

import java.sql.*;
import com.silverwrist.dynamo.except.*;
import com.silverwrist.dynamo.iface.*;

class WrappedConnection implements Connection
{
  /*--------------------------------------------------------------------------------
   * Attributes
   *--------------------------------------------------------------------------------
   */

  private DBConnectionPool m_datapool;
  private Connection m_conn;

  /*--------------------------------------------------------------------------------
   * Constructor
   *--------------------------------------------------------------------------------
   */

  WrappedConnection(DBConnectionPool datapool, Connection conn)
  {
    m_datapool = datapool;
    m_conn = conn;

  } // end constructor

  /*--------------------------------------------------------------------------------
   * Overrides from class Object
   *--------------------------------------------------------------------------------
   */

  protected void finalize() throws Throwable
  {
    if (m_conn!=null)
      this.close();
    super.finalize();

  } // end finalize

  /*--------------------------------------------------------------------------------
   * Implementations from interface Connection
   *--------------------------------------------------------------------------------
   */

  /**
   * Creates a <code>Statement</code> object for sending
   * SQL statements to the database.
   *
   * @return a new Statement object 
   * @exception SQLException if a database access error occurs
   */
  public Statement createStatement() throws SQLException
  {
    return m_conn.createStatement();

  } // end createStatement

  /**
   * Creates a <code>PreparedStatement</code> object for sending
   * parameterized SQL statements to the database.
   *
   * @param sql a SQL statement that may contain one or more '?' IN parameter placeholders
   * @return a new PreparedStatement object containing the pre-compiled statement 
   * @exception SQLException if a database access error occurs
   */
  public PreparedStatement prepareStatement(String sql) throws SQLException
  {
    return m_conn.prepareStatement(sql);

  } // end prepareStatement

  /**
   * Creates a <code>CallableStatement</code> object for calling
   * database stored procedures.
   *
   * @param sql a SQL statement that may contain one or more '?' parameter placeholders.
   *            Typically this  statement is a JDBC function call escape string.
   * @return a new CallableStatement object containing the pre-compiled SQL statement 
   * @exception SQLException if a database access error occurs
   */
  public CallableStatement prepareCall(String sql) throws SQLException
  {
    return m_conn.prepareCall(sql);

  } // end prepareCall
						
  /**
   * Converts the given SQL statement into the system's native SQL grammar.
   *
   * @param sql a SQL statement that may contain one or more '?' parameter placeholders
   * @return the native form of this statement
   * @exception SQLException if a database access error occurs
   */
  public String nativeSQL(String sql) throws SQLException
  {
    return m_conn.nativeSQL(sql);

  } // end nativeSQL

  /**
   * Sets this connection's auto-commit mode.
   *
   * @param autoCommit true enables auto-commit; false disables auto-commit.  
   * @exception SQLException if a database access error occurs
   */
  public void setAutoCommit(boolean autoCommit) throws SQLException
  {
    m_conn.setAutoCommit(autoCommit);

  } // end setAutoCommit

  /**
   * Gets the current auto-commit state.
   *
   * @return the current state of auto-commit mode
   * @exception SQLException if a database access error occurs
   * @see #setAutoCommit 
   */
  public boolean getAutoCommit() throws SQLException
  {
    return m_conn.getAutoCommit();

  } // end getAutoCommit

  /**
   * Makes all changes made since the previous
   * commit/rollback permanent and releases any database locks
   * currently held by the Connection. This method should be
   * used only when auto-commit mode has been disabled.
   *
   * @exception SQLException if a database access error occurs
   * @see #setAutoCommit 
   */
  public void commit() throws SQLException
  {
    m_conn.commit();

  } // end commit

  /**
   * Drops all changes made since the previous
   * commit/rollback and releases any database locks currently held
   * by this Connection. This method should be used only when auto-
   * commit has been disabled.
   *
   * @exception SQLException if a database access error occurs
   * @see #setAutoCommit 
   */
  public void rollback() throws SQLException
  {
    m_conn.rollback();

  } // end rollback

  /**
   * Releases a Connection's database and JDBC resources
   * immediately instead of waiting for them to be automatically released.
   *
   * @exception SQLException if a database access error occurs
   */
  public synchronized void close() throws SQLException
  {
    try
    { // blow away the connection
      if (!(m_conn.getAutoCommit()))
	m_conn.rollback();
      m_datapool.releaseConnection(m_conn);
      m_conn = null;

    } // end try
    catch (DatabaseException e)
    { // database exception becomes SQLException
      SQLException sqle = new SQLException(e.getMessage());
      sqle.initCause(e);
      throw sqle;

    } // end catch

  } // end close

  /**
   * Tests to see if a Connection is closed.
   *
   * @return true if the connection is closed; false if it's still open
   * @exception SQLException if a database access error occurs
   */
  public boolean isClosed() throws SQLException
  {
    return (m_conn==null) ? true : m_conn.isClosed();

  } // end isClosed

  /**
   * Gets the metadata regarding this connection's database.
   *
   * @return a DatabaseMetaData object for this Connection 
   * @exception SQLException if a database access error occurs
   */
  public DatabaseMetaData getMetaData() throws SQLException
  {
    return m_conn.getMetaData();

  } // end getMetaData

  /**
   * Puts this connection in read-only mode as a hint to enable 
   * database optimizations.
   *
   * @param readOnly true enables read-only mode; false disables read-only mode.  
   * @exception SQLException if a database access error occurs
   */
  public void setReadOnly(boolean readOnly)
  { // do nothing
  } // end setReadOnly

  /**
   * Tests to see if the connection is in read-only mode.
   *
   * @return true if connection is read-only and false otherwise
   * @exception SQLException if a database access error occurs
   */
  public boolean isReadOnly()
  {
    return false;

  } // end isReadOnly

  /**
   * Sets a catalog name in order to select 	
   * a subspace of this Connection's database in which to work.
   * If the driver does not support catalogs, it will
   * silently ignore this request.
   *
   * @exception SQLException if a database access error occurs
   */
  public void setCatalog(String catalog)
  { // do nothing
  } // end setCatalog

  /**
   * Returns the Connection's current catalog name.
   *
   * @return the current catalog name or null
   * @exception SQLException if a database access error occurs
   */
  public String getCatalog() throws SQLException
  {
    return m_conn.getCatalog();

  } // end getCatalog

  /**
   * Attempts to change the transaction
   * isolation level to the one given.
   * The constants defined in the interface <code>Connection</code>
   * are the possible transaction isolation levels.
   *
   * @param level one of the TRANSACTION_* isolation values with the exception of TRANSACTION_NONE;
   *              some databases may not support other values
   * @exception SQLException if a database access error occurs
   * @see DatabaseMetaData#supportsTransactionIsolationLevel 
   */
  public void setTransactionIsolation(int level)
  { // do nothing
  } // end setTransactionIsolation

  /**
   * Gets this Connection's current transaction isolation level.
   *
   * @return the current TRANSACTION_* mode value
   * @exception SQLException if a database access error occurs
   */
  public int getTransactionIsolation() throws SQLException
  {
    return m_conn.getTransactionIsolation();

  } // end getTransactionIsolation

  /**
   * Returns the first warning reported by calls on this Connection.
   *
   * @return the first SQLWarning or null 
   * @exception SQLException if a database access error occurs
   */
  public SQLWarning getWarnings() throws SQLException
  {
    return m_conn.getWarnings();

  } // end getWarnings

  /**
   * Clears all warnings reported for this <code>Connection</code> object.	
   * After a call to this method, the method <code>getWarnings</code>
   * returns null until a new warning is reported for this Connection.  
   *
   * @exception SQLException if a database access error occurs
   */
  public void clearWarnings() throws SQLException
  {
    m_conn.clearWarnings();

  } // end clearWarnings

  /**
   * Creates a <code>Statement</code> object that will generate
   * <code>ResultSet</code> objects with the given type and concurrency.
   *
   * @param resultSetType a result set type; see ResultSet.TYPE_XXX
   * @param resultSetConcurrency a concurrency type; see ResultSet.CONCUR_XXX
   * @return a new Statement object 
   * @exception SQLException if a database access error occurs
   * @since 1.2
   * @see <a href="package-summary.html#2.0 API">What Is in the JDBC 2.0 API</a>
   */
  public Statement createStatement(int resultSetType, int resultSetConcurrency) throws SQLException
  {
    return m_conn.createStatement(resultSetType,resultSetConcurrency);

  } // end createStatement

  public Statement createStatement(int resultSetType, int resultSetConcurrency, int resultSetHoldability)
      throws SQLException
  {
    return m_conn.createStatement(resultSetType,resultSetConcurrency,resultSetHoldability);

  } // end createStatement

  /**
   * Creates a <code>PreparedStatement</code> object that will generate
   * <code>ResultSet</code> objects with the given type and concurrency.
   * This method is the same as the <code>prepareStatement</code> method
   * above, but it allows the default result set
   * type and result set concurrency type to be overridden.
   *
   * @param resultSetType a result set type; see ResultSet.TYPE_XXX
   * @param resultSetConcurrency a concurrency type; see ResultSet.CONCUR_XXX
   * @return a new PreparedStatement object containing the pre-compiled SQL statement 
   * @exception SQLException if a database access error occurs
   * @since 1.2
   * @see <a href="package-summary.html#2.0 API">What Is in the JDBC 2.0 API</a>
   */
  public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency)
      throws SQLException
  {
    return m_conn.prepareStatement(sql,resultSetType,resultSetConcurrency);

  } // end prepareStatement

  public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency,
					    int resultSetHoldability) throws SQLException
  {
    return m_conn.prepareStatement(sql,resultSetType,resultSetConcurrency,resultSetHoldability);

  } // end prepareStatement

  public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys) throws SQLException
  {
    return m_conn.prepareStatement(sql,autoGeneratedKeys);

  } // end prepareStatement

  public PreparedStatement prepareStatement(String sql, int[] columnIndexes) throws SQLException
  {
    return m_conn.prepareStatement(sql,columnIndexes);

  } // end prepareStatement

  public PreparedStatement prepareStatement(String sql, String[] columnNames) throws SQLException
  {
    return m_conn.prepareStatement(sql,columnNames);

  } // end prepareStatement

  /**
   * Creates a <code>CallableStatement</code> object that will generate
   * <code>ResultSet</code> objects with the given type and concurrency.
   * This method is the same as the <code>prepareCall</code> method
   * above, but it allows the default result set
   * type and result set concurrency type to be overridden.
   *
   * @param resultSetType a result set type; see ResultSet.TYPE_XXX
   * @param resultSetConcurrency a concurrency type; see ResultSet.CONCUR_XXX
   * @return a new CallableStatement object containing the pre-compiled SQL statement 
   * @exception SQLException if a database access error occurs
   * @since 1.2
   * @see <a href="package-summary.html#2.0 API">What Is in the JDBC 2.0 API</a>
   */
  public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency)
      throws SQLException
  {
    return m_conn.prepareCall(sql,resultSetType,resultSetConcurrency);

  } // end prepareCall

  public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency,
				       int resultSetHoldability) throws SQLException
  {
    return m_conn.prepareCall(sql,resultSetType,resultSetConcurrency,resultSetHoldability);

  } // end prepareCall

  /**
   * Gets the type map object associated with this connection.
   * Unless the application has added an entry to the type map,
   * the map returned will be empty.
   *
   * @return the <code>java.util.Map</code> object associated with this <code>Connection</code> object
   * @since 1.2
   * @see <a href="package-summary.html#2.0 API">What Is in the JDBC 2.0 API</a>
   */
  public java.util.Map getTypeMap() throws SQLException
  {
    return m_conn.getTypeMap();

  } // end getTypeMap

  /**
   * Installs the given type map as the type map for
   * this connection.  The type map will be used for the
   * custom mapping of SQL structured types and distinct types.
   *
   * @param the <code>java.util.Map</code> object to install
   *        as the replacement for this <code>Connection</code>
   *        object's default type map
   * @since 1.2
   * @see <a href="package-summary.html#2.0 API">What Is in the JDBC 2.0 API</a>
   */
  public void setTypeMap(java.util.Map map) throws SQLException
  {
    m_conn.setTypeMap(map);

  } // end setTypeMap

  public int getHoldability() throws SQLException
  {
    return m_conn.getHoldability();

  } // end getHoldability

  public void setHoldability(int holdability) throws SQLException
  { // do nothing
  } // end setHoldability

  public Savepoint setSavepoint() throws SQLException
  {
    return m_conn.setSavepoint();

  } // end setSavepont

  public Savepoint setSavepoint(String name) throws SQLException
  {
    return m_conn.setSavepoint(name);

  } // end setSavepoint

  public void rollback(Savepoint savepoint) throws SQLException
  {
    m_conn.rollback(savepoint);

  } // end rollback

  public void releaseSavepoint(Savepoint savepoint) throws SQLException
  {
    m_conn.releaseSavepoint(savepoint);

  } // end releaseSavepoint

  /*--------------------------------------------------------------------------------
   * Attributes
   *--------------------------------------------------------------------------------
   */

  Connection getRealConnection()
  {
    return m_conn;

  } // end getRealConnection

} // end class WrappedConnection
