diff --git a/extensions/liquibase/deployment/src/main/java/io/quarkus/liquibase/deployment/LiquibaseProcessor.java b/extensions/liquibase/deployment/src/main/java/io/quarkus/liquibase/deployment/LiquibaseProcessor.java index 66e45af582ff92..da1f958c7c6880 100644 --- a/extensions/liquibase/deployment/src/main/java/io/quarkus/liquibase/deployment/LiquibaseProcessor.java +++ b/extensions/liquibase/deployment/src/main/java/io/quarkus/liquibase/deployment/LiquibaseProcessor.java @@ -3,6 +3,7 @@ import static io.quarkus.deployment.annotations.ExecutionTime.STATIC_INIT; import static java.util.function.Predicate.not; +import java.io.FileNotFoundException; import java.io.IOException; import java.nio.file.Paths; import java.util.ArrayList; @@ -20,9 +21,14 @@ import java.util.stream.Collectors; import java.util.stream.Stream; +import io.quarkus.liquibase.runtime.LiquibaseDataSourceBuildTimeConfig; +import io.quarkus.runtime.util.StringUtil; import jakarta.enterprise.context.ApplicationScoped; import jakarta.enterprise.inject.Default; +import liquibase.resource.CompositeResourceAccessor; +import liquibase.resource.DirectoryResourceAccessor; +import liquibase.resource.ResourceAccessor; import org.jboss.jandex.AnnotationInstance; import org.jboss.jandex.AnnotationTarget; import org.jboss.jandex.ClassType; @@ -360,57 +366,88 @@ private List getChangeLogs(Collection dataSourceNames, Liquibase return Collections.emptyList(); } - ChangeLogParameters changeLogParameters = new ChangeLogParameters(); + List liquibaseDataSources = new ArrayList<>(); - ChangeLogParserFactory changeLogParserFactory = ChangeLogParserFactory.getInstance(); + if (DataSourceUtil.hasDefault(dataSourceNames)) { + liquibaseDataSources.add(liquibaseBuildConfig.defaultDataSource); + } + + for (String dataSourceName : dataSourceNames) { + if (!DataSourceUtil.isDefault(dataSourceName)) { + liquibaseDataSources.add(liquibaseBuildConfig.getConfigForDataSourceName(dataSourceName)); + } + } + ChangeLogParameters changeLogParameters = new ChangeLogParameters(); + ChangeLogParserFactory changeLogParserFactory = ChangeLogParserFactory.getInstance(); Set resources = new LinkedHashSet<>(); + for (LiquibaseDataSourceBuildTimeConfig liquibaseDataSourceConfig : liquibaseDataSources ){ - ClassLoaderResourceAccessor classLoaderResourceAccessor = new ClassLoaderResourceAccessor( - Thread.currentThread().getContextClassLoader()); + Optional> oSearchPaths = liquibaseDataSourceConfig.searchPath; + String changeLog = liquibaseDataSourceConfig.changeLog; + String parsedChangeLog = parseChangeLog(oSearchPaths, changeLog); - try { - // default datasource - if (DataSourceUtil.hasDefault(dataSourceNames)) { - resources.addAll(findAllChangeLogFiles(liquibaseBuildConfig.defaultDataSource.changeLog, changeLogParserFactory, - classLoaderResourceAccessor, changeLogParameters)); + try(ResourceAccessor resourceAccessor = resolveResourceAccessor(oSearchPaths, changeLog)) { + resources.addAll(findAllChangeLogFiles(parsedChangeLog, changeLogParserFactory, + resourceAccessor, changeLogParameters)); + } catch (Exception ex) { + throw new IllegalStateException(ex); } + } - // named datasources - Collection namedDataSourceChangeLogs = dataSourceNames.stream() - .filter(n -> !DataSourceUtil.isDefault(n)) - .map(liquibaseBuildConfig::getConfigForDataSourceName) - .map(c -> c.changeLog) - .collect(Collectors.toCollection(LinkedHashSet::new)); - - for (String namedDataSourceChangeLog : namedDataSourceChangeLogs) { - resources.addAll( - findAllChangeLogFiles(namedDataSourceChangeLog, changeLogParserFactory, classLoaderResourceAccessor, - changeLogParameters)); - } + LOGGER.debugf("Liquibase changeLogs: %s", resources); + return new ArrayList<>(resources); + } - LOGGER.debugf("Liquibase changeLogs: %s", resources); + private ResourceAccessor resolveResourceAccessor(Optional> oSearchPaths, String changeLog) throws FileNotFoundException { - return new ArrayList<>(resources); + CompositeResourceAccessor compositeResourceAccessor = new CompositeResourceAccessor(); + compositeResourceAccessor + .addResourceAccessor(new ClassLoaderResourceAccessor(Thread.currentThread().getContextClassLoader())); - } finally { - try { - classLoaderResourceAccessor.close(); - } catch (Exception ignored) { - // close() really shouldn't declare that exception, see also https://github.com/liquibase/liquibase/pull/2576 - } + if (!changeLog.startsWith("filesystem:") && oSearchPaths.isEmpty()) { + return compositeResourceAccessor; } + + if (oSearchPaths.isEmpty()) { + compositeResourceAccessor.addResourceAccessor( + new DirectoryResourceAccessor( + Paths.get(StringUtil.changePrefix(changeLog, "filesystem:", "")).getParent())); + return compositeResourceAccessor; + } + + for (String searchPath : oSearchPaths.get()) { + compositeResourceAccessor.addResourceAccessor(new DirectoryResourceAccessor(Paths.get(searchPath))); + } + + return compositeResourceAccessor; + } + + private String parseChangeLog(Optional> oSearchPaths, String changeLog) { + + if (changeLog.startsWith("filesystem:") && oSearchPaths.isEmpty()) { + return Paths.get(StringUtil.changePrefix(changeLog, "filesystem:", "")).getFileName().toString(); + } + + if (changeLog.startsWith("filesystem:")) { + return StringUtil.changePrefix(changeLog, "filesystem:", ""); + } + + if (changeLog.startsWith("classpath:")) { + return StringUtil.changePrefix(changeLog, "classpath:", ""); + } + + return changeLog; } /** * Finds all resource files for the given change log file */ private Set findAllChangeLogFiles(String file, ChangeLogParserFactory changeLogParserFactory, - ClassLoaderResourceAccessor classLoaderResourceAccessor, - ChangeLogParameters changeLogParameters) { + ResourceAccessor resourceAccessor, ChangeLogParameters changeLogParameters) { try { - ChangeLogParser parser = changeLogParserFactory.getParser(file, classLoaderResourceAccessor); - DatabaseChangeLog changelog = parser.parse(file, changeLogParameters, classLoaderResourceAccessor); + ChangeLogParser parser = changeLogParserFactory.getParser(file, resourceAccessor); + DatabaseChangeLog changelog = parser.parse(file, changeLogParameters, resourceAccessor); if (changelog != null) { Set result = new LinkedHashSet<>();