/*
 * Copyright 2002 Sun Microsystems, Inc. All rights reserved.
 * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 */

/*
 * @(#)batUpdExceptClient.java	1.9 02/01/12
 */

package com.sun.cts.tests.jdbc.ee.exception.batUpdExcept;

import java.io.*;
import java.util.*;

import java.sql.*;
import javax.sql.*;

import com.sun.cts.util.*;
import com.sun.cts.porting.*;
import com.sun.cts.harness.*;

import java.rmi.RemoteException;

import javasoft.sqe.javatest.Status;
import com.sun.cts.tests.jdbc.ee.common.*;


// Merant DataSource class
// import com.merant.sequelink.jdbcx.datasource.*;


/**
 * The batUpdExceptClient class tests methods of BatchUpdateException using
 * Sun's J2EE Reference Implementation.
 * @author  
 * @version 1.7, 06/16/99
 */

public class batUpdExceptClient extends ServiceEETest implements Serializable 
{
	private static final String testName = "jdbc.ee.exception.batUpdExcept";

        /*
         * used by testGetUpdateCounts to represent:
         *  1. number of entries in the attempted batch
         *  2. updateCount array offset that will fail
         *  3. Status to be returned in the updatecount array offset if
         *     the driver continues after the failure.
         */
        private static final int MAXUPDATECOUNT_ENTRIES = 4;
        private static final int UPDATECOUNTERROR_LOCATION = 3; 
        private static final int DRIVERCONTINUES_ERRORSTATE = -3;

	//Naming specific member variables
	private CTSNamingContextInterface jc = null;

	//Harness requirements 

	private transient Connection conn = null;
	private ResultSet rs=null;
	private Statement stmt=null;
	private DataSource ds1 = null;
	private dbSchema dbSch=null;
	private	String drManager=null;
	private transient DatabaseMetaData dbmd=null;
	private Properties sqlp = null;
	private boolean supbatupdflag; 
	private boolean isThrown = false ; 
	private int[] intialVal = new int[MAXUPDATECOUNT_ENTRIES] ;
	private String sReason = null ;
	private String sSqlState = null ;
	private String sVendorCode = null;
	private String sIntialVal = null ;
	private String sUsr,sPass,sUrl ;
	private int vendorCode = 0,maxVal = 0,minVal = 0;
	private int[] updateCount = null ;

	/* Run test in standalone mode */
	public static void main(String[] args) 
	{
		batUpdExceptClient theTests = new batUpdExceptClient();
		Status s=theTests.run(args, System.out, System.err);
		s.exit();
	}

	/*
	 *   @class.setup_props: Driver, the Driver name;
	 *			db1, the database name with url;
	 *			user1, the database user name;
	 *			password1, the database password;
	 *			db2, the database name with url;
	 *			user2, the database user name;
	 *			password2, the database password;
	 *			DriverManager, flag for DriverManager;
	 *			ptable, the primary table;
	 *			ftable, the foreign table;
	 *			cofSize, the initial size of the ptable;
	 *			cofTypeSize, the initial size of the ftable;
	 *			binarySize, size of binary data type;
	 *			varbinarySize, size of varbinary data type;
	 *			longvarbinarySize, size of longvarbinary data type;
	 *  @class.testArgs:     -ap ctssql.stmt
	 */
	public void setup(String[] args,Properties p) throws Fault 
	{
		try 
		{
			try
			{
				drManager = p.getProperty("DriverManager","");
				if (drManager.length() == 0)
					throw new Fault("Invalid DriverManager Name");
				sUrl =  p.getProperty("db1","" );
				sUsr = p.getProperty("user1","" );
				sPass = p.getProperty("password1","" );
				sqlp=p;

				if(drManager.equals("yes"))
				{
					logMsg("Using DriverManager");
					DriverManagerConnection dmCon = new DriverManagerConnection();
					conn = dmCon.getConnection(p);
				}
				else 
				{
					logMsg("Using DataSource");
					DataSourceConnection dsCon = new DataSourceConnection();
					conn = dsCon.getConnection(p);
				}
				dbSch=new dbSchema();
				dbSch.createData(p,conn);
				dbmd=conn.getMetaData();
				supbatupdflag=dbmd.supportsBatchUpdates();
				logMsg("Driver Supports BatchUpdates  : " + supbatupdflag);
				if(!supbatupdflag)
				{
					logMsg("Driver does not support Batch Updates ");
					throw new Fault("Driver does not support Batch Updates ");
				}
				

				stmt=conn.createStatement();
				StringTokenizer sToken = null ;
				sReason = sqlp.getProperty("Reason_BatUpdExec");
				logMsg("Reason : " + sReason);
				sSqlState  = sqlp.getProperty("SQLState_BatUpdExec");
				logMsg("SQLState : " + sSqlState);
				sVendorCode = sqlp.getProperty("VendorCode_BatUpdExec");
				logMsg("VendorCode : " + sVendorCode);
				sIntialVal = sqlp.getProperty("IntialValue_BatUpdExec");
				logMsg("IntialVal : " + sIntialVal);
				sVendorCode = sVendorCode.trim();
				vendorCode = Integer.valueOf(sVendorCode).intValue();
				sIntialVal = sIntialVal.substring(sIntialVal.indexOf('{')+1,sIntialVal.lastIndexOf('}'));
				sToken = new StringTokenizer(sIntialVal,",");
				updateCount = new int[sToken.countTokens()] ;
				int i = 0 ;
				while(sToken.hasMoreTokens())
				{
					updateCount[i++] = Integer.parseInt(sToken.nextToken());
				}
			}
			catch(SQLException ex)
			{
				logErr("SQL Exception : " + ex.getMessage());
				throw new Fault("Set Up Failed");
			}
		} 
		catch ( Exception e ) 
		{
			logErr("Setup Failed!");
			TestUtil.printStackTrace(e);
			throw new Fault("Setup Failed");
		}
	}

	/*
	 * @testName:         testGetUpdateCounts
	 * @assertion:        The batch update facility provided by the JDBC 2.0 API 
	 *                    allows a statement object to submit multiple SQL commands 
	 *                    (except Select) together as a single batch to the DBMS.  
	 *                    If the command is a query which will return a ResultSet, 
	 *                    the method executeBatch should throw a BatchUpdateException.  
	 *                    (See section 40.1.6 JDBC 2.0 API Reference & Tutorial 2nd edition)
	 *                    
	 *                    The JDBC drivers must provide full support for batch updates.
	 *                    (See section 6.2.2.3 of Java2 Platform Enterprise Edition (J2EE) 
	 *                    Specification v1.2)
	 *                    
	 *                    The getUpdateCounts method returns an array of int containing
	 *                    the update counts for the updates that were executed 
	 *                    successfully before an error occured. (See JDK 1.2.2 API
	 *                    documentation).
	 *                    
	 * @test_Strategy:    Get a Statement object and call the addBatch() method 
	 *                    with 4 SQL statements ,out of which first 3 statements
	 *                    are insert,update and delete statements followed by 
	 *                    a select statement and call the executeBatch() method.
	 *                    This causes a BatchUpdateException being thrown and 
	 *                    getUpdateCounts() method on this BatchUpdateException 
	 *                    object should return an integer array of length 3 with each
	 *                    value indicating the number of corressponding rows 
	 *                    affected by execution of 3 SQL statements in the same order 
	 *                    as added to the batch.
	 *
	 */
	 
	public void testGetUpdateCounts() throws Fault 
	{
		try
		{
			isThrown = false ;
			loading(stmt);
		}
		catch(BatchUpdateException b)
		{
			isThrown = true ;
			boolean isFailure = false ;
			int retVal[] = b.getUpdateCounts(); 
			logMsg("The Length of return array " + retVal.length);
			logMsg("The Length of orginal array " + intialVal.length);
                        if(retVal.length < MAXUPDATECOUNT_ENTRIES) 
                        {
				for(int i = 0 ; i < retVal.length ; i++)
				{
					logMsg(retVal[i] + " " + intialVal[i]);
					if(intialVal[i] != retVal[i])
					{
						isFailure = true ;
						logErr(" getUpdateCount doesnot return the correct number of effected rows in the update count offset. ");
                                        	break;
					}
		 		   }
                        }
                        else if(retVal.length == MAXUPDATECOUNT_ENTRIES) 
                        {
				if(retVal[UPDATECOUNTERROR_LOCATION] != DRIVERCONTINUES_ERRORSTATE) 
				{
					isFailure = true;
					logErr( "Driver Continues after error but does not return an error state of " + DRIVERCONTINUES_ERRORSTATE + " in the correct update count offset. ");
				}
			} 
			else if(retVal.length > MAXUPDATECOUNT_ENTRIES) 
			{
				isFailure = true;
				logErr( "More entries returned in update count than queries executed. ");
                        }

			if(isFailure) 
			{
				throw new Fault("Call to getUpdateCounts is Failed!");
			} 
			else 
			{
				logMsg(" getUpdateCounts returns the number of rows affected ");
			}
		}
		catch(SQLException sqle)
		{
			logErr("SQL Exception " + sqle.getMessage());
			throw new Fault("Call to getUpdateCounts Failed!");
		}
		catch(Exception ex)
		{
			logErr("Unexpected Exception " + ex.getMessage());
			throw new Fault("Call to getUpdateCount Failed!");
		}
		if(!isThrown)
		{
			logErr("BatchUpdateException not thrown" );
			throw new Fault("Call to getUpdateCount Failed!");
		}
	}


	/*
	 *The methods adds the SQL statements to Statement object using 
	 *addBatch() method and sets the initialisation counter to the 
	 *number of statements added to the batch.
	 */
	public void loading(Statement stmt) throws java.sql.BatchUpdateException,java.sql.SQLException,java.lang.Exception
	{
		
		Statement state = conn.createStatement();
		int i = 0;
		ResultSet result = null ;
		boolean isReturn = false ; 
		String sInsCount = null;
		try
		{
			
			String sUpdCoffee = sqlp.getProperty("Coffee_UpdTab");
			String sDelCoffee = sqlp.getProperty("Coffee_DelTab");
			String sInsCoffee = sqlp.getProperty("Coffee_InsTab");
			String sSelCoffee = sqlp.getProperty("Coffee_SelTab");
			
			String sUpdCount = sqlp.getProperty("Coffee_Updcount_Query");
			String sDelCount = sqlp.getProperty("Coffee_Delcount_Query");
			sInsCount = sqlp.getProperty("Coffee_Inscount_Query");
			 
			result = state.executeQuery(sUpdCount);
			isReturn = result.next();
			if(isReturn)
			{
				intialVal[i++] = result.getInt(1);
			}
			
			result = state.executeQuery(sDelCount);
			isReturn =  result.next();
			if(isReturn)
			{
				intialVal[i++] = result.getInt(1);
			}

			stmt.addBatch(sUpdCoffee);
			logMsg(sUpdCoffee);
			
			stmt.addBatch(sDelCoffee);
			logMsg(sDelCoffee);
			
			stmt.addBatch(sInsCoffee);
			logMsg(sInsCoffee);
						
			stmt.addBatch(sSelCoffee);
			logMsg(sSelCoffee);
			
			stmt.executeBatch();
		}
		catch(BatchUpdateException e)
		{
			logMsg(e.toString());
			result = state.executeQuery(sInsCount);
			isReturn =  result.next();
			if(isReturn)
			{
				intialVal[i++] = result.getInt(1);
			}
			throw e;
		}
	}

	/*
	 * @testName:         testBatchUpdateException01
	 * @assertion:        The batch update facility provided by the JDBC 2.0 API 
	 *                    allows a statement object to submit multiple SQL commands 
	 *                    (except Select) together as a single batch to the DBMS.  
	 *                    If the command is a query which will return a ResultSet, 
	 *                    the method executeBatch should throw a BatchUpdateException.  
	 *                    (See section 40.1.6 JDBC 2.0 API Reference & Tutorial 2nd edition)
	 *                    
	 *                    The JDBC drivers must provide full support for batch updates.
	 *                    (See section 6.2.2.3 of Java2 Platform Enterprise Edition (J2EE) 
	 *                    Specification v1.2)
	 *                    
	 *                    The BatchUpdateException() constructor returns a 
	 *                    BatchUpdateException object initialized with null, null, null
	 *                    and 0. (See JDK 1.2.2 API documentation).
	 *                     
	 * @test_Strategy:    This method constructs a BatchUpdateException Object
	 *                    with no arguments and for that object the reason,
	 *                    SQLState,ErrorCode and updateCounts are checked for 
	 *                    default values.
	 */

	public void testBatchUpdateException01() throws Fault 
	{
		try
		{
			isThrown = false ;
			throw new BatchUpdateException();
		}
		catch(BatchUpdateException b)
		{
			isThrown = true ;
			if((b.getMessage() != null) || (b.getSQLState() != null) || (b.getErrorCode() != 0) || (b.getUpdateCounts() != null))
			{
				logErr("BatchUpdateException() Constructor Fails");
				throw new Fault("Call to BatchUpdateException() constructor Fails");
			}
			else
			{
				logMsg("BatchUpdateException() constructor is implemented");
			}
		}
		catch(Exception ex)
		{
			logErr("Unexpected Exception " + ex.getMessage());
			throw new Fault("Call to BatchUpdateException() constructor Fails");
		}
	
		if(!isThrown)
		{
			logErr("BatchUpdateException not thrown" );
			throw new Fault("Call to BatchUpdateException() constructor Fails");
		}
	}


	/*
	 * @testName:         testBatchUpdateException02
	 * @assertion:        The batch update facility provided by the JDBC 2.0 API 
	 *                    allows a statement object to submit multiple SQL commands 
	 *                    (except Select) together as a single batch to the DBMS.  
	 *                    If the command is a query which will return a ResultSet, 
	 *                    the method executeBatch should throw a BatchUpdateException.  
	 *                    (See section 40.1.6 JDBC 2.0 API Reference & Tutorial 2nd edition)
	 *                    
	 *                    The JDBC drivers must provide full support for batch updates.
	 *                    (See section 6.2.2.3 of Java2 Platform Enterprise Edition (J2EE) 
	 *                    Specification v1.2)
	 *                    
	 *                    The BatchUpdateException(int[] updcount) constructor returns a 
	 *                    BatchUpdateException object initialized with null, null, 0
	 *                    and updcount. (See JDK 1.2.2 API documentation).
	 *                     
	 * @test_Strategy:    This method constructs a BatchUpdateException Object
	 *                    with one argument and for that object the reason,
	 *                    SQLState,ErrorCode are checked for default values.The
	 *                    updateCount array is checked for whatever is been assigned
	 *                    while creating the new instance.
	 */


	public void testBatchUpdateException02() throws Fault 
	{
		try
		{
			isThrown = false ;
			throw new BatchUpdateException(updateCount);
		}
		catch(BatchUpdateException b)
		{
			isThrown = true ;
			if((b.getMessage() != null) || (b.getSQLState() != null) || (b.getErrorCode() != 0))
			{
				logErr("BatchUpdateException(int[]) Constructor Fails");
				throw new Fault("Call to BatchUpdateException(int []) Constructor Fails");	
			}
			else
			{
				if(!checkForUpdateCount(b.getUpdateCounts()))
				{
					logErr("BatchUpdateException(int []) Constructor Fails");
					throw new Fault("Call to BatchUpdateException(int []) Constructor Fails");
				}
				else
				{
					logMsg("BatchUpdateException(int []) Constructor is implemented");
				}
			}
		}
		catch(Exception ex)
		{
			logErr("Unexpected Exception " + ex.getMessage());
			throw new Fault("BatchUpdateException(int []) Constructor Fails");
		}
	
		if(!isThrown)
		{
			logErr("BatchUpdateException(int []) not thrown" );
			throw new Fault("BatchUpdateException(int []) Constructor Fails");
		}
	}


	/*
	 * @testName:         testBatchUpdateException03
	 * @assertion:        The batch update facility provided by the JDBC 2.0 API 
	 *                    allows a statement object to submit multiple SQL commands 
	 *                    (except Select) together as a single batch to the DBMS.  
	 *                    If the command is a query which will return a ResultSet, 
	 *                    the method executeBatch should throw a BatchUpdateException.  
	 *                    (See section 40.1.6 JDBC 2.0 API Reference & Tutorial 2nd edition)
	 *                    
	 *                    The JDBC drivers must provide full support for batch updates.
	 *                    (See section 6.2.2.3 of Java2 Platform Enterprise Edition (J2EE) 
	 *                    Specification v1.2)
	 *                    
	 *                    The BatchUpdateException(String reason, int[] updcount) 
	 *                    constructor returns a BatchUpdateException object initialized 
	 *                    with reason, null, 0 and updcount. 
	 *                    (See JDK 1.2.2 API documentation).
	 *                    
	 * @test_Strategy:    This method constructs a BatchUpdateException Object
	 *                    with two arguments and for that object. SQLState,ErrorCode 
	 *                    are checked for default values.The reason and updateCount 
	 *                    array is checked for whatever is been assigned while
	 *                    creating the new instance.
	 */
	 
	public void testBatchUpdateException03() throws Fault 
	{
		try
		{
			isThrown = false ;
			throw new BatchUpdateException(sReason,updateCount);
		}
		catch(BatchUpdateException b)
		{
			isThrown = true ;
			if((b.getSQLState() != null) || (b.getErrorCode() != 0))
			{
				logErr("BatchUpdateException(String,int []) Constructor Fails");
				throw new Fault("Call to BatchUpdateException(String,int []) constructor Fails");
			}
			else
			{
				if((!checkForUpdateCount(b.getUpdateCounts())) || (!sReason.equals(b.getMessage())))
				{
					logErr("BatchUpdateException(String,int []) Constructor Fails");
					throw new Fault("Call to BatchUpdateException(String,int []) constructor Fails");
				}
				else
				{
					logMsg("Call to BatchUpdateException(String,int []) constructor Passes");
				}
			}
		}
		catch(Exception ex)
		{
			logErr("Unexcepted Exception " + ex.getMessage());
			throw new Fault("Call to BatchUpdateException(String,int []) constructor Fails");
		}
	
		if(!isThrown)
		{
			logErr("Call to BatchUpdateException(String,int []) constructor Fails");
			throw new Fault("Call to BatchUpdateException(String,int []) constructor Fails");
		}
	}


	/*
	 * @testName:         testBatchUpdateException04
	 * @assertion:        The batch update facility provided by the JDBC 2.0 API 
	 *                    allows a statement object to submit multiple SQL commands 
	 *                    (except Select) together as a single batch to the DBMS.  
	 *                    If the command is a query which will return a ResultSet, 
	 *                    the method executeBatch should throw a BatchUpdateException.  
	 *                    (See section 40.1.6 JDBC 2.0 API Reference & Tutorial 2nd edition)
	 *                    
	 *                    The JDBC drivers must provide full support for batch updates.
	 *                    (See section 6.2.2.3 of Java2 Platform Enterprise Edition (J2EE) 
	 *                    Specification v1.2)
	 *                    
	 *                    The BatchUpdateException(String reason,String sqlst, int[] updcount) 
	 *                    constructor returns a BatchUpdateException object initialized 
	 *                    with reason, sqlst, 0 and updcount. 
	 *                    (See JDK 1.2.2 API documentation)
	 *                      
	 * @test_Strategy:    This method constructs a BatchUpdateException Object
	 *                    with three arguments and for that object. ErrorCode 
	 *                    is checked for default values.The reason,SQLState and 
	 *                    updateCount array is checked for whatever is been assigned 
	 *                    while creating the new instance.
	 */
	
	public void testBatchUpdateException04() throws Fault 
	{
		try
		{
			isThrown = false ;
			throw new BatchUpdateException(sReason,sSqlState,updateCount);
		}
		catch(BatchUpdateException b)
		{
			isThrown = true ;
			if((b.getErrorCode() != 0))
			{
				logErr("BatchUpdateException(string,string,int[]) Constructor Fails");
				throw new Fault("Call to BatchUpdateException(string,string,int[]) Constructor Fails");
			}
			else
			{
				if((!checkForUpdateCount(b.getUpdateCounts())) || (!sReason.equals(b.getMessage())) || (!sSqlState.equals(b.getSQLState())))
				{
					logErr("BatchUpdateException(string,string,int[]) Constructor Fails");
					throw new Fault("Call to BatchUpdateException(string,string,int[]) Constructor Fails");
				}
				else
				{
					logMsg("BatchUpdateException(string,string,int[]) Constructor is implemented");
				}
			}
		}
		catch(Exception ex)
		{
			logErr("UnexpectedException " + ex.getMessage());
			throw new Fault("Call to BatchUpdateException(string,string,int[]) Constructor Fails");
		}
	
		if(!isThrown)
		{
			logErr("BatchUpdateException(string,string,int[]) Constructor not thrown");
			throw new Fault("Call to BatchUpdateException(string,string,int[]) Constructor Fails");
		}
	}


	/*
	 * @testName:         testBatchUpdateException05
	 * @assertion:        The batch update facility provided by the JDBC 2.0 API 
	 *                    allows a statement object to submit multiple SQL commands 
	 *                    (except Select) together as a single batch to the DBMS.  
	 *                    If the command is a query which will return a ResultSet, 
	 *                    the method executeBatch should throw a BatchUpdateException.  
	 *                    (See section 40.1.6 JDBC 2.0 API Reference & Tutorial 2nd edition)
	 *                    
	 *                    The JDBC drivers must provide full support for batch updates.
	 *                    (See section 6.2.2.3 of Java2 Platform Enterprise Edition (J2EE) 
	 *                    Specification v1.2)
	 *                    
	 *                    BatchUpdateException(String rea,String sqlst,int vencod,int[] updcnt) 
	 *                    constructor returns a BatchUpdateException object initialized 
	 *                    with rea, sqlst, vencod and updcnt. 
	 *                    (See JDK 1.2.2 API documentation)
	 *                      
	 * @test_Strategy:    This method constructs a BatchUpdateException Object
	 *                    with four arguments The reason,SQLState ,ErrorCode and
	 *                    updateCount array is checked for whatever is been assigned 
	 *                    while creating the new instance.
	 */
	 
	public void testBatchUpdateException05() throws Fault 
	{
		try
		{
			isThrown = false ;
			throw new BatchUpdateException(sReason,sSqlState,vendorCode,updateCount);
		}
		catch(BatchUpdateException b)
		{
			isThrown = true ;
			if((!checkForUpdateCount(b.getUpdateCounts())) || (!sReason.equals(b.getMessage())) || (!sSqlState.equals(b.getSQLState())) || (!(vendorCode == b.getErrorCode())))
			{
				logErr("BatchUpdateException(string,string,int,int []) Constructor Fails");
				throw new Fault("Call to BatchUpdateException(string,string,int,int[]) Constructor Fails");
			}
			else
			{
				logMsg("BatchUpdateException(string,string,int,int []) Constructor is implemented");
			}
		}
		catch(Exception ex)
		{
			logErr("UnexpectedException " + ex.getMessage());
			throw new Fault("Call to BatchUpdateException(string,string,int,int[]) Constructor Fails");
		}
	
		if(!isThrown)
		{
			logErr("BatchUpdateException(string,string,int,int[]) Constructor Fails");
			throw new Fault("Call to BatchUpdateException(string,string,int,int[]) Constructor Fails");
		}
	}


	/*
	 * This method is used for checking each element of the updateCount array 
	 * and the Return array.It returns true if all elements matches or else it
	 * returns false .
	 */
	public boolean checkForUpdateCount(int[] retVal)
	{
		for(int i = 0 ; i < retVal.length ; i++)
		{
			logMsg("IntialVal : " + updateCount[i] + " ReturnVal :" + retVal[i]);
			if(updateCount[i] != retVal[i])
				return false ;
		}
		
		return true ;
	}


	/* cleanup */
	public void  cleanup() throws Fault
	{
		try
		{
			stmt.close();
			dbSch.destroyData(conn);
			// Close the database 
			dbSch.dbUnConnect(conn);
			logMsg("Cleanup ok;");
		}
		catch(Exception e)
		{
			logErr("An error occurred while closing the database connection");
		}
	}
}

