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