From 72862b565ce507c75efb978a5bbe235e5f2094bc Mon Sep 17 00:00:00 2001 From: Phillip Webb Date: Sat, 18 Nov 2017 20:29:43 -0800 Subject: [PATCH] Polish location check with vendor placeholder Closes gh-10387 --- .../flyway/FlywayAutoConfiguration.java | 101 +++++++++++------- .../flyway/FlywayAutoConfigurationTests.java | 6 +- 2 files changed, 68 insertions(+), 39 deletions(-) diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/flyway/FlywayAutoConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/flyway/FlywayAutoConfiguration.java index 1f16fd868f..dc2802431b 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/flyway/FlywayAutoConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/flyway/FlywayAutoConfiguration.java @@ -17,6 +17,7 @@ package org.springframework.boot.autoconfigure.flyway; import java.util.Arrays; +import java.util.Collection; import java.util.Collections; import java.util.HashSet; import java.util.List; @@ -104,8 +105,6 @@ public class FlywayAutoConfiguration { private List flywayCallbacks; - private static final String VENDOR_PLACEHOLDER = "{vendor}"; - public FlywayConfiguration(FlywayProperties properties, ResourceLoader resourceLoader, ObjectProvider dataSource, @FlywayDataSource ObjectProvider flywayDataSource, @@ -136,49 +135,22 @@ public class FlywayAutoConfiguration { } flyway.setCallbacks(this.flywayCallbacks .toArray(new FlywayCallback[this.flywayCallbacks.size()])); - String[] locations = resolveLocations(this.properties.getLocations().toArray(new String[0]), flyway.getDataSource()); + String[] locations = new LocationResolver(flyway.getDataSource()) + .resolveLocations(this.properties.getLocations()); checkLocationExists(locations); flyway.setLocations(locations); return flyway; } - private static String[] resolveLocations(String[] locations, DataSource dataSource) { - if (usesVendorLocation(locations)) { - try { - String url = (String) JdbcUtils - .extractDatabaseMetaData(dataSource, "getURL"); - DatabaseDriver vendor = DatabaseDriver.fromJdbcUrl(url); - if (vendor != DatabaseDriver.UNKNOWN) { - for (int i = 0; i < locations.length; i++) { - locations[i] = locations[i].replace(VENDOR_PLACEHOLDER, - vendor.getId()); - } - } - } - catch (MetaDataAccessException ex) { - throw new IllegalStateException(ex); - } - } - return locations; - } - - private static boolean usesVendorLocation(String... locations) { - for (String location : locations) { - if (location.contains(VENDOR_PLACEHOLDER)) { - return true; - } - } - return false; - } - private void checkLocationExists(String... locations) { if (this.properties.isCheckLocation()) { Assert.state(locations.length != 0, "Migration script locations not configured"); boolean exists = hasAtLeastOneLocation(locations); Assert.state(exists, - () -> "Cannot find migrations location in: " + Arrays.asList(locations) - + " (please add migrations or check your Flyway configuration)"); + () -> "Cannot find migrations location in: " + Arrays.asList( + locations) + + " (please add migrations or check your Flyway configuration)"); } } @@ -235,9 +207,64 @@ public class FlywayAutoConfiguration { @Override public void setLocations(String... locations) { - locations = FlywayConfiguration.resolveLocations(locations, - getDataSource()); - super.setLocations(locations); + super.setLocations( + new LocationResolver(getDataSource()).resolveLocations(locations)); + } + + } + + private static class LocationResolver { + + private static final String VENDOR_PLACEHOLDER = "{vendor}"; + + private final DataSource dataSource; + + public LocationResolver(DataSource dataSource) { + this.dataSource = dataSource; + } + + public String[] resolveLocations(Collection locations) { + return resolveLocations(locations.toArray(new String[locations.size()])); + } + + public String[] resolveLocations(String[] locations) { + if (usesVendorLocation(locations)) { + DatabaseDriver databaseDriver = getDatabaseDriver(); + return replaceVendorLocations(locations, databaseDriver); + } + return locations; + } + + private String[] replaceVendorLocations(String[] locations, + DatabaseDriver databaseDriver) { + if (databaseDriver == DatabaseDriver.UNKNOWN) { + return locations; + } + String vendor = databaseDriver.getId(); + return Arrays.stream(locations) + .map((location) -> location.replace(VENDOR_PLACEHOLDER, vendor)) + .toArray(String[]::new); + } + + private DatabaseDriver getDatabaseDriver() { + try { + String url = (String) JdbcUtils.extractDatabaseMetaData(this.dataSource, + "getURL"); + return DatabaseDriver.fromJdbcUrl(url); + } + catch (MetaDataAccessException ex) { + throw new IllegalStateException(ex); + } + + } + + private boolean usesVendorLocation(String... locations) { + for (String location : locations) { + if (location.contains(VENDOR_PLACEHOLDER)) { + return true; + } + } + return false; } } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/flyway/FlywayAutoConfigurationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/flyway/FlywayAutoConfigurationTests.java index 8d8006350c..da365536f7 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/flyway/FlywayAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/flyway/FlywayAutoConfigurationTests.java @@ -258,11 +258,13 @@ public class FlywayAutoConfigurationTests { @Test public void useOneLocationWithVendorDirectory() { this.contextRunner.withUserConfiguration(EmbeddedDataSourceConfiguration.class) - .withPropertyValues("spring.flyway.locations=classpath:db/vendors/{vendor}") + .withPropertyValues( + "spring.flyway.locations=classpath:db/vendors/{vendor}") .run((context) -> { assertThat(context).hasSingleBean(Flyway.class); Flyway flyway = context.getBean(Flyway.class); - assertThat(flyway.getLocations()).containsExactly("classpath:db/vendors/h2"); + assertThat(flyway.getLocations()) + .containsExactly("classpath:db/vendors/h2"); }); }