/*
 * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
 * agreements. See the NOTICE file distributed with this work for additional information regarding
 * copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance with the License. You may obtain a
 * copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the License
 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
 * or implied. See the License for the specific language governing permissions and limitations under
 * the License.
 */
/*
 * CacheJUnitTest.java JUnit based test
 *
 * Created on March 28, 2005, 10:59 AM
 */
package org.apache.geode.internal.jta.functional;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

import javax.naming.Context;
import javax.naming.NamingException;
import javax.sql.DataSource;
import javax.transaction.UserTransaction;

import org.apache.logging.log4j.Logger;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import org.apache.geode.cache.AttributesFactory;
import org.apache.geode.cache.Cache;
import org.apache.geode.cache.CacheException;
import org.apache.geode.cache.CacheExistsException;
import org.apache.geode.cache.CacheFactory;
import org.apache.geode.cache.CacheLoader;
import org.apache.geode.cache.CacheLoaderException;
import org.apache.geode.cache.LoaderHelper;
import org.apache.geode.cache.Region;
import org.apache.geode.distributed.internal.InternalDistributedSystem;
import org.apache.geode.internal.jta.CacheUtils;
import org.apache.geode.internal.jta.JTAUtils;
import org.apache.geode.logging.internal.log4j.api.LogService;

/**
 * This JUnit version is created from class org.apache.geode.internal.jta.functional.CacheTest1.
 * Tests functional behavior. Assumes that CacheUtils.java always creates table(s) and inserts data
 * in the form: 1 => name1, 2 => name2, 3 => name3...as the values of ID and name fields
 * respectively. Test # 15 & 16 has the dependency to run on CloudScape database only due to
 * variations in DDL.
 *
 */
public class CacheJUnitTest {

  private static final Logger logger = LogService.getLogger();

  private Region currRegion;
  private Cache cache;
  private int tblIDFld;
  private String tblNameFld;
  private String tblName;

  @Before
  public void setUp() throws Exception {
    this.tblName = CacheUtils.init("CacheJUnitTest");
    assertFalse(this.tblName == null || this.tblName.equals(""));

    this.cache = CacheUtils.getCache();
    assertNotNull(this.cache);

    this.currRegion = this.cache.getRegion("root");
    assertTrue(this.currRegion.getFullPath().equals("/root"));
  }

  @After
  public void tearDown() throws java.lang.Exception {
    try {
      CacheUtils.closeCache();
      CacheUtils.destroyTable(this.tblName);
    } finally {
      InternalDistributedSystem ids = InternalDistributedSystem.getAnyInstance();
      if (ids != null) {
        ids.disconnect();
      }
    }
  }

  /**
   * Test of testScenario1 method, of class org.apache.geode.internal.jta.functional.CacheTest1.
   * Tests a simple User Transaction with Cache lookup.
   */
  @Test
  public void testScenario1() throws Exception {
    this.tblIDFld = 1;
    this.tblNameFld = "test1";
    JTAUtils jtaObj = new JTAUtils(cache, currRegion);

    jtaObj.deleteRows(this.tblName);

    Context ctx = cache.getJNDIContext();
    UserTransaction ta = (UserTransaction) ctx.lookup("java:/UserTransaction");
    Connection conn = null;

    try {
      ta.begin();

      DataSource da = (DataSource) ctx.lookup("java:/XAPooledDataSource");

      conn = da.getConnection();

      Statement stmt = conn.createStatement();

      String sqlSTR = "insert into " + this.tblName + " values (" + this.tblIDFld + "," + "'"
          + this.tblNameFld + "'" + ")";
      stmt.executeUpdate(sqlSTR);

      stmt.close();
      ta.commit();
      conn.close();
    } catch (NamingException e) {
      ta.rollback();
      fail(" failed " + e.getMessage());
    } catch (SQLException e) {
      ta.rollback();
      fail(" failed " + e.getMessage());
    } catch (Exception e) {
      ta.rollback();
      fail(" failed " + e.getMessage());
    } finally {
      if (conn != null)
        try {
          conn.close();
        } catch (SQLException ex) {
          fail("SQL exception: " + ex.getMessage());
        }
    }
  }

  /**
   * Test of testScenario2 method, of class org.apache.geode.internal.jta.functional.CacheTest1.
   * Tests a simple User Transaction with Cache lookup but closing the Connection object before
   * committing the Transaction.
   */
  @Test
  public void testScenario2() throws Exception {
    this.tblIDFld = 2;
    this.tblNameFld = "test2";
    boolean rollback_chances = true;

    JTAUtils jtaObj = new JTAUtils(cache, currRegion);

    jtaObj.deleteRows(this.tblName);

    Context ctx = cache.getJNDIContext();
    System.out.print(" looking up UserTransaction... ");
    UserTransaction ta = (UserTransaction) ctx.lookup("java:/UserTransaction");
    Connection conn = null;

    try {
      ta.begin();

      DataSource da = (DataSource) ctx.lookup("java:/XAPooledDataSource");

      conn = da.getConnection();

      Statement stmt = conn.createStatement();

      String sqlSTR = "insert into " + this.tblName + " values (" + this.tblIDFld + "," + "'"
          + this.tblNameFld + "'" + ")";
      stmt.executeUpdate(sqlSTR);

      stmt.close();
      conn.close();
      ta.commit();

      rollback_chances = false;

      int ifAnyRows = jtaObj.getRows(this.tblName);
      if (ifAnyRows == 0) {
        // no rows are there !!! failure :)
        fail(" no rows retrieved even after txn commit after conn close.");
      }

    } catch (NamingException e) {
      if (rollback_chances)
        ta.rollback();
      fail(" failed " + e.getMessage());
    } catch (SQLException e) {
      if (rollback_chances)
        ta.rollback();
      fail(" failed " + e.getMessage());
    } catch (Exception e) {
      ta.rollback();
      fail(" failed " + e.getMessage());
    } finally {
      if (conn != null)
        try {
          conn.close();
        } catch (SQLException e) {
        }
    }
  }

  /**
   * Test of testScenario3 method, of class org.apache.geode.internal.jta.functional.CacheTest1.
   * Tests whether a user transaction with cache lookup and with XAPooledDataSOurce supports Cache
   * put and get operations accordingly. Put and get are done within the transaction block and also
   * db updates are done. After committing we check whether commit is proper in db and also in
   * Cache.
   */
  @Test
  public void testScenario3() throws Exception {
    this.tblIDFld = 3;
    this.tblNameFld = "test3";
    boolean rollback_chances = true;
    final String DEFAULT_RGN = "root";

    JTAUtils jtaObj = new JTAUtils(cache, currRegion);

    jtaObj.deleteRows(this.tblName);

    Context ctx = cache.getJNDIContext();
    UserTransaction ta = (UserTransaction) ctx.lookup("java:/UserTransaction");
    Connection conn = null;

    try {
      /** begin the transaction **/
      ta.begin();

      String current_region = jtaObj.currRegion.getName();
      assertEquals("the default region is not root", DEFAULT_RGN, current_region);

      jtaObj.getRegionFromCache("region1");

      String current_fullpath = jtaObj.currRegion.getFullPath();
      assertEquals("failed retrieving current region fullpath", "/" + DEFAULT_RGN + "/region1",
          current_fullpath);

      jtaObj.put("key1", "value1");

      String str = jtaObj.get("key1");
      String tok = jtaObj.parseGetValue(str);
      assertEquals("get failed for corresponding put", "\"value1\"", tok);

      current_fullpath = jtaObj.currRegion.getFullPath();
      assertEquals("failed retrieving current region fullpath", "/" + DEFAULT_RGN + "/region1",
          current_fullpath);

      DataSource da = (DataSource) ctx.lookup("java:/XAPooledDataSource");

      conn = da.getConnection();

      Statement stmt = conn.createStatement();

      String sqlSTR = "insert into " + this.tblName + " values (" + this.tblIDFld + "," + "'"
          + this.tblNameFld + "'" + ")";
      stmt.executeUpdate(sqlSTR);

      stmt.close();
      ta.commit();
      conn.close();

      rollback_chances = false;

      current_fullpath = jtaObj.currRegion.getFullPath();
      assertEquals("failed retrieving current region fullpath after txn commit",
          "/" + DEFAULT_RGN + "/region1", current_fullpath);

      int ifAnyRows = jtaObj.getRows(this.tblName);
      assertEquals("rows retrieved is:" + ifAnyRows, 1, ifAnyRows);
      /*
       * if (ifAnyRows == 0) { fail (" DB FAILURE: no rows retrieved even after txn commit."); }
       */
      // after jdbc commit cache value in region1 for key1 must retain...
      str = jtaObj.get("key1");
      tok = jtaObj.parseGetValue(str);
      assertEquals("cache put didn't commit, value retrieved is: " + tok, "\"value1\"", tok);
    } catch (CacheExistsException e) {
      ta.rollback();
      fail(" test 3 failed ");
    } catch (NamingException e) {
      if (rollback_chances)
        ta.rollback();
      fail(" test 3 failed " + e.getMessage());
    } catch (SQLException e) {
      if (rollback_chances)
        ta.rollback();
      fail(" test 3 failed " + e.getMessage());
    } catch (Exception e) {
      if (rollback_chances)
        ta.rollback();
      fail(" test 3 failed " + e.getMessage());
    } finally {
      if (conn != null)
        try {
          conn.close();
        } catch (SQLException e) {
        }
    }
  }

  /**
   * Test of testScenario4 method, of class org.apache.geode.internal.jta.functional.CacheTest1.
   * Tests whether a user transaction with cache lookup and with XAPooledDataSOurce supports Cache
   * put and get operations accordingly along with JTA behavior. Put and get are done within the
   * transaction block and also db updates are done. After rollback the transaction explicitly we
   * check whether it was proper in db and also in Cache, which should also rollback.
   */
  @Test
  public void testScenario4() throws Exception {
    this.tblIDFld = 4;
    this.tblNameFld = "test4";
    boolean rollback_chances = true;
    final String DEFAULT_RGN = "root";

    JTAUtils jtaObj = new JTAUtils(cache, currRegion);

    jtaObj.deleteRows(this.tblName);

    Context ctx = cache.getJNDIContext();
    UserTransaction ta = (UserTransaction) ctx.lookup("java:/UserTransaction");
    Connection conn = null;

    try {
      String current_region = jtaObj.currRegion.getName();
      assertEquals("default region is not root", DEFAULT_RGN, current_region);

      jtaObj.getRegionFromCache("region1");
      String current_fullpath = jtaObj.currRegion.getFullPath();
      assertEquals(
          "failed retrieving current region fullpath after doing getRegionFromCache(region1)",
          "/" + DEFAULT_RGN + "/region1", current_fullpath);

      jtaObj.put("key1", "test");
      ta.begin();

      jtaObj.put("key1", "value1");
      String str = jtaObj.get("key1");
      String tok = jtaObj.parseGetValue(str);
      assertEquals("get value do not match with the put", "\"value1\"", tok);

      current_fullpath = jtaObj.currRegion.getFullPath();
      assertEquals("failed retrieving current region fullpath", "/" + DEFAULT_RGN + "/region1",
          current_fullpath);

      DataSource da = (DataSource) ctx.lookup("java:/XAPooledDataSource");

      conn = da.getConnection();
      Statement stmt = conn.createStatement();

      String sqlSTR = "insert into " + this.tblName + " values (" + this.tblIDFld + "," + "'"
          + this.tblNameFld + "'" + ")";
      stmt.executeUpdate(sqlSTR);

      stmt.close();
      ta.rollback();
      conn.close();

      rollback_chances = false;

      current_fullpath = jtaObj.currRegion.getFullPath();
      assertEquals("failed retirieving current region fullpath after txn rollback",
          "/" + DEFAULT_RGN + "/region1", current_fullpath);

      int ifAnyRows = jtaObj.getRows(this.tblName);
      assertEquals("rows retrieved is: " + ifAnyRows, 0, ifAnyRows);
      /*
       * if (ifAnyRows != 0) { fail (" DB FAILURE"); }
       */
      str = jtaObj.get("key1");
      tok = jtaObj.parseGetValue(str);
      assertEquals("value existing in cache is: " + tok, "\"test\"", tok);
    } catch (CacheExistsException e) {
      ta.rollback();
      fail(" failed " + e.getMessage());
    } catch (NamingException e) {
      if (rollback_chances)
        ta.rollback();
      fail(" failed " + e.getMessage());
    } catch (SQLException e) {
      if (rollback_chances)
        ta.rollback();
      fail(" failed " + e.getMessage());
    } catch (Exception e) {
      if (rollback_chances)
        ta.rollback();
      fail(" failed " + e.getMessage());
    } finally {
      if (conn != null)
        try {
          conn.close();
        } catch (SQLException e) {
        }
    }
  }

  /**
   * Test of testScenario5 method, of class org.apache.geode.internal.jta.functional.CacheTest1.
   * Tests whether a user transaction with cache lookup and with XAPooledDataSOurce supports Cache
   * put and get operations accordingly along with JTA behavior. Put and get are done within the
   * transaction block and also db updates are done. We try to rollback the transaction by violating
   * primary key constraint in db table, nad then we check whether rollback was proper in db and
   * also in Cache, which should also rollback.
   */
  @Test
  public void testScenario5() throws Exception {
    this.tblIDFld = 5;
    this.tblNameFld = "test5";
    boolean rollback_chances = false;
    final String DEFAULT_RGN = "root";

    JTAUtils jtaObj = new JTAUtils(cache, currRegion);

    jtaObj.deleteRows(this.tblName);

    Context ctx = cache.getJNDIContext();
    UserTransaction ta = (UserTransaction) ctx.lookup("java:/UserTransaction");
    Connection conn = null;

    try {
      String current_region = jtaObj.currRegion.getName();
      assertEquals("default region is not root", DEFAULT_RGN, current_region);

      // trying to create a region 'region1' under /root, if it doesn't exist.
      // And point to the new region...
      jtaObj.getRegionFromCache("region1");

      // now current region should point to region1, as done from within
      // getRegionFromCache method...
      String current_fullpath = jtaObj.currRegion.getFullPath();
      assertEquals("failed retirieving current fullpath", "/" + DEFAULT_RGN + "/region1",
          current_fullpath);

      jtaObj.put("key1", "test");
      ta.begin();

      jtaObj.put("key1", "value1");

      String str = jtaObj.get("key1");
      String tok = jtaObj.parseGetValue(str);
      assertEquals("get value mismatch with put", "\"value1\"", tok);

      current_fullpath = jtaObj.currRegion.getFullPath();
      assertEquals("failed retrieving current fullpath, current fullpath: " + current_fullpath,
          "/" + DEFAULT_RGN + "/region1", current_fullpath);

      DataSource da = (DataSource) ctx.lookup("java:/XAPooledDataSource");

      conn = da.getConnection();
      Statement stmt = conn.createStatement();

      String sqlSTR = "insert into " + this.tblName + " values (" + this.tblIDFld + "," + "'"
          + this.tblNameFld + "'" + ")";
      stmt.executeUpdate(sqlSTR);

      rollback_chances = true;

      // capable of throwing SQLException during insert operation
      sqlSTR = "insert into " + this.tblName + " values (" + this.tblIDFld + "," + "'"
          + this.tblNameFld + "'" + ")";
      stmt.executeUpdate(sqlSTR);

      stmt.close();
      ta.commit();
      conn.close();
    } catch (CacheExistsException e) {
      ta.rollback();
      fail("test failed " + e.getMessage());
    } catch (NamingException e) {
      ta.rollback();
      fail("test failed " + e.getMessage());
    } catch (SQLException e) {
      // exception thrown during inserts are handeled as below by rollback
      if (rollback_chances) {
        try {
          ta.rollback();
        } catch (Exception ex) {
          fail("failed: " + ex.getMessage());
        }

        // intended error is checked w.r.t database first
        int ifAnyRows = 0;
        try {
          ifAnyRows = jtaObj.getRows(this.tblName);
        } catch (Exception ex) {
          fail(" failed: " + ex.getMessage());
        }
        assertEquals("rows found after rollback is: " + ifAnyRows, 0, ifAnyRows);
        /*
         * if (ifAnyRows != 0) { fail (" DB FAILURE"); }
         */
        // intended error is checked w.r.t. cache second
        String current_fullpath = jtaObj.currRegion.getFullPath();
        assertEquals(
            "failed retrieving current fullpath after rollback, fullpath is: " + current_fullpath,
            "/" + DEFAULT_RGN + "/region1", current_fullpath);

        // after jdbc rollback, cache value in region1 for key1 must vanish...
        String str1 = null;
        try {
          str1 = jtaObj.get("key1");
        } catch (CacheException ex) {
          fail("failed getting value for 'key1': " + ex.getMessage());
        }

        String tok1 = jtaObj.parseGetValue(str1);
        assertEquals("value found in cache: " + tok1 + ", after rollback", "\"test\"", tok1);
      } else {
        fail(" failed: " + e.getMessage());
        ta.rollback();
      }
    } catch (Exception e) {
      ta.rollback();
      fail(" failed: " + e.getMessage());
    } finally {
      if (conn != null)
        try {
          conn.close();
        } catch (SQLException ex) {
          fail("Exception: " + ex.getMessage());
        }
    }
  }

  /**
   * Test of testScenario7 method, of class org.apache.geode.internal.jta.functional.CacheTest1.
   * Tests a user transaction with cache lookup and with XAPooledDataSource lookup. It does get and
   * put operations on the cache within the transaction block and checks whether these operations
   * are committed once the transaction is committed.
   */
  @Test
  public void testScenario7() throws Exception {
    this.tblIDFld = 7;
    this.tblNameFld = "test7";
    boolean rollback_chances = true;
    final String DEFAULT_RGN = "root";

    JTAUtils jtaObj = new JTAUtils(cache, currRegion);

    jtaObj.deleteRows(this.tblName);

    Context ctx = cache.getJNDIContext();
    UserTransaction ta = (UserTransaction) ctx.lookup("java:/UserTransaction");
    Connection conn = null;

    try {
      ta.begin();

      String current_region = jtaObj.currRegion.getName();
      assertEquals("default region is not root", DEFAULT_RGN, current_region);

      jtaObj.getRegionFromCache("region1");

      // now current region should point to region1, as done from within
      // getRegionFromCache method...
      String current_fullpath = jtaObj.currRegion.getFullPath();
      assertEquals("failed retrieving the current region fullpath", "/" + DEFAULT_RGN + "/region1",
          current_fullpath);

      jtaObj.put("key1", "value1");

      // try to get value1 from key1 in the same region
      String str = jtaObj.get("key1");
      String tok = jtaObj.parseGetValue(str);
      assertEquals("get value mismatch with put", "\"value1\"", tok);

      current_fullpath = jtaObj.currRegion.getFullPath();
      assertEquals("failed retrieving current region fullpath", "/" + DEFAULT_RGN + "/region1",
          current_fullpath);

      DataSource da = (DataSource) ctx.lookup("java:/XAPooledDataSource");

      conn = da.getConnection();
      ta.commit();
      conn.close();

      rollback_chances = false;

      current_fullpath = jtaObj.currRegion.getFullPath();
      assertEquals("failed retrieving current region fullpath after txn commit, fullpath is: "
          + current_region, "/" + DEFAULT_RGN + "/region1", current_fullpath);

      str = jtaObj.get("key1");
      tok = jtaObj.parseGetValue(str);
      assertEquals("cache value found is: " + tok, "\"value1\"", tok);

    } catch (CacheExistsException e) {
      if (rollback_chances)
        ta.rollback();
      fail(" failed due to: " + e.getMessage());
    } catch (NamingException e) {
      ta.rollback();
      fail(" failed due to: " + e.getMessage());
    } catch (SQLException e) {
      ta.rollback();
      fail(" failed due to: " + e.getMessage());
    } catch (Exception e) {
      if (rollback_chances)
        ta.rollback();
      fail(" failed due to: " + e.getMessage());
    } finally {
      if (conn != null)
        try {
          conn.close();
        } catch (Exception e) {
        }
    }
  }

  /**
   * Test of testScenario9 method, of class org.apache.geode.internal.jta.functional.CacheTest1.
   * Tests a user transaction with cache lookup and with XAPooledDataSource lookup performing a db
   * update within the transaction block and committing the transaction. Then agin we perform
   * another db update with the same DataSource and finally close the Connection. The first update
   * only should be committed in db and the second will not participate in transaction throwing an
   * SQLException.
   */
  @Test
  public void testScenario9() throws Exception {
    this.tblIDFld = 9;
    this.tblNameFld = "test9";
    boolean rollback_chances = true;
    int first_field = this.tblIDFld;

    JTAUtils jtaObj = new JTAUtils(cache, currRegion);

    // delete the rows inserted from CacheUtils createTable, otherwise conflict
    // in PK's
    jtaObj.deleteRows(this.tblName);

    Context ctx = cache.getJNDIContext();
    UserTransaction ta = (UserTransaction) ctx.lookup("java:/UserTransaction");
    Connection conn = null;

    try {
      ta.begin();

      DataSource da = (DataSource) ctx.lookup("java:/XAPooledDataSource");
      conn = da.getConnection();
      Statement stmt = conn.createStatement();

      String sqlSTR = "insert into " + this.tblName + " values (" + this.tblIDFld + "," + "'"
          + this.tblNameFld + "'" + ")";
      stmt.executeUpdate(sqlSTR);
      ta.commit();

      rollback_chances = false;

      // intended test for failure-- capable of throwing SQLException
      this.tblIDFld += 1;
      sqlSTR = "insert into " + this.tblName + " values (" + this.tblIDFld + "," + "'"
          + this.tblNameFld + "'" + ")";
      stmt.executeUpdate(sqlSTR);

      stmt.close();
      conn.close();

      rollback_chances = true;
    } catch (NamingException e) {
      fail(" failed due to: " + e.getMessage());
      ta.rollback();
    } catch (SQLException e) {
      if (!rollback_chances) {
        int ifAnyRows = jtaObj.getRows(this.tblName);
        assertEquals("rows found is: " + ifAnyRows, 1, ifAnyRows);
        boolean matched = jtaObj.checkTableAgainstData(this.tblName, first_field + ""); // first
                                                                                        // field
                                                                                        // must
                                                                                        // be
                                                                                        // there.
        assertEquals("first entry to db is not found", true, matched);
      } else {
        ta.rollback();
        fail(" failed due to: " + e.getMessage());
      }
    } catch (Exception e) {
      fail(" failed due to: " + e.getMessage());
      if (rollback_chances) {
        ta.rollback();
      }
    } finally {
      if (conn != null)
        try {
          conn.close();
        } catch (SQLException e) {
        }
    }
  }

  /**
   * Test of testScenario10 method, of class org.apache.geode.internal.jta.functional.CacheTest1.
   * Test a user transaction with cache lookup and with XAPooledDataSource for multiple JDBC
   * Connections. This should not be allowed for Facets datasource. For other relational DB the
   * behaviour will be DB specific. For Oracle DB, n connections in a tranxn can be used provided ,
   * n-1 connections are closed before opening nth connection.
   */
  @Test
  public void testScenario10() throws Exception {
    this.tblIDFld = 10;
    this.tblNameFld = "test10";
    int rows_inserted = 0;
    int ifAnyRows = 0;
    int field1 = this.tblIDFld, field2 = 0;

    JTAUtils jtaObj = new JTAUtils(cache, currRegion);

    jtaObj.deleteRows(this.tblName);

    Context ctx = cache.getJNDIContext();
    UserTransaction ta = (UserTransaction) ctx.lookup("java:/UserTransaction");
    Connection conn1 = null;
    Connection conn2 = null;

    try {
      ta.begin();
      DataSource da = (DataSource) ctx.lookup("java:/XAPooledDataSource");
      conn1 = da.getConnection(); // the first Connection

      Statement stmt = conn1.createStatement();

      String sqlSTR = "insert into " + this.tblName + " values (" + this.tblIDFld + "," + "'"
          + this.tblNameFld + "'" + ")";
      stmt.executeUpdate(sqlSTR);
      rows_inserted += 1;

      conn1.close();

      conn2 = da.getConnection(); // the second Connection
      stmt = conn2.createStatement();

      this.tblIDFld += 1;
      field2 = this.tblIDFld;
      sqlSTR = "insert into " + this.tblName + " values (" + this.tblIDFld + "," + "'"
          + this.tblNameFld + "'" + ")";

      stmt.executeUpdate(sqlSTR);
      rows_inserted += 1;

      stmt.close();
      conn2.close();
      ta.commit();

      // if we reach here check for proper entries in db
      ifAnyRows = jtaObj.getRows(this.tblName);
      if (ifAnyRows == rows_inserted) {
        boolean matched1 = jtaObj.checkTableAgainstData(this.tblName, (field1 + ""));
        boolean matched2 = jtaObj.checkTableAgainstData(this.tblName, (field2 + ""));

        if (matched1)
          System.out.print("(PK " + field1 + "found ");
        else
          System.out.print("(PK " + field1 + "not found ");
        if (matched2)
          System.out.print("PK " + field2 + "found)");
        else
          System.out.print("PK " + field2 + "not found)");

        if (matched1 & matched2) {
          System.out.println("ok");
        } else {
          fail(" inserted data not found in DB !... failed");
        }
      } else {
        fail(" test interrupted, rows found=" + ifAnyRows + ", rows inserted=" + rows_inserted);
      }
    } catch (NamingException e) {
      ta.rollback();
    } catch (SQLException e) {
      ta.rollback();
    } catch (Exception e) {
      ta.rollback();
    } finally {
      if (conn1 != null)
        try {
          conn1.close();
        } catch (SQLException e) {
        }

      if (conn2 != null)
        try {
          conn2.close();
        } catch (SQLException e) {
        }
    }

  }

  /**
   * Test of testScenario11 method, of class org.apache.geode.internal.jta.functional.CacheTest1.
   * Tests Simple DataSource lookup within a transaction. Things should not participate in the
   * transaction.
   */
  @Test
  public void testScenario11() throws Exception {
    this.tblIDFld = 11;
    this.tblNameFld = "test11";
    boolean rollback_chances = false;

    JTAUtils jtaObj = new JTAUtils(cache, currRegion);

    jtaObj.deleteRows(this.tblName);

    Context ctx = cache.getJNDIContext();
    UserTransaction ta = (UserTransaction) ctx.lookup("java:/UserTransaction");
    Connection conn = null;

    try {
      ta.begin();
      DataSource da = (DataSource) ctx.lookup("java:/SimpleDataSource");

      conn = da.getConnection();
      Statement stmt = conn.createStatement();

      String sqlSTR = "insert into " + this.tblName + " values (" + this.tblIDFld + "," + "'"
          + this.tblNameFld + "'" + ")";
      stmt.executeUpdate(sqlSTR);

      rollback_chances = true;

      // try insert the same data once more and see if all info gets rolled
      // back...
      // capable of throwing SQLException
      sqlSTR = "insert into " + this.tblName + " values (" + this.tblIDFld + "," + "'"
          + this.tblNameFld + "'" + ")";
      stmt.executeUpdate(sqlSTR);

      stmt.close();
      ta.commit();
      conn.close();
    } catch (NamingException e) {
      ta.rollback();
    } catch (SQLException e) {
      if (rollback_chances) {
        try {
          ta.rollback();
        } catch (Exception ex) {
          fail("failed due to : " + ex.getMessage());
        }

        // try to check in the db whether any rows (the first one) are there
        // now...
        int ifAnyRows = jtaObj.getRows(this.tblName);
        assertEquals("first row not found in case of Simple Datasource", 1, ifAnyRows); // one
                                                                                        // row--
                                                                                        // the
                                                                                        // first
                                                                                        // one
                                                                                        // shud
                                                                                        // be
                                                                                        // there.
        boolean matched = jtaObj.checkTableAgainstData(this.tblName, this.tblIDFld + ""); // checking
                                                                                          // the
                                                                                          // existence
                                                                                          // of
                                                                                          // first
                                                                                          // row
        assertEquals("first row PK didn't matched", true, matched);
      } else {
        ta.rollback();
      }

    } catch (Exception e) {
      fail(" failed due to: " + e.getMessage());
      ta.rollback();
    } finally {
      if (conn != null)
        try {
          conn.close();
        } catch (SQLException e) {
        }
    }

  }

  /**
   * Test of testScenario14 method, of class org.apache.geode.internal.jta.functional.CacheTest1.
   * Tests a local Cache Loader with XADataSource lookup to get the connection. The Connection
   * should not participate in the transaction and commit/rollback should take affect accordingly
   * along with cache.
   */
  @Test
  public void testScenario14() throws Exception {
    final String TABLEID = "2";
    // final String TABLEFLD = "name2";
    JTAUtils jtaObj = new JTAUtils(cache, currRegion);

    Context ctx = cache.getJNDIContext();
    UserTransaction utx = (UserTransaction) ctx.lookup("java:/UserTransaction");
    utx.begin();
    AttributesFactory fac = new AttributesFactory(currRegion.getAttributes());
    fac.setCacheLoader(new XACacheLoaderTxn(this.tblName));
    Region re = currRegion.createSubregion("employee", fac.create());
    String retVal = (String) re.get(TABLEID); // TABLEID correspondes to
                                              // "name1".
    if (!retVal.equals("newname"))
      fail("Uncommitted value 'newname' not read by cacheloader name = " + retVal);
    utx.rollback();

    DataSource ds = (DataSource) ctx.lookup("java:/XAPooledDataSource");
    Connection conn = ds.getConnection();
    Statement stm = conn.createStatement();
    String str = "select name from " + tblName + "  where id= (2)";
    ResultSet rs = stm.executeQuery(str);
    rs.next();
    String str1 = rs.getString(1);
    if (!str1.equals("name2"))
      fail("Rollback not occurred on XAConnection got in a cache loader");
  }

  /**
   * Test of testScenario15 method, of class org.apache.geode.internal.jta.functional.CacheTest1.
   * Tests performing DDL operations by looking up a XAPooledDataSource and without transaction.
   */
  @Test
  public void testScenario15() throws Exception {
    this.tblIDFld = 15;
    this.tblNameFld = "test15";
    String tbl = "";
    boolean row_num = true;
    int ddl_return = 1;

    JTAUtils jtaObj = new JTAUtils(cache, currRegion);
    // delete the rows inserted from CacheUtils createTable, otherwise conflict
    // in PK's. Basically not needed for this test
    jtaObj.deleteRows(this.tblName);

    Context ctx = cache.getJNDIContext();
    // UserTransaction ta = null;
    Connection conn = null;
    Statement stmt = null;
    /*
     * try { ta = (UserTransaction)ctx.lookup("java:/UserTransaction");
     *
     * } catch (NamingException e) { fail ("user txn lookup failed: " + e.getMessage ()); }
     */

    try {
      DataSource da = (DataSource) ctx.lookup("java:/XAPooledDataSource");
      conn = da.getConnection();
      stmt = conn.createStatement();

      // Do some DDL stuff
      String time = new Long(System.currentTimeMillis()).toString();
      tbl = "my_table" + time;
      // String sql = "create table " + tbl +
      // " (my_id number primary key, my_name varchar2(50))";
      String sql = "create table " + tbl
          + " (my_id integer NOT NULL, my_name varchar(50), CONSTRAINT my_keyx PRIMARY KEY(my_id))";
      ddl_return = stmt.executeUpdate(sql);

      // check whether the table was created properly
      sql = "select * from " + tbl;
      ResultSet rs = null;
      rs = stmt.executeQuery(sql);
      row_num = rs.next();
      rs.close();
      if (ddl_return == 0 && !row_num) {
        sql = "drop table " + tbl;
        try {
          stmt = conn.createStatement();
          stmt.executeUpdate(sql);
        } catch (SQLException e) {
          fail(" failed to drop, " + e.getMessage());
        }
      } else
        fail("unable to create table");

      /** Code meant for Oracle DB **/
      /*
       * tbl = tbl.toUpperCase(); sql = "select * from tab where tname like '%tbl%'"; ResultSet rs =
       * null; rs = stmt.executeQuery(sql); rs.close(); sql = "drop table "+tbl; stmt =
       * conn.createStatement(); stmt.execute(sql); System.out.println (this.space + "ok");
       */
      stmt.close();
      conn.close();

    } catch (NamingException e) {
      fail("failed, " + e.getMessage());
    } catch (SQLException e) {
      fail("failed, " + e.getMessage());
    } catch (Exception e) {
      fail("failed, " + e.getMessage());
    } finally {
      if (conn != null)
        conn.close();
    }
  }

  /**
   * Test of testScenario16 method, of class org.apache.geode.internal.jta.functional.CacheTest1.
   * Tests DDL operations on XAPooledDataSOurce lookup, without transaction but making auto commit
   * false just before performing DDL queries and making it true before closing the Connection. The
   * operations should be committed.
   */
  @Test
  public void testScenario16() throws Exception {
    this.tblIDFld = 16;
    this.tblNameFld = "test16";
    String tbl = "";
    int ddl_return = 1;
    boolean row_num = true;

    JTAUtils jtaObj = new JTAUtils(cache, currRegion);

    jtaObj.deleteRows(this.tblName);

    Context ctx = cache.getJNDIContext();
    Connection conn = null;
    Statement stmt = null;

    try {
      DataSource da = (DataSource) ctx.lookup("java:/XAPooledDataSource");
      conn = da.getConnection();
      conn.setAutoCommit(false);
      stmt = conn.createStatement();

      String time = new Long(System.currentTimeMillis()).toString();
      tbl = "my_table" + time;
      // String sql = "create table " + tbl +
      // " (my_id number primary key, my_name varchar2(50))";
      String sql = "create table " + tbl
          + " (my_id integer NOT NULL, my_name varchar(50), CONSTRAINT my_key PRIMARY KEY(my_id))";
      ddl_return = stmt.executeUpdate(sql);

      sql = "select * from " + tbl;
      ResultSet rs = null;
      rs = stmt.executeQuery(sql);
      row_num = rs.next();
      rs.close();
      if (ddl_return == 0 && !row_num) {
        sql = "drop table " + tbl;
        try {
          stmt = conn.createStatement();
          stmt.executeUpdate(sql);
        } catch (SQLException e) {
          fail(" failed to drop, " + e.getMessage());
        }
      } else
        fail("table do not exists");

      /*** Code meant for Oracle DB ***/
      /*
       * tbl = tbl.toUpperCase(); sql = "select * from tab where tname like '%tbl%'"; ResultSet rs =
       * null; rs = stmt.executeQuery(sql); rs.close(); sql = "drop table "+tbl; stmt =
       * conn.createStatement(); stmt.executeUpdate(sql); System.out.println (this.space + "ok");
       */
      conn.setAutoCommit(true);
      stmt.close();
      conn.close();
    } catch (NamingException e) {
      fail("failed, " + e.getMessage());
    } catch (SQLException e) {
      fail("failed, " + e.getMessage());
    } catch (Exception e) {
      fail("failed, " + e.getMessage());
    } finally {
      if (conn != null)
        try {
          conn.close();
        } catch (SQLException e) {
        }
    }
  }

  /**
   * Test of testScenario18 method, of class org.apache.geode.internal.jta.functional.CacheTest1.
   * Get a connection (conn1) outside a transaction with pooled datasource lookup and another
   * connection (conn2) within the same transaction with XAPooled datasource lookup. After making
   * updates we do a rollback on the transaction and close both connections in the order of opening
   * them. The connection opened within transaction will only participate in the transaction.
   */
  @Test
  public void testScenario18() throws Exception {
    this.tblIDFld = 18;
    this.tblNameFld = "test18";
    boolean rollback_chances = true;
    int ifAnyRows = 0;

    JTAUtils jtaObj = new JTAUtils(cache, currRegion);

    jtaObj.deleteRows(this.tblName);

    Context ctx = cache.getJNDIContext();

    Connection conn2 = null; // connection within txn

    DataSource da = (DataSource) ctx.lookup("java:/PooledDataSource");
    Connection conn1 = da.getConnection(); // connection outside txn
    UserTransaction ta = (UserTransaction) ctx.lookup("java:/UserTransaction");

    try {
      ta.begin();
      Statement stmt = conn1.createStatement();
      String sqlSTR = "insert into " + this.tblName + " values (" + this.tblIDFld + "," + "'"
          + this.tblNameFld + "'" + ")";
      stmt.executeUpdate(sqlSTR);
      stmt.close();

      ifAnyRows = jtaObj.getRows(this.tblName);
      if (ifAnyRows == 0) {
        fail("failed no rows are there...");
      }
      // tryin a XAPooled lookup for second connection
      da = (DataSource) ctx.lookup("java:/XAPooledDataSource");
      conn2 = da.getConnection();
      stmt = conn2.createStatement();

      this.tblIDFld += 1;
      sqlSTR = "insert into " + this.tblName + " values (" + this.tblIDFld + "," + "'"
          + this.tblNameFld + "'" + ")";
      stmt.executeUpdate(sqlSTR);
      ta.rollback(); // intensional rollback

      stmt.close();
      conn2.close();
      conn1.close();

      rollback_chances = false;
      // if we reach here check whether the rollback was success for conn1 and
      // conn2
      ifAnyRows = jtaObj.getRows(this.tblName);
      assertEquals("at least one row not retained after rollback", 1, ifAnyRows);

      boolean matched = jtaObj.checkTableAgainstData(this.tblName, this.tblIDFld + ""); // checking
                                                                                        // conn2's
                                                                                        // field
      if (matched) { // data is still in db
        fail(", PK " + this.tblIDFld + " found in db)" + "   " + "rollback for conn #2 failed");
      }
    } finally {
      if (conn1 != null)
        try {
          conn1.close();
        } catch (SQLException ex) {
          fail(" Exception: " + ex.getMessage());
        }
      if (conn2 != null)
        try {
          conn2.close();
        } catch (SQLException ex) {
          fail(" Exception: " + ex.getMessage());
        }
    }
  }

  /**
   * required for test # 14
   */
  static class XACacheLoaderTxn implements CacheLoader {

    String tableName;

    /** Creates a new instance of XACacheLoaderTxn */
    public XACacheLoaderTxn(String str) {
      this.tableName = str;
    }

    @Override
    public Object load(LoaderHelper helper) throws CacheLoaderException {
      System.out.println("In Loader.load for" + helper.getKey());
      return loadFromDatabase(helper.getKey());
    }

    private Object loadFromDatabase(Object ob) {
      Object obj = null;
      try {
        Context ctx = CacheFactory.getAnyInstance().getJNDIContext();
        DataSource ds = (DataSource) ctx.lookup("java:/XAPooledDataSource");
        Connection conn = ds.getConnection();
        Statement stm = conn.createStatement();
        String str = "update " + tableName + " set name ='newname' where id = ("
            + (new Integer(ob.toString())).intValue() + ")";
        stm.executeUpdate(str);
        ResultSet rs = stm.executeQuery("select name from " + tableName + " where id = ("
            + (new Integer(ob.toString())).intValue() + ")");
        rs.next();
        obj = rs.getString(1);
        stm.close();
        conn.close();
        return obj;
      } catch (Exception e) {
        throw new Error(e);
      }
    }

    @Override
    public void close() {}
  }
}
