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