/*
 * 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 jakarta.transaction.SystemException;
import jakarta.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");
        }
    }
}
