import java.io.IOException;
import java.lang.reflect.Field;
import java.sql.SQLException;

import javax.sql.ConnectionPoolDataSource;

import org.apache.commons.dbcp.datasources.SharedPoolDataSource;

import com.mysql.jdbc.jdbc2.optional.ConnectionWrapper;
import com.mysql.jdbc.jdbc2.optional.MysqlConnectionPoolDataSource;


/**
 * PoolDeadlockTest
 * TODO Describe the purpose of this class! 
 * @since 29.07.2009
 */
public class PoolDeadlockTest {

	/**
	 * TODO Describe the purpose of this method! 
	 * @param args
	 * @throws IOException 
	 * @throws SQLException 
	 * @since 29.07.2009
	 */
	public static void main(String[] args) throws IOException, SQLException {
		final SharedPoolDataSource dataSource = new SharedPoolDataSource();
		dataSource.setConnectionPoolDataSource(createConnectionPoolDataSource(
				"jdbc:mysql://localhost:3306/?useGmtMillisForDatetimes=true&autoReconnect=true",
				"EIM", "CAS"));
		dataSource.setValidationQuery("SELECT 1");
		dataSource.setTestOnReturn(true);
		dataSource.setTestWhileIdle(true);
		dataSource.setTestOnBorrow(true);
		dataSource.setTimeBetweenEvictionRunsMillis(1);
		dataSource.setMinEvictableIdleTimeMillis(10);
		dataSource.setMaxActive(40);
		
//		Statement statement = dataSource.getConnection().createStatement();
//		statement.execute("Select 1 from dual");
		for (int i=0; i<5; i++) {
			new Thread(new TestRunnable(dataSource)).start();
		}
		
		System.in.read();
	}
	
	public static ConnectionPoolDataSource createConnectionPoolDataSource(final String dbUrl,
			final String userName, final String password) {
			MysqlConnectionPoolDataSource mysqlConnectionPoolDataSource = new MysqlConnectionPoolDataSource();
			// Set basic parameters
			mysqlConnectionPoolDataSource.setURL(dbUrl);
			mysqlConnectionPoolDataSource.setUser(userName);
			mysqlConnectionPoolDataSource.setPassword(password);
			// set reconnect parameters
			mysqlConnectionPoolDataSource.setAutoReconnect(true);
			mysqlConnectionPoolDataSource.setAutoReconnectForConnectionPools(true);
			mysqlConnectionPoolDataSource.setAutoReconnectForPools(true);

			return mysqlConnectionPoolDataSource;
		}

	static class TestRunnable implements Runnable {
		
		private SharedPoolDataSource dataSource;
		
		
		/**
		 * Constructs a new TestRunnable.
		 * @param dataSource
		 */
		public TestRunnable(SharedPoolDataSource dataSource) {
			super();
			this.dataSource = dataSource;
		}


		public void run() {
			try {
				while(true) {
					ConnectionWrapper connection = (ConnectionWrapper) dataSource.getConnection();
					Field field = connection.getClass().getDeclaredField("mc");
					field.setAccessible(true);
					System.out.println(field.get(connection));
					Thread.sleep(50);
					connection.close();
				}
			}
			catch (Exception e) {
				e.printStackTrace();
			}
	
		}
	}
}
