001package io.ebean.test.config;
002
003import io.ebean.config.AutoConfigure;
004import io.ebean.config.DatabaseConfig;
005import io.ebean.datasource.DataSourceConfig;
006import io.ebean.test.config.platform.PlatformAutoConfig;
007import io.ebean.test.config.provider.ProviderAutoConfig;
008import org.slf4j.Logger;
009import org.slf4j.LoggerFactory;
010
011import java.util.Properties;
012
013/**
014 * Automatically configure ServerConfig for testing purposes.
015 * <p>
016 * Can setup and execute docker based databases and other containers.
017 * Can setup DataSource configuration (to match docker db setup).
018 * Can setup a CurrentUserProvider and CurrentTenantProvider for testing.
019 * Can setup a EncryptKeyManager for testing purposes with fixed key.
020 */
021public class AutoConfigureForTesting implements AutoConfigure {
022
023  private static final Logger log = LoggerFactory.getLogger("io.ebean.test");
024
025  /**
026   * System property that can override the platform.  mvn clean test -Ddb=sqlserver
027   */
028  private final String environmentDb = System.getProperty("db");
029
030  @Override
031  public void preConfigure(DatabaseConfig config) {
032
033    Properties properties = config.getProperties();
034    if (isExtraServer(config, properties)) {
035      setupExtraDataSourceIfNecessary(config);
036      return;
037    }
038
039    String testPlatform = properties.getProperty("ebean.test.platform");
040    log.debug("automatic testing config - with ebean.test.platform:{} environment db:{} name:{}", testPlatform, environmentDb, config.getName());
041
042    if (RunOnceMarker.isRun()) {
043      setupPlatform(environmentDb, config);
044    }
045  }
046
047  @Override
048  public void postConfigure(DatabaseConfig config) {
049    setupProviders(config);
050    
051    if (org.h2.engine.Constants.VERSION_MAJOR == 1) {
052      // This code may be removed later, when droppinv H2 1.xxx compatibility
053      System.err.println("Running tests in H2 1.xxx compatibility mode");
054      System.setProperty("ebean.h2.useV1Syntax", "true");
055      makeV1Compatible(config.getDataSourceConfig());
056      makeV1Compatible(config.getReadOnlyDataSourceConfig());
057    }
058  }
059
060  private void makeV1Compatible(DataSourceConfig ds) {
061    if (ds == null) {
062      return;
063    }
064    String url = ds.getUrl();
065    if (url == null || !url.startsWith("jdbc:h2:")) {
066      return;
067    }
068    // remove illegal URL options
069    url = url.replace(";MODE=LEGACY", "");
070    url = url.replace(";NON_KEYWORDS=KEY,VALUE", "");
071    url = url.replace(";NON_KEYWORDS=KEY", "");
072    ds.setUrl(url);
073  }
074
075  /**
076   * Check if this is not the primary server and return true if that is the case.
077   */
078  private boolean isExtraServer(DatabaseConfig config, Properties properties) {
079    String extraDb = properties.getProperty("ebean.test.extraDb.dbName", properties.getProperty("ebean.test.extraDb"));
080    if (extraDb != null && extraDb.equals(config.getName())) {
081      config.setDefaultServer(false);
082      return true;
083    }
084    return false;
085  }
086
087  /**
088   * Setup the DataSource on the extra database if necessary.
089   */
090  private void setupExtraDataSourceIfNecessary(DatabaseConfig config) {
091    DataSourceConfig dataSourceConfig = config.getDataSourceConfig();
092    if (dataSourceConfig == null || dataSourceConfig.getUsername() == null) {
093      new PlatformAutoConfig(environmentDb, config)
094        .configExtraDataSource();
095    }
096  }
097
098  /**
099   * Setup support for Who, Multi-Tenant and DB encryption if they are not already set.
100   */
101  private void setupProviders(DatabaseConfig config) {
102    new ProviderAutoConfig(config).run();
103  }
104
105  /**
106   * Setup the platform for testing including docker as needed and adjusting datasource config as needed.
107   */
108  private void setupPlatform(String db, DatabaseConfig config) {
109    new PlatformAutoConfig(db, config).run();
110  }
111}