/******************************************************************************* * Copyright (c) 2012-2017 Codenvy, S.A. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Codenvy, S.A. - initial API and implementation *******************************************************************************/ package org.eclipse.che.core.db.schema.impl.flyway; import com.google.inject.Inject; import com.google.inject.name.Named; import org.eclipse.che.core.db.schema.SchemaInitializationException; import org.eclipse.che.core.db.schema.SchemaInitializer; import org.flywaydb.core.Flyway; import org.flywaydb.core.internal.dbsupport.DbSupport; import org.flywaydb.core.internal.dbsupport.DbSupportFactory; import org.flywaydb.core.internal.util.PlaceholderReplacer; import javax.sql.DataSource; import java.sql.Connection; import java.sql.SQLException; /** * <a href="https://flywaydb.org/">Flyway</a> based schema initializer. * * @author Yevhenii Voevodin */ public class FlywaySchemaInitializer implements SchemaInitializer { private final DataSource dataSource; private final String[] locations; private final String scriptsPrefix; private final String scriptsSuffix; private final String versionSeparator; private final boolean baselineOnMigrate; private final String baselineVersion; private final PlaceholderReplacer placeholderReplacer; /** * Creates a new instance of flyway schema initializer. * * @param scriptsLocations * the locations where to search migration scripts, * if locations is not prefixed or prefixed with <i>classpath:</i> * then initializer will try to find scripts in classpath using * {@code Thread.currentThread().}{@link Thread#getContextClassLoader() getContextClassLoader()} * @param scriptsPrefix * prefix of migration scripts e.g. 'v' or empty string * @param scriptsSuffix * suffix of migration scripts e.g. '.sql' * @param versionSeparator * separate version from the other part of script name e.g. '.' or '__' * @param baselineOnMigrate * whether to ignore scripts up to the version configured by {@code baselineVersion} * @param baselineVersion * up to this version all the scripts ignored, unless schema is initialized first time, * note that scripts with version equal to baseline version are also ignored * @param dataSource * data source used for migrations * @param placeholderReplacer * used to replace variables in script with configured values */ @Inject public FlywaySchemaInitializer(@Named("db.schema.flyway.scripts.locations") String[] scriptsLocations, @Named("db.schema.flyway.scripts.prefix") String scriptsPrefix, @Named("db.schema.flyway.scripts.suffix") String scriptsSuffix, @Named("db.schema.flyway.scripts.version_separator") String versionSeparator, @Named("db.schema.flyway.baseline.enabled") boolean baselineOnMigrate, @Named("db.schema.flyway.baseline.version") String baselineVersion, DataSource dataSource, PlaceholderReplacer placeholderReplacer) { this.dataSource = dataSource; this.locations = scriptsLocations; this.scriptsPrefix = scriptsPrefix; this.scriptsSuffix = scriptsSuffix; this.versionSeparator = versionSeparator; this.baselineOnMigrate = baselineOnMigrate; this.baselineVersion = baselineVersion; this.placeholderReplacer = placeholderReplacer; } /** Creates a new flyway based initializer with default values. */ public FlywaySchemaInitializer(DataSource dataSource, String... locations) { this(locations, "", ".sql", "__", false, "", dataSource, PlaceholderReplacer.NO_PLACEHOLDERS); } @Override public void init() throws SchemaInitializationException { try (final Connection conn = dataSource.getConnection()) { final Flyway flyway = new Flyway(); flyway.setDataSource(dataSource); flyway.setLocations(locations); flyway.setClassLoader(Thread.currentThread().getContextClassLoader()); final DbSupport dbSupport = DbSupportFactory.createDbSupport(conn, true); final String productName = conn.getMetaData().getDatabaseProductName().toLowerCase(); flyway.setResolvers(new CustomSqlMigrationResolver(productName, dbSupport, placeholderReplacer)); flyway.setSkipDefaultResolvers(true); flyway.setBaselineOnMigrate(baselineOnMigrate); if (baselineOnMigrate) { flyway.setBaselineVersionAsString(baselineVersion); } flyway.setSqlMigrationSeparator(versionSeparator); flyway.setSqlMigrationSuffix(scriptsSuffix); flyway.setSqlMigrationPrefix(scriptsPrefix); flyway.migrate(); } catch (SQLException | RuntimeException x) { throw new SchemaInitializationException(x.getLocalizedMessage(), x); } } }