001package io.ebean.docker.commands;
002
003import io.ebean.docker.container.Container;
004
005import java.sql.Connection;
006import java.sql.SQLException;
007import java.util.List;
008import java.util.Properties;
009
010/**
011 * Commands for controlling an Oracle docker container.
012 */
013public class OracleContainer extends JdbcBaseDbContainer implements Container {
014
015  /**
016   * Create Postgres container with configuration from properties.
017   */
018  public static OracleContainer create(String version, Properties properties) {
019    return new OracleContainer(new OracleConfig(version, properties));
020  }
021
022  private final OracleConfig oracleConfig;
023
024  private boolean oracleScript;
025
026  /**
027   * Create with configuration.
028   */
029  public OracleContainer(OracleConfig config) {
030    super(config);
031    this.oracleConfig = config;
032    this.checkConnectivityUsingAdmin = true;
033    this.waitForConnectivityAttempts = 2000;
034  }
035
036  @Override
037  void createDatabase() {
038    createRoleAndDatabase(false);
039  }
040
041  @Override
042  void dropCreateDatabase() {
043    createRoleAndDatabase(true);
044  }
045
046  private void createRoleAndDatabase(boolean withDrop) {
047    try (Connection connection = config.createAdminConnection()) {
048      if (withDrop) {
049        dropUser(connection);
050      }
051      createUser(connection, withDrop);
052
053    } catch (SQLException e) {
054      throw new RuntimeException("Error when creating database and role", e);
055    }
056  }
057
058  private void sqlRunOracleScript(Connection connection) {
059    if (!oracleScript) {
060      sqlRun(connection, "alter session set \"_ORACLE_SCRIPT\"=true");
061      oracleScript = true;
062    }
063  }
064
065  private void dropUser(Connection connection) {
066    if (userExists(connection)) {
067      sqlRunOracleScript(connection);
068      sqlRun(connection, "drop user " + dbConfig.getUsername() + " cascade");
069    }
070  }
071
072  private void createUser(Connection connection, boolean withDrop) {
073    if (withDrop || !userExists(connection)) {
074      sqlRunOracleScript(connection);
075      sqlRun(connection, "create user " + dbConfig.getUsername() + " identified by " + dbConfig.getPassword());
076      sqlRun(connection, "grant connect, resource,  create view, unlimited tablespace to " + dbConfig.getUsername());
077    }
078  }
079
080  private boolean userExists(Connection connection) {
081    String sql = "select 1 from dba_users where lower(username) = '"+dbConfig.getUsername().toLowerCase()+"'";
082    return sqlHasRow(connection, sql);
083  }
084
085  @Override
086  protected ProcessBuilder runProcess() {
087    List<String> args = dockerRun();
088    args.add("-p");
089    args.add(oracleConfig.getApexPort() + ":" + oracleConfig.getInternalApexPort());
090    args.add("-e");
091    args.add("ORACLE_PWD=" + oracleConfig.getAdminPassword());
092    args.add(config.getImage());
093    return createProcessBuilder(args);
094  }
095
096}