Package org.teiid.test.framework.datasource

Source Code of org.teiid.test.framework.datasource.DataSourceFactory$DataBaseTypes

package org.teiid.test.framework.datasource;

import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;

import org.teiid.core.util.PropertiesUtils;
import org.teiid.core.util.StringUtil;
import org.teiid.test.framework.ConfigPropertyLoader;
import org.teiid.test.framework.ConfigPropertyNames;
import org.teiid.test.framework.TestLogger;
import org.teiid.test.framework.exception.QueryTestFailedException;
import org.teiid.test.framework.exception.TransactionRuntimeException;



/**
* The DataSourceFactory is responsible for managing the datasources used during a single test.
* It ensures the same data source is used in both the connector binding and during validation to ensure validation is performed
* against the same datasource the test was performed on.
*
* The following are the available options for controlling which datasources are used during a test:
* <li>Control which datasources are used and to which model they are assigned</li>
*
* <p>
* Use the {@link ConfigPropertyNames#USE_DATASOURCES_PROP} property to specify a comma delimited ordered list to control which data sources to use.
*
* <br><br>
* This will enable integration testing to be setup to use well known combinations, to ensure coverage and makes it easier to replicate issues.  
*
* This indicates to use only the specified datasources for this test.   This option can be used in test cases where only
* specific sources are to be used and tested against.
*
* This ordered list will map to the model:order mapping in the config.properties file.
* <br><br>
* Example:  in the config.properties file, the models in the test and their order can be specified:
*   <li>    pm1=1  </li>
*   <li>    pm2=2  </li>
* <br>
*
* Then set property: ConfigPropertyNames.USE_DATASOURCES_PROP=oracle,sqlserver
*
* This will use oracle and sqlserver datasources in the test, and when a datasource is requested for model "pm1", the oracle datasource will be returned.  And when a data source
* for "pm2" is requested, the data source mapped to 2nd ordered datasource of sqlserver will be returned.
*
* </p>
* <li>Control which datasources of a specific database type to exclude</li>
* <p>
*
* Use the {@link ConfigPropertyNames#EXCLUDE_DATASBASE_TYPES_PROP} property to specify a comma delimited list of {@link DataBaseTypes} to exclude.
* <br><br>
* This will remove all datasources of a specific database type from the list of available datasources.  This option will be applied after
* {@link ConfigPropertyNames#USE_DATASOURCES_PROP} option.   This is done because there are some test that will not work with certain database
* types, and therefore, if the required datasources are not met, the test will be bypassed for execution.
*</p>
* <li>Control for a specfic model, which database type of datasource to be assigned</li>
* <p>
* This option gives the developer even more fine grain control of how datasources are assigned.   There are cases where a specific model must be assigned
* to a datasource of a specific database type.
*
* To use this option,
* </p>
* @author vanhalbert
*
*/
public class DataSourceFactory {
 
  /**
   * These types match the "ddl" directories for supported database types
   * and it also found in the datasources connection.properties defined by the DB_TYPE property
   * These are also the values used to specify the required database types.
   *
   */
  public static interface DataBaseTypes{
    public static String MYSQL = "mysql";
    public static String ORACLE = "oracle";
    public static String POSTRES = "postgres";
    public static String SQLSERVER = "sqlserver";
    public static String DB2 = "db2";
    public static String SYBASE = "sybase";
    public static String DERBY = "derby"
    public static String ANY = "any";
   
  }

  // the DO_NO_USE_DEFAULT will be passed in when the test are run from maven and no property is passed in for UseDataSources
  private static final String DO_NOT_USE_DEFAULT="${" + ConfigPropertyNames.USE_DATASOURCES_PROP + "}";
   
  private Properties configprops;
 
  // contains the names of the datasources when the -Dusedatasources option is used
  private Map<String, String> useDS = null;
 
  // contains all the datasources available to be used
  private Map<String, DataSource> availDS = null;

 
  // contains any dbtype preconditions on a model, which requires a model to be assigned a certain database type
  private Map<String, String> requiredDataBaseTypes = null; // key=modelname  value=dbtype

  // this set is use to track datasources that have already been assigned
  private Set<String> assignedDataSources = new HashSet<String>();

  private int lastassigned = 0;
 
  // indicates if the datasource requirements have been, it will be false in the case
  // a specific dbtype is required and that type was not one of the available types defined
  private boolean metDBRequiredTypes = true;
 
  // indicates that there are required dbtypes to consider
  private boolean hasRequiredDBTypes = false;

 
  public DataSourceFactory(ConfigPropertyLoader config) {
        this.configprops = PropertiesUtils.clone(config.getProperties(), null, true);
    this.requiredDataBaseTypes = config.getModelAssignedDatabaseTypes();

  }
 
  public Properties getConfigProperties() {
      return this.configprops;
  }

  /**
   * config is called at the start / setup of the {@link
   * TransactionContainer#} test. This is to ensure any exclusions /
   * inclusions are considered for the next executed set of test.
   *
   *
   *   1st, check for the usedatasource property, if exist, then only add those specific datasources
   *     to the useDataSources, otherwise add all available.
   *  2nd, if the exclude option is used, then remove any excluded datasources from the useDataSources.
   * 
   * @since
   */
  protected void config(DataSourceMgr dsmgr) {
      TestLogger.logDebug("Configure Datasource Factory ");
     
        dsmgr = DataSourceMgr.getInstance();
   
    Map<String, DataSource> availDatasources = dsmgr.getDataSources();
   
    availDS = new HashMap<String, DataSource>(availDatasources.size());
   
    String usedstypeprop = configprops
    .getProperty(ConfigPropertyNames.USE_DATASOURCE_TYPES_PROP);
   
    Set<String> useDBTypes = null;

    if (usedstypeprop != null && usedstypeprop.length() > 0) {
      List<String> eprops = StringUtil.split(usedstypeprop, ",");
      useDBTypes = new HashSet<String>(eprops.size());
      useDBTypes.addAll(eprops);
      System.out.println("EXCLUDE datasources: " + usedstypeprop);
    } else {
        useDBTypes = Collections.EMPTY_SET;
    }
   
    String excludeprop = configprops
    .getProperty(ConfigPropertyNames.EXCLUDE_DATASBASE_TYPES_PROP);
   
    Set<String> excludedDBTypes = null;

    if (excludeprop != null && excludeprop.length() > 0) {
      List<String> eprops = StringUtil.split(excludeprop, ",");
      excludedDBTypes = new HashSet<String>(eprops.size());
      excludedDBTypes.addAll(eprops);
      System.out.println("EXCLUDE datasources: " + excludeprop);
    } else {
      excludedDBTypes = Collections.EMPTY_SET;
    }

   
    String limitdsprop = configprops
        .getProperty(ConfigPropertyNames.USE_DATASOURCES_PROP);
    if (limitdsprop != null && limitdsprop.length() > 0 && ! limitdsprop.equalsIgnoreCase(DO_NOT_USE_DEFAULT)) {
        TestLogger.log("Use ONLY datasources: " + limitdsprop);

      List<String> dss = StringUtil.split(limitdsprop, ",");

      useDS = new HashMap<String, String>(dss.size());
      DataSource ds = null;
      int i = 1;
      for (Iterator<String> it = dss.iterator(); it.hasNext(); i++) {
        String dssName = it.next();
        ds = availDatasources.get(dssName);
       
        if (ds != null && !excludedDBTypes.contains(ds.getDBType())) {
       
          useDS.put(String.valueOf(i), dssName);
       
          availDS.put(dssName, ds);
          TestLogger.logInfo("Using ds: " + dssName);
        }
       
      }

    } else {
      for (Iterator<DataSource> it = availDatasources.values().iterator(); it.hasNext(); ) {
        DataSource ds = it.next();
        // if the datasource type is not excluded, then consider for usages
        if (!excludedDBTypes.contains(ds.getDBType())) {
           
            // if use a specific db type is specified, then it must match,
            // otherwise add it to the available list
            if (useDBTypes.size() > 0)  {
                    if ( usedstypeprop.contains(ds.getDBType())) {
                  availDS.put(ds.getName(), ds);
                    }
            } else {
          availDS.put(ds.getName(), ds);
            }
           
        }
      }
       
       
    }

   
   
    if (requiredDataBaseTypes != null && requiredDataBaseTypes.size() > 0) {
      this.hasRequiredDBTypes = true;
     
      Iterator<String> rit = this.requiredDataBaseTypes.keySet().iterator();

      // go thru all the datasources and remove those that are excluded
        while (rit.hasNext()) {
          String modelName = rit.next();
          String rdbtype = this.requiredDataBaseTypes.get(modelName);
         
          Iterator<DataSource> ait = availDS.values().iterator();

          metDBRequiredTypes = false;
         
          // go thru all the datasources and find the matching datasource of the correct dbtype
          while (ait.hasNext()) {
            DataSource ds = ait.next();
            if (ds.getDBType().equalsIgnoreCase(rdbtype)) {
              assignedDataSources.add(ds.getName());

              dsmgr.setDataSource(modelName, ds);
            //  modelToDatasourceMap.put(modelName, ds);
              metDBRequiredTypes = true;
       
            }
           
          }
         
          if (!metDBRequiredTypes) {
            // did find a required dbtype, no need going any further
            break;
          }
         
        }
               
    }
   
   
  }
 
  public int getNumberAvailableDataSources() {
    return (metDBRequiredTypes ? this.availDS.size() :0);
  }

  public synchronized DataSource getDatasource(String modelName) throws QueryTestFailedException {
    DataSource ds = null;

    // map the datasource to the model and datasourceid
    // this is so the next time this combination is requested,
    // the same datasource is returned to ensure when consecutive calls
    // during the process
    // corresponds to the same datasource
    String key = null;

    key = modelName;
    //+ "_" + datasourceid;

    // if the datasourceid represents a group name, then use the group name
    // so that all future request using that group name for a specified
    // model
    // will use the same datasource
   
       
    if (this.hasRequiredDBTypes) {
      if (this.requiredDataBaseTypes.containsKey(modelName)) {
        String dbtype = this.requiredDataBaseTypes.get(modelName);
       
        Iterator<DataSource> it = availDS.values().iterator();

        // need to go thru all the datasources to know if any has already been
        // assigned
        // because the datasourceid passed in was a group name
        while (it.hasNext()) {
          DataSource checkit = it.next();

          if (dbtype.equalsIgnoreCase(checkit.getDBType())) {
            ds = checkit;
            break;
          }

        }

       
      }
     
    } else if (useDS != null) {
        String dsname = useDS.get(modelName);
        if (dsname != null) {
          ds = availDS.get(dsname);
          if (ds == null) {
            throw new QueryTestFailedException("Datasource name "
                + dsname
                + " was not found in the allDatasources map");
 
          }
        }
 

    } else {
   
      Iterator<DataSource> it = availDS.values().iterator();
 
      // need to go thru all the datasources to know if any has already been
      // assigned
      // because the datasourceid passed in was a group name
      while (it.hasNext()) {
        DataSource checkit = it.next();
 
        if (!assignedDataSources.contains(checkit.getName())) {
          ds = checkit;
          break;
        }
 
      }
    }

    if (ds == null) {
      int cnt = 0;
      Iterator<String> itds = assignedDataSources.iterator();

      // when all the datasources have been assigned, but a new model
      // datasource id is
      // passed in, need to reassign a previously assigned datasource
      // This case will happen when more models are defined than there are
      // defined datasources.
      while (itds.hasNext()) {
        String dsname = itds.next();

        if (cnt == this.lastassigned) {

          ds = availDS.get(dsname);

          this.lastassigned++;
          if (lastassigned >= assignedDataSources.size()) {
            this.lastassigned = 0;
          }

          break;
        }
      }

    }
   
    if (ds != null) {
        assignedDataSources.add(ds.getName());
    }

    return ds;

  }

  public void cleanup() {

    assignedDataSources.clear();
//    requiredDataBaseTypes.clear();

    if (useDS != null) useDS.clear();
//    if (availDS != null) availDS.clear();

  }
 
  public static void main(String[] args) {
    //NOTE: to run this test to validate the DataSourceMgr, do the following:
    //   ---  need 3 datasources,   Oracle, SqlServer and 1 other
   
    ConfigPropertyLoader config = ConfigPropertyLoader.getInstance();
   
    DataSourceFactory factory = new DataSourceFactory(config);

    try {
      if (factory.getDatasource("model1") == null) {
        throw new TransactionRuntimeException("No datasource was not found");
      }
     

    } catch (QueryTestFailedException e) {
      e.printStackTrace();
    }
   
    factory.cleanup();
   
    ConfigPropertyLoader.reset();

   
    // the following verifies that order of "use" datasources is applied to request for datasources.
    config = ConfigPropertyLoader.getInstance();
   
    config.setProperty(ConfigPropertyNames.USE_DATASOURCES_PROP, "oracle,sqlserver");
       
    factory = new DataSourceFactory(config);

    try {
     
      DataSource dsfind = factory.getDatasource( "model2");
      if (dsfind == null) {
        throw new TransactionRuntimeException("No datasource was not found as the 2nd datasource");
       
      }
     
      if (dsfind.getConnectorType() == null) {
        throw new TransactionRuntimeException("Connector types was not defined");
      }
     
      if (!dsfind.getName().equalsIgnoreCase("sqlserver")) {
        throw new TransactionRuntimeException("Sqlserver was not found as the 2nd datasource");
       
      }
     
      dsfind = factory.getDatasource( "model1");
      if (dsfind == null) {
        throw new TransactionRuntimeException("No datasource was not found as the 2nd datasource");
       
      }
      if (!dsfind.getName().equalsIgnoreCase("oracle")) {
        throw new TransactionRuntimeException("Oracle was not found as the 2nd datasource");
       
      }
      System.out.println("Datasource :" + dsfind.getName() + " was found");
     
     
      // the following test verifies that a sqlserver datasource is not
      // returned (excluded)
      factory.cleanup();
   
      ConfigPropertyLoader.reset();


      config = ConfigPropertyLoader.getInstance();
      config.setProperty(ConfigPropertyNames.EXCLUDE_DATASBASE_TYPES_PROP, "sqlserver");

     
      factory = new DataSourceFactory(config);

      int n = factory.getNumberAvailableDataSources();
      TestLogger.log("Num avail datasources: " + n);

      for (int i=0; i<n; i++) {
       
        String k = String.valueOf(i);
        DataSource ds1 = factory.getDatasource( "model" + k);
        if (ds1 == null) {
          throw new TransactionRuntimeException("No datasource was found for: model:" + k);
         
        } if (ds1.getDBType().equalsIgnoreCase(DataSourceFactory.DataBaseTypes.SQLSERVER)) {
          throw new TransactionRuntimeException("sqlserver dbtype should have been excluded");
        }
      }
       
       
        DataSource reuse = factory.getDatasource( "model1");
        if (reuse != null) {
         
        } else {
          throw new TransactionRuntimeException("The process was not able to reassign an already used datasource");
         
        }
       
        factory.cleanup();
       
        ConfigPropertyLoader.reset();

       
        // test required database types
        // test 1 source

        config = ConfigPropertyLoader.getInstance();
       
        config.setModelAssignedToDatabaseType("pm1", DataSourceFactory.DataBaseTypes.ORACLE);
     
        factory = new DataSourceFactory(config);

        DataSource ds1 = factory.getDatasource("pm1");
        if (!ds1.getDBType().equalsIgnoreCase(DataSourceFactory.DataBaseTypes.ORACLE)) {
          throw new TransactionRuntimeException("Required DB Type of oracle for model pm1 is :" + ds1.getDBType());
        }
       
        TestLogger.log("Test1 Required DS1 " + ds1.getDBType());
        factory.cleanup();
       
        ConfigPropertyLoader.reset();

        // test required database types
        // test 2 sources, 1 required and other ANY
        config = ConfigPropertyLoader.getInstance();
     
       
        config.setModelAssignedToDatabaseType("pm2", DataSourceFactory.DataBaseTypes.SQLSERVER);
        config.setModelAssignedToDatabaseType("pm1", DataSourceFactory.DataBaseTypes.ANY);
     
        factory = new DataSourceFactory(config);

        DataSource ds2 = factory.getDatasource("pm2");
        if (!ds2.getDBType().equalsIgnoreCase(DataSourceFactory.DataBaseTypes.SQLSERVER)) {
          throw new TransactionRuntimeException("Required DB Type of sqlserver for model pm2 is :" + ds2.getDBType());
        }
        TestLogger.log("Test2 Required DS2 " + ds2.getDBType());
     
        factory.cleanup();
        ConfigPropertyLoader.reset();

       
        // test required database types
        // test 2 sources, 2 required
        config = ConfigPropertyLoader.getInstance();
     
       
        config.setModelAssignedToDatabaseType("pm2", DataSourceFactory.DataBaseTypes.SQLSERVER);
        config.setModelAssignedToDatabaseType("pm1", DataSourceFactory.DataBaseTypes.ORACLE);
     
        factory = new DataSourceFactory(config);

        DataSource ds3a = factory.getDatasource("pm2");
        if (!ds3a.getDBType().equalsIgnoreCase(DataSourceFactory.DataBaseTypes.SQLSERVER)) {
          throw new TransactionRuntimeException("Required DB Type of sqlserver for model pm12 is :" + ds3a.getDBType());
        }
       
        DataSource ds3b = factory.getDatasource("pm1");
        if (!ds3b.getDBType().equalsIgnoreCase(DataSourceFactory.DataBaseTypes.ORACLE)) {
          throw new TransactionRuntimeException("Required DB Type of oracle for model pm1  is :" + ds3b.getDBType());
        }
        TestLogger.log("Test3 Required DS3a " + ds3a.getDBType());
        TestLogger.log("Test3 Required DS3b " + ds3b.getDBType());
       
        factory.cleanup();
     
       
    } catch (QueryTestFailedException e) {
      e.printStackTrace();
    }
  }

}
TOP

Related Classes of org.teiid.test.framework.datasource.DataSourceFactory$DataBaseTypes

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.