LegacyConfigurationManager.java
/*-
* ========================LICENSE_START=================================
* flyway-commandline
* ========================================================================
* Copyright (C) 2010 - 2025 Red Gate Software Ltd
* ========================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* =========================LICENSE_END==================================
*/
package org.flywaydb.commandline.configuration;
import lombok.CustomLog;
import org.flywaydb.commandline.Main;
import org.flywaydb.core.api.configuration.Configuration;
import org.flywaydb.core.api.configuration.FluentConfiguration;
import org.flywaydb.core.internal.configuration.ConfigUtils;
import org.flywaydb.core.internal.util.ClassUtils;
import org.flywaydb.core.internal.util.StringUtils;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static org.flywaydb.core.internal.configuration.ConfigUtils.DEFAULT_CLI_JARS_LOCATION;
import static org.flywaydb.core.internal.configuration.ConfigUtils.DEFAULT_CLI_SQL_LOCATION;
import static org.flywaydb.core.internal.configuration.ConfigUtils.makeRelativeJarDirsBasedOnWorkingDirectory;
import static org.flywaydb.core.internal.configuration.ConfigUtils.makeRelativeLocationsBasedOnWorkingDirectory;
@CustomLog
public class LegacyConfigurationManager implements ConfigurationManager {
public Configuration getConfiguration(CommandLineArguments commandLineArguments) {
Map<String, String> config = new HashMap<>();
String installDirectory = commandLineArguments.isWorkingDirectorySet() ? commandLineArguments.getWorkingDirectory() : ClassUtils.getInstallDir(Main.class);
String workingDirectory = commandLineArguments.getWorkingDirectoryOrNull();
File jarDir = new File(installDirectory, DEFAULT_CLI_JARS_LOCATION);
ConfigUtils.warnIfUsingDeprecatedMigrationsFolder(jarDir, ".jar");
if (jarDir.exists()) {
config.put(ConfigUtils.JAR_DIRS, jarDir.getAbsolutePath());
}
Map<String, String> envVars = ConfigUtils.environmentVariablesToPropertyMap();
loadConfigurationFromConfigFiles(config, commandLineArguments, envVars);
config.putAll(envVars);
config = overrideConfiguration(config, commandLineArguments.getConfiguration(false));
File sqlFolder = new File(installDirectory, DEFAULT_CLI_SQL_LOCATION);
if (ConfigUtils.shouldUseDefaultCliSqlLocation(sqlFolder, StringUtils.hasText(config.get(ConfigUtils.LOCATIONS)))) {
config.put(ConfigUtils.LOCATIONS, "filesystem:" + sqlFolder.getAbsolutePath());
}
if (workingDirectory != null) {
makeRelativeLocationsBasedOnWorkingDirectory(workingDirectory, config);
makeRelativeJarDirsBasedOnWorkingDirectory(workingDirectory, config);
}
ClassLoader classLoader = buildClassLoaderBasedOnJarDirs(Thread.currentThread().getContextClassLoader(), config);
ConfigUtils.dumpConfigurationMap(config, "Using configuration:");
filterProperties(config);
return new FluentConfiguration(classLoader).configuration(config).workingDirectory(workingDirectory);
}
protected void loadConfigurationFromConfigFiles(Map<String, String> config, CommandLineArguments commandLineArguments, Map<String, String> envVars) {
String encoding = determineConfigurationFileEncoding(commandLineArguments, envVars);
File installationDir = new File(ClassUtils.getInstallDir(Main.class));
String workingDirectory = commandLineArguments.getWorkingDirectoryOrNull();
config.putAll(ConfigUtils.loadDefaultConfigurationFiles(installationDir, workingDirectory, encoding));
for (File configFile : determineLegacyConfigFilesFromArgs(commandLineArguments)) {
config.putAll(ConfigUtils.loadConfigurationFile(configFile, encoding, true));
}
}
/**
* @return The encoding. (default: UTF-8)
*/
private static String determineConfigurationFileEncoding(CommandLineArguments commandLineArguments, Map<String, String> envVars) {
if (envVars.containsKey(ConfigUtils.CONFIG_FILE_ENCODING)) {
return envVars.get(ConfigUtils.CONFIG_FILE_ENCODING);
}
if (commandLineArguments.isConfigFileEncodingSet()) {
return commandLineArguments.getConfigFileEncoding();
}
return "UTF-8";
}
private static List<File> determineLegacyConfigFilesFromArgs(CommandLineArguments commandLineArguments) {
List<File> legacyFiles = commandLineArguments.getConfigFilePathsFromEnv(false);
legacyFiles.addAll(commandLineArguments.getConfigFiles().stream().filter(s -> !s.endsWith(".toml")).map(File::new).toList());
return legacyFiles;
}
private static Map<String, String> overrideConfiguration(Map<String, String> existingConfiguration, Map<String, String> newConfiguration) {
Map<String, String> combinedConfiguration = new HashMap<>();
combinedConfiguration.putAll(existingConfiguration);
combinedConfiguration.putAll(newConfiguration);
return combinedConfiguration;
}
/**
* Filters the properties to remove the Flyway Commandline-specific ones.
*/
private void filterProperties(Map<String, String> config) {
config.remove(ConfigUtils.CONFIG_FILES);
config.remove(ConfigUtils.CONFIG_FILE_ENCODING);
}
private ClassLoader buildClassLoaderBasedOnJarDirs(ClassLoader parentClassLoader, Map<String, String> config) {
List<File> jarFiles = new ArrayList<>(CommandLineConfigurationUtils.getJdbcDriverJarFiles());
String jarDirs = config.get(ConfigUtils.JAR_DIRS);
if (StringUtils.hasText(jarDirs)) {
jarFiles.addAll(CommandLineConfigurationUtils.getJavaMigrationJarFiles(StringUtils.tokenizeToStringArray(jarDirs.replace(File.pathSeparator, ","), ",")));
}
if (!jarFiles.isEmpty()) {
return ClassUtils.addJarsOrDirectoriesToClasspath(parentClassLoader, jarFiles);
}
return parentClassLoader;
}
}