gt:             if (jdbcPassword == null) jdbcPassword = "";
context: /*
     Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
  
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
     the Free Software Foundation; version 2 of the License.
  
     This program is distributed in the hope that it will be useful,
     but WITHOUT ANY WARRANTY; without even the implied warranty of
     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     GNU General Public License for more details.
  
     You should have received a copy of the GNU General Public License
     along with this program; if not, write to the Free Software
     Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
  */
  
  package testsuite.clusterj;
  
  import com.mysql.clusterj.ClusterJException;
  import com.mysql.clusterj.ClusterJHelper;
  
  import com.mysql.clusterj.Constants;
  import com.mysql.clusterj.Session;
  import com.mysql.clusterj.SessionFactory;
  import com.mysql.clusterj.Transaction;
  
  import java.io.BufferedReader;
  import java.io.File;
  import java.io.FileInputStream;
  import java.io.FileNotFoundException;
  import java.io.IOException;
  import java.io.InputStream;
  
  import java.io.InputStreamReader;
  import java.sql.Connection;
  import java.sql.DriverManager;
  import java.sql.PreparedStatement;
  import java.sql.SQLException;
  import java.util.ArrayList;
  import java.util.Collection;
  import java.util.Collections;
  import java.util.Comparator;
  import java.util.Iterator;
  import java.util.LinkedList;
  import java.util.List;
  import java.util.Map.Entry;
  import java.util.Properties;
  
  import junit.framework.TestCase;
  
  public abstract class AbstractClusterJCoreTest extends TestCase {
  
      /** 
       * Indicates an exception thrown in method <code>tearDown</code>.
       * At the end of method <code>tearDown</code> this field is nullified. 
       */
      private Throwable tearDownThrowable;
  
      /** 
       * A list of registered oid instances. 
       * Corresponding pc instances are deleted in <code>localTearDown</code>.
       */
      private Collection tearDownInstances = new LinkedList();
  
      /** 
       * A list of registered pc classes. 
       * The extents of these classes are deleted in <code>tearDown</code>.
       */
      private Collection<Class> tearDownClasses = new LinkedList<Class>();
  
      /** 
       * Error messages collected during a test.
       */
      private StringBuffer errorMessages;
  
      private String NL = "\n";
  
      /** A1 values. */
      String[] a1values = new String[]{"dc=abc", "dc=prs", "dc=xyz"};
  
      /** This method is called by JUnit 
       * before each test case in each test class.
       */
      @Override
      protected final void setUp() throws Exception {
          setupDn2idPK();
          localSetUp();
      }
  
      /**
       * Subclasses may override this method to allocate any data and resources
       * that they need in order to successfully execute this testcase.
       * Adding teardown classes and instances is done in the overridden method.
       */
      protected void localSetUp() {}
  
      /** This method is called by JUnit 
       * after each test case in each test class.
       */
      @Override
      protected final void tearDown() throws Exception {
          localTearDown();
          // if session is null or closed, test class has already cleaned up
          if (session != null && !(session.isClosed())) {
              // if tx is null, get it again
              if (tx == null) {
                  tx = session.currentTransaction();
              }
              // if transaction is active (leftover), roll it back
              if (tx.isActive()) {
                  tx.rollback();
              }
              // if any work to do, start a transaction and clean up
              if (!tearDownClasses.isEmpty() | !tearDownInstances.isEmpty()) {
                  tx.begin();
                  for (Class<?> cls: tearDownClasses) {
                      session.deletePersistentAll(cls);
                  }
                  for (Object o: tearDownInstances) {
                      session.deletePersistent(o);
                  }
                  tx.commit();
              session.close();
              session = null;
              }
          }
      }
  
      /**
       * Subclasses may override this method to deallocate any data and resources
       * that they needed in order to successfully execute this testcase.
       */
      protected void localTearDown() {}
  
      protected void addTearDownClasses(Class... classes) {
          for (Class cls: classes) {
              tearDownClasses.add(cls);
          }
      }
  
      protected Object[] dn2idPK = new Object[16];
  
      public AbstractClusterJCoreTest() {
      }
  
      /** The name of the properties file; default "clusterj.properties". */
      String PROPS_FILE_NAME = System.getProperty(
              "clusterj.properties", "clusterj.properties");
  
      /** The properties for this test run */
      protected static Properties props;
      
      /** The JDBC Driver name */
      protected static String jdbcDriverName;
      
      /** The JDBC URL */
      protected static String jdbcURL;
  
      /** The JDBC Username */
      protected static String jdbcUsername;
  
      /** The JDBC Password */
      protected static String jdbcPassword;
  
      /** The JDBC Connection */
      protected static Connection connection;
  
      /** The Schema initialization statements */
      protected static List<String> schemaDefinition = new ArrayList<String>();
  
      /** Has the schema been initialized */
      protected static boolean schemaInitialized = false;
  
      /** The connection sessionFactory. */
      protected SessionFactory sessionFactory;
  
      /** The connection. Local setUp should initialize this if needed. */
      protected Session session;
  
      /** The transaction. Local setUp should initialize this if needed. */
      protected Transaction tx;
  
      /** 
       * Get a connection sessionFactory.
       */
      protected void createSessionFactory() {
          loadProperties();
          if (sessionFactory == null) {
              sessionFactory = ClusterJHelper.getSessionFactory(props);
          }
          loadSchema();
      }
  
      /** Create a file from a property name. */
      Properties getProperties(String fileName) {
          Properties result = null;
          try {
              InputStream stream = new FileInputStream(new File(fileName));
              result = new Properties();
              result.load(stream);
              return result;
          } catch (FileNotFoundException ex) {
          } catch (IOException ex) {
          }
          if (result == null) {
              try {
                  // try to load the resource from the class loader
                  ClassLoader cl = this.getClass().getClassLoader();
                  InputStream stream = cl.getResourceAsStream(fileName);
                  result = new Properties();
                  result.load(stream);
                  return result;
              } catch (IOException ex) {
                  fail("Could not create ConnectionFactory " + ex);
              }
          }
          return null; // not reached; fail will throw an exception
      }
  
      protected String getA1for(int number, int index) {
          int a1factor = 1 + number/a1values.length;
          return a1values[index/a1factor];
      }
  
      protected String getA3for(long i) {
          return "employeenumber=100000" + i;
      }
  
      protected void setupDn2idPK() {
          dn2idPK[0] = "dc=com";
          // pk[1] changes and is set inside loop
          dn2idPK[1] = "dc=example";
          dn2idPK[2] = "ou=people";
          // pk[3] changes and is set inside loop
          dn2idPK[4] = "";
          dn2idPK[5] = "";
          dn2idPK[6] = "";
          dn2idPK[7] = "";
          dn2idPK[8] = "";
          dn2idPK[9] = "";
          dn2idPK[10] = "";
          dn2idPK[11] = "";
          dn2idPK[12] = "";
          dn2idPK[13] = "";
          dn2idPK[14] = "";
          dn2idPK[15] = "";
      }
  
      /** Load the schema for tests */
      protected void loadSchema() {
          initializeJDBC();
          if (!schemaInitialized) {
              loadSchemaDefinition();
              if (!testSchema()) {
                  initializeSchema();
              }
          }
      }
      
      /** Initialize the JDBC driver */
      protected void initializeJDBC() {
          loadProperties();
          getConnection();
      }
  
      /** Load properties from clusterj.properties */
      protected void loadProperties() {
          if (props == null) {
              props = getProperties(PROPS_FILE_NAME);
          }
      }
  
      /** Load JDBC driver */
      protected void getConnection() {
          if (connection == null) {
              jdbcDriverName = props.getProperty(Constants.PROPERTY_JDBC_DRIVER_NAME);
              jdbcURL = props.getProperty(Constants.PROPERTY_JDBC_URL);
              jdbcUsername = props.getProperty(Constants.PROPERTY_JDBC_USERNAME);
              jdbcPassword = props.getProperty(Constants.PROPERTY_JDBC_PASSWORD);
  