/*
 * 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.util.Enumeration;
import java.util.Properties;
import java.util.Vector;

import org.apache.xalan.res.XSLMessages;
import org.apache.xalan.res.XSLTErrorResources;

/**
 * For internal connectiones, i.e. Connection information supplies in the
 * Stylesheet. The Default Connection Pool will be used.
 */
public class DefaultConnectionPool implements ConnectionPool
{
  /**
   */
  private static final boolean DEBUG = false;

  /**
   * The basic information to make a JDBC Connection
   */
  private String m_driver = new String("");
  /**
   */
  private String m_url = new String("");


  /**
   * The mimimum size of the connection pool, if the
   * number of available connections falls below this
   * mark, min connections will be allocated. The Connection
   * Pool will always be somewhere between MinSize and MinSize*2
   */
  private int m_PoolMinSize = 1;


  /**
   * Always implement the properties mechinism, if the Password
   * or Username is set seperatly then we will add them to the
   * property manually.
   */
  private Properties m_ConnectionProtocol = new Properties();

  /**
   * Storage for the PooledConnections
   */
  private Vector m_pool = new Vector();

  /**
   * Are we active ??
   */
  private boolean m_IsActive = false;

  /**
   */
  public DefaultConnectionPool( ) {}


  /**
   * Return our current Active state
   * @return
   */
  public boolean isEnabled( )
  {
    return m_IsActive;
  }

  /**
   * Set the driver call to be used to create connections
   * @param d
   * @return
   */
  public void setDriver( String d )
  {
    m_driver = d;
  }

  /**
   * Set the url used to connect to the database
   * @param url
   * @return
   */
  public void setURL( String url )
  {
    m_url = url;
  }

  /**
   * Go through the connection pool and release any connections
   * that are not InUse;
   * @return
   */
  public void freeUnused( )
  {
    // Iterate over the entire pool closing the
    // JDBC Connections.
    for ( int x = 0; x < m_pool.size(); x++ )
    {


      PooledConnection pcon =
        (PooledConnection) m_pool.elementAt(x);

      // If the PooledConnection is not in use, close it
      if ( pcon.inUse() == false )
      {
        if (DEBUG)
        {
          System.err.println("Closing JDBC Connection " + x);
        }

        pcon.close();
      }
    }

  }

  /**
   * Is our ConnectionPool have any connections that are still in Use ??
   * @return
   */
  public boolean hasActiveConnections( )
  {
    return (m_pool.size() > 0);
  }


  /**
   * Set the password in the property set.
   * @param p
   * @return
   */
  public void setPassword( String p )
  {
    m_ConnectionProtocol.put("password", p);
  }

  /**
   * Set the user name in the property set
   * @param u
   * @return
   */
  public void setUser( String u )
  {
    m_ConnectionProtocol.put("user", u);
  }

  /**
   * The Protocol string is used to pass in other connection
   * properties. A properties file is a general purpose container
   *
   * @param p
   * @return
   */
  public void setProtocol( Properties p )
  {
    Enumeration e = p.keys();
    while (e.hasMoreElements())
    {
      String key = (String) e.nextElement();
      m_ConnectionProtocol.put(key, p.getProperty(key));
    }
  }


  /**
   * Override the current number of connections to keep in the pool. This
   * setting will only have effect on a new pool or when a new connection
   * is requested and there is less connections that this setting.
   * @param n
   * @return
   */
  public void setMinConnections( int n )
  {
    m_PoolMinSize = n;
  }

  /**
   * Try to aquire a new connection, if it succeeds then return
   * true, else return false.
   * Note: This method will cause the connection pool to be built.
   * @return
   */
  public boolean testConnection( )
  {
    try
    {
      if (DEBUG)
      {
        System.out.println("Testing Connection");
      }

      Connection conn = getConnection();

      if (DEBUG)
      {
        DatabaseMetaData dma = conn.getMetaData();

        System.out.println("\nConnected to " + dma.getURL());
        System.out.println("Driver   " + dma.getDriverName());
        System.out.println("Version  " + dma.getDriverVersion());
        System.out.println("");
      }

      if (conn == null) return false;

      releaseConnection(conn);

      if (DEBUG)
      {
        System.out.println("Testing Connection, SUCCESS");
      }

      return true;
    }
    catch(Exception e)
    {
      if (DEBUG)
      {
        System.out.println("Testing Connection, FAILED");
        e.printStackTrace();
      }

      return false;
    }

  }


  // Find an available connection
  /**
   * @return Connection
   * @throws SQLException
   * @throws IllegalArgumentException
   */
  public synchronized Connection getConnection( )throws IllegalArgumentException, SQLException
  {

    PooledConnection pcon = null;

    // We will fill up the pool any time it is less than the
    // Minimum. THis could be cause by the enableing and disabling
    // or the pool.
    //
    if ( m_pool.size() < m_PoolMinSize ) { initializePool(); }

    // find a connection not in use
    for ( int x = 0; x < m_pool.size(); x++ )
    {

      pcon = (PooledConnection) m_pool.elementAt(x);

      // Check to see if the Connection is in use
      if ( pcon.inUse() == false )
      {
        // Mark it as in use
        pcon.setInUse(true);
        // return the JDBC Connection stored in the
        // PooledConnection object
        return pcon.getConnection();
      }
    }

    // Could not find a free connection,
    // create and add a new one

    // Create a new JDBC Connection
    Connection con = createConnection();

    // Create a new PooledConnection, passing it the JDBC
    // Connection
    pcon = new PooledConnection(con);

    // Mark the connection as in use
    pcon.setInUse(true);

    // Add the new PooledConnection object to the pool
    m_pool.addElement(pcon);

    // return the new Connection
    return pcon.getConnection();
  }

  /**
   * @param con
   * @return
   * @throws SQLException
   */
  public synchronized void releaseConnection( Connection con )throws SQLException
  {

    // find the PooledConnection Object
    for ( int x = 0; x < m_pool.size(); x++ )
    {

      PooledConnection pcon =
        (PooledConnection) m_pool.elementAt(x);

      // Check for correct Connection
      if ( pcon.getConnection() == con )
      {
        if (DEBUG)
        {
          System.out.println("Releasing Connection " + x);
        }

        if (! isEnabled())
        {
          con.close();
          m_pool.removeElementAt(x);
          if (DEBUG)
          {
            System.out.println("-->Inactive Pool, Closing connection");
          }

        }
        else
        {
          // Set it's inuse attribute to false, which
          // releases it for use
          pcon.setInUse(false);
        }

        break;
      }
    }
  }


  /**
   * @param con
   * @return
   * @throws SQLException
   */
  public synchronized void releaseConnectionOnError( Connection con )throws SQLException
  {

    // find the PooledConnection Object
    for ( int x = 0; x < m_pool.size(); x++ )
    {

      PooledConnection pcon =
        (PooledConnection) m_pool.elementAt(x);

      // Check for correct Connection
      if ( pcon.getConnection() == con )
      {
        if (DEBUG)
        {
          System.out.println("Releasing Connection On Error" + x);
        }

        con.close();
        m_pool.removeElementAt(x);
        if (DEBUG)
        {
          System.out.println("-->Inactive Pool, Closing connection");
        }
        break;
      }
    }
  }


  /**
   * @return
   * @throws SQLException
   */
  private Connection createConnection( )throws SQLException
  {
    Connection con = null;

    // Create a Connection
    con = DriverManager.getConnection( m_url, m_ConnectionProtocol );

    return con;
  }

  // Initialize the pool
  /**
   * @return
   * @throws IllegalArgumentException
   * @throws SQLException
   */
  public synchronized void initializePool( )throws IllegalArgumentException, SQLException
  {

     // Check our initial values
     if ( m_driver == null )
     {
       throw new IllegalArgumentException(XSLMessages.createMessage(XSLTErrorResources.ER_NO_DRIVER_NAME_SPECIFIED, null));
       // "No Driver Name Specified!");
     }

     if ( m_url == null )
     {
       throw new IllegalArgumentException(XSLMessages.createMessage(XSLTErrorResources.ER_NO_URL_SPECIFIED, null));
       // "No URL Specified!");
     }

     if ( m_PoolMinSize < 1 )
     {
       throw new IllegalArgumentException(XSLMessages.createMessage(XSLTErrorResources.ER_POOLSIZE_LESS_THAN_ONE, null));
       // "Pool size is less than 1!");
     }

     // Create the Connections
     // Load the Driver class file

     try
     {
       Class.forName( m_driver );
     }
     catch(ClassNotFoundException e)
     {
       throw new IllegalArgumentException(XSLMessages.createMessage(XSLTErrorResources.ER_INVALID_DRIVER_NAME, null));
       // "Invalid Driver Name Specified!");
     }

     // IF we are not active, don't actuall build a pool yet
     // Just set up the driver and periphal items.
     if ( !m_IsActive) return;

    // Create Connections based on the size member
    do
    {

      Connection con = createConnection();

      if ( con != null )
      {

        // Create a PooledConnection to encapsulate the
        // real JDBC Connection
        PooledConnection pcon = new PooledConnection(con);

        // Add the Connection the pool.
        addConnection(pcon);

        if (DEBUG) System.out.println("Adding DB Connection to the Pool");
      }
    }
    while (m_pool.size() < m_PoolMinSize);
  }

  // Adds the PooledConnection to the pool
  /**
   * @param value
   * @return
   */
  private void addConnection( PooledConnection value )
  {
    // Add the PooledConnection Object to the vector
    m_pool.addElement(value);
  }


  /**
   * @return
   * @throws Throwable
   */
  protected void finalize( )throws Throwable
  {
    if (DEBUG)
    {
      System.out.println("In Default Connection Pool, Finalize");
    }

    // Iterate over the entire pool closing the
    // JDBC Connections.
    for ( int x = 0; x < m_pool.size(); x++ )
    {

      if (DEBUG)
      {
        System.out.println("Closing JDBC Connection " + x);
      }

      PooledConnection pcon =
        (PooledConnection) m_pool.elementAt(x);

      // If the PooledConnection is not in use, close it
      if ( pcon.inUse() == false ) { pcon.close();  }
      else
      {
        if (DEBUG)
        {
          System.out.println("--> Force close");
        }

        // If it still in use, sleep for 30 seconds and
        // force close.
        try
        {
          java.lang.Thread.sleep(30000);
          pcon.close();
        }
        catch (InterruptedException ie)
        {
          if (DEBUG) System.err.println(ie.getMessage());
        }
      }
    }

    if (DEBUG)
    {
      System.out.println("Exit Default Connection Pool, Finalize");
    }

    super.finalize();
  }

  /**
   * The Pool can be Enabled and Disabled. Disabling the pool
   * closes all the outstanding Unused connections and any new
   * connections will be closed upon release.
   * @param flag Control the Connection Pool. If it is enabled then Connections will actuall be held
   * around. If disabled then all unused connections will be instantly closed and as
   * connections are released they are closed and removed from the pool.
   * @return
   */
  public void setPoolEnabled( final boolean flag )
  {

  }


}
