/* JFox, the OpenSource J2EE Application Server
 *
 * Copyright (C) 2002 huihoo.com
 * Distributable under GNU LGPL license
 * See the GNU Lesser General Public License for more details.
 */

package org.jfox.jdbc;

import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.SQLWarning;
import java.sql.Savepoint;
import java.sql.Statement;
import java.util.Map;

/**
 * ClientConnection 拦截 close 调用,使其无效
 * 对于 Oracle,是不能调用 close 方法的,否则事务无法提交
 *  
 * @author <a href="mailto:young_yy@hotmail.com">Young Yang</a>
 */

public class ClientConnection implements Connection{
  private Connection conn = null;
  private boolean isClosed = false;

  public ClientConnection(Connection conn) {
    if(conn == null) {
      throw new RuntimeException("conn is null.");
    }
    try {
      if(conn.isClosed()) {
        throw new RuntimeException("conn is closed.");
      }
    }
    catch(SQLException e){
      throw new RuntimeException(e);
    }
    this.conn = conn;
  }

  public void rollback(Savepoint savepoint) throws SQLException {
    checkClosed();
    conn.rollback(savepoint);
  }

  public PreparedStatement prepareStatement(String sql, String columnNames[]) throws SQLException {
    checkClosed();
    return new LoggablePreparedStatement(conn.prepareStatement(sql,columnNames),sql);
  }

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

  public void rollback() throws SQLException {
    conn.rollback();
  }

  public DatabaseMetaData getMetaData() throws SQLException {
    checkClosed();
    return conn.getMetaData();
  }

  public SQLWarning getWarnings() throws SQLException {
    checkClosed();
    return conn.getWarnings();
  }

  public PreparedStatement prepareStatement(String sql, int columnIndexes[]) throws SQLException {
    checkClosed();
    return new LoggablePreparedStatement(conn.prepareStatement(sql,columnIndexes),sql);
  }

  public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException {
    checkClosed();
    return new LoggablePreparedStatement(conn.prepareStatement(sql,resultSetType,resultSetConcurrency,resultSetHoldability),sql);
  }

  public boolean getAutoCommit() throws SQLException {
    checkClosed();
    return conn.getAutoCommit();
  }

  public String nativeSQL(String sql) throws SQLException {
    checkClosed();
    return conn.nativeSQL(sql);
  }

  public void setTransactionIsolation(int level) throws SQLException {
    checkClosed();
    conn.setTransactionIsolation(level);
  }

  public PreparedStatement prepareStatement(String sql) throws SQLException {
    checkClosed();
    return new LoggablePreparedStatement(conn.prepareStatement(sql),sql);
  }

  public int getHoldability() throws SQLException {
    checkClosed();
    return conn.getHoldability();
  }

  public void clearWarnings() throws SQLException {
    checkClosed();
    conn.clearWarnings();
  }

  public Savepoint setSavepoint() throws SQLException {
    checkClosed();
    return conn.setSavepoint();
  }

  public Map getTypeMap() throws SQLException {
    checkClosed();
    return conn.getTypeMap();
  }

  public void setTypeMap(Map map) throws SQLException {
    checkClosed();
    conn.setTypeMap(map);
  }

  public void commit() throws SQLException {
    conn.commit();
  }

  public void setCatalog(String catalog) throws SQLException {
    checkClosed();
    conn.setCatalog(catalog);
  }

  public boolean isClosed() throws SQLException {
    return isClosed;
  }

  public void setHoldability(int holdability) throws SQLException {
    checkClosed();
    conn.setHoldability(holdability);
  }

  public String getCatalog() throws SQLException {
    checkClosed();
    return conn.getCatalog();
  }

  public void setReadOnly(boolean readOnly) throws SQLException {
    checkClosed();
    conn.setReadOnly(readOnly);
  }

  public Savepoint setSavepoint(String name) throws SQLException {
    checkClosed();
    return conn.setSavepoint(name);
  }

  public void releaseSavepoint(Savepoint savepoint) throws SQLException {
    checkClosed();
    conn.releaseSavepoint(savepoint);
  }

  public CallableStatement prepareCall(String sql) throws SQLException {
    checkClosed();
    return conn.prepareCall(sql);
  }

  public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency) throws SQLException {
    checkClosed();
    return new LoggablePreparedStatement(conn.prepareStatement(sql,resultSetType,resultSetConcurrency),sql);
  }

  public void close() throws SQLException {
    checkClosed();
//    System.out.println("Warning: call connection.close explicit");
    isClosed = true;
    // do nothing
  }

  public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys) throws SQLException {
    checkClosed();
    return new LoggablePreparedStatement(conn.prepareStatement(sql,autoGeneratedKeys),sql);
  }

  public int getTransactionIsolation() throws SQLException {
    checkClosed();
    return conn.getTransactionIsolation();
  }

  public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency) throws SQLException {
    checkClosed();
    return conn.prepareCall(sql,resultSetType,resultSetConcurrency);
  }

  public boolean isReadOnly() throws SQLException {
    checkClosed();
    return conn.isReadOnly();
  }

  public Statement createStatement() throws SQLException {
    checkClosed();
    return conn.createStatement();
  }

  public void setAutoCommit(boolean autoCommit) throws SQLException {
    checkClosed();
    conn.setAutoCommit(autoCommit);
  }

  public Statement createStatement(int resultSetType, int resultSetConcurrency) throws SQLException {
    checkClosed();
    return conn.createStatement(resultSetType,resultSetConcurrency);
  }

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

  private void checkClosed() throws SQLException {
    if(isClosed) {
      throw new SQLException("connection closed");
    }
  }

  public static void main(String[] args) {

  }
}