001package io.ebean.dbmigration;
002
003import java.sql.Connection;
004import java.sql.DriverManager;
005import java.sql.SQLException;
006import java.util.Map;
007import java.util.Properties;
008
009/**
010 * Configuration used to run the migration.
011 */
012public class MigrationConfig {
013
014  private String migrationPath = "dbmigration";
015
016  private String metaTable = "db_migration";
017
018  private String applySuffix = ".sql";
019
020  private String runPlaceholders;
021
022  private boolean skipChecksum;
023
024  private Map<String, String> runPlaceholderMap;
025
026  private ClassLoader classLoader;
027
028  private String dbUsername;
029  private String dbPassword;
030  private String dbDriver;
031  private String dbUrl;
032
033  private String dbSchema;
034  private boolean createSchemaIfNotExists;
035  private String platformName;
036
037  /**
038   * Return the name of the migration table.
039   */
040  public String getMetaTable() {
041    return metaTable;
042  }
043
044  /**
045   * Set the name of the migration table.
046   */
047  public void setMetaTable(String metaTable) {
048    this.metaTable = metaTable;
049  }
050
051  /**
052   * Return true if checksum check should be skipped (during development).
053   */
054  public boolean isSkipChecksum() {
055    return skipChecksum;
056  }
057
058  /**
059   * Set to true to skip the checksum check.
060   * <p>
061   * This is intended for use during development only.
062   * </p>
063   */
064  public void setSkipChecksum(boolean skipChecksum) {
065    this.skipChecksum = skipChecksum;
066  }
067
068  /**
069   * Return a Comma and equals delimited key/value placeholders to replace in DDL scripts.
070   */
071  public String getRunPlaceholders() {
072    return runPlaceholders;
073  }
074
075  /**
076   * Set a Comma and equals delimited key/value placeholders to replace in DDL scripts.
077   */
078  public void setRunPlaceholders(String runPlaceholders) {
079    this.runPlaceholders = runPlaceholders;
080  }
081
082  /**
083   * Return a map of name/value pairs that can be expressions replaced in migration scripts.
084   */
085  public Map<String, String> getRunPlaceholderMap() {
086    return runPlaceholderMap;
087  }
088
089  /**
090   * Set a map of name/value pairs that can be expressions replaced in migration scripts.
091   */
092  public void setRunPlaceholderMap(Map<String, String> runPlaceholderMap) {
093    this.runPlaceholderMap = runPlaceholderMap;
094  }
095
096  /**
097   * Return the root path used to find migrations.
098   */
099  public String getMigrationPath() {
100    return migrationPath;
101  }
102
103  /**
104   * Set the root path used to find migrations.
105   */
106  public void setMigrationPath(String migrationPath) {
107    this.migrationPath = migrationPath;
108  }
109
110  /**
111   * Return the suffix for migration resources (defaults to .sql).
112   */
113  public String getApplySuffix() {
114    return applySuffix;
115  }
116
117  /**
118   * Set the suffix for migration resources.
119   */
120  public void setApplySuffix(String applySuffix) {
121    this.applySuffix = applySuffix;
122  }
123
124  /**
125   * Return the DB username.
126   * <p>
127   * Used when a Connection to run the migration is not supplied.
128   * </p>
129   */
130  public String getDbUsername() {
131    return dbUsername;
132  }
133
134  /**
135   * Set the DB username.
136   * <p>
137   * Used when a Connection to run the migration is not supplied.
138   * </p>
139   */
140  public void setDbUsername(String dbUsername) {
141    this.dbUsername = dbUsername;
142  }
143
144  /**
145   * Return the DB password.
146   * <p>
147   * Used when creating a Connection to run the migration.
148   * </p>
149   */
150  public String getDbPassword() {
151    return dbPassword;
152  }
153
154  /**
155   * Set the DB password.
156   * <p>
157   * Used when creating a Connection to run the migration.
158   * </p>
159   */
160  public void setDbPassword(String dbPassword) {
161    this.dbPassword = dbPassword;
162  }
163
164  /**
165   * Return the DB Driver.
166   * <p>
167   * Used when creating a Connection to run the migration.
168   * </p>
169   */
170  public String getDbDriver() {
171    return dbDriver;
172  }
173
174  /**
175   * Set the DB Driver.
176   * <p>
177   * Used when creating a Connection to run the migration.
178   * </p>
179   */
180  public void setDbDriver(String dbDriver) {
181    this.dbDriver = dbDriver;
182  }
183
184  /**
185   * Return the DB connection URL.
186   * <p>
187   * Used when creating a Connection to run the migration.
188   * </p>
189   */
190  public String getDbUrl() {
191    return dbUrl;
192  }
193
194  /**
195   * Set the DB connection URL.
196   * <p>
197   * Used when creating a Connection to run the migration.
198   * </p>
199   */
200  public void setDbUrl(String dbUrl) {
201    this.dbUrl = dbUrl;
202  }
203
204  /**
205   * Return the DB connection Schema.
206   * <p>
207   * Used when creating a Connection to run the migration.
208   * </p>
209   */
210  public String getDbSchema() {
211    return dbSchema;
212  }
213
214  /**
215   * Set the DB connection Schema.
216   * <p>
217   * Used when creating a Connection to run the migration.
218   * </p>
219   */
220  public void setDbSchema(String dbSchema) {
221    this.dbSchema = dbSchema;
222  }
223
224  /**
225   * Return true if migration should create the schema if it does not exist.
226   */
227  public boolean isCreateSchemaIfNotExists() {
228    return createSchemaIfNotExists;
229  }
230
231  /**
232   * Set to create Schema if it does not exist.
233   */
234  public void setCreateSchemaIfNotExists(boolean createSchemaIfNotExists) {
235    this.createSchemaIfNotExists = createSchemaIfNotExists;
236  }
237
238  /**
239   * Return the DB platform name (used for platform create table and select for update syntax).
240   */
241  public String getPlatformName() {
242    return platformName;
243  }
244
245  /**
246   * Set a DB platform name (to load specific create table and select for update syntax).
247   */
248  public void setPlatformName(String platformName) {
249    this.platformName = platformName;
250  }
251
252  /**
253   * Return the ClassLoader to use to load resources.
254   */
255  public ClassLoader getClassLoader() {
256    if (classLoader == null) {
257      classLoader = Thread.currentThread().getContextClassLoader();
258      if (classLoader == null) {
259        classLoader = this.getClass().getClassLoader();
260      }
261    }
262    return classLoader;
263  }
264
265  /**
266   * Set the ClassLoader to use when loading resources.
267   */
268  public void setClassLoader(ClassLoader classLoader) {
269    this.classLoader = classLoader;
270  }
271
272  /**
273   * Load configuration from standard properties.
274   */
275  public void load(Properties props) {
276
277    dbUsername = props.getProperty("dbmigration.username", dbUsername);
278    dbPassword = props.getProperty("dbmigration.password", dbPassword);
279    dbDriver = props.getProperty("dbmigration.driver", dbDriver);
280    dbUrl = props.getProperty("dbmigration.url", dbUrl);
281
282    String skip = props.getProperty("dbmigration.skipchecksum");
283    if (skip != null) {
284      skipChecksum = Boolean.parseBoolean(skip);
285    }
286    platformName = props.getProperty("dbmigration.platformName", platformName);
287    applySuffix = props.getProperty("dbmigration.applySuffix", applySuffix);
288    metaTable = props.getProperty("dbmigration.metaTable", metaTable);
289    migrationPath = props.getProperty("dbmigration.migrationPath", migrationPath);
290    runPlaceholders = props.getProperty("dbmigration.placeholders", runPlaceholders);
291  }
292
293  /**
294   * Create a Connection to the database using the configured driver, url, username etc.
295   * <p>
296   * Used when an existing DataSource or Connection is not supplied.
297   * </p>
298   */
299  public Connection createConnection() {
300
301    if (dbUsername == null) throw new MigrationException("Database username is null?");
302    if (dbPassword == null) throw new MigrationException("Database password is null?");
303    if (dbDriver == null) throw new MigrationException("Database Driver is null?");
304    if (dbUrl == null) throw new MigrationException("Database connection URL is null?");
305
306    loadDriver();
307
308    try {
309      Properties props = new Properties();
310      props.setProperty("user", dbUsername);
311      props.setProperty("password", dbPassword);
312      return DriverManager.getConnection(dbUrl, props);
313
314    } catch (SQLException e) {
315      throw new MigrationException("Error trying to create Connection", e);
316    }
317  }
318
319  private void loadDriver() {
320    try {
321      ClassLoader contextLoader = getClassLoader();
322      Class.forName(dbDriver, true, contextLoader);
323    } catch (Throwable e) {
324      throw new MigrationException("Problem loading Database Driver [" + dbDriver + "]: " + e.getMessage(), e);
325    }
326  }
327
328}