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

package org.jfox.jdbc.datasource;

import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import javax.naming.NamingException;
import javax.naming.Reference;
import javax.naming.Referenceable;
import javax.naming.StringRefAddr;
import javax.sql.DataSource;

import org.huihoo.jfox.system.ComponentSupport;

/**
 * @author <a href="mailto:kelvin_wym@hotmail.com">Kelvin Wu</a>
 */
public class PoolDataSource extends ComponentSupport implements DataSource, Referenceable {
  protected ConnectionPool pool = null; // The connection pool used the get connections.
  private String dbDriver; // database driver class name.
  private String dbURL; // database url
  private String user; // database user
  private String password; //database password
  private int initNum = 2;
  private int maxRest = 10;


  /**
   * Constructor specify database connection parameters to generate a valid and usable datasource.
   * 
   * @param dbDriver database class name according your dabase
   * @param dbURL    database url used to access database
   * @param user     valid database user
   * @param password // corresponding database password
   * @throws Exception any exception who cares?
   */
  public PoolDataSource(String dbDriver, String dbURL, String user, String password) throws Exception {
    this.dbDriver = dbDriver;
    this.dbURL = dbURL;
    this.user = user;
    this.password = password;
  }

  /**
   * Get usable connection from datasource
   * 
   * @return Connection the valid database connection can used by user
   * @throws SQLException 
   */
  public Connection getConnection() throws SQLException {
    // since the pool.getConnection() throws out exception, so I have to catch it.
    // Please Young consider about the excpetion handler meshiasm.
    try {
      return pool.getConnection();
    }
    catch (SQLException sqle) {
      throw sqle;
    }
    catch (Exception e) {
      e.printStackTrace();
      throw new SQLException(e.getMessage());
    }
  }

  /**
   * Get connection by specific user name and password, the connection is not pooled by
   * Connection Pool
   * 
   * @param username 
   * @param password 
   * @return 
   * @throws SQLException 
   */
  public Connection getConnection(String username, String password)
          throws SQLException {
    return DriverManager.getConnection(dbURL, username, password);

  }

  /**
   * Get logger writer
   * 
   * @return 
   * @throws SQLException 
   */
  public PrintWriter getLogWriter() throws SQLException {
    return DriverManager.getLogWriter();
  }

  /**
   * @param out 
   * @throws SQLException 
   */
  public void setLogWriter(PrintWriter out) throws SQLException {
    DriverManager.setLogWriter(out);
  }

  /**
   * @param seconds 
   * @throws SQLException 
   */
  public void setLoginTimeout(int seconds) throws SQLException {
    DriverManager.setLoginTimeout(seconds);
  }

  /**
   * @return 
   * @throws SQLException 
   */
  public int getLoginTimeout() throws SQLException {
    return DriverManager.getLoginTimeout();
  }

  /**
   * Method that inherited from Referenceable.
   * 
   * @return 
   * @throws javax.naming.NamingException 
   */
  public Reference getReference() throws NamingException {
    Reference ref = new Reference(getClass().getName(), DataSourceObjectFactory.class.getName(), null);
    ref.add(new StringRefAddr("dbDriver", dbDriver));
    ref.add(new StringRefAddr("dbURL", dbURL));
    ref.add(new StringRefAddr("user", user));
    ref.add(new StringRefAddr("password", password));
    return ref;
  }

  public String getDbDriver() {
    return dbDriver;
  }

  public String getDbURL() {
    return dbURL;
  }

  public String getUser() {
    return user;
  }

  public String getPassword() {
    return password;
  }

  public int getMaxRest() {
    return maxRest;
  }

  public int getInitNum(){
    return initNum;
  }

  public void setInitNum(int initNum) {
    this.initNum = initNum;
  }

  public void setMaxRest(int maxRest) {
    this.maxRest = maxRest;
  }

  protected void doInit() throws Exception {
    pool = new ConnectionPool(dbDriver, dbURL, user, password);
    pool.setInitNum(initNum);
    pool.setMaxRest(maxRest);
    pool.init();
  }

  protected void doDestroy() throws Exception {
    pool.destroy();
  }
}