001/* 002 * Licensed under the Apache License, Version 2.0 (the "License"); 003 * you may not use this file except in compliance with the License. 004 * You may obtain a copy of the License at 005 * 006 * http://www.apache.org/licenses/LICENSE-2.0 007 * 008 * Unless required by applicable law or agreed to in writing, software 009 * distributed under the License is distributed on an "AS IS" BASIS, 010 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 011 * See the License for the specific language governing permissions and 012 * limitations under the License. 013 */ 014package de.softwareforge.testing.postgres.embedded; 015 016import static com.google.common.base.Preconditions.checkNotNull; 017 018import java.io.IOException; 019import java.util.Set; 020import java.util.function.Consumer; 021import javax.sql.DataSource; 022 023import com.google.common.collect.ImmutableList; 024import edu.umd.cs.findbugs.annotations.NonNull; 025import org.flywaydb.core.Flyway; 026import org.flywaydb.core.api.FlywayException; 027import org.flywaydb.core.api.configuration.FluentConfiguration; 028import org.slf4j.Logger; 029import org.slf4j.LoggerFactory; 030 031/** 032 * An {@link EmbeddedPostgresPreparer<DataSource>} that uses the <a href="https://flywaydb.org/">Flyway version control for your database</a> framework to 033 * migrate a data source to a known state. 034 */ 035public final class FlywayPreparer implements EmbeddedPostgresPreparer<DataSource> { 036 037 private static final Logger LOG = LoggerFactory.getLogger(FlywayPreparer.class); 038 039 private final ImmutableList.Builder<Consumer<FluentConfiguration>> customizers = ImmutableList.builder(); 040 041 /** 042 * Creates a new instance using one or more classpath locations. 043 * 044 * @param locations One or more locations on the classpath. 045 * @return A {@link FlywayPreparer} instance. 046 */ 047 @NonNull 048 public static FlywayPreparer forClasspathLocation(String... locations) { 049 FlywayPreparer preparer = new FlywayPreparer(); 050 preparer.addCustomizer(c -> c.locations(locations)); 051 return preparer; 052 } 053 054 /** 055 * Create a new, uninitialized preparer instance. Use {@link #addCustomizer(Consumer)} to modify the configuration for the {@link FluentConfiguration} 056 * object. 057 */ 058 public FlywayPreparer() { 059 } 060 061 /** 062 * Add a customizer instance. Each customizer is called once with the {@link FluentConfiguration} instance before setting the datasource and calling {@link 063 * FluentConfiguration#load()} and {@link Flyway#migrate()}. 064 * 065 * @param customizer A {@link Consumer<FluentConfiguration>} instance. Must not be null. 066 * @return This object. 067 */ 068 @NonNull 069 public FlywayPreparer addCustomizer(@NonNull Consumer<FluentConfiguration> customizer) { 070 checkNotNull(customizer, "customizer is null"); 071 customizers.add(customizer); 072 073 return this; 074 } 075 076 /** 077 * Add customizer instances. Each customizer is called once with the {@link FluentConfiguration} instance before setting the datasource and calling {@link 078 * FluentConfiguration#load()} and {@link Flyway#migrate()}. 079 * 080 * @param customizers A set of {@link Consumer<FluentConfiguration>} instances. Must not be null. 081 * @return This object. 082 */ 083 @NonNull 084 public FlywayPreparer addCustomizers(@NonNull Set<Consumer<FluentConfiguration>> customizers) { 085 checkNotNull(customizers, "customizers is null"); 086 customizers.addAll(customizers); 087 088 return this; 089 } 090 091 /** 092 * @deprecated Use {@link #addCustomizer(Consumer)}. 093 */ 094 @Deprecated 095 @NonNull 096 public FlywayPreparer customize(@NonNull Consumer<FluentConfiguration> customizer) { 097 return addCustomizer(customizer); 098 } 099 100 @Override 101 public void prepare(@NonNull DataSource dataSource) throws IOException { 102 checkNotNull(dataSource, "dataSource is null"); 103 104 try { 105 final FluentConfiguration config = Flyway.configure(); 106 107 customizers.build().forEach(c -> c.accept(config)); 108 109 config.dataSource(dataSource); 110 Flyway flyway = config.load(); 111 flyway.migrate(); 112 113 } catch (FlywayException e) { 114 throw new IOException(e); 115 } 116 } 117}