package io.ebean.config;
import io.ebean.EbeanVersion;
import io.ebean.annotation.Platform;
import io.ebean.migration.MigrationConfig;
import io.ebean.migration.MigrationRunner;
import io.ebean.util.StringHelper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Map;
import java.util.Properties;
Configuration for the DB migration processing.
/**
* Configuration for the DB migration processing.
*/
public class DbMigrationConfig {
protected static final Logger logger = LoggerFactory.getLogger(DbMigrationConfig.class);
protected MigrationConfig runnerConfig = new MigrationConfig();
The database platform to generate migration DDL for.
/**
* The database platform to generate migration DDL for.
*/
protected Platform platform;
Resource path for the migration xml and sql.
/**
* Resource path for the migration xml and sql.
*/
protected String migrationPath = "dbmigration";
protected String migrationInitPath = "dbinit";
Subdirectory the model xml files go into.
/**
* Subdirectory the model xml files go into.
*/
protected String modelPath = "model";
protected String applySuffix = ".sql";
Set this to "V" to be compatible with FlywayDB.
/**
* Set this to "V" to be compatible with FlywayDB.
*/
protected String applyPrefix = "";
protected String modelSuffix = ".model.xml";
For running migration the DB table that holds migration execution status.
/**
* For running migration the DB table that holds migration execution status.
*/
protected String metaTable = "db_migration";
Flag set to true means to run any outstanding migrations on startup.
/**
* Flag set to true means to run any outstanding migrations on startup.
*/
protected boolean runMigration;
Comma and equals delimited key/value placeholders to replace in DDL scripts.
/**
* Comma and equals delimited key/value placeholders to replace in DDL scripts.
*/
protected String runPlaceholders;
Map of key/value placeholders to replace in DDL scripts.
/**
* Map of key/value placeholders to replace in DDL scripts.
*/
protected Map<String, String> runPlaceholderMap;
DB schema used for the migration (and testing).
/**
* DB schema used for the migration (and testing).
*/
protected String dbSchema;
Set to true if we consider this the 'default schema' (Postgres schema that matches DB username)
/**
* Set to true if we consider this the 'default schema' (Postgres schema that matches DB username)
*/
protected boolean defaultDbSchema;
DB user used to run the DB migration.
/**
* DB user used to run the DB migration.
*/
protected String dbUsername;
DB password used to run the DB migration.
/**
* DB password used to run the DB migration.
*/
protected String dbPassword;
protected String patchInsertOn;
protected String patchResetChecksumOn;
Mode used to check non-null columns added via migration have a default value specified etc.
/**
* Mode used to check non-null columns added via migration have a default value specified etc.
*/
protected boolean strictMode = true;
Contains the DDL-header information.
/**
* Contains the DDL-header information.
*/
protected String ddlHeader;
Return the DB platform to generate migration DDL for.
We typically need to explicitly specify this as migration can often be generated
when running against H2.
/**
* Return the DB platform to generate migration DDL for.
* <p>
* We typically need to explicitly specify this as migration can often be generated
* when running against H2.
*/
public Platform getPlatform() {
return platform;
}
Set the DB platform to generate migration DDL for.
/**
* Set the DB platform to generate migration DDL for.
*/
public void setPlatform(Platform platform) {
this.platform = platform;
}
Return the path for normal migrations or dbinit migrations.
Params: - dbinitMigration – When true return the path for dbinit migrations.
/**
* Return the path for normal migrations or dbinit migrations.
*
* @param dbinitMigration When true return the path for dbinit migrations.
*/
public String getMigrationPath(boolean dbinitMigration) {
return dbinitMigration ? migrationInitPath : migrationPath;
}
Return the resource path for db migrations.
/**
* Return the resource path for db migrations.
*/
public String getMigrationPath() {
return migrationPath;
}
Set the resource path for db migrations.
The default of "dbmigration" is reasonable in most cases. You may look to set this
to be something like "dbmigration/myapp" where myapp gives it a unique resource path
in the case there are multiple Database applications in the single classpath.
/**
* Set the resource path for db migrations.
* <p>
* The default of "dbmigration" is reasonable in most cases. You may look to set this
* to be something like "dbmigration/myapp" where myapp gives it a unique resource path
* in the case there are multiple Database applications in the single classpath.
* </p>
*/
public void setMigrationPath(String migrationPath) {
this.migrationPath = migrationPath;
}
Return the relative path for the model files (defaults to model).
/**
* Return the relative path for the model files (defaults to model).
*/
public String getModelPath() {
return modelPath;
}
Set the relative path for the model files.
/**
* Set the relative path for the model files.
*/
public void setModelPath(String modelPath) {
this.modelPath = modelPath;
}
Return the model suffix (defaults to model.xml)
/**
* Return the model suffix (defaults to model.xml)
*/
public String getModelSuffix() {
return modelSuffix;
}
Set the model suffix.
/**
* Set the model suffix.
*/
public void setModelSuffix(String modelSuffix) {
this.modelSuffix = modelSuffix;
}
Return the apply script suffix (defaults to sql).
/**
* Return the apply script suffix (defaults to sql).
*/
public String getApplySuffix() {
return applySuffix;
}
Set the apply script suffix (defaults to sql).
/**
* Set the apply script suffix (defaults to sql).
*/
public void setApplySuffix(String applySuffix) {
this.applySuffix = applySuffix;
}
Return the apply prefix.
/**
* Return the apply prefix.
*/
public String getApplyPrefix() {
return applyPrefix;
}
Set the apply prefix. This might be set to "V" for use with FlywayDB.
/**
* Set the apply prefix. This might be set to "V" for use with FlywayDB.
*/
public void setApplyPrefix(String applyPrefix) {
this.applyPrefix = applyPrefix;
}
Return the table name that holds the migration run details
(used by DB Migration runner only).
/**
* Return the table name that holds the migration run details
* (used by DB Migration runner only).
*/
public String getMetaTable() {
return metaTable;
}
Set the table name that holds the migration run details
(used by DB Migration runner only).
/**
* Set the table name that holds the migration run details
* (used by DB Migration runner only).
*/
public void setMetaTable(String metaTable) {
this.metaTable = metaTable;
}
Return a comma and equals delimited placeholders that are substituted in SQL scripts when running migration
(used by DB Migration runner only).
/**
* Return a comma and equals delimited placeholders that are substituted in SQL scripts when running migration
* (used by DB Migration runner only).
*/
public String getRunPlaceholders() {
// environment properties take precedence
String placeholders = readEnvironment("ddl.migration.placeholders");
if (placeholders != null) {
return placeholders;
}
return runPlaceholders;
}
Set a comma and equals delimited placeholders that are substituted in SQL scripts when running migration
(used by DB Migration runner only).
/**
* Set a comma and equals delimited placeholders that are substituted in SQL scripts when running migration
* (used by DB Migration runner only).
*/
public void setRunPlaceholders(String runPlaceholders) {
this.runPlaceholders = runPlaceholders;
}
Return a map of placeholder values that are substituted in SQL scripts when running migration
(used by DB Migration runner only).
/**
* Return a map of placeholder values that are substituted in SQL scripts when running migration
* (used by DB Migration runner only).
*/
public Map<String, String> getRunPlaceholderMap() {
return runPlaceholderMap;
}
Set a map of placeholder values that are substituted when running migration
(used by DB Migration runner only).
/**
* Set a map of placeholder values that are substituted when running migration
* (used by DB Migration runner only).
*/
public void setRunPlaceholderMap(Map<String, String> runPlaceholderMap) {
this.runPlaceholderMap = runPlaceholderMap;
}
Return true if the DB migration should be run on startup.
/**
* Return true if the DB migration should be run on startup.
*/
public boolean isRunMigration() {
// environment properties take precedence
String run = readEnvironment("ddl.migration.run");
if (run != null) {
return "true".equalsIgnoreCase(run.trim());
}
return runMigration;
}
Set to true to run the DB migration on startup.
/**
* Set to true to run the DB migration on startup.
*/
public void setRunMigration(boolean runMigration) {
this.runMigration = runMigration;
}
Return the DB username to use for running DB migrations.
/**
* Return the DB username to use for running DB migrations.
*/
public String getDbUsername() {
// environment properties take precedence
String user = readEnvironment("ddl.migration.user");
if (user != null) {
return user;
}
return dbUsername;
}
Set the DB username to use for running DB migrations.
/**
* Set the DB username to use for running DB migrations.
*/
public void setDbUsername(String dbUsername) {
this.dbUsername = dbUsername;
}
Return the DB password to use for running DB migrations.
/**
* Return the DB password to use for running DB migrations.
*/
public String getDbPassword() {
String user = readEnvironment("ddl.migration.password");
if (user != null) {
return user;
}
return dbPassword;
}
Set the DB password to use for running DB migrations.
/**
* Set the DB password to use for running DB migrations.
*/
public void setDbPassword(String dbPassword) {
this.dbPassword = dbPassword;
}
Return the DB schema to use (for migration, testing etc).
/**
* Return the DB schema to use (for migration, testing etc).
*/
public String getDbSchema() {
String schema = readEnvironment("ddl.migration.schema");
if (schema != null) {
return schema;
}
return dbSchema;
}
Set the Db schema to use.
/**
* Set the Db schema to use.
*/
public void setDbSchema(String dbSchema) {
this.dbSchema = dbSchema;
}
Set the Db schema if it hasn't already been defined.
/**
* Set the Db schema if it hasn't already been defined.
*/
public void setDefaultDbSchema(String dbSchema) {
this.defaultDbSchema = true;
this.dbSchema = dbSchema;
}
Return true if this is considered the default DB schema (Postgres schema matching DB username).
/**
* Return true if this is considered the default DB schema (Postgres schema matching DB username).
*/
public boolean isDefaultDbSchema() {
return defaultDbSchema;
}
Return migration versions that should be added to history without running.
/**
* Return migration versions that should be added to history without running.
*/
public String getPatchInsertOn() {
return patchInsertOn;
}
Set migration versions that should be added to history without running.
Value can be a string containing comma delimited list of version numbers.
/**
* Set migration versions that should be added to history without running.
* <p>
* Value can be a string containing comma delimited list of version numbers.
* </p>
*/
public void setPatchInsertOn(String patchInsertOn) {
this.patchInsertOn = patchInsertOn;
}
Return migration versions that should have their checksum reset and not run.
/**
* Return migration versions that should have their checksum reset and not run.
*/
public String getPatchResetChecksumOn() {
return patchResetChecksumOn;
}
Returns a DDL header prepend for each DDL. E.g. for copyright headers
You can use placeholders like ${version} or ${timestamp} in properties file.
/**
* Returns a DDL header prepend for each DDL. E.g. for copyright headers
* You can use placeholders like ${version} or ${timestamp} in properties file.
*/
public String getDdlHeader() {
if (ddlHeader != null && !ddlHeader.isEmpty()) {
ddlHeader = StringHelper.replaceString(ddlHeader, "${version}", EbeanVersion.getVersion());
ddlHeader = StringHelper.replaceString(ddlHeader, "${timestamp}", ZonedDateTime.now().format( DateTimeFormatter.ISO_INSTANT ));
}
return ddlHeader;
}
Set the header prepended to the DDL.
/**
* Set the header prepended to the DDL.
*/
public void setDdlHeader(String ddlHeader) {
this.ddlHeader = ddlHeader;
}
Set migration versions that should have their checksum reset and not run.
Value can be a string containing comma delimited list of version numbers.
/**
* Set migration versions that should have their checksum reset and not run.
* <p>
* Value can be a string containing comma delimited list of version numbers.
* </p>
*/
public void setPatchResetChecksumOn(String patchResetChecksumOn) {
this.patchResetChecksumOn = patchResetChecksumOn;
}
Return true if strict mode is used which includes a check that non-null columns have a default value.
/**
* Return true if strict mode is used which includes a check that non-null columns have a default value.
*/
public boolean isStrictMode() {
String envValue = readEnvironment("ddl.migration.strictMode");
if (!isEmpty(envValue)) {
return Boolean.parseBoolean(envValue.trim());
}
return strictMode;
}
Set to false to turn off strict mode allowing non-null columns to not have a default value.
/**
* Set to false to turn off strict mode allowing non-null columns to not have a default value.
*/
public void setStrictMode(boolean strictMode) {
this.strictMode = strictMode;
}
Return the underlying migration runner configuration allowing for more advanced settings.
/**
* Return the underlying migration runner configuration allowing for more advanced settings.
*/
public MigrationConfig getRunnerConfig() {
return runnerConfig;
}
Load the settings from the PropertiesWrapper.
/**
* Load the settings from the PropertiesWrapper.
*/
public void loadSettings(PropertiesWrapper properties, String serverName) {
migrationPath = properties.get("migration.migrationPath", migrationPath);
migrationInitPath = properties.get("migration.migrationInitPath", migrationInitPath);
modelPath = properties.get("migration.modelPath", modelPath);
applyPrefix = properties.get("migration.applyPrefix", applyPrefix);
applySuffix = properties.get("migration.applySuffix", applySuffix);
modelSuffix = properties.get("migration.modelSuffix", modelSuffix);
platform = properties.getEnum(Platform.class, "migration.platform", platform);
patchInsertOn = properties.get("migration.patchInsertOn", patchInsertOn);
patchResetChecksumOn = properties.get("migration.patchResetChecksumOn", patchResetChecksumOn);
runMigration = properties.getBoolean("migration.run", runMigration);
metaTable = properties.get("migration.metaTable", metaTable);
runPlaceholders = properties.get("migration.placeholders", runPlaceholders);
dbSchema = properties.get("migration.dbSchema", dbSchema);
//Do not set user and pass from "datasource.db.username"
//There is a null test in MigrationRunner::getConnection to handle this
//String adminUser = properties.get("datasource." + serverName + ".username", dbUsername);
String adminUser = properties.get("datasource." + serverName + ".adminusername", dbUsername);
dbUsername = properties.get("migration.dbusername", adminUser);
//String adminPwd = properties.get("datasource." + serverName + ".password", dbPassword);
String adminPwd = properties.get("datasource." + serverName + ".adminpassword", dbPassword);
dbPassword = properties.get("migration.dbpassword", adminPwd);
ddlHeader = properties.get("ddl.header", ddlHeader);
}
Return the system or environment property.
/**
* Return the system or environment property.
*/
protected String readEnvironment(String key) {
String val = System.getProperty(key);
if (val == null) {
val = System.getenv(key);
}
return val;
}
Return true if the string is null or empty.
/**
* Return true if the string is null or empty.
*/
protected boolean isEmpty(String val) {
return val == null || val.trim().isEmpty();
}
Create the MigrationRunner to run migrations if necessary.
/**
* Create the MigrationRunner to run migrations if necessary.
*/
public MigrationRunner createRunner(ClassLoader classLoader, Properties properties) {
runnerConfig.setMetaTable(metaTable);
runnerConfig.setApplySuffix(applySuffix);
runnerConfig.setMigrationPath(migrationPath);
runnerConfig.setMigrationInitPath(migrationInitPath);
runnerConfig.setRunPlaceholderMap(runPlaceholderMap);
runnerConfig.setRunPlaceholders(runPlaceholders);
runnerConfig.setDbUsername(getDbUsername());
runnerConfig.setDbPassword(getDbPassword());
runnerConfig.setDbSchema(getDbSchema());
if (defaultDbSchema) {
runnerConfig.setSetCurrentSchema(false);
}
runnerConfig.setClassLoader(classLoader);
if (patchInsertOn != null) {
runnerConfig.setPatchInsertOn(patchInsertOn);
}
if (patchResetChecksumOn != null) {
runnerConfig.setPatchResetChecksumOn(patchResetChecksumOn);
}
if (properties != null) {
runnerConfig.load(properties);
}
return new MigrationRunner(runnerConfig);
}
}