/*
 * Copyright (c) 2017, 2018 Oracle and/or its affiliates. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0, which is available at
 * http://www.eclipse.org/legal/epl-2.0.
 *
 * This Source Code may also be made available under the following Secondary
 * Licenses when the conditions for such availability set forth in the
 * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
 * version 2 with the GNU Classpath Exception, which is available at
 * https://www.gnu.org/software/classpath/license.html.
 *
 * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
 */

/*
 * UnpooledTest.java
 *
 * Created on October 31, 2006, 11:44 AM
 *
 * To change this template, choose Tools | Template Manager
 * and open the template in the editor.
 */

package com.sun.s1asdev.jdbc.switchoffACCConnPooling.client;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.sql.DataSource;
import java.sql.Connection;
import javax.transaction.SystemException;
import javax.transaction.UserTransaction;
import java.util.HashSet;

import com.sun.ejte.ccl.reporter.SimpleReporterAdapter;

/**
 *
 * @author kshitiz
 */
public class Client {
    
    private static int count = 10;
    private static boolean rollback;
    private static String tableName = "COFFEE";
    
    //static SimpleReporterAdapter stat = new SimpleReporterAdapter("appserv-tests");
    private static SimpleReporterAdapter stat = new SimpleReporterAdapter();
    private static final String testSuite = "switchoffACCconnpooling";
    private static int testCount = 0;
    
    private static boolean isXA=false;

    /** Creates a new instance of UnpooledTest */
    public Client() {
    }
    
    
    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        stat.addDescription("Switch-Off connection pooling in ACC");
        System.out.println("verifying uniqueness of all connection");
        openAndCloseConnection("jdbc/nonxaresource", 40);
        System.out.println("creating connection upto max-pool-size of 32");
        openMaxConnections("jdbc/nonxaresource", 32);
        rollback = false;
        System.out.println("rollback set to " + rollback);
        runTest();
        rollback = true;
        System.out.println("rollback set to " + rollback);
        runTest();
        stat.printSummary();
    }
    
    private static void runTest() {
        
        //Connection opened and closed within transaction
        //non-xa resource
        isXA = false;
        test1("jdbc/nonxaresource");
        //xa resource
        isXA = true;
        test1("jdbc/xaresource");
        
        //Connection opened within transaction 
        //but closed after transaction
        isXA = false;
        //non-xa resource
        test2("jdbc/nonxaresource");
        //xa resource
        isXA = true;
        test2("jdbc/xaresource");
                
        //XA and Non-XA resource within same transaction
        //non-xa resource and xa  resource together
        test3("jdbc/nonxaresource", "jdbc/xaresource");
       
        test4("jdbc/nonxaresource", "jdbc/xaresource");	
        //openAndCloseConnection("jdbc/oraclexa", 40);
    }
    
    public static void test1(String dsName) {
        UserTransaction ut = null;
        try {
            InitialContext ic = new InitialContext();
            DataSource ds = (DataSource) ic.lookup(dsName);
            printConnection(ds);
            
            createTable(ds);
            
            int count1 = getCount(ds);
            System.out.println("count1 : " + count1);
            
            ut = (UserTransaction) ic.lookup("java:comp/UserTransaction");
            ut.begin();
            
            for(int i=0; i< count; i++)
                insertRow(ds);
            if(rollback)
                ut.rollback();
            else
                ut.commit();
            
            int count2=getCount(ds);
            
            System.out.println("count2 : " + count2);
            
            int diff = count2 - count1;
            if(( diff == count && !rollback) || (diff == 0 && rollback))
                printStatus(true);
            else
                printStatus(false);
            
        } catch(Exception e){
            printStatus(false);
            e.printStackTrace();
            if(ut != null){
                try {
                    ut.rollback();
                } catch (IllegalStateException ex) {
                    ex.printStackTrace();
                } catch (SecurityException ex) {
                    ex.printStackTrace();
                } catch (SystemException ex) {
                    ex.printStackTrace();
                }
            }
        };
        
    }
    
    public static void test2(String dsName) {
        UserTransaction ut = null;
        try {
            InitialContext ic = new InitialContext();
            DataSource ds = (DataSource) ic.lookup(dsName);
            printConnection(ds);
            Connection[] con;

            createTable(ds);
            
            int count1 = getCount(ds);
            System.out.println("count1 : " + count1);
            
            ut = (UserTransaction) ic.lookup("java:comp/UserTransaction");
            ut.begin();
            
            con = openConnections(dsName, count);
            insertRow(con);
            closeConnections(con, count);
            
            if(rollback)
                ut.rollback();
            else
                ut.commit();
            
            int count2=getCount(ds);
            
            System.out.println("count2 : " + count2);
            
            int diff = count2 - count1;
            if(( diff == count && !rollback) || (diff == 0 && rollback))
                printStatus(true);
            else
                printStatus(false);
            
        } catch(Exception e){
            printStatus(false);
            e.printStackTrace();
            if(ut != null){
                try {
                    ut.rollback();
                } catch (IllegalStateException ex) {
                    ex.printStackTrace();
                } catch (SecurityException ex) {
                    ex.printStackTrace();
                } catch (SystemException ex) {
                    ex.printStackTrace();
                }
            }
        };
        
    }
    
    
    public static void test4(String dsName, String xaDsName) {
        UserTransaction ut = null;
        try {
            InitialContext ic = new InitialContext();
            DataSource ds = (DataSource) ic.lookup(dsName);
	    DataSource xads = (DataSource) ic.lookup(xaDsName);
            printConnection(ds);
            Connection[] con;
	    Connection[] xaCon;

	    isXA = false;
            createTable(ds);
            isXA = true;
	    createTable(xads);

	    isXA = false;
            int count1 = getCount(ds);
	    isXA = true;
	    int xacount1 = getCount(xads);

            System.out.println("count1 : " + count1 + " xacount1 : " + xacount1);
            
            ut = (UserTransaction) ic.lookup("java:comp/UserTransaction");
            ut.begin();
            
            con = openConnections(dsName, count);
	    xaCon = openConnections(xaDsName, 1);
	    isXA = false;
            insertRow(con);
	    isXA = true;
	    insertRow(xaCon);

	    isXA = false;
            closeConnections(con, count);

	    isXA = true;
	    closeConnections(xaCon, 1);
            
            if(rollback)
                ut.rollback();
            else
                ut.commit();
            
	    isXA = false;
            int count2=getCount(ds);
	    isXA = true;
	    int xacount2 = getCount(xads);
            
            System.out.println("count2 : " + count2 + " xacount2 : " + xacount2);
            
            int diff = count2 - count1;
	    int xadiff = xacount2 - xacount1;

            if((( diff == count && !rollback) || (diff == 0 && rollback)) && 
			((xadiff == 1 && !rollback) || (xadiff == 0 && rollback)))
                printStatus(true);
            else
                printStatus(false);
            
        } catch(Exception e){
            printStatus(false);
            e.printStackTrace();
            if(ut != null){
                try {
                    ut.rollback();
                } catch (IllegalStateException ex) {
                    ex.printStackTrace();
                } catch (SecurityException ex) {
                    ex.printStackTrace();
                } catch (SystemException ex) {
                    ex.printStackTrace();
                }
            }
        };
        
    }
    
    
    public static void test3(String ds1Name, String ds2Name) {
        UserTransaction ut = null;
        try {
            InitialContext ic = new InitialContext();
            DataSource ds1 = (DataSource) ic.lookup(ds1Name);
            printConnection(ds1);
            DataSource ds2 = (DataSource) ic.lookup(ds2Name);
            printConnection(ds2);
            
            isXA = false;
            createTable(ds1);
            isXA = true;
            createTable(ds2);
            
            isXA = false;
            int count1 = getCount(ds1);
            isXA = true;
            int count3 = getCount(ds2);
            System.out.println("count1 : " + count1);
            System.out.println("count3 : " + count3);
            
            ut = (UserTransaction) ic.lookup("java:comp/UserTransaction");
            ut.begin();
            
            isXA = false;
            for(int i=0; i< count; i++)
                insertRow(ds1);
            isXA = true;
            for(int i=0; i< count; i++)
                insertRow(ds2);
            
            if(rollback)
                ut.rollback();
            else
                ut.commit();
            
            isXA = false;
            int count2=getCount(ds1);
            isXA = true;
            int count4=getCount(ds2);
            
            System.out.println("count2 : " + count2);
            System.out.println("count4 : " + count4);
            
            int diff1 = count2 - count1;
            int diff2 = count4 - count3;
            if((( diff1 == count && !rollback) || (diff1 == 0 && rollback))
            && (( diff2 == count && !rollback) || (diff2 == 0 && rollback)))
                printStatus(true);
            else
                printStatus(false);
            
        } catch(Exception e){
            printStatus(false);
            e.printStackTrace();
            if(ut != null){
                try {
                    ut.rollback();
                } catch (IllegalStateException ex) {
                    ex.printStackTrace();
                } catch (SecurityException ex) {
                    ex.printStackTrace();
                } catch (SystemException ex) {
                    ex.printStackTrace();
                }
            }
        };
        
    }
    
    private static void createTable(final DataSource ds) throws SQLException {
        String tableName;
        if(isXA)
            tableName = "COFFEE_XA";
        else
            tableName = "COFFEE";
        
        Connection con;
        Statement stmt;
        con = ds.getConnection();
        stmt = con.createStatement();
        
        try{
            stmt.executeUpdate("drop table " + tableName);
        }catch(Exception ex){
            ex.printStackTrace();
        }
        stmt.executeUpdate("create table " + tableName + " (name varchar(32), qty integer)");
        stmt.close();
        con.close();
    }
    
    private static int getCount(final DataSource ds) throws SQLException {
        String tableName;
        if(isXA)
            tableName = "COFFEE_XA";
        else
            tableName = "COFFEE";
        Statement stmt;
        Connection con;
        ResultSet rs;
        con = ds.getConnection();
        stmt = con.createStatement();
        rs = stmt.executeQuery( "SELECT count(*) FROM " + tableName);
        rs.next();
        int count = rs.getInt(1);
        rs.close();
        stmt.close();
        con.close();
        return count;
    }
    
    private static void insertRow(final DataSource ds) throws SQLException {
        String tableName;
        if(isXA)
            tableName = "COFFEE_XA";
        else
            tableName = "COFFEE";
        Statement stmt;
        Connection con;
        con = ds.getConnection();
        stmt = con.createStatement();
        stmt.executeUpdate("INSERT INTO " + tableName + " values ('COFFEE', 100)");
        stmt.close();
        con.close();
    }
    
    private static void insertRow(final Connection[] con) throws SQLException {
        String tableName;
        if(isXA)
            tableName = "COFFEE_XA";
        else
            tableName = "COFFEE";
        Statement stmt;
        for(int i=0; i < con.length; i++){
            stmt = con[i].createStatement();
            stmt.executeUpdate("INSERT INTO " + tableName + " values ('COFFEE', 100)");
	    stmt.close();
        }
    }
    
   
    private static void printConnection(final DataSource ds) throws SQLException{
        com.sun.appserv.jdbc.DataSource dsTyped = (com.sun.appserv.jdbc.DataSource) ds;
        Connection wrapper = dsTyped.getConnection();
        System.out.println("Connection type : " + dsTyped.getConnection(wrapper));
        wrapper.close();
    }
    
    private static void openAndCloseConnection(String dsName, int count) {
        try {
            InitialContext ic = new InitialContext();
            DataSource ds = (DataSource) ic.lookup(dsName);
            com.sun.appserv.jdbc.DataSource dsTyped = (com.sun.appserv.jdbc.DataSource) ds;
	    HashSet<String> connections = new HashSet<String>();
            Connection con;
	    String conType;
	    boolean status = true;
	    int i = 0;
            for(; i < count; i++){
                con = ds.getConnection();
		conType = dsTyped.getConnection(con).toString();
        	System.out.println("Connection type : " + conType);
                con.close();
		if(!connections.add(conType)){
			status = false;
			break;
		}
            }
       	    System.out.println("Total connection requested :  " + count);
       	    System.out.println("Total connection created :  " + i);
       	    System.out.println("Total number of unique connection :  " + connections.size());
	    printStatus(status);
        }catch(Exception ex){
            ex.printStackTrace();
        }
    }
    
    private static void openMaxConnections(String dsName, int count) {
        DataSource ds = null;
	try{
        	InitialContext ic = new InitialContext();
		ds = (DataSource) ic.lookup(dsName);
	}catch(NamingException ex){
		System.out.println("Unable to lookup datasource");
		ex.printStackTrace();
		return;
	}
        
        Connection[] con = new Connection[count];
	int i = 0;
        for(; i < count; i++){
	   try{
           	con[i] = ds.getConnection();
	   }catch(SQLException ex){
		System.out.println("Unable to create max connections");
		printStatus(false);	
	   }
	}

	if(i ==  count){
		System.out.println("Able to create max connections");
		printStatus(true);	
		try{
			ds.getConnection();
                	System.out.println("Able to create beyond max connections");
                	printStatus(false);
		}catch(SQLException ex){
                	System.out.println("Unable to create beyond max connections");
                	printStatus(true);
           	}
	}
        
        for(; i > 0; i--){
	   try{
            	con[i - 1].close();
	   }catch(SQLException ex){
		System.out.println("Unable to close connection");
	   }
	}
    }

    private static Connection[] openConnections(String dsName, int count) throws NamingException, SQLException {
        InitialContext ic = new InitialContext();
        DataSource ds = (DataSource) ic.lookup(dsName);
        
        Connection[] con = new Connection[count];
        for(int i=0; i < count; i++) {
            con[i] = ds.getConnection();
	    System.out.println("con[" + i+ "]=" + con[i]);
	}
        return con;
    }
    
    private static void closeConnections(Connection[] con, int count) throws SQLException {
        for(int i=0; i < count; i++)
            con[i].close();
    }
    
    private static void printStatus(boolean status){
        String testcaseID = testSuite + "-test" + (++testCount) ;
        if(status){
            stat.addStatus(testcaseID, stat.PASS);
            System.out.println(testcaseID + ": passed");
        }
        else{
            stat.addStatus(testcaseID, stat.FAIL);
            System.out.println(testcaseID + ": failed");
        }
    }
}
