diff --git a/liquibase-core/src/main/java/liquibase/integration/spring/SpringResourceAccessor.java b/liquibase-core/src/main/java/liquibase/integration/spring/SpringResourceAccessor.java index 8d6189f2cf9..722635aee82 100644 --- a/liquibase-core/src/main/java/liquibase/integration/spring/SpringResourceAccessor.java +++ b/liquibase-core/src/main/java/liquibase/integration/spring/SpringResourceAccessor.java @@ -102,10 +102,10 @@ protected String getResourcePath(Resource resource) { if (url.contains("!")) { return url.replaceFirst(".*!", ""); } else { - while (!resourceLoader.getResource("classpath:"+url).exists()) { + while (!resourceLoader.getResource("classpath:" + url).exists()) { String newUrl = url.replaceFirst("^/?.*?/", ""); if (newUrl.equals(url)) { - throw new UnexpectedLiquibaseException("Could determine path for "+resource.getURL().toExternalForm()); + throw new UnexpectedLiquibaseException("Could determine path for " + resource.getURL().toExternalForm()); } url = newUrl; } @@ -115,7 +115,7 @@ protected String getResourcePath(Resource resource) { } catch (IOException e) { //the path gets stored in the databasechangelog table, so if it gets returned incorrectly it will cause future problems. //so throw a breaking error now rather than wait for bigger problems down the line - throw new UnexpectedLiquibaseException("Cannot determine resource path for "+resource.getDescription()); + throw new UnexpectedLiquibaseException("Cannot determine resource path for " + resource.getDescription()); } } @@ -163,12 +163,12 @@ protected boolean resourceIsFile(Resource resource) throws IOException { * Default implementation adds "classpath:" and removes duplicated /'s and classpath:'s */ protected String finalizeSearchPath(String searchPath) { - searchPath = "classpath:"+searchPath; - searchPath = searchPath - .replaceAll("classpath\\*:", "classpath:") - .replace("\\", "/") - .replaceAll("//+", "/") - .replace("classpath:classpath:", "classpath:"); + searchPath = searchPath.replace("\\", "/"); + searchPath = searchPath.replaceAll("classpath\\*?:", ""); + searchPath = "/" + searchPath; + searchPath = searchPath.replaceAll("//+", "/"); + + searchPath = "classpath*:" + searchPath; return searchPath; } diff --git a/liquibase-core/src/test/groovy/liquibase/integration/spring/SpringResourceAccessorTest.groovy b/liquibase-core/src/test/groovy/liquibase/integration/spring/SpringResourceAccessorTest.groovy index b620ee14d15..21fab7bd8d0 100644 --- a/liquibase-core/src/test/groovy/liquibase/integration/spring/SpringResourceAccessorTest.groovy +++ b/liquibase-core/src/test/groovy/liquibase/integration/spring/SpringResourceAccessorTest.groovy @@ -2,6 +2,7 @@ package liquibase.integration.spring import org.springframework.core.io.DefaultResourceLoader import spock.lang.Specification +import spock.lang.Unroll class SpringResourceAccessorTest extends Specification { @@ -75,5 +76,23 @@ class SpringResourceAccessorTest extends Specification { list.contains("MSSQLDatabaseTest.class,") } + @Unroll + def finalizeSearchPath() { + expect: + new SpringResourceAccessor().finalizeSearchPath(input) == expected + + where: + input | expected + "/path/to/file" | "classpath*:/path/to/file" + "//path////to/file" | "classpath*:/path/to/file" + "path/to/file" | "classpath*:/path/to/file" + "classpath:path/to/file" | "classpath*:/path/to/file" + "classpath:/path/to/file" | "classpath*:/path/to/file" + "classpath:classpath:/path/to/file" | "classpath*:/path/to/file" + "classpath*:/path/to/file" | "classpath*:/path/to/file" + "classpath*:path/to/file" | "classpath*:/path/to/file" + + } + }