/*
 * 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");
        }
    }
}
