diff --git a/liquibase-cdi/src/main/java/liquibase/integration/cdi/CDILiquibase.java b/liquibase-cdi/src/main/java/liquibase/integration/cdi/CDILiquibase.java index 6daaaed69d7..5ed40bd091f 100644 --- a/liquibase-cdi/src/main/java/liquibase/integration/cdi/CDILiquibase.java +++ b/liquibase-cdi/src/main/java/liquibase/integration/cdi/CDILiquibase.java @@ -4,8 +4,7 @@ import liquibase.LabelExpression; import liquibase.Liquibase; import liquibase.Scope; -import liquibase.configuration.GlobalConfiguration; -import liquibase.configuration.LiquibaseConfiguration; +import liquibase.GlobalConfiguration; import liquibase.database.Database; import liquibase.database.DatabaseFactory; import liquibase.database.jvm.JdbcConnection; @@ -107,12 +106,10 @@ public void onStartup() { return; } - LiquibaseConfiguration liquibaseConfiguration = LiquibaseConfiguration.getInstance(); - if (!liquibaseConfiguration.getConfiguration(GlobalConfiguration.class).getShouldRun()) { + if (!GlobalConfiguration.SHOULD_RUN.getCurrentValue()) { log.info(String.format("Liquibase did not run on %s because %s was set to false.", hostName, - liquibaseConfiguration.describeValueLookupLogic( - GlobalConfiguration.class, GlobalConfiguration.SHOULD_RUN) + GlobalConfiguration.SHOULD_RUN.getKey() )); return; } diff --git a/liquibase-cdi/src/test/java/liquibase/integration/cdi/CDILiquibaseTest.java b/liquibase-cdi/src/test/java/liquibase/integration/cdi/CDILiquibaseTest.java index e6e8a7e5b48..c88d9d1bcf7 100644 --- a/liquibase-cdi/src/test/java/liquibase/integration/cdi/CDILiquibaseTest.java +++ b/liquibase-cdi/src/test/java/liquibase/integration/cdi/CDILiquibaseTest.java @@ -21,7 +21,6 @@ public class CDILiquibaseTest { public void clearProperty() { System.clearProperty("liquibase.shouldRun"); System.clearProperty("liquibase.config.shouldRun"); - LiquibaseConfiguration.getInstance().reset(); } private void validateRunningState(boolean shouldBeRunning) { diff --git a/liquibase-cli/pom.xml b/liquibase-cli/pom.xml new file mode 100644 index 00000000000..d9d19909b4f --- /dev/null +++ b/liquibase-cli/pom.xml @@ -0,0 +1,20 @@ + + 4.0.0 + + + org.liquibase + liquibase-base-module + ${liquibase.version} + ../base-module.pom.xml + + + Liquibase CLI interface + + liquibase-cli + + + + + + diff --git a/liquibase-cli/src/main/java/liquibase/integration/commandline/NewMain.java b/liquibase-cli/src/main/java/liquibase/integration/commandline/NewMain.java new file mode 100644 index 00000000000..4fd136cab30 --- /dev/null +++ b/liquibase-cli/src/main/java/liquibase/integration/commandline/NewMain.java @@ -0,0 +1,18 @@ +package liquibase.integration.commandline; + +import liquibase.Scope; +import liquibase.configuration.ConfigurationDefinition; +import liquibase.configuration.LiquibaseConfiguration; + +import java.util.SortedSet; + +public class NewMain { + public static void main(String[] args) { + System.out.println("New CLI!"); + + final SortedSet definitions = Scope.getCurrentScope().getSingleton(LiquibaseConfiguration.class).getRegisteredDefinitions(); + for (ConfigurationDefinition def : definitions) { + System.out.println("See " + def.getKey() + " = " + def.getCurrentValue() + " -- " + def.getDescription()); + } + } +} diff --git a/liquibase-core/src/main/java/liquibase/GlobalConfiguration.java b/liquibase-core/src/main/java/liquibase/GlobalConfiguration.java new file mode 100644 index 00000000000..efd547b8fcb --- /dev/null +++ b/liquibase-core/src/main/java/liquibase/GlobalConfiguration.java @@ -0,0 +1,145 @@ +package liquibase; + +import liquibase.configuration.ConfigurationDefinition; +import liquibase.configuration.AutoloadedConfigurations; + +/** + * Configuration container for global properties. + */ +public class GlobalConfiguration implements AutoloadedConfigurations { + + public static final ConfigurationDefinition SHOULD_RUN; + public static final ConfigurationDefinition DATABASECHANGELOG_TABLE_NAME; + public static final ConfigurationDefinition DATABASECHANGELOGLOCK_TABLE_NAME; + public static final ConfigurationDefinition LIQUIBASE_TABLESPACE_NAME; + public static final ConfigurationDefinition LIQUIBASE_CATALOG_NAME; + public static final ConfigurationDefinition LIQUIBASE_SCHEMA_NAME; + public static final ConfigurationDefinition OUTPUT_LINE_SEPARATOR; + public static final ConfigurationDefinition OUTPUT_ENCODING; + public static final ConfigurationDefinition CHANGELOGLOCK_WAIT_TIME; + public static final ConfigurationDefinition CHANGELOGLOCK_POLL_RATE; + public static final ConfigurationDefinition CONVERT_DATA_TYPES; + public static final ConfigurationDefinition GENERATE_CHANGESET_CREATED_VALUES; + public static final ConfigurationDefinition AUTO_REORG; + public static final ConfigurationDefinition DIFF_COLUMN_ORDER; + public static final ConfigurationDefinition ALWAYS_OVERRIDE_STORED_LOGIC_SCHEMA; + public static final ConfigurationDefinition GENERATED_CHANGESET_IDS_INCLUDE_DESCRIPTION; + public static final ConfigurationDefinition INCLUDE_CATALOG_IN_SPECIFICATION; + public static final ConfigurationDefinition SHOULD_SNAPSHOT_DATA; + public static final ConfigurationDefinition FILTER_LOG_MESSAGES; + public static final ConfigurationDefinition HEADLESS; + + static { + ConfigurationDefinition.Builder builder = new ConfigurationDefinition.Builder("liquibase"); + + SHOULD_RUN = builder.define("shouldRun", Boolean.class) + .setDescription("Should Liquibase commands execute") + .setDefaultValue(true) + .addAliasKey("should.run") + .build(); + + DATABASECHANGELOG_TABLE_NAME = builder.define("databaseChangelogTableName", String.class) + .addAliasKey("liquibase.databaseChangeLogTableName") + .setDescription("Name of table to use for tracking change history") + .setDefaultValue("DATABASECHANGELOG") + .build(); + + DATABASECHANGELOGLOCK_TABLE_NAME = builder.define("databaseChangelogLockTableName", String.class) + .addAliasKey("liquibase.databaseChangeLogLockTableName") + .setDescription("Name of table to use for tracking concurrent Liquibase usage") + .setDefaultValue("DATABASECHANGELOGLOCK") + .build(); + + CHANGELOGLOCK_WAIT_TIME = builder.define("changelogLockWaitTimeInMinutes", Long.class) + .addAliasKey("liquibase.changeLogLockWaitTimeInMinutes") + .setDescription("Number of minutes to wait for the changelog lock to be available before giving up") + .setDefaultValue(5L) + .build(); + + CHANGELOGLOCK_POLL_RATE = builder.define("changelogLockPollRate", Long.class) + .addAliasKey("liquibase.changeLogLockPollRate") + .setDescription("Number of seconds wait between checks to the changelog lock when it is locked") + .setDefaultValue(10L) + .build(); + + LIQUIBASE_TABLESPACE_NAME = builder.define("tablespaceName", String.class) + .setDescription("Tablespace to use for Liquibase objects") + .build(); + + LIQUIBASE_CATALOG_NAME = builder.define("catalogName", String.class) + .setDescription("Catalog to use for Liquibase objects") + .build(); + + LIQUIBASE_SCHEMA_NAME = builder.define("schemaName", String.class) + .setDescription("Schema to use for Liquibase objects") + .build(); + + OUTPUT_LINE_SEPARATOR = builder.define("outputLineSeparator", String.class) + .setDescription("Line separator for output. Defaults to OS default") + .setDefaultValue(System.getProperty("line.separator")) + .build(); + + OUTPUT_ENCODING = builder.define("outputFileEncoding", String.class) + .setDescription("Encoding to output text in. Defaults to file.encoding system property or UTF-8") + .setDefaultValue("UTF-8") + .addAliasKey("file.encoding") + .setCommonlyUsed(true) + .build(); + + CONVERT_DATA_TYPES = builder.define("convertDataTypes", Boolean.class) + .setDescription("Should Liquibase convert to/from STANDARD data types. Applies to both snapshot and " + + "update commands.") + .setDefaultValue(true) + .build(); + + GENERATE_CHANGESET_CREATED_VALUES = builder.define("generateChangesetCreatedValues", Boolean.class) + .addAliasKey("liquibase.generateChangeSetCreatedValues") + .setDescription("Should Liquibase include a 'created' attribute in diff/generateChangelog changesets with" + + " the current datetime") + .setDefaultValue(false) + .build(); + + AUTO_REORG = builder.define("autoReorg", Boolean.class) + .setDescription("Should Liquibase automatically include REORG TABLE commands when needed?") + .setDefaultValue(true) + .build(); + + DIFF_COLUMN_ORDER = builder.define("diffColumnOrder", Boolean.class) + .setDescription("Should Liquibase compare column order in diff operation?") + .setDefaultValue(true) + .build(); + + ALWAYS_OVERRIDE_STORED_LOGIC_SCHEMA = builder.define("alwaysOverrideStoredLogicSchema", Boolean.class) + .setDescription("When generating SQL for createProcedure, should the procedure schema be forced to the default schema if no schemaName attribute is set?") + .setDefaultValue(false) + .build(); + + + GENERATED_CHANGESET_IDS_INCLUDE_DESCRIPTION = builder.define("generatedChangesetIdsContainsDescription", Boolean.class) + .addAliasKey("liquibase.generatedChangeSetIdsContainsDescription") + .setDescription("Should Liquibase include the change description in the id when generating changesets?") + .setDefaultValue(false) + .build(); + + INCLUDE_CATALOG_IN_SPECIFICATION = builder.define("includeCatalogInSpecification", Boolean.class) + .setDescription("Should Liquibase include the catalog name when determining equality?") + .setDefaultValue(false) + .build(); + + SHOULD_SNAPSHOT_DATA = builder.define("shouldSnapshotData", Boolean.class) + .setDescription("Should Liquibase snapshot data by default?") + .setDefaultValue(false) + .build(); + + FILTER_LOG_MESSAGES = builder.define("filterLogMessages", Boolean.class) + .setDescription("Should Liquibase filter log messages for potentially insecure data?") + .setDefaultValue(true) + .build(); + + HEADLESS = builder.define("headless", Boolean.class) + .setDescription("Force liquibase think it has no access to a keyboard?") + .setDefaultValue(false) + .setCommonlyUsed(true) + .build(); + } +} diff --git a/liquibase-core/src/main/java/liquibase/Liquibase.java b/liquibase-core/src/main/java/liquibase/Liquibase.java index a55f0f53455..c258271fb8d 100644 --- a/liquibase-core/src/main/java/liquibase/Liquibase.java +++ b/liquibase-core/src/main/java/liquibase/Liquibase.java @@ -8,7 +8,6 @@ import liquibase.command.CommandExecutionException; import liquibase.command.CommandFactory; import liquibase.command.core.DropAllCommand; -import liquibase.configuration.HubConfiguration; import liquibase.configuration.LiquibaseConfiguration; import liquibase.database.Database; import liquibase.database.DatabaseConnection; @@ -26,10 +25,7 @@ import liquibase.executor.Executor; import liquibase.executor.ExecutorService; import liquibase.executor.LoggingExecutor; -import liquibase.hub.HubService; -import liquibase.hub.HubServiceFactory; -import liquibase.hub.HubUpdater; -import liquibase.hub.LiquibaseHubException; +import liquibase.hub.*; import liquibase.hub.listener.HubChangeExecListener; import liquibase.hub.model.Connection; import liquibase.hub.model.HubChangeLog; @@ -311,13 +307,12 @@ public Connection getConnection(DatabaseChangeLog changeLog) throws LiquibaseHub if (executor instanceof LoggingExecutor) { return null; } - HubConfiguration hubConfiguration = LiquibaseConfiguration.getInstance().getConfiguration(HubConfiguration.class); String changeLogId = changeLog.getChangeLogId(); HubUpdater hubUpdater = new HubUpdater(new Date(), changeLog, database); if (hubUpdater.hubIsNotAvailable(changeLogId)) { - if (StringUtil.isNotEmpty(hubConfiguration.getLiquibaseHubApiKey()) && changeLogId == null) { + if (StringUtil.isNotEmpty(HubConfiguration.LIQUIBASE_HUB_API_KEY.getCurrentValue()) && changeLogId == null) { String message = - "The API key '" + hubConfiguration.getLiquibaseHubApiKey() + "' was found, but no changelog ID exists.\n" + + "The API key '" + HubConfiguration.LIQUIBASE_HUB_API_KEY.getCurrentValue() + "' was found, but no changelog ID exists.\n" + "No operations will be reported. Register this changelog with Liquibase Hub to generate free deployment reports.\n" + "Learn more at https://hub.liquibase.com."; Scope.getCurrentScope().getUI().sendMessage("WARNING: " + message); @@ -329,7 +324,7 @@ public Connection getConnection(DatabaseChangeLog changeLog) throws LiquibaseHub // // Warn about the situation where there is a changeLog ID, but no API key // - if (StringUtil.isEmpty(hubConfiguration.getLiquibaseHubApiKey()) && changeLogId != null) { + if (StringUtil.isEmpty(HubConfiguration.LIQUIBASE_HUB_API_KEY.getCurrentValue()) && changeLogId != null) { String message = "The changelog ID '" + changeLogId + "' was found, but no API Key exists.\n" + "No operations will be reported. Simply add a liquibase.hub.apiKey setting to generate free deployment reports.\n" + "Learn more at https://hub.liquibase.com."; @@ -1783,15 +1778,16 @@ public final void dropAll(CatalogAndSchema... schemas) throws DatabaseException runInScope(new Scope.ScopedRunner() { @Override public void run() throws Exception { + final CommandFactory commandFactory = Scope.getCurrentScope().getSingleton(CommandFactory.class); - DropAllCommand dropAll = (DropAllCommand) CommandFactory.getInstance().getCommand("dropAll"); + DropAllCommand dropAll = (DropAllCommand) commandFactory.getCommand("dropAll"); dropAll.setDatabase(Liquibase.this.getDatabase()); dropAll.setSchemas(finalSchemas); dropAll.setLiquibase(Liquibase.this); dropAll.setChangeLogFile(changeLogFile); try { - dropAll.execute(); + commandFactory.execute(dropAll); } catch (CommandExecutionException e) { throw new DatabaseException(e); } diff --git a/liquibase-core/src/main/java/liquibase/Scope.java b/liquibase-core/src/main/java/liquibase/Scope.java index 1190605bc06..7439869d667 100644 --- a/liquibase-core/src/main/java/liquibase/Scope.java +++ b/liquibase-core/src/main/java/liquibase/Scope.java @@ -1,5 +1,6 @@ package liquibase; +import liquibase.configuration.LiquibaseConfiguration; import liquibase.database.Database; import liquibase.database.DatabaseConnection; import liquibase.database.OfflineConnection; @@ -66,6 +67,13 @@ public static Scope getCurrentScope() { Scope rootScope = new Scope(); scopeManager.setCurrentScope(rootScope); + rootScope.values.put(Attr.logService.name(), new JavaLogService()); + rootScope.values.put(Attr.resourceAccessor.name(), new ClassLoaderResourceAccessor()); + rootScope.values.put(Attr.serviceLocator.name(), new StandardServiceLocator()); + + rootScope.values.put(Attr.ui.name(), new ConsoleUIService()); + rootScope.getSingleton(LiquibaseConfiguration.class).init(rootScope); + LogService overrideLogService = rootScope.getSingleton(LogServiceFactory.class).getDefaultLogService(); if (overrideLogService == null) { throw new UnexpectedLiquibaseException("Cannot find default log service"); @@ -109,10 +117,6 @@ public static void setScopeManager(ScopeManager scopeManager) { * Defaults serviceLocator to {@link StandardServiceLocator} */ private Scope() { - values.put(Attr.logService.name(), new JavaLogService()); - values.put(Attr.resourceAccessor.name(), new ClassLoaderResourceAccessor()); - values.put(Attr.serviceLocator.name(), new StandardServiceLocator()); - values.put(Attr.ui.name(), new ConsoleUIService()); } protected Scope(Scope parent, Map scopeValues) { diff --git a/liquibase-core/src/main/java/liquibase/ScopeManager.java b/liquibase-core/src/main/java/liquibase/ScopeManager.java index af9e7b87252..c497ca8969c 100644 --- a/liquibase-core/src/main/java/liquibase/ScopeManager.java +++ b/liquibase-core/src/main/java/liquibase/ScopeManager.java @@ -2,7 +2,6 @@ public abstract class ScopeManager { - public abstract Scope getCurrentScope(); protected abstract void setCurrentScope(Scope scope); diff --git a/liquibase-core/src/main/java/liquibase/change/AbstractSQLChange.java b/liquibase-core/src/main/java/liquibase/change/AbstractSQLChange.java index 82c63b2d200..9cf405f8b72 100644 --- a/liquibase-core/src/main/java/liquibase/change/AbstractSQLChange.java +++ b/liquibase-core/src/main/java/liquibase/change/AbstractSQLChange.java @@ -2,8 +2,7 @@ import liquibase.change.core.RawSQLChange; import liquibase.Scope; -import liquibase.configuration.GlobalConfiguration; -import liquibase.configuration.LiquibaseConfiguration; +import liquibase.GlobalConfiguration; import liquibase.database.Database; import liquibase.database.core.MSSQLDatabase; import liquibase.database.core.PostgresDatabase; @@ -194,11 +193,7 @@ public CheckSum generateCheckSum() { } if (sql != null) { - stream = new ByteArrayInputStream( - sql.getBytes( - LiquibaseConfiguration.getInstance().getConfiguration(GlobalConfiguration.class) - .getOutputEncoding() - ) + stream = new ByteArrayInputStream(sql.getBytes(GlobalConfiguration.OUTPUT_ENCODING.getCurrentValue()) ); } @@ -295,7 +290,7 @@ public static class NormalizingStream extends InputStream { public NormalizingStream(String endDelimiter, Boolean splitStatements, Boolean stripComments, InputStream stream) { this.stream = new PushbackInputStream(stream, 2048); try { - this.headerStream = new ByteArrayInputStream((endDelimiter+":"+splitStatements+":"+stripComments+":").getBytes(LiquibaseConfiguration.getInstance().getConfiguration(GlobalConfiguration.class).getOutputEncoding())); + this.headerStream = new ByteArrayInputStream((endDelimiter+":"+splitStatements+":"+stripComments+":").getBytes(GlobalConfiguration.OUTPUT_ENCODING.getCurrentValue())); } catch (UnsupportedEncodingException e) { throw new UnexpectedLiquibaseException(e); } diff --git a/liquibase-core/src/main/java/liquibase/change/core/CreateProcedureChange.java b/liquibase-core/src/main/java/liquibase/change/core/CreateProcedureChange.java index 0dec8574a2a..5e99f161830 100644 --- a/liquibase-core/src/main/java/liquibase/change/core/CreateProcedureChange.java +++ b/liquibase-core/src/main/java/liquibase/change/core/CreateProcedureChange.java @@ -3,9 +3,7 @@ import liquibase.Scope; import liquibase.change.*; import liquibase.changelog.ChangeLogParameters; -import liquibase.changelog.ChangeSet; -import liquibase.configuration.GlobalConfiguration; -import liquibase.configuration.LiquibaseConfiguration; +import liquibase.GlobalConfiguration; import liquibase.database.Database; import liquibase.database.DatabaseList; import liquibase.database.core.*; @@ -251,8 +249,7 @@ public CheckSum generateCheckSum() { procedureText = ""; } - String encoding = - LiquibaseConfiguration.getInstance().getConfiguration(GlobalConfiguration.class).getOutputEncoding(); + String encoding = GlobalConfiguration.OUTPUT_ENCODING.getCurrentValue(); if (procedureText != null) { try { stream = new ByteArrayInputStream(procedureText.getBytes(encoding)); diff --git a/liquibase-core/src/main/java/liquibase/change/core/CreateViewChange.java b/liquibase-core/src/main/java/liquibase/change/core/CreateViewChange.java index 907ec808e7d..3f9309962d1 100644 --- a/liquibase-core/src/main/java/liquibase/change/core/CreateViewChange.java +++ b/liquibase-core/src/main/java/liquibase/change/core/CreateViewChange.java @@ -3,8 +3,7 @@ import liquibase.Scope; import liquibase.change.*; import liquibase.changelog.ChangeLogParameters; -import liquibase.configuration.GlobalConfiguration; -import liquibase.configuration.LiquibaseConfiguration; +import liquibase.GlobalConfiguration; import liquibase.database.Database; import liquibase.database.core.OracleDatabase; import liquibase.database.core.SQLiteDatabase; @@ -199,7 +198,7 @@ public CheckSum generateCheckSum() { selectQuery = ""; } - String encoding = LiquibaseConfiguration.getInstance().getConfiguration(GlobalConfiguration.class).getOutputEncoding(); + String encoding = GlobalConfiguration.OUTPUT_ENCODING.getCurrentValue(); if (selectQuery != null) { try { stream = new ByteArrayInputStream(selectQuery.getBytes(encoding)); diff --git a/liquibase-core/src/main/java/liquibase/change/core/ExecuteShellCommandChange.java b/liquibase-core/src/main/java/liquibase/change/core/ExecuteShellCommandChange.java index 4c78cb6f7b2..6b09985df8a 100644 --- a/liquibase-core/src/main/java/liquibase/change/core/ExecuteShellCommandChange.java +++ b/liquibase-core/src/main/java/liquibase/change/core/ExecuteShellCommandChange.java @@ -5,8 +5,7 @@ import liquibase.change.ChangeMetaData; import liquibase.change.DatabaseChange; import liquibase.change.DatabaseChangeProperty; -import liquibase.configuration.GlobalConfiguration; -import liquibase.configuration.LiquibaseConfiguration; +import liquibase.GlobalConfiguration; import liquibase.database.Database; import liquibase.exception.UnexpectedLiquibaseException; import liquibase.exception.ValidationErrors; @@ -25,7 +24,6 @@ import java.io.*; import java.util.*; -import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeoutException; import java.util.concurrent.atomic.AtomicBoolean; import java.util.regex.Matcher; @@ -216,10 +214,8 @@ protected void executeCommand(Database database) throws Exception { Thread.currentThread().interrupt(); } - String errorStreamOut = errorStream.toString(LiquibaseConfiguration.getInstance().getConfiguration - (GlobalConfiguration.class).getOutputEncoding()); - String infoStreamOut = inputStream.toString(LiquibaseConfiguration.getInstance().getConfiguration - (GlobalConfiguration.class).getOutputEncoding()); + String errorStreamOut = errorStream.toString(GlobalConfiguration.OUTPUT_ENCODING.getCurrentValue()); + String infoStreamOut = inputStream.toString(GlobalConfiguration.OUTPUT_ENCODING.getCurrentValue()); if (errorStreamOut != null && !errorStreamOut.isEmpty()) { Scope.getCurrentScope().getLog(getClass()).severe(errorStreamOut); diff --git a/liquibase-core/src/main/java/liquibase/changelog/ChangeLogParameters.java b/liquibase-core/src/main/java/liquibase/changelog/ChangeLogParameters.java index 43923be15fa..32b18c14b5c 100644 --- a/liquibase-core/src/main/java/liquibase/changelog/ChangeLogParameters.java +++ b/liquibase-core/src/main/java/liquibase/changelog/ChangeLogParameters.java @@ -8,7 +8,7 @@ import liquibase.database.Database; import liquibase.database.DatabaseList; import liquibase.exception.DatabaseException; -import liquibase.parser.ChangeLogParserCofiguration; +import liquibase.parser.ChangeLogParserConfiguration; import liquibase.util.StringUtil; import java.util.*; @@ -210,8 +210,7 @@ protected static class ExpressionExpander { public ExpressionExpander(ChangeLogParameters changeLogParameters) { this.changeLogParameters = changeLogParameters; - this.enableEscaping = LiquibaseConfiguration.getInstance() - .getConfiguration(ChangeLogParserCofiguration.class).getSupportPropertyEscaping(); + this.enableEscaping = ChangeLogParserConfiguration.SUPPORT_PROPERTY_ESCAPING.getCurrentValue(); } public String expandExpressions(String text, DatabaseChangeLog changeLog) { diff --git a/liquibase-core/src/main/java/liquibase/changelog/ChangelogRewriter.java b/liquibase-core/src/main/java/liquibase/changelog/ChangelogRewriter.java index ef5c356f154..fb98253fe40 100644 --- a/liquibase-core/src/main/java/liquibase/changelog/ChangelogRewriter.java +++ b/liquibase-core/src/main/java/liquibase/changelog/ChangelogRewriter.java @@ -1,7 +1,7 @@ package liquibase.changelog; import liquibase.Scope; -import liquibase.configuration.GlobalConfiguration; +import liquibase.GlobalConfiguration; import liquibase.configuration.LiquibaseConfiguration; import liquibase.parser.core.xml.XMLChangeLogSAXParser; import liquibase.resource.InputStreamList; @@ -38,7 +38,7 @@ public static ChangeLogRewriterResult removeChangeLogId(String changeLogFile, St list = resourceAccessor.openStreams("", changeLogFile); List uris = list.getURIs(); InputStream is = list.iterator().next(); - String encoding = LiquibaseConfiguration.getInstance().getConfiguration(GlobalConfiguration.class).getOutputEncoding(); + String encoding = GlobalConfiguration.OUTPUT_ENCODING.getCurrentValue(); String changeLogString = StreamUtil.readStreamAsString(is, encoding); if (changeLogFile.toLowerCase().endsWith(".xml")) { // @@ -133,7 +133,7 @@ public static ChangeLogRewriterResult addChangeLogId(String changeLogFile, Strin list = resourceAccessor.openStreams("", changeLogFile); List uris = list.getURIs(); InputStream is = list.iterator().next(); - String encoding = LiquibaseConfiguration.getInstance().getConfiguration(GlobalConfiguration.class).getOutputEncoding(); + String encoding = GlobalConfiguration.OUTPUT_ENCODING.getCurrentValue(); String changeLogString = StreamUtil.readStreamAsString(is, encoding); if (changeLogFile.toLowerCase().endsWith(".xml")) { String patternString = "(?ms).*]*>"; @@ -229,4 +229,4 @@ public ChangeLogRewriterResult(String message, boolean success) { public String message; public boolean success; } -} \ No newline at end of file +} diff --git a/liquibase-core/src/main/java/liquibase/changelog/OfflineChangeLogHistoryService.java b/liquibase-core/src/main/java/liquibase/changelog/OfflineChangeLogHistoryService.java index a895d5bc110..719098d51e7 100644 --- a/liquibase-core/src/main/java/liquibase/changelog/OfflineChangeLogHistoryService.java +++ b/liquibase-core/src/main/java/liquibase/changelog/OfflineChangeLogHistoryService.java @@ -5,8 +5,7 @@ import liquibase.Scope; import liquibase.change.CheckSum; import liquibase.changelog.ChangeSet.ExecType; -import liquibase.configuration.GlobalConfiguration; -import liquibase.configuration.LiquibaseConfiguration; +import liquibase.GlobalConfiguration; import liquibase.database.Database; import liquibase.database.OfflineConnection; import liquibase.exception.DatabaseException; @@ -18,7 +17,6 @@ import liquibase.statement.core.MarkChangeSetRanStatement; import liquibase.statement.core.RemoveChangeSetRanStatusStatement; import liquibase.statement.core.UpdateChangeSetChecksumStatement; -import liquibase.structure.core.Column; import liquibase.util.ISODateFormat; import liquibase.util.LiquibaseUtil; import liquibase.util.csv.CSVReader; @@ -26,7 +24,6 @@ import java.io.*; import java.util.ArrayList; -import java.util.Arrays; import java.util.Date; import java.util.List; @@ -122,7 +119,7 @@ public void init() throws DatabaseException { protected void writeHeader(File file) throws IOException { try (FileOutputStream outputStream = new FileOutputStream(file); Writer writer = new OutputStreamWriter(outputStream, - LiquibaseConfiguration.getInstance().getConfiguration(GlobalConfiguration.class).getOutputEncoding()) + GlobalConfiguration.OUTPUT_ENCODING.getCurrentValue()) ) { CSVWriter csvWriter = new CSVWriter(writer); String[] columns = new String[Columns.values().length]; @@ -151,7 +148,7 @@ public String[] execute(String[] line) { @Override public List getRanChangeSets() throws DatabaseException { try ( - Reader reader = new InputStreamReader(new FileInputStream(this.changeLogFile), LiquibaseConfiguration.getInstance().getConfiguration(GlobalConfiguration.class).getOutputEncoding()); + Reader reader = new InputStreamReader(new FileInputStream(this.changeLogFile), GlobalConfiguration.OUTPUT_ENCODING.getCurrentValue()); ) { CSVReader csvReader = new CSVReader(reader); @@ -207,8 +204,8 @@ protected void replaceChangeSet(ChangeSet changeSet, ReplaceChangeSetLogic repla File newFile = new File(oldFile.getParentFile(), oldFile.getName()+".new"); try ( - Reader reader = new InputStreamReader(new FileInputStream(oldFile), LiquibaseConfiguration.getInstance().getConfiguration(GlobalConfiguration.class).getOutputEncoding()); - Writer writer = new OutputStreamWriter(new FileOutputStream(newFile), LiquibaseConfiguration.getInstance().getConfiguration(GlobalConfiguration.class).getOutputEncoding()); + Reader reader = new InputStreamReader(new FileInputStream(oldFile), GlobalConfiguration.OUTPUT_ENCODING.getCurrentValue()); + Writer writer = new OutputStreamWriter(new FileOutputStream(newFile), GlobalConfiguration.OUTPUT_ENCODING.getCurrentValue()); CSVReader csvReader = new CSVReader(reader); CSVWriter csvWriter = new CSVWriter(writer); ) @@ -235,8 +232,8 @@ protected void appendChangeSet(ChangeSet changeSet, ChangeSet.ExecType execType) File newFile = new File(oldFile.getParentFile(), oldFile.getName()+".new"); try ( - Reader reader = new InputStreamReader(new FileInputStream(oldFile), LiquibaseConfiguration.getInstance().getConfiguration(GlobalConfiguration.class).getOutputEncoding()); - Writer writer = new OutputStreamWriter(new FileOutputStream(newFile), LiquibaseConfiguration.getInstance().getConfiguration(GlobalConfiguration.class).getOutputEncoding()); + Reader reader = new InputStreamReader(new FileInputStream(oldFile), GlobalConfiguration.OUTPUT_ENCODING.getCurrentValue()); + Writer writer = new OutputStreamWriter(new FileOutputStream(newFile), GlobalConfiguration.OUTPUT_ENCODING.getCurrentValue()); CSVReader csvReader = new CSVReader(reader); CSVWriter csvWriter = new CSVWriter(writer); ) @@ -319,7 +316,7 @@ public int getNextSequenceValue() throws LiquibaseException { lastChangeSetSequenceValue = 0; try ( - Reader reader = new InputStreamReader(new FileInputStream(this.changeLogFile), LiquibaseConfiguration.getInstance().getConfiguration(GlobalConfiguration.class).getOutputEncoding()); + Reader reader = new InputStreamReader(new FileInputStream(this.changeLogFile), GlobalConfiguration.OUTPUT_ENCODING.getCurrentValue()); ) { diff --git a/liquibase-core/src/main/java/liquibase/command/AbstractCommand.java b/liquibase-core/src/main/java/liquibase/command/AbstractCommand.java index a5c78f31e0e..2be7820f055 100644 --- a/liquibase-core/src/main/java/liquibase/command/AbstractCommand.java +++ b/liquibase-core/src/main/java/liquibase/command/AbstractCommand.java @@ -1,30 +1,21 @@ package liquibase.command; -import liquibase.servicelocator.PrioritizedService; +import java.util.SortedSet; +import java.util.TreeSet; public abstract class AbstractCommand implements LiquibaseCommand { @Override public int getPriority(String commandName) { if ((commandName != null) && commandName.equalsIgnoreCase(getName())) { - return PrioritizedService.PRIORITY_DEFAULT; + return PRIORITY_DEFAULT; } else { - return -1; + return PRIORITY_NOT_APPLICABLE; } } - public final T execute() throws CommandExecutionException { - this.validate(); - try { - return this.run(); - } catch (Exception e) { - if (e instanceof CommandExecutionException) { - throw (CommandExecutionException) e; - } else { - throw new CommandExecutionException(e); - } - } + @Override + public SortedSet getArguments() { + return new TreeSet<>(); } - - protected abstract T run() throws Exception; } diff --git a/liquibase-core/src/main/java/liquibase/command/CommandArgument.java b/liquibase-core/src/main/java/liquibase/command/CommandArgument.java new file mode 100644 index 00000000000..ac0b7760644 --- /dev/null +++ b/liquibase-core/src/main/java/liquibase/command/CommandArgument.java @@ -0,0 +1,45 @@ +package liquibase.command; + +import java.util.Objects; + +public class CommandArgument implements Comparable { + + private String name; + private String description; + private Class dataType; + private boolean required; + + public String getName() { + return name; + } + + public String getDescription() { + return description; + } + + public Class getDataType() { + return dataType; + } + + public boolean isRequired() { + return required; + } + + @Override + public int compareTo(Object o) { + return this.getName().compareTo(((CommandArgument) o).getName()); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + CommandArgument that = (CommandArgument) o; + return Objects.equals(name, that.name); + } + + @Override + public int hashCode() { + return Objects.hash(name); + } +} diff --git a/liquibase-core/src/main/java/liquibase/command/CommandFactory.java b/liquibase-core/src/main/java/liquibase/command/CommandFactory.java index af9a7937901..03e2d911548 100644 --- a/liquibase-core/src/main/java/liquibase/command/CommandFactory.java +++ b/liquibase-core/src/main/java/liquibase/command/CommandFactory.java @@ -1,79 +1,42 @@ package liquibase.command; -import liquibase.Scope; -import liquibase.exception.UnexpectedLiquibaseException; -import liquibase.servicelocator.ServiceLocator; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; -import java.util.List; +import liquibase.plugin.AbstractPluginFactory; /** * Manages {@link LiquibaseCommand} implementations. */ -public class CommandFactory { - - private static CommandFactory instance; - - private List commands; +public class CommandFactory extends AbstractPluginFactory { - private CommandFactory() { - commands = new ArrayList<>(); - try { - for (LiquibaseCommand command : Scope.getCurrentScope().getServiceLocator().findInstances(LiquibaseCommand.class)) { - register(command); - } - } catch (Exception e) { - throw new UnexpectedLiquibaseException(e); - } + protected CommandFactory() { } - public static synchronized CommandFactory getInstance() { - if (instance == null) { - instance = new CommandFactory(); - } - return instance; + @Override + protected Class getPluginClass() { + return LiquibaseCommand.class; } - public static synchronized void reset() { - instance = new CommandFactory(); + @Override + protected int getPriority(LiquibaseCommand obj, Object... args) { + return obj.getPriority((String) args[0]); } + public LiquibaseCommand getCommand(String commandName) { + return getPlugin(commandName); + } - public LiquibaseCommand getCommand(final String commandName) { - - Comparator commandComparator = new Comparator() { - @Override - public int compare(LiquibaseCommand o1, LiquibaseCommand o2) { - return Integer.valueOf(o2.getPriority(commandName)).compareTo(o1.getPriority(commandName)); - } - }; - - - List sortedCommands = new ArrayList<>(commands); - Collections.sort(sortedCommands, commandComparator); - if (sortedCommands.isEmpty()) { - throw new UnexpectedLiquibaseException("Could not find command class for "+commandName); - } + public T execute(LiquibaseCommand command) throws CommandExecutionException { + command.validate(); try { - LiquibaseCommand command = sortedCommands.iterator().next().getClass().getConstructor().newInstance(); - - if (command.getPriority(commandName) <= 0) { - throw new UnexpectedLiquibaseException("Could not find command class for "+commandName); - } - return command; + return command.run(); } catch (Exception e) { - throw new UnexpectedLiquibaseException(e); + if (e instanceof CommandExecutionException) { + throw (CommandExecutionException) e; + } else { + throw new CommandExecutionException(e); + } } - } - public void register(LiquibaseCommand command) { - commands.add(command); } - public void unregister(LiquibaseCommand command) { - commands.remove(command); - } } diff --git a/liquibase-core/src/main/java/liquibase/command/LiquibaseCommand.java b/liquibase-core/src/main/java/liquibase/command/LiquibaseCommand.java index 3627208a775..bab1d21652b 100644 --- a/liquibase-core/src/main/java/liquibase/command/LiquibaseCommand.java +++ b/liquibase-core/src/main/java/liquibase/command/LiquibaseCommand.java @@ -1,20 +1,27 @@ package liquibase.command; +import liquibase.plugin.Plugin; + +import java.util.SortedSet; + /** * Commands are higher-level functions. They may execute multiple {@link liquibase.change.Change}s and usually interact with the outside world. * Commands are different from Actions in that they implement end-user functionality rather than small pieces of logic. * We package functionaly as commands so that the command line interface as well as other integrations can all use the same business logic. */ -public interface LiquibaseCommand { +public interface LiquibaseCommand extends Plugin { String getName(); + int getPriority(String commandName); + + SortedSet getArguments(); + CommandValidationErrors validate(); /** - * Executes the command. Should call {@link #validate()} as part of this method and throw {@link CommandExecutionException} if validation fails or there are any errors executing the command. + * Function that performs the actual logic. This should not be called directly by any code, + * only by {@link CommandFactory#execute(LiquibaseCommand)} */ - T execute() throws CommandExecutionException; - - int getPriority(String commandName); -} \ No newline at end of file + T run() throws Exception; +} diff --git a/liquibase-core/src/main/java/liquibase/command/core/DeactivateChangeLogCommand.java b/liquibase-core/src/main/java/liquibase/command/core/DeactivateChangeLogCommand.java index b5059ae6983..ec127f243cc 100644 --- a/liquibase-core/src/main/java/liquibase/command/core/DeactivateChangeLogCommand.java +++ b/liquibase-core/src/main/java/liquibase/command/core/DeactivateChangeLogCommand.java @@ -56,7 +56,7 @@ public void setOutputStream(PrintStream outputStream) { } @Override - protected CommandResult run() throws Exception { + public CommandResult run() throws Exception { // // Access the HubService // Stop if we do no have a key diff --git a/liquibase-core/src/main/java/liquibase/command/core/DiffCommand.java b/liquibase-core/src/main/java/liquibase/command/core/DiffCommand.java index a765f7f6638..225a9124c40 100644 --- a/liquibase-core/src/main/java/liquibase/command/core/DiffCommand.java +++ b/liquibase-core/src/main/java/liquibase/command/core/DiffCommand.java @@ -130,7 +130,7 @@ public DiffCommand setCompareControl(CompareControl compareControl) { } @Override - protected CommandResult run() throws Exception { + public CommandResult run() throws Exception { SnapshotCommand.logUnsupportedDatabase(this.getReferenceDatabase(), this.getClass()); DiffResult diffResult = createDiffResult(); diff --git a/liquibase-core/src/main/java/liquibase/command/core/DiffToChangeLogCommand.java b/liquibase-core/src/main/java/liquibase/command/core/DiffToChangeLogCommand.java index 548f1db0d94..b58bba748b6 100644 --- a/liquibase-core/src/main/java/liquibase/command/core/DiffToChangeLogCommand.java +++ b/liquibase-core/src/main/java/liquibase/command/core/DiffToChangeLogCommand.java @@ -51,7 +51,7 @@ public DiffToChangeLogCommand setDiffOutputControl(DiffOutputControl diffOutputC } @Override - protected CommandResult run() throws Exception { + public CommandResult run() throws Exception { SnapshotCommand.logUnsupportedDatabase(this.getReferenceDatabase(), this.getClass()); DiffResult diffResult = createDiffResult(); diff --git a/liquibase-core/src/main/java/liquibase/command/core/DropAllCommand.java b/liquibase-core/src/main/java/liquibase/command/core/DropAllCommand.java index ffbe6d8fba0..e63b7565628 100644 --- a/liquibase-core/src/main/java/liquibase/command/core/DropAllCommand.java +++ b/liquibase-core/src/main/java/liquibase/command/core/DropAllCommand.java @@ -7,8 +7,7 @@ import liquibase.command.AbstractCommand; import liquibase.command.CommandResult; import liquibase.command.CommandValidationErrors; -import liquibase.configuration.HubConfiguration; -import liquibase.configuration.LiquibaseConfiguration; +import liquibase.hub.HubConfiguration; import liquibase.database.Database; import liquibase.exception.DatabaseException; import liquibase.exception.LiquibaseException; @@ -101,7 +100,7 @@ public void setHubConnectionId(String hubConnectionIdString) { } @Override - protected CommandResult run() throws Exception { + public CommandResult run() throws Exception { LockService lockService = LockServiceFactory.getInstance().getLockService(database); Logger log = Scope.getCurrentScope().getLog(getClass()); HubUpdater hubUpdater = null; @@ -159,9 +158,8 @@ protected CommandResult run() throws Exception { // a LiquibaseHubException // private HubChangeLog getHubChangeLog(DatabaseChangeLog changeLog) throws LiquibaseHubException { - HubConfiguration hubConfiguration = LiquibaseConfiguration.getInstance().getConfiguration(HubConfiguration.class); - String apiKey = StringUtil.trimToNull(hubConfiguration.getLiquibaseHubApiKey()); - String hubMode = StringUtil.trimToNull(hubConfiguration.getLiquibaseHubMode()); + String apiKey = StringUtil.trimToNull(HubConfiguration.LIQUIBASE_HUB_API_KEY.getCurrentValue()); + String hubMode = StringUtil.trimToNull(HubConfiguration.LIQUIBASE_HUB_MODE.getCurrentValue()); String changeLogId = changeLog.getChangeLogId(); final HubServiceFactory hubServiceFactory = Scope.getCurrentScope().getSingleton(HubServiceFactory.class); if (apiKey == null || hubMode.equals("off") || !hubServiceFactory.isOnline()) { diff --git a/liquibase-core/src/main/java/liquibase/command/core/ExecuteSqlCommand.java b/liquibase-core/src/main/java/liquibase/command/core/ExecuteSqlCommand.java index 07f6fa414c5..cf9a7b38b04 100644 --- a/liquibase-core/src/main/java/liquibase/command/core/ExecuteSqlCommand.java +++ b/liquibase-core/src/main/java/liquibase/command/core/ExecuteSqlCommand.java @@ -65,7 +65,7 @@ public CommandValidationErrors validate() { } @Override - protected CommandResult run() throws Exception { + public CommandResult run() throws Exception { Executor executor = Scope.getCurrentScope().getSingleton(ExecutorService.class).getExecutor("jdbc", database); String sqlText; if (sqlFile == null) { diff --git a/liquibase-core/src/main/java/liquibase/command/core/GenerateChangeLogCommand.java b/liquibase-core/src/main/java/liquibase/command/core/GenerateChangeLogCommand.java index d2f28fac0de..169815e60e0 100644 --- a/liquibase-core/src/main/java/liquibase/command/core/GenerateChangeLogCommand.java +++ b/liquibase-core/src/main/java/liquibase/command/core/GenerateChangeLogCommand.java @@ -48,7 +48,7 @@ public GenerateChangeLogCommand setContext(String context) { } @Override - protected CommandResult run() throws Exception { + public CommandResult run() throws Exception { outputBestPracticeMessage(); String changeLogFile = StringUtil.trimToNull(getChangeLogFile()); diff --git a/liquibase-core/src/main/java/liquibase/command/core/HistoryCommand.java b/liquibase-core/src/main/java/liquibase/command/core/HistoryCommand.java index c5faeccafbd..35bd90859da 100644 --- a/liquibase-core/src/main/java/liquibase/command/core/HistoryCommand.java +++ b/liquibase-core/src/main/java/liquibase/command/core/HistoryCommand.java @@ -52,7 +52,7 @@ public void setOutputStream(PrintStream outputStream) { } @Override - protected CommandResult run() throws Exception { + public CommandResult run() throws Exception { ChangeLogHistoryService historyService = ChangeLogHistoryServiceFactory.getInstance().getChangeLogService(database); outputStream.println("Liquibase History for " + database.getConnection().getURL()); diff --git a/liquibase-core/src/main/java/liquibase/command/core/RegisterChangeLogCommand.java b/liquibase-core/src/main/java/liquibase/command/core/RegisterChangeLogCommand.java index bf536d13dbf..5b507dd85e8 100644 --- a/liquibase-core/src/main/java/liquibase/command/core/RegisterChangeLogCommand.java +++ b/liquibase-core/src/main/java/liquibase/command/core/RegisterChangeLogCommand.java @@ -6,8 +6,8 @@ import liquibase.command.AbstractSelfConfiguratingCommand; import liquibase.command.CommandResult; import liquibase.command.CommandValidationErrors; -import liquibase.configuration.HubConfiguration; -import liquibase.configuration.LiquibaseConfiguration; +import liquibase.GlobalConfiguration; +import liquibase.hub.HubConfiguration; import liquibase.exception.CommandLineParsingException; import liquibase.exception.LiquibaseException; import liquibase.hub.HubService; @@ -71,7 +71,7 @@ public void setOutputStream(PrintStream outputStream) { } @Override - protected CommandResult run() throws Exception { + public CommandResult run() throws Exception { // // Access the HubService // Stop if we do no have a key @@ -212,8 +212,7 @@ public int compare(Project o1, Project o2) { private String readProjectNameFromConsole() throws CommandLineParsingException { final UIService ui = Scope.getCurrentScope().getUI(); - HubConfiguration hubConfiguration = LiquibaseConfiguration.getInstance().getConfiguration(HubConfiguration.class); - String hubUrl = hubConfiguration.getLiquibaseHubUrl(); + String hubUrl = HubConfiguration.LIQUIBASE_HUB_URL.getCurrentValue(); String input = ui.prompt("Please enter your Project name and press [enter]. This is editable in your Liquibase Hub account at " + hubUrl, null, null, String.class); return StringUtil.trimToEmpty(input); } diff --git a/liquibase-core/src/main/java/liquibase/command/core/SnapshotCommand.java b/liquibase-core/src/main/java/liquibase/command/core/SnapshotCommand.java index 01d879e5a73..d69f10751b0 100644 --- a/liquibase-core/src/main/java/liquibase/command/core/SnapshotCommand.java +++ b/liquibase-core/src/main/java/liquibase/command/core/SnapshotCommand.java @@ -94,7 +94,7 @@ public void setSnapshotMetadata(Map snapshotMetadata) { } @Override - protected SnapshotCommandResult run() throws Exception { + public SnapshotCommandResult run() throws Exception { SnapshotCommand.logUnsupportedDatabase(database, this.getClass()); SnapshotControl snapshotControl = new SnapshotControl(database); snapshotControl.setSnapshotListener(snapshotListener); diff --git a/liquibase-core/src/main/java/liquibase/command/core/SyncHubCommand.java b/liquibase-core/src/main/java/liquibase/command/core/SyncHubCommand.java index 1440b3eeb6d..04041b1a448 100644 --- a/liquibase-core/src/main/java/liquibase/command/core/SyncHubCommand.java +++ b/liquibase-core/src/main/java/liquibase/command/core/SyncHubCommand.java @@ -80,7 +80,7 @@ public CommandValidationErrors validate() { } @Override - protected CommandResult run() throws Exception { + public CommandResult run() throws Exception { final HubServiceFactory hubServiceFactory = Scope.getCurrentScope().getSingleton(HubServiceFactory.class); if (! hubServiceFactory.isOnline()) { if (failIfOnline) { diff --git a/liquibase-core/src/main/java/liquibase/configuration/AbstractConfigurationContainer.java b/liquibase-core/src/main/java/liquibase/configuration/AbstractConfigurationContainer.java index 4e52cd9a8c5..d089e13bc40 100644 --- a/liquibase-core/src/main/java/liquibase/configuration/AbstractConfigurationContainer.java +++ b/liquibase-core/src/main/java/liquibase/configuration/AbstractConfigurationContainer.java @@ -1,161 +1,109 @@ package liquibase.configuration; -import liquibase.exception.UnexpectedLiquibaseException; +import liquibase.Scope; +import liquibase.configuration.core.DeprecatedConfigurationValueProvider; -import java.util.*; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; /** - * Base class for configuration classes used by {@link liquibase.configuration.LiquibaseConfiguration}. - * Implementations must have a no-arg constructor for LiquibaseConfiguration to initialize them as needed. - *

- * AbstractConfigurationContainer implementations contain a "namespace" which can be used as the prefix to system properties or cases where there may be name conflicts. - *

- * Properties can be accessed by name using the {@link #getValue(String, Class)} method, but implementation should implement standard get/set methods for easier use. + * @deprecated Use new {@link ConfigurationDefinition} style */ public abstract class AbstractConfigurationContainer implements ConfigurationContainer { - private ConfigurationContainer configurationContainer; + private final String namespace; + private final ConfigurationContainer container; + private Map properties = new HashMap<>(); - /** - * Subclasses must call this constructor passing the namespace, but must themselves provide a no-arg public constructor. - */ - protected AbstractConfigurationContainer(String namespace) { - this.configurationContainer = new ConfigurationContainer(namespace); + public AbstractConfigurationContainer(String namespace) { + this.namespace = namespace; + this.container = new ConfigurationContainer(); } + /** + * @deprecated + */ protected ConfigurationContainer getContainer() { - return configurationContainer; + return container; } /** - * Return the ConfigurationProperty object for the given property name. - * Normally {@link #getValue(String, Class)} is the easiest method to call. + * @deprecated */ @Override public ConfigurationProperty getProperty(String propertyName) { - return getContainer().getProperty(propertyName); + return properties.get(propertyName); } /** - * Return all available properties. + * @deprecated */ @Override public Set getProperties() { - return new HashSet<>(getContainer().properties.values()); + return new HashSet<>(properties.values()); } /** - * Returns the value for the given property cast to the passed returnType. - * If the type of the property and the given return type are not compatible an exception will be thrown. - * If the passed propertyName is not a defined property, an exception is thrown. + * @deprecated */ @Override public T getValue(String propertyName, Class returnType) { - return getContainer().getValue(propertyName, returnType); + final ConfiguredValue currentValue = Scope.getCurrentScope().getSingleton(LiquibaseConfiguration.class).getCurrentConfiguredValue(namespace + "." + propertyName); + return (T) currentValue.getValue(); } - /** - * Override default values for properties with the given ConfigurationProviders. + * @deprecated */ - @Override - public void init(ConfigurationValueProvider... configurationValueProviders) { - if (configurationValueProviders != null) { - for (ConfigurationProperty property : getContainer().properties.values()) { - property.init(configurationValueProviders); - } - } - } - @Override public void setValue(String propertyName, Object value) { - getContainer().setValue(propertyName, value); + DeprecatedConfigurationValueProvider.setData(namespace + "." + propertyName, value); } + /** + * @deprecated + */ @Override public String getNamespace() { - return getContainer().getNamespace(); + return namespace; } /** - * Like a java.util.Map, but with extra logic for working with ConfigurationProperties. - * Used to define and hold available properties. Methods return "this" to allow easy chaining. + * @deprecated */ - protected static class ConfigurationContainer { - - private final String namespace; - private final Map properties = new HashMap<>(); - - protected ConfigurationContainer(String namespace) { - this.namespace = namespace; - } - - public String getNamespace() { - return namespace; - } + protected class ConfigurationContainer { /** - * Adds a property definition to this configuration. + * @deprecated */ public ConfigurationProperty addProperty(String propertyName, Class type) { - ConfigurationProperty property = new ConfigurationProperty(namespace, propertyName, type); - properties.put(propertyName, property); + final ConfigurationDefinition.Builder builder = new ConfigurationDefinition.Builder(namespace); + final ConfigurationDefinition.Builder.NewDefinition newDefinition = builder.define(propertyName, type); + final ConfigurationProperty property = new ConfigurationProperty(namespace, newDefinition); + + properties.put(propertyName, property); return property; } - /** - * Returns the ConfigurationProperty object with the given name. If the property was not defined, an exception is thrown. - */ public ConfigurationProperty getProperty(String propertyName) { - ConfigurationProperty property = properties.get(propertyName); - if (property != null) { - return property; - } - - // - // Not matching with the actual key then try case insensitive - // - for (Map.Entry entry : properties.entrySet()) { - if (entry.getKey().equalsIgnoreCase(propertyName)) { - return entry.getValue(); - } - } - - // - // No match so throw the exception - // - throw new UnexpectedLiquibaseException("Unknown property on "+getClass().getName()+": "+propertyName); + return AbstractConfigurationContainer.this.getProperty(propertyName); } - /** - * Returns the value for the given property. If the property was not defined, an exception is thrown. - */ public T getValue(String propertyName, Class returnType) { - ConfigurationProperty property = getProperty(propertyName); - - if (!property.getType().isAssignableFrom(returnType)) { - throw new UnexpectedLiquibaseException("Property "+propertyName+" on "+getClass().getName()+" is of type "+property.getType().getName()+", not "+returnType.getName()); - } - - return (T) property.getValue(); + return AbstractConfigurationContainer.this.getValue(propertyName, returnType); } - /** - * Sets the value for the given property. - * Any value set through this method will overwrite any default values found by the configured ConfigurationPropertyProviders. - * If the property was not defined, an exception is thrown. - */ public void setValue(String propertyName, Object value) { - ConfigurationProperty property = getProperty(propertyName); // properties.get(propertyName); - - if (property == null) { - throw new UnexpectedLiquibaseException("Unknown property on "+getClass().getName()+": "+propertyName); - } - - property.setValue(value); - + AbstractConfigurationContainer.this.setValue(propertyName, value); } } + protected static class DelegatedConfigurationContainer extends AbstractConfigurationContainer { + public DelegatedConfigurationContainer(String namespace) { + super(namespace); + } + } } diff --git a/liquibase-core/src/main/java/liquibase/configuration/AbstractConfigurationValueProvider.java b/liquibase-core/src/main/java/liquibase/configuration/AbstractConfigurationValueProvider.java new file mode 100644 index 00000000000..1fd7cb7f48c --- /dev/null +++ b/liquibase-core/src/main/java/liquibase/configuration/AbstractConfigurationValueProvider.java @@ -0,0 +1,7 @@ +package liquibase.configuration; + +/** + * Convenience base class for {@link ConfigurationValueProvider} implementations + */ +public abstract class AbstractConfigurationValueProvider implements ConfigurationValueProvider { +} diff --git a/liquibase-core/src/main/java/liquibase/configuration/AbstractMapConfigurationValueProvider.java b/liquibase-core/src/main/java/liquibase/configuration/AbstractMapConfigurationValueProvider.java new file mode 100644 index 00000000000..527f169cee0 --- /dev/null +++ b/liquibase-core/src/main/java/liquibase/configuration/AbstractMapConfigurationValueProvider.java @@ -0,0 +1,88 @@ +package liquibase.configuration; + +import liquibase.util.StringUtil; + +import java.util.Map; + +/** + * Convenience class for {@link ConfigurationValueProvider}s that can collect the possible values into a Map. + * By default, it will follow standardized fuzzy-matching rules including being case insensitive, checking camelCase and kabob-case, etc. + * + * @see #keyMatches(String, String) + */ +public abstract class AbstractMapConfigurationValueProvider extends AbstractConfigurationValueProvider { + + protected abstract Map getMap(); + + protected abstract String getSourceDescription(); + + /** + * Finds the given key in the result of {@link #getMap()} using {@link #keyMatches(String, String)} to determine key equality + */ + @Override + public ProvidedValue getProvidedValue(String key) { + if (key == null) { + return null; + } + + final Map sourceData = getMap(); + + //try direct lookup first, for performance: + if (sourceData.containsKey(key)) { + final Object foundValue = sourceData.get(key); + if (isValueSet(foundValue)) { + return new ProvidedValue(key, key, foundValue, getSourceDescription(), this); + } + } + + + for (Map.Entry entry : sourceData.entrySet()) { + final String actualKey = String.valueOf(entry.getKey()); + + if (keyMatches(key, actualKey)) { + final Object value = entry.getValue(); + if (isValueSet(value)) { + return new ProvidedValue(key, actualKey, value, getSourceDescription(), this); + } + } + } + + return null; + } + + /** + * Used by {@link #getProvidedValue(String)} to determine if the given value is a "real" value. + * This implementation returns false if value is null or if it is an empty string + */ + protected boolean isValueSet(Object value) { + if (value == null) { + return false; + } + if (value instanceof String) { + return StringUtil.isNotEmpty((String) value); + } + + return false; + } + + /** + * Used by {@link #getProvidedValue(String)} to determine of a given map entry matches the wanted key. + * This implementation compares the values case-insensitively, and will replace camelCase words with kabob-case + * @param wantedKey the configuration key requested + * @param storedKey the key stored in the map + */ + protected boolean keyMatches(String wantedKey, String storedKey) { + if (storedKey.equalsIgnoreCase(wantedKey)) { + return true; + } + + //convert camelCase to kabob-case + wantedKey = wantedKey.replaceAll("([A-Z])", "-$1"); + if (storedKey.equalsIgnoreCase(wantedKey)) { + return true; + } + + return false; + } + +} diff --git a/liquibase-core/src/main/java/liquibase/configuration/AutoloadedConfigurations.java b/liquibase-core/src/main/java/liquibase/configuration/AutoloadedConfigurations.java new file mode 100644 index 00000000000..223ea9b783f --- /dev/null +++ b/liquibase-core/src/main/java/liquibase/configuration/AutoloadedConfigurations.java @@ -0,0 +1,9 @@ +package liquibase.configuration; + +/** + * Marker interface for a class containing {@link ConfigurationDefinition} which should be auto-loaded at Liquibase startup. + * All classes that implement this interface must still be registered in the META-INF/services/liquibase.configuration.AutoloadedConfigurations file. + */ +public interface AutoloadedConfigurations { + +} diff --git a/liquibase-core/src/main/java/liquibase/configuration/ConfigurationContainer.java b/liquibase-core/src/main/java/liquibase/configuration/ConfigurationContainer.java index 3cc529f6f5d..36186531940 100644 --- a/liquibase-core/src/main/java/liquibase/configuration/ConfigurationContainer.java +++ b/liquibase-core/src/main/java/liquibase/configuration/ConfigurationContainer.java @@ -2,16 +2,33 @@ import java.util.Set; +/** + * @deprecated interface from old style configuration code. Use {@link ConfigurationDefinition} and {@link AutoloadedConfigurations} now. + */ public interface ConfigurationContainer { + + /** + * @deprecated + */ ConfigurationProperty getProperty(String propertyName); + /** + * @deprecated + */ Set getProperties(); + /** + * @deprecated + */ T getValue(String propertyName, Class returnType); - - void setValue(String propertyName, Object value); - void init(ConfigurationValueProvider... configurationValueProviders); + /** + * @deprecated + */ + void setValue(String propertyName, Object value); + /** + * @deprecated + */ String getNamespace(); } diff --git a/liquibase-core/src/main/java/liquibase/configuration/ConfigurationDefinition.java b/liquibase-core/src/main/java/liquibase/configuration/ConfigurationDefinition.java new file mode 100644 index 00000000000..831eb692fb0 --- /dev/null +++ b/liquibase-core/src/main/java/liquibase/configuration/ConfigurationDefinition.java @@ -0,0 +1,354 @@ +package liquibase.configuration; + +import liquibase.Scope; +import liquibase.util.ObjectUtil; + +import java.util.Objects; +import java.util.Set; +import java.util.TreeSet; +import java.util.regex.Pattern; + +/** + * A higher-level/detailed definition to provide type-safety, metadata, default values, etc.. + * Any code that is working with configurations should be using an instance of this class, rather than the lower-level, generic {@link LiquibaseConfiguration} + *

+ * ConfigurationDefinitions that are registered with {@link LiquibaseConfiguration#registerDefinition(ConfigurationDefinition)} will + * be available in generated help etc. + *

+ * These objects are immutable, so to construct definitions, use {@link Builder} + *

+ * The definition keys should be dot-separated, camelCased names, using a unique "namespace" as part of it. + * For example:

yourCorp.yourProperty
or
yourCorp.sub.otherProperty
. + * Liquibase uses "liquibase" as the base namespace like
liquibase.shouldRun
+ * + */ +public class ConfigurationDefinition implements Comparable> { + + private final String key; + private final Set aliasKeys = new TreeSet<>(); + private final Class type; + private String description; + private DataType defaultValue; + private boolean commonlyUsed; + private ConfigurationValueConverter valueHandler; + private ConfigurationValueObfuscator valueObfuscator; + + private static final Pattern ALLOWED_KEY_PATTERN = Pattern.compile("[a-zA-Z0-9.]+"); + + /** + * @return if the given {@link ConfiguredValue} was set by a default value + */ + public static boolean wasDefaultValueUsed(ConfiguredValue configuredValue) { + for (ProvidedValue providedValue : configuredValue.getProvidedValues()) { + if (providedValue.getProvider() != null && providedValue.getProvider() instanceof ConfigurationDefinition.DefaultValueProvider) { + return true; + } + } + + return false; + } + + /** + * Constructor private to force {@link Builder} usage + */ + private ConfigurationDefinition(String key, Class type) { + if (!ALLOWED_KEY_PATTERN.matcher(key).matches()) { + throw new IllegalArgumentException("Invalid key format: "+key); + } + + this.key = key; + this.type = type; + this.valueHandler = value -> ObjectUtil.convert(value, type); + } + + /** + * Convenience method around {@link #getCurrentConfiguredValue()} to return the value. + */ + public DataType getCurrentValue() { + final Object value = getCurrentConfiguredValue().getProvidedValue().getValue(); + try { + return (DataType) value; + } catch (ClassCastException e) { + throw new IllegalArgumentException("The current value of "+key+" not the expected type: "+ e.getMessage(), e); + } + } + + /** + * Convenience method around {@link #getCurrentConfiguredValue()} to return the obfuscated version of the value. + * @return the obfuscated value, or the plain-text value if no obfuscator is defined for this definition. + */ + public DataType getCurrentValueObfuscated() { + final DataType currentValue = getCurrentValue(); + + if (this.valueObfuscator == null) { + return currentValue; + } + + return this.valueObfuscator.obfuscate(currentValue); + } + + /** + * @return Full details on the current value for this definition. + * Will always return a {@link ConfiguredValue}, + */ + public ConfiguredValue getCurrentConfiguredValue() { + final LiquibaseConfiguration liquibaseConfiguration = Scope.getCurrentScope().getSingleton(LiquibaseConfiguration.class); + + ConfiguredValue configurationValue = liquibaseConfiguration.getCurrentConfiguredValue(this.getKey()); + ConfiguredValue initialConfigurationValue = configurationValue; + + for (String alias : this.aliasKeys) { + if (configurationValue.found()) { + break; + } + configurationValue = liquibaseConfiguration.getCurrentConfiguredValue(alias); + } + + if (!configurationValue.found()) { + //set back to initial version, not the alias + configurationValue = initialConfigurationValue; + } + + if (!configurationValue.found()) { + defaultValue = this.getDefaultValue(); + if (defaultValue != null) { + configurationValue.override(new DefaultValueProvider(this.getDefaultValue()).getProvidedValue(key)); + } + } + + final ProvidedValue providedValue = configurationValue.getProvidedValue(); + final DataType finalValue = valueHandler.convert(providedValue.getValue()); + if (providedValue != finalValue) { + configurationValue.override(new ConvertedValueProvider(finalValue, providedValue).getProvidedValue(key)); + } + + return (ConfiguredValue) configurationValue; + } + + /** + * The standard configuration key for this definition. See the {@link ConfigurationDefinition} class-level docs on key format. + */ + public String getKey() { + return key; + } + + /** + * @return alternate configuration keys to check for values. Used for backwards compatibility. + */ + public Set getAliasKeys() { + return aliasKeys; + } + + /** + * @return the type of data this definition returns. + */ + public Class getType() { + return type; + } + + /** + * A user-friendly description of this definition. + * This will be exposed to end-users in generated help. + */ + public String getDescription() { + return description; + } + + /** + * The default value used by this definition if no value is currently configured. + *

+ * NOTE: this is only used if none of the {@link ConfigurationValueProvider}s have a configuration for the property. + * Even if some return "null", that is still considered a provided value to use rather than this default. + */ + public DataType getDefaultValue() { + return defaultValue; + } + + /** + * Returns true if this is configuration users are often interested in setting. + * Used to simplify generated help by hiding less commonly used settings. + */ + public boolean getCommonlyUsed() { + return commonlyUsed; + } + + @Override + public int compareTo(ConfigurationDefinition o) { + return this.getKey().compareTo(o.getKey()); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + ConfigurationDefinition that = (ConfigurationDefinition) o; + return Objects.equals(key, that.key); + } + + @Override + public int hashCode() { + return Objects.hash(key); + } + + /** + * Return true if the given key matches this definition. + */ + public boolean equalsKey(String key) { + if (key == null) { + return false; + } + + if (getKey().equalsIgnoreCase(key)) { + return true; + } + + for (String alias : getAliasKeys()) { + if (alias.equalsIgnoreCase(key)) { + return true; + } + } + + return false; + } + + /** + * Used to construct new {@link ConfigurationDefinition} instances. + */ + public static class Builder { + private final String defaultKeyPrefix; + + /** + * @param defaultKeyPrefix the prefix to add to new keys that are not fully qualified + */ + public Builder(String defaultKeyPrefix) { + if (!ALLOWED_KEY_PATTERN.matcher(defaultKeyPrefix).matches()) { + throw new IllegalArgumentException("Invalid prefix format: "+defaultKeyPrefix); + } + + this.defaultKeyPrefix = defaultKeyPrefix; + } + + /** + * Starts a new definition with the given key. Always adds the defaultKeyPrefix. + */ + public NewDefinition define(String key, Class dataType) { + final ConfigurationDefinition definition = new ConfigurationDefinition<>(defaultKeyPrefix + "." + key, dataType); + + return new NewDefinition<>(definition); + } + + public static class NewDefinition { + + private final ConfigurationDefinition definition; + + private NewDefinition(ConfigurationDefinition definition) { + this.definition = definition; + } + + public NewDefinition addAliasKey(String alias) { + if (!ALLOWED_KEY_PATTERN.matcher(alias).matches()) { + throw new IllegalArgumentException("Invalid alias format: "+alias); + } + + definition.aliasKeys.add(alias); + + return this; + } + + public NewDefinition setDescription(String description) { + definition.description = description; + return this; + } + + public NewDefinition setDefaultValue(DataType defaultValue) { + definition.defaultValue = defaultValue; + return this; + } + + public NewDefinition setValueHandler(ConfigurationValueConverter handler) { + definition.valueHandler = handler; + + return this; + } + + public NewDefinition setValueObfuscator(ConfigurationValueObfuscator handler) { + definition.valueObfuscator = handler; + + return this; + } + + public NewDefinition setCommonlyUsed(boolean commonlyUsed) { + definition.commonlyUsed = commonlyUsed; + + return this; + } + + /** + * Finishes building this definition AND registers it with {@link LiquibaseConfiguration#registerDefinition(ConfigurationDefinition)}. + * To not register this definition, use {@link #buildTemporary()} + */ + public ConfigurationDefinition build() { + Scope.getCurrentScope().getSingleton(LiquibaseConfiguration.class).registerDefinition(definition); + + return definition; + } + + /** + * Finishes building this definition WITHOUT registering it with {@link LiquibaseConfiguration#registerDefinition(ConfigurationDefinition)}. + * To automatically register this definition, use {@link #build()} + */ + public ConfigurationDefinition buildTemporary() { + return definition; + } + } + } + + /** + * Used to track configuration values set by a default + */ + private static final class DefaultValueProvider implements ConfigurationValueProvider { + + private final Object value; + + public DefaultValueProvider(Object value) { + this.value = value; + } + + @Override + public int getPrecedence() { + return -1; + } + + @Override + public ProvidedValue getProvidedValue(String key) { + return new ProvidedValue(key, key, value, "Default value", this); + } + } + + /** + * Used to track configuration values converted by a handler + */ + private static final class ConvertedValueProvider implements ConfigurationValueProvider { + + private final DataType value; + private final String originalSource; + private final String actualKey; + + public ConvertedValueProvider(DataType value, ProvidedValue originalProvidedValue) { + this.value = value; + this.actualKey = originalProvidedValue.getActualKey(); + this.originalSource = originalProvidedValue.getSourceDescription(); + } + + @Override + public int getPrecedence() { + return -1; + } + + @Override + public ProvidedValue getProvidedValue(String key) { + return new ProvidedValue(key, actualKey, value, originalSource, this); + } + } +} + diff --git a/liquibase-core/src/main/java/liquibase/configuration/ConfigurationProperty.java b/liquibase-core/src/main/java/liquibase/configuration/ConfigurationProperty.java index 51e89b2a6ad..5f215ef3ebd 100644 --- a/liquibase-core/src/main/java/liquibase/configuration/ConfigurationProperty.java +++ b/liquibase-core/src/main/java/liquibase/configuration/ConfigurationProperty.java @@ -1,77 +1,39 @@ package liquibase.configuration; +import liquibase.configuration.core.DeprecatedConfigurationValueProvider; import liquibase.exception.UnexpectedLiquibaseException; -import liquibase.util.ObjectUtil; import liquibase.util.StringUtil; import java.math.BigDecimal; -import java.util.ArrayList; -import java.util.Arrays; import java.util.List; /** - * Contains the definition and current value of a given configuration property. + * @deprecated */ public class ConfigurationProperty { + private final ConfigurationDefinition.Builder.NewDefinition definitionBuilder; + private ConfigurationDefinition definition; private final String namespace; - private final String name; - private final Class type; - private List aliases = new ArrayList<>(); - private Object value; - private String description; - private Object defaultValue; - private boolean wasOverridden; - - private ConfigurationValueHandler valueHandler; - - public ConfigurationProperty(String namespace, String propertyName, Class type) { + public ConfigurationProperty(String namespace, ConfigurationDefinition.Builder.NewDefinition definitionBuilder) { this.namespace = namespace; - this.name = propertyName; - this.type = type; + this.definitionBuilder = definitionBuilder; + this.definition = definitionBuilder.buildTemporary(); } - /** - * Initialize this property with values in the given ConfigurationProvers. If the configurationValueProviders do not contain - * a default value, the property is initialized with the value set by {@link #setDefaultValue(Object)}. - * If multiple configurationValueProviders contain values, the first in the list wins. - */ - protected void init(ConfigurationValueProvider[] configurationValueProviders) { - Object containerValue = null; - - for (ConfigurationValueProvider container : configurationValueProviders) { - containerValue = container.getValue(namespace, name); - for (String alias : aliases) { - if (containerValue != null) { - break; - } - containerValue = container.getValue(namespace, alias); - } - } - - if (containerValue == null) { - value = defaultValue; - } else { - try { - value = valueOf(containerValue); - wasOverridden = true; - } catch (NumberFormatException e) { - throw new UnexpectedLiquibaseException("Error parsing "+containerValue+" as a "+type.getSimpleName()); - } - } - } - - /** * Returns the property name. + * + * @deprecated */ public String getName() { - return name; + return definition.getKey().replace(namespace+".", ""); } /** * Returns the namespace used by this property's {@link ConfigurationContainer} + * @deprecated */ public String getNamespace() { return namespace; @@ -79,15 +41,18 @@ public String getNamespace() { /** * Returns the type of value stored in this property + * @deprecated */ public Class getType() { - return type; + return definition.getType(); } /** * Converts an object of a different type to the type used by this property. If types are not convertible, an exception is thrown. + * @deprecated */ protected Object valueOf(Object value) { + Class type = definition.getType(); if (value == null) { return value; } else if (type.isAssignableFrom(value.getClass())) { @@ -100,7 +65,7 @@ protected Object valueOf(Object value) { } else if (type.equals(BigDecimal.class)) { return new BigDecimal((String) value); } else if (type.equals(Long.class)) { - return Long.valueOf((String) value); + return Long.valueOf((String) value); } else if (type.equals(List.class)) { return StringUtil.splitAndTrim((String) value, ","); } else { @@ -113,45 +78,43 @@ protected Object valueOf(Object value) { /** * Returns the value currently stored in this property without any casting. + * @deprecated */ public Object getValue() { - return value; + return definition.getCurrentValue(); } /** * Returns the value currently stored in this property cast to the given type. + * @deprecated */ public T getValue(Class type) { - if (!this.type.isAssignableFrom(type)) { - throw new UnexpectedLiquibaseException("Property "+name+" on is of type "+this.type.getSimpleName()+", not "+type.getSimpleName()); + if (!this.definition.getType().isAssignableFrom(type)) { + throw new UnexpectedLiquibaseException("Property "+definition.getType()+" on is of type "+this.definition.getType().getSimpleName()+", not "+type.getSimpleName()); } - return (T) value; + return (T) definition.getCurrentValue(); } /** * Overwrites the value currently stored in this property. It he passed type is not compatible with the defined type, an exception is thrown. + * @deprecated */ public void setValue(Object value) { - if (valueHandler == null) { - value = ObjectUtil.convert(value, type); - } else { - value = valueHandler.convert(value); - } - if ((value != null) && !type.isAssignableFrom(value.getClass())) { - throw new UnexpectedLiquibaseException("Property "+name+" is of type "+type.getSimpleName()+", not "+value.getClass().getSimpleName()); - } - - this.value = value; - wasOverridden = true; + DeprecatedConfigurationValueProvider.setData(definition, value); } /** * Adds an alias for this property. An alias is an alternate to the "name" field that can be used by the ConfigurationProvers to look up starting values. + * @deprecated */ public ConfigurationProperty addAlias(String... aliases) { if (aliases != null) { - this.aliases.addAll(Arrays.asList(aliases)); + for (String alias : aliases) { + definitionBuilder.addAliasKey(alias); + } + + definition = definitionBuilder.buildTemporary(); } return this; @@ -159,48 +122,55 @@ public ConfigurationProperty addAlias(String... aliases) { /** * Returns a human-readable definition of this property + * @deprecated */ public String getDescription() { - return description; + return definition.getDescription(); } + /** + * @deprecated + */ public ConfigurationProperty setDescription(String description) { - this.description = description; + this.definitionBuilder.setDescription(description); + this.definition = definitionBuilder.buildTemporary(); + return this; } /** * Returns the default value to use if no ConfigurationProviders override it. + * @deprecated */ public Object getDefaultValue() { - return defaultValue; + return definition.getDefaultValue(); } /** * Sets the default value to use if no ConfigurationProviders override it. Throws an exception if the given object is not compatible with the defined type. + * @deprecated */ public ConfigurationProperty setDefaultValue(Object defaultValue) { - if ((defaultValue != null) && !type.isAssignableFrom(defaultValue.getClass())) { - if ((type == Long.class) && (defaultValue instanceof Integer)) { - return setDefaultValue(((Integer) defaultValue).longValue()); - } - throw new UnexpectedLiquibaseException("Property "+name+" on is of type "+type.getSimpleName()+", not "+defaultValue.getClass().getSimpleName()); - } - - this.defaultValue = defaultValue; + this.definitionBuilder.setDefaultValue(defaultValue); + this.definition = definitionBuilder.buildTemporary(); return this; } /** * Returns true if the value has been set by a ConfigurationValueProvider or by {@link #setValue(Object)} + * @deprecated */ public boolean getWasOverridden() { - return wasOverridden; + return !ConfigurationDefinition.wasDefaultValueUsed(this.definition.getCurrentConfiguredValue()); } + /** + * @deprecated + */ public ConfigurationProperty setValueHandler(ConfigurationValueHandler handler) { - this.valueHandler = handler; + this.definitionBuilder.setValueHandler(value -> handler.convert(value)); + this.definition = definitionBuilder.buildTemporary(); return this; } diff --git a/liquibase-core/src/main/java/liquibase/configuration/ConfigurationValueConverter.java b/liquibase-core/src/main/java/liquibase/configuration/ConfigurationValueConverter.java new file mode 100644 index 00000000000..c69c5244276 --- /dev/null +++ b/liquibase-core/src/main/java/liquibase/configuration/ConfigurationValueConverter.java @@ -0,0 +1,17 @@ +package liquibase.configuration; + +/** + * Used by {@link ConfigurationDefinition#getCurrentConfiguredValue()} to translate whatever object type a {@link ConfigurationValueProvider} is returning + * into the object type the definition uses. + */ +public interface ConfigurationValueConverter { + + /** + * Converts an arbitrary object into the correct type. + * Implementations should be able to handle any type passed them, often types by calling toString() on the incoming value and parsing the string. + * Normally, a null value will be returned as a null value, but that is up to the implementation. + * + * @throws IllegalArgumentException if the value cannot be parsed or is an invalid value. + */ + DataType convert(Object value) throws IllegalArgumentException; +} diff --git a/liquibase-core/src/main/java/liquibase/configuration/ConfigurationValueHandler.java b/liquibase-core/src/main/java/liquibase/configuration/ConfigurationValueHandler.java index 6c086177763..d6d322d7a77 100644 --- a/liquibase-core/src/main/java/liquibase/configuration/ConfigurationValueHandler.java +++ b/liquibase-core/src/main/java/liquibase/configuration/ConfigurationValueHandler.java @@ -1,9 +1,8 @@ package liquibase.configuration; /** - * Implementations can convert specified {@link ConfigurationProperty} values + * @deprecated */ public interface ConfigurationValueHandler { - Object convert(Object value); } diff --git a/liquibase-core/src/main/java/liquibase/configuration/ConfigurationValueObfuscator.java b/liquibase-core/src/main/java/liquibase/configuration/ConfigurationValueObfuscator.java new file mode 100644 index 00000000000..533fd531d44 --- /dev/null +++ b/liquibase-core/src/main/java/liquibase/configuration/ConfigurationValueObfuscator.java @@ -0,0 +1,12 @@ +package liquibase.configuration; + +/** + * Used by {@link ConfigurationDefinition#getCurrentValueObfuscated()} to obfuscate the current value. + */ +public interface ConfigurationValueObfuscator { + + /** + * Return an "obfuscated" version of the given value, suitable for logging or storing in non-secure environments. + */ + DataType obfuscate(DataType value); +} diff --git a/liquibase-core/src/main/java/liquibase/configuration/ConfigurationValueProvider.java b/liquibase-core/src/main/java/liquibase/configuration/ConfigurationValueProvider.java index 18df84963cd..6ad4f468ba9 100644 --- a/liquibase-core/src/main/java/liquibase/configuration/ConfigurationValueProvider.java +++ b/liquibase-core/src/main/java/liquibase/configuration/ConfigurationValueProvider.java @@ -1,19 +1,33 @@ package liquibase.configuration; /** - * Interface for classes that are able to lookup overriding default LiquibaseConfiguration values. - * For example, {@link liquibase.configuration.SystemPropertyProvider} can look up property values in system properties. + * Defines a way for {@link LiquibaseConfiguration} to find configured values. */ public interface ConfigurationValueProvider { /** - * Return the value for a given namespace and property. Returns null if this provider does not have a value for this property. + * Returns the precedence of values returned by this provider. Higher a provider with higher precedence overrides values from lower precedence providers. + *

+ * Standard provider precedence: + *

    + *
  • 400 {@link liquibase.configuration.core.ScopeValueProvider}
  • + *
  • 350 {@link liquibase.configuration.core.DeprecatedConfigurationValueProvider}
  • + *
  • 300: TODO JNDI attributes
  • + *
  • 250: TODO Servlet Context
  • + *
  • 200 {@link liquibase.configuration.core.SystemPropertyValueProvider}
  • + *
  • 150 EnvironmentValueProvider
  • + *
  • 100: TODO profile/context specific properties files
  • + *
  • 50: TODO default properties files
  • + *
*/ - Object getValue(String namespace, String property); + int getPrecedence(); /** - * Generates a human consumable description of how the configured ConfigurationValueProvider(s) will attempt to set a default value. - * See {@link LiquibaseConfiguration#describeValueLookupLogic(ConfigurationProperty)} + * Lookup the given key in this source. + * It is up to the implementation to provide any "smoothing" or translation of key names. + * For example, a SystemEnvironmentValueProvider will look check environment variables containing _'s rather than .'s. + * + * @return null if the key is not defined in this provider. */ - String describeValueLookupLogic(ConfigurationProperty property); + ProvidedValue getProvidedValue(String key); } diff --git a/liquibase-core/src/main/java/liquibase/configuration/ConfiguredValue.java b/liquibase-core/src/main/java/liquibase/configuration/ConfiguredValue.java new file mode 100644 index 00000000000..e2aadc4ed25 --- /dev/null +++ b/liquibase-core/src/main/java/liquibase/configuration/ConfiguredValue.java @@ -0,0 +1,82 @@ +package liquibase.configuration; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +/** + * This wraps all the {@link ProvidedValue}s to return the overall value returned from the collection of {@link ConfigurationValueProvider}s. + * Returned by {@link LiquibaseConfiguration#getCurrentConfiguredValue(String)} + */ +public class ConfiguredValue { + + private static final NoValueProvider NO_VALUE_PROVIDER = new NoValueProvider(); + + private final List providedValues = new ArrayList<>(); + private final String key; + + protected ConfiguredValue(String key) { + this.key = key; + } + + public DataType getValue() { + final ProvidedValue providedValue = getProvidedValue(); + if (providedValue == null) { + return null; + } + + return (DataType) providedValue.getValue(); + } + + + /** + * Returns the "winning" value across all the possible {@link ConfigurationValueProvider}. + * A {@link ProvidedValue} is always returned, even if the value was not configured. + * + * @see #found() + */ + public ProvidedValue getProvidedValue() { + return getProvidedValues().get(0); + } + + + /** + * Replaces the current configured value with a higher-precedence one. + */ + protected void override(ProvidedValue details) { + this.providedValues.add(0, details); + } + + /** + * @return a full list of where the configuration value was set and/or overridden. + */ + public List getProvidedValues() { + if (providedValues.size() == 0) { + return Collections.singletonList(NO_VALUE_PROVIDER.getProvidedValue(key)); + } + + return Collections.unmodifiableList(providedValues); + } + + /** + * @return true if a value was found across the providers. + */ + public boolean found() { + return providedValues.size() > 0; + } + + /** + * Used to track configuration with no value set + */ + private static final class NoValueProvider implements ConfigurationValueProvider { + @Override + public int getPrecedence() { + return -1; + } + + @Override + public ProvidedValue getProvidedValue(String key) { + return new ProvidedValue(key, key, null, "No configuration or default value found", this); + } + } +} diff --git a/liquibase-core/src/main/java/liquibase/configuration/GlobalConfiguration.java b/liquibase-core/src/main/java/liquibase/configuration/GlobalConfiguration.java index ec0789dc1ea..128fd7e1a75 100644 --- a/liquibase-core/src/main/java/liquibase/configuration/GlobalConfiguration.java +++ b/liquibase-core/src/main/java/liquibase/configuration/GlobalConfiguration.java @@ -1,219 +1,258 @@ package liquibase.configuration; +import liquibase.configuration.core.DeprecatedConfigurationValueProvider; + +import java.util.Set; + /** - * Configuration container for global properties. + * @deprecated use {@link liquibase.GlobalConfiguration} */ -public class GlobalConfiguration extends AbstractConfigurationContainer { - - public static final String SHOULD_RUN = "shouldRun"; - public static final String DATABASECHANGELOG_TABLE_NAME = "databaseChangeLogTableName"; - public static final String DATABASECHANGELOGLOCK_TABLE_NAME = "databaseChangeLogLockTableName"; - public static final String LIQUIBASE_TABLESPACE_NAME = "tablespaceName"; - public static final String LIQUIBASE_CATALOG_NAME = "catalogName"; - public static final String LIQUIBASE_SCHEMA_NAME = "schemaName"; - public static final String OUTPUT_LINE_SEPARATOR = "outputLineSeparator"; - public static final String OUTPUT_ENCODING = "outputFileEncoding"; - public static final String CHANGELOGLOCK_WAIT_TIME = "changeLogLockWaitTimeInMinutes"; - public static final String CHANGELOGLOCK_POLL_RATE = "changeLogLockPollRate"; - public static final String CONVERT_DATA_TYPES = "convertDataTypes"; - public static final String GENERATE_CHANGESET_CREATED_VALUES = "generateChangeSetCreatedValues"; - public static final String AUTO_REORG = "autoReorg"; - public static final String DIFF_COLUMN_ORDER = "diffColumnOrder"; - public static final String ALWAYS_OVERRIDE_STORED_LOGIC_SCHEMA = "alwaysOverrideStoredLogicSchema"; - public static final String GENERATED_CHANGESET_IDS_INCLUDE_DESCRIPTION = "generatedChangeSetIdsContainsDescription"; - public static final String INCLUDE_CATALOG_IN_SPECIFICATION = "includeCatalogInSpecification"; - public static final String SHOULD_SNAPSHOT_DATA = "shouldSnapshotData"; - public static final String FILTER_LOG_MESSAGES = "filterLogMessages"; - public static final String HEADLESS = "headless"; - - public GlobalConfiguration() { - super("liquibase"); +public class GlobalConfiguration extends liquibase.GlobalConfiguration implements ConfigurationContainer { - getContainer().addProperty(SHOULD_RUN, Boolean.class) - .setDescription("Should Liquibase commands execute") - .setDefaultValue(true) - .addAlias("should.run"); + /** + * @deprecated + */ + public static final String SHOULD_RUN = liquibase.GlobalConfiguration.SHOULD_RUN.getKey(); - getContainer().addProperty(DATABASECHANGELOG_TABLE_NAME, String.class) - .setDescription("Name of table to use for tracking change history") - .setDefaultValue("DATABASECHANGELOG"); + /** + * @deprecated + */ + public static final String DATABASECHANGELOG_TABLE_NAME = liquibase.GlobalConfiguration.DATABASECHANGELOG_TABLE_NAME.getKey(); - getContainer().addProperty(DATABASECHANGELOGLOCK_TABLE_NAME, String.class) - .setDescription("Name of table to use for tracking concurrent Liquibase usage") - .setDefaultValue("DATABASECHANGELOGLOCK"); + /** + * @deprecated + */ + public static final String DATABASECHANGELOGLOCK_TABLE_NAME = liquibase.GlobalConfiguration.DATABASECHANGELOGLOCK_TABLE_NAME.getKey(); - getContainer().addProperty(CHANGELOGLOCK_WAIT_TIME, Long.class) - .setDescription("Number of minutes to wait for the changelog lock to be available before giving up") - .setDefaultValue(5); + /** + * @deprecated + */ + public static final String LIQUIBASE_TABLESPACE_NAME = liquibase.GlobalConfiguration.LIQUIBASE_TABLESPACE_NAME.getKey(); - getContainer().addProperty(CHANGELOGLOCK_POLL_RATE, Long.class) - .setDescription("Number of seconds wait between checks to the changelog lock when it is locked") - .setDefaultValue(10); + /** + * @deprecated + */ + public static final String LIQUIBASE_CATALOG_NAME = liquibase.GlobalConfiguration.LIQUIBASE_CATALOG_NAME.getKey(); - getContainer().addProperty(LIQUIBASE_TABLESPACE_NAME, String.class) - .setDescription("Tablespace to use for Liquibase objects"); + /** + * @deprecated + */ + public static final String LIQUIBASE_SCHEMA_NAME = liquibase.GlobalConfiguration.LIQUIBASE_SCHEMA_NAME.getKey(); - getContainer().addProperty(LIQUIBASE_CATALOG_NAME, String.class) - .setDescription("Catalog to use for Liquibase objects"); + /** + * @deprecated + */ + public static final String OUTPUT_LINE_SEPARATOR = liquibase.GlobalConfiguration.OUTPUT_LINE_SEPARATOR.getKey(); - getContainer().addProperty(LIQUIBASE_SCHEMA_NAME, String.class) - .setDescription("Schema to use for Liquibase objects"); + /** + * @deprecated + */ + public static final String OUTPUT_ENCODING = liquibase.GlobalConfiguration.OUTPUT_ENCODING.getKey(); - getContainer().addProperty(OUTPUT_LINE_SEPARATOR, String.class) - .setDescription("Line separator for output. Defaults to OS default") - .setDefaultValue(System.getProperty("line.separator")); + /** + * @deprecated + */ + public static final String CHANGELOGLOCK_WAIT_TIME = liquibase.GlobalConfiguration.CHANGELOGLOCK_WAIT_TIME.getKey(); - getContainer().addProperty(OUTPUT_ENCODING, String.class) - .setDescription("Encoding to output text in. Defaults to file.encoding system property or UTF-8") - .setDefaultValue("UTF-8") - .addAlias("file.encoding"); + /** + * @deprecated + */ + public static final String CHANGELOGLOCK_POLL_RATE = liquibase.GlobalConfiguration.CHANGELOGLOCK_POLL_RATE.getKey(); - getContainer().addProperty(CONVERT_DATA_TYPES, Boolean.class) - .setDescription("Should Liquibase convert to/from STANDARD data types. Applies to both snapshot and " + - "update commands.") - .setDefaultValue(true); + /** + * @deprecated + */ + public static final String CONVERT_DATA_TYPES = liquibase.GlobalConfiguration.CONVERT_DATA_TYPES.getKey(); - getContainer().addProperty(GENERATE_CHANGESET_CREATED_VALUES, Boolean.class) - .setDescription("Should Liquibase include a 'created' attribute in diff/generateChangeLog changeSets with" + - " the current datetime") - .setDefaultValue(false); + /** + * @deprecated + */ + public static final String GENERATE_CHANGESET_CREATED_VALUES = liquibase.GlobalConfiguration.GENERATE_CHANGESET_CREATED_VALUES.getKey(); - getContainer().addProperty(AUTO_REORG, Boolean.class) - .setDescription("Should Liquibase automatically include REORG TABLE commands when needed?") - .setDefaultValue(true); + /** + * @deprecated + */ + public static final String AUTO_REORG = liquibase.GlobalConfiguration.AUTO_REORG.getKey(); - getContainer().addProperty(DIFF_COLUMN_ORDER, Boolean.class) - .setDescription("Should Liquibase compare column order in diff operation?") - .setDefaultValue(true); + /** + * @deprecated + */ + public static final String DIFF_COLUMN_ORDER = liquibase.GlobalConfiguration.DIFF_COLUMN_ORDER.getKey(); - getContainer().addProperty(ALWAYS_OVERRIDE_STORED_LOGIC_SCHEMA, Boolean.class) - .setDescription("When generating SQL for createProcedure, should the procedure schema be forced to the default schema if no schemaName attribute is set?") - .setDefaultValue(false); + /** + * @deprecated + */ + public static final String ALWAYS_OVERRIDE_STORED_LOGIC_SCHEMA = liquibase.GlobalConfiguration.ALWAYS_OVERRIDE_STORED_LOGIC_SCHEMA.getKey(); + /** + * @deprecated + */ + public static final String GENERATED_CHANGESET_IDS_INCLUDE_DESCRIPTION = liquibase.GlobalConfiguration.GENERATED_CHANGESET_IDS_INCLUDE_DESCRIPTION.getKey(); - getContainer().addProperty(GENERATED_CHANGESET_IDS_INCLUDE_DESCRIPTION, Boolean.class) - .setDescription("Should Liquibase include the change description in the id when generating changeSets?") - .setDefaultValue(false); + /** + * @deprecated + */ + public static final String INCLUDE_CATALOG_IN_SPECIFICATION = liquibase.GlobalConfiguration.INCLUDE_CATALOG_IN_SPECIFICATION.getKey(); - getContainer().addProperty(INCLUDE_CATALOG_IN_SPECIFICATION, Boolean.class) - .setDescription("Should Liquibase include the catalog name when determining equality?") - .setDefaultValue(false); + /** + * @deprecated + */ + public static final String SHOULD_SNAPSHOT_DATA = liquibase.GlobalConfiguration.SHOULD_SNAPSHOT_DATA.getKey(); - getContainer().addProperty(SHOULD_SNAPSHOT_DATA, Boolean.class) - .setDescription("Should Liquibase snapshot data by default?") - .setDefaultValue(false); + /** + * @deprecated + */ + public static final String FILTER_LOG_MESSAGES = liquibase.GlobalConfiguration.FILTER_LOG_MESSAGES.getKey(); - getContainer().addProperty(FILTER_LOG_MESSAGES, Boolean.class) - .setDescription("Should Liquibase filter log messages for potentially insecure data?") - .setDefaultValue(true); + /** + * @deprecated + */ + public static final String HEADLESS = liquibase.GlobalConfiguration.HEADLESS.getKey(); - getContainer().addProperty(HEADLESS, Boolean.class) - .setDescription("Force liquibase think it has no access to a keyboard?") - .setDefaultValue(false); + private static final AbstractConfigurationContainer.DelegatedConfigurationContainer containerDelegate = new AbstractConfigurationContainer.DelegatedConfigurationContainer("liquibase"); + public GlobalConfiguration() { } /** * Should Liquibase execute + * @deprecated */ public boolean getShouldRun() { - return getContainer().getValue(SHOULD_RUN, Boolean.class); + return liquibase.GlobalConfiguration.SHOULD_RUN.getCurrentValue(); } + /** + * @deprecated + */ public GlobalConfiguration setShouldRun(boolean shouldRun) { - getContainer().setValue(SHOULD_RUN, shouldRun); + DeprecatedConfigurationValueProvider.setData(liquibase.GlobalConfiguration.SHOULD_RUN, shouldRun); return this; } /** * Table name to use for DATABASECHANGELOG + * @deprecated */ public String getDatabaseChangeLogTableName() { - return getContainer().getValue(DATABASECHANGELOG_TABLE_NAME, String.class); + return liquibase.GlobalConfiguration.DATABASECHANGELOG_TABLE_NAME.getCurrentValue(); } + /** + * @deprecated + */ public GlobalConfiguration setDatabaseChangeLogTableName(String name) { - getContainer().setValue(DATABASECHANGELOG_TABLE_NAME, name); + DeprecatedConfigurationValueProvider.setData(liquibase.GlobalConfiguration.DATABASECHANGELOG_TABLE_NAME, name); return this; } /** * Table name to use for DATABASECHANGELOGLOCK + * @deprecated */ public String getDatabaseChangeLogLockTableName() { - return getContainer().getValue(DATABASECHANGELOGLOCK_TABLE_NAME, String.class); + return liquibase.GlobalConfiguration.DATABASECHANGELOGLOCK_TABLE_NAME.getCurrentValue(); } + /** + * @deprecated + */ public GlobalConfiguration setDatabaseChangeLogLockTableName(String name) { - getContainer().setValue(DATABASECHANGELOGLOCK_TABLE_NAME, name); + DeprecatedConfigurationValueProvider.setData(liquibase.GlobalConfiguration.DATABASECHANGELOGLOCK_TABLE_NAME, name); return this; } /** * Wait time (in minutes) to wait to receive the changelog lock before giving up. + * @deprecated */ public Long getDatabaseChangeLogLockWaitTime() { - return getContainer().getValue(CHANGELOGLOCK_WAIT_TIME, Long.class); + return liquibase.GlobalConfiguration.CHANGELOGLOCK_WAIT_TIME.getCurrentValue(); } + /** + * @deprecated + */ public GlobalConfiguration setDatabaseChangeLogLockWaitTime(Long minutes) { - getContainer().setValue(CHANGELOGLOCK_WAIT_TIME, minutes); + DeprecatedConfigurationValueProvider.setData(liquibase.GlobalConfiguration.CHANGELOGLOCK_WAIT_TIME, minutes); return this; } /** * Wait time (in seconds) between polling requests to the changelog lock system. + * @deprecated */ public Long getDatabaseChangeLogLockPollRate() { - return getContainer().getValue(CHANGELOGLOCK_POLL_RATE, Long.class); + return liquibase.GlobalConfiguration.CHANGELOGLOCK_POLL_RATE.getCurrentValue(); } + /** + * @deprecated + */ public GlobalConfiguration setDatabaseChangeLogLockPollRate(Long seconds) { - getContainer().setValue(CHANGELOGLOCK_POLL_RATE, seconds); + DeprecatedConfigurationValueProvider.setData(liquibase.GlobalConfiguration.CHANGELOGLOCK_POLL_RATE, seconds); return this; } /** * Name of the tablespace to use for liquibase database objects + * @deprecated */ public String getLiquibaseTablespaceName() { - return getContainer().getValue(LIQUIBASE_TABLESPACE_NAME, String.class); + return liquibase.GlobalConfiguration.LIQUIBASE_TABLESPACE_NAME.getCurrentValue(); } + /** + * @deprecated + */ public GlobalConfiguration setLiquibaseTablespaceName(String name) { - getContainer().setValue(LIQUIBASE_TABLESPACE_NAME, name); + DeprecatedConfigurationValueProvider.setData(liquibase.GlobalConfiguration.LIQUIBASE_TABLESPACE_NAME, name); return this; } /** - * * Should Liquibase snapshot data for table by default - * + * @deprecated */ public boolean getShouldSnapshotData() { - return getContainer().getValue(SHOULD_SNAPSHOT_DATA, Boolean.class); + return liquibase.GlobalConfiguration.SHOULD_SNAPSHOT_DATA.getCurrentValue(); } + /** + * @deprecated + */ public GlobalConfiguration setShouldSnapshotData(boolean shouldSnapshotData) { - getContainer().setValue(SHOULD_SNAPSHOT_DATA, shouldSnapshotData); + DeprecatedConfigurationValueProvider.setData(liquibase.GlobalConfiguration.SHOULD_SNAPSHOT_DATA, shouldSnapshotData); return this; } + /** + * @deprecated + */ public boolean getShouldFilterLogMessages() { - return getContainer().getValue(FILTER_LOG_MESSAGES, Boolean.class); + return liquibase.GlobalConfiguration.FILTER_LOG_MESSAGES.getCurrentValue(); } + /** + * @deprecated + */ public GlobalConfiguration setShouldFilterLogMessages(boolean filter) { - getContainer().setValue(FILTER_LOG_MESSAGES, filter); + DeprecatedConfigurationValueProvider.setData(liquibase.GlobalConfiguration.FILTER_LOG_MESSAGES, filter); return this; } + /** + * @deprecated + */ public boolean getHeadless() { - return getContainer().getValue(HEADLESS, Boolean.class); + return liquibase.GlobalConfiguration.HEADLESS.getCurrentValue(); } + /** + * @deprecated + */ public GlobalConfiguration setHeadless(boolean headless) { - getContainer().setValue(HEADLESS, headless); + DeprecatedConfigurationValueProvider.setData(liquibase.GlobalConfiguration.HEADLESS, headless); return this; } @@ -221,11 +260,12 @@ public GlobalConfiguration setHeadless(boolean headless) { * Name of the catalog to use for liquibase database objects */ public String getLiquibaseCatalogName() { - return getContainer().getValue(LIQUIBASE_CATALOG_NAME, String.class); + return liquibase.GlobalConfiguration.LIQUIBASE_CATALOG_NAME.getCurrentValue(); + } public GlobalConfiguration setLiquibaseCatalogName(String name) { - getContainer().setValue(LIQUIBASE_CATALOG_NAME, name); + DeprecatedConfigurationValueProvider.setData(liquibase.GlobalConfiguration.LIQUIBASE_CATALOG_NAME, name); return this; } @@ -233,64 +273,119 @@ public GlobalConfiguration setLiquibaseCatalogName(String name) { * Name of the schema to use for liquibase database objects */ public String getLiquibaseSchemaName() { - return getContainer().getValue(LIQUIBASE_SCHEMA_NAME, String.class); + return liquibase.GlobalConfiguration.LIQUIBASE_SCHEMA_NAME.getCurrentValue(); } + /** + * @deprecated + */ public GlobalConfiguration setLiquibaseSchemaName(String name) { - getContainer().setValue(LIQUIBASE_SCHEMA_NAME, name); + DeprecatedConfigurationValueProvider.setData(liquibase.GlobalConfiguration.LIQUIBASE_SCHEMA_NAME, name); return this; } /** * Line separator to use in output + * @deprecated */ public String getOutputLineSeparator() { - return getContainer().getValue(OUTPUT_LINE_SEPARATOR, String.class); + return liquibase.GlobalConfiguration.OUTPUT_LINE_SEPARATOR.getCurrentValue(); } + /** + * @deprecated + */ public GlobalConfiguration setOutputLineSeparator(String name) { - getContainer().setValue(OUTPUT_LINE_SEPARATOR, name); + DeprecatedConfigurationValueProvider.setData(liquibase.GlobalConfiguration.OUTPUT_LINE_SEPARATOR, name); return this; } /** * String encoding to use in output. + * @deprecated */ public String getOutputEncoding() { - return getContainer().getValue(OUTPUT_ENCODING, String.class); + return liquibase.GlobalConfiguration.OUTPUT_ENCODING.getCurrentValue(); } + /** + * @deprecated + */ public GlobalConfiguration setOutputEncoding(String name) { - getContainer().setValue(OUTPUT_ENCODING, name); + DeprecatedConfigurationValueProvider.setData(liquibase.GlobalConfiguration.OUTPUT_ENCODING, name); return this; } + /** + * @deprecated + */ public Boolean getDiffColumnOrder() { - return getContainer().getValue(DIFF_COLUMN_ORDER, Boolean.class); + return liquibase.GlobalConfiguration.DIFF_COLUMN_ORDER.getCurrentValue(); } + /** + * @deprecated + */ public GlobalConfiguration setDiffColumnOrder(boolean diff) { - getContainer().setValue(DIFF_COLUMN_ORDER, diff); + DeprecatedConfigurationValueProvider.setData(liquibase.GlobalConfiguration.DIFF_COLUMN_ORDER, diff); return this; } + /** + * @deprecated + */ public Boolean getAlwaysOverrideStoredLogicSchema() { - return getContainer().getValue(ALWAYS_OVERRIDE_STORED_LOGIC_SCHEMA, Boolean.class); + return liquibase.GlobalConfiguration.ALWAYS_OVERRIDE_STORED_LOGIC_SCHEMA.getCurrentValue(); + } + /** + * @deprecated + */ public GlobalConfiguration setAlwaysOverrideStoredLogicSchema(boolean override) { - getContainer().setValue(ALWAYS_OVERRIDE_STORED_LOGIC_SCHEMA, override); + DeprecatedConfigurationValueProvider.setData(liquibase.GlobalConfiguration.ALWAYS_OVERRIDE_STORED_LOGIC_SCHEMA, override); return this; } + /** + * @deprecated + */ public Boolean getGeneratedChangeSetIdsContainDescription() { - return getContainer().getValue(GENERATED_CHANGESET_IDS_INCLUDE_DESCRIPTION, Boolean.class); + return liquibase.GlobalConfiguration.GENERATED_CHANGESET_IDS_INCLUDE_DESCRIPTION.getCurrentValue(); } + /** + * @deprecated + */ public GlobalConfiguration setGeneratedChangeSetIdsContainDescription(boolean containDescription) { - getContainer().setValue(GENERATED_CHANGESET_IDS_INCLUDE_DESCRIPTION, containDescription); + DeprecatedConfigurationValueProvider.setData(liquibase.GlobalConfiguration.GENERATED_CHANGESET_IDS_INCLUDE_DESCRIPTION, containDescription); return this; } + + @Override + public ConfigurationProperty getProperty(String propertyName) { + return containerDelegate.getProperty(propertyName); + } + + @Override + public Set getProperties() { + return containerDelegate.getProperties(); + } + + @Override + public T getValue(String propertyName, Class returnType) { + return containerDelegate.getValue(propertyName, returnType); + } + + @Override + public void setValue(String propertyName, Object value) { + containerDelegate.setValue(propertyName, value); + } + + @Override + public String getNamespace() { + return containerDelegate.getNamespace(); + } } diff --git a/liquibase-core/src/main/java/liquibase/configuration/HubConfiguration.java b/liquibase-core/src/main/java/liquibase/configuration/HubConfiguration.java deleted file mode 100644 index e7027737cc1..00000000000 --- a/liquibase-core/src/main/java/liquibase/configuration/HubConfiguration.java +++ /dev/null @@ -1,117 +0,0 @@ -package liquibase.configuration; - -import liquibase.Scope; -import liquibase.util.StringUtil; - -import java.util.Arrays; -import java.util.List; -import java.util.logging.Level; - -/** - * Configuration container for global properties. - */ -public class HubConfiguration extends AbstractConfigurationContainer { - - public static final String LIQUIBASE_HUB_API_KEY = "apiKey"; - public static final String LIQUIBASE_HUB_URL = "url"; - public static final String LIQUIBASE_HUB_MODE = "mode"; - public static final String LIQUIBASE_HUB_LOGLEVEL = "logLevel"; - - public HubConfiguration() { - super("liquibase.hub"); - - getContainer().addProperty(LIQUIBASE_HUB_API_KEY, String.class) - .setDescription("Liquibase Hub API key for operations"); - getContainer().addProperty(LIQUIBASE_HUB_URL, String.class) - .setDescription("Liquibase Hub URL for operations") - .setValueHandler(value -> { - if (value == null) { - return null; - } - return value.toString().replaceFirst("(https?://[^/]+).*", "$1"); - }); - getContainer().addProperty(LIQUIBASE_HUB_MODE, String.class) - .setDescription("Content to send to Liquibase Hub during operations. Values can be 'all', 'meta', or 'off'") - .setDefaultValue("all"); - getContainer().addProperty(LIQUIBASE_HUB_LOGLEVEL, String.class) - .setDescription("Log level for filtering log messages to send to Liquibase Hub during operations. Values can be any acceptable log level.") - .setDefaultValue("INFO"); - } - - @Override - public void setValue(String propertyName, Object value) { - super.setValue(propertyName, value); - } - - /** - * Output {@link #getLiquibaseHubApiKey()} but in a way that is secure for message output. - * - */ - public String getLiquibaseHubApiKeySecureDescription() { - final String key = getContainer().getValue(LIQUIBASE_HUB_API_KEY, String.class); - if (key == null) { - return null; - } - return key.substring(0,6) + "************"; - } - - public String getLiquibaseHubApiKey() { - return getContainer().getValue(LIQUIBASE_HUB_API_KEY, String.class); - } - - public HubConfiguration setLiquibaseHubApiKey(String liquibaseHubApiKey) { - getContainer().setValue(LIQUIBASE_HUB_API_KEY, liquibaseHubApiKey); - return this; - } - - public HubConfiguration setLiquibaseHubUrl(String liquibaseHubUrl) { - getContainer().setValue(LIQUIBASE_HUB_URL, liquibaseHubUrl); - return this; - } - - public String getLiquibaseHubUrl() { - String hubUrl = getContainer().getValue(LIQUIBASE_HUB_URL, String.class); - if (hubUrl == null || hubUrl.isEmpty()) { - return "https://hub.liquibase.com"; - } - return hubUrl; - } - - public HubConfiguration setLiquibaseHubMode(String liquibaseHubMode) { - getContainer().setValue(LIQUIBASE_HUB_MODE, liquibaseHubMode); - return this; - } - - public String getLiquibaseHubMode() { - final String value = getContainer().getValue(LIQUIBASE_HUB_MODE, String.class); - - final List validValues = Arrays.asList("off", "meta", "all"); - if (!validValues.contains(value.toLowerCase())) { - throw new RuntimeException(" An invalid liquibase.hub.mode value of "+value+" detected. Acceptable values are "+StringUtil.join(validValues, ", ")); - } - return value; - } - - public HubConfiguration setLiquibaseHubLogLevel(String liquibaseHubLogLevel) { - getContainer().setValue(LIQUIBASE_HUB_LOGLEVEL, liquibaseHubLogLevel); - return this; - } - - public String getLiquibaseHubLogLevel() { - String value = getContainer().getValue(LIQUIBASE_HUB_LOGLEVEL, String.class); - - final List validValues = Arrays.asList("OFF", "FINE", "WARN", "ERROR", "INFO"); - if (!validValues.contains(value.toUpperCase())) { - Level logLevel = Level.INFO; - try { - logLevel = Level.parse(value.toUpperCase()); - } catch (IllegalArgumentException e) { - String message = "An invalid liquibase.hub.logLevel value of " + value + " detected. Acceptable values are " + StringUtil.join(validValues, ","); - Scope.getCurrentScope().getLog(HubConfiguration.class).warning(message); - } - value = logLevel.toString(); - } - return value; - } - -} diff --git a/liquibase-core/src/main/java/liquibase/configuration/LiquibaseConfiguration.java b/liquibase-core/src/main/java/liquibase/configuration/LiquibaseConfiguration.java index b623258de18..ffe4b2c3c2f 100644 --- a/liquibase-core/src/main/java/liquibase/configuration/LiquibaseConfiguration.java +++ b/liquibase-core/src/main/java/liquibase/configuration/LiquibaseConfiguration.java @@ -1,184 +1,167 @@ package liquibase.configuration; +import liquibase.Scope; +import liquibase.SingletonObject; import liquibase.exception.UnexpectedLiquibaseException; -import liquibase.util.StringUtil; +import liquibase.servicelocator.ServiceLocator; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.*; /** * Provides unified management of configuration properties within Liquibase core and in extensions. *

- * This class is the top level container used to access {@link ConfigurationContainer} implementations which contain - * the actual configuration properties. - * Normal use is to call - * LiquibaseConfiguration.getInstance().getConfiguration(NEEDED_CONFIGURATION.class).getYOUR_PROPERTY() + * Because this class focuses on raw/untyped access to what is actually configured, it is usually best to interact with {@link ConfigurationDefinition} instances + * which provide type safety, standardized key naming, default values, and more. + *

+ * "Registered" configuration definitions will be available for generated help. + *

+ * This class will search through the configured {@link ConfigurationValueProvider}s. Standard value providers are auto-loaded on startup, but more can be added/removed at runtime. *

- * This class is implemented as a singleton with a single global set of configuration objects, but the - * {@link #setInstance(LiquibaseConfiguration)} method can be used to replace - * the singleton with an alternate implementation that uses ThreadLocal objects or any other way of managing - * configurations. */ -public class LiquibaseConfiguration { - - private Map configurations; +public class LiquibaseConfiguration implements SingletonObject { - private ConfigurationValueProvider[] configurationValueProviders; - - private static LiquibaseConfiguration instance; + private final SortedSet configurationValueProviders; + private final SortedSet definitions = new TreeSet<>(); /** - * Returns the singleton instance, creating it if necessary. On creation, the configuration is initialized with {@link liquibase.configuration.SystemPropertyProvider} + * Track looked up values we have logged to avoid infinite loops between this and the log system using configurations + * and to limit logged messages. + * Only re-log when values changed from the last time they were logged. */ - public static synchronized LiquibaseConfiguration getInstance() { - if (instance == null) { - instance = new LiquibaseConfiguration(); - instance.init(new SystemPropertyProvider()); - } + private final Map lastLoggedKeyValues = new HashMap<>(); - return instance; - } + protected LiquibaseConfiguration() { + configurationValueProviders = new TreeSet<>((o1, o2) -> { + if (o1.getPrecedence() < o2.getPrecedence()) { + return -1; + } else if (o1.getPrecedence() > o2.getPrecedence()) { + return 1; + } - /** - * Overrides the standard singleton instance created by getInstance(). - * Useful for alternate implementations with more complex AbstractConfigurationContainer lookup logic such - * as different configurations per thread. - */ - public static synchronized void setInstance(LiquibaseConfiguration instance) { - LiquibaseConfiguration.instance = instance; - } + return o1.getClass().getName().compareTo(o2.getClass().getName()); + }); + } /** - * Constructor protected to prevent construction outside getInstance() + * @deprecated use {@link Scope#getSingleton(Class)} */ - protected LiquibaseConfiguration() { + public static LiquibaseConfiguration getInstance() { + return Scope.getCurrentScope().getSingleton(LiquibaseConfiguration.class); } - /** - * Re-initialize the configuration with the given ConfigurationProviders. Any existing - * AbstractConfigurationContainer instances are reset to defaults. + * Finishes configuration of this service. Called as the root scope is set up, should not be called elsewhere. */ - public void init(ConfigurationValueProvider... configurationValueProviders) { - if (configurationValueProviders == null) { - configurationValueProviders = new ConfigurationValueProvider[0]; + public void init(Scope scope) { + configurationValueProviders.clear(); + ServiceLocator serviceLocator = scope.getServiceLocator(); + final List containers = serviceLocator.findInstances(AutoloadedConfigurations.class); + for (AutoloadedConfigurations container : containers) { + Scope.getCurrentScope().getLog(getClass()).fine("Found ConfigurationDefinitions in " + container.getClass().getName()); } - this.configurationValueProviders = configurationValueProviders; - this.reset(); + configurationValueProviders.addAll(serviceLocator.findInstances(ConfigurationValueProvider.class)); } /** - * Resets existing AbstractConfigurationContainer instances to their default values. + * Adds a new {@link ConfigurationValueProvider} to the active collection of providers. */ - public void reset() { - this.configurations = new HashMap<>(); + public void registerProvider(ConfigurationValueProvider valueProvider) { + this.configurationValueProviders.add(valueProvider); } + /** + * Removes a specific {@link ConfigurationValueProvider} from the active collection of providers. + * + * @return true if the provider was removed. + */ + public boolean removeProvider(ConfigurationValueProvider provider) { + return this.configurationValueProviders.remove(provider); + } /** - * Return an instance of the passed AbstractConfigurationContainer type. - * The same instance is returned from every call to getConfiguration() + * @deprecated use {@link ConfigurationDefinition} instances directly */ public T getConfiguration(Class type) { - if (!configurations.containsKey(type)) { - configurations.put(type, createConfiguration(type)); + try { + return type.newInstance(); + } catch (Throwable e) { + throw new UnexpectedLiquibaseException(e); } - - return (T) configurations.get(type); } + /** + * Searches for the given key in the current providers. * - * Return an instance of the passed ConfigurationContainer type - * The typeName can be the name of a class or the namespace associated with the container - * - * @param typeName - * @return ConfigurationContainer - * + * @return the value for the key, or null if not configured. */ - public ConfigurationContainer getConfiguration(String typeName) { - // - // Lookup by class name - // - for (Map.Entry entry : configurations.entrySet()) { - if (entry.getKey().getName().equals(typeName)) { - return entry.getValue(); + public ConfiguredValue getCurrentConfiguredValue(String key) { + ConfiguredValue details = new ConfiguredValue<>(key); + + for (ConfigurationValueProvider provider : configurationValueProviders) { + final ProvidedValue providerValue = provider.getProvidedValue(key); + + if (providerValue != null) { + details.override(providerValue); } } - // - // Lookup by namespace - // - for (ConfigurationContainer container : configurations.values()) { - String namespace = container.getNamespace(); - if (namespace.equalsIgnoreCase(typeName)) { - return container; + final String foundValue = String.valueOf(details.getValue()); + if (!foundValue.equals(lastLoggedKeyValues.get(key))) { + lastLoggedKeyValues.put(key, foundValue); + + //avoid infinite loop when logging is getting set up + StringBuilder logMessage = new StringBuilder("Found '" + key + "' configuration of '"+foundValue+"'"); + boolean foundFirstValue = false; + for (ProvidedValue providedValue : details.getProvidedValues()) { + logMessage.append("\n "); + if (foundFirstValue) { + logMessage.append("Overrides "); + } + logMessage.append(providedValue.describe()); + final Object value = providedValue.getValue(); + if (value != null) { + logMessage.append(" of '").append(providedValue.getValue()).append("'"); + } + foundFirstValue = true; } - } - // - // Instantiate and put in the map - // - try { - Class typeClass = Class.forName(typeName); - configurations.put(typeClass, createConfiguration(typeClass)); - return configurations.get(typeClass); - } catch (Exception e) { - throw new UnexpectedLiquibaseException(e); + Scope.getCurrentScope().getLog(getClass()).fine(logMessage.toString()); } + + return details; } /** - * Convenience method for liquibaseConfiguration.getConfiguration(type).getProperty(property) + * Registers a {@link ConfigurationDefinition} so it will be returned by {@link #getRegisteredDefinitions()} */ - public ConfigurationProperty getProperty(Class type, String property) { - ConfigurationContainer configuration = getConfiguration(type); - return configuration.getProperty(property); - } - - protected T createConfiguration(Class type) { - try { - T configuration = type.getConstructor().newInstance(); - configuration.init(configurationValueProviders); - return configuration; - } catch (Exception e) { - throw new UnexpectedLiquibaseException("Cannot create default configuration "+type.getName(), e); - } + public void registerDefinition(ConfigurationDefinition definition) { + this.definitions.add(definition); } /** - * Convenience method for {@link #describeValueLookupLogic(ConfigurationProperty)} + * Returns all registered {@link ConfigurationDefinition}s. Registered definitions are used for generated help documentation. */ - public String describeValueLookupLogic(Class config, String property) { - return describeValueLookupLogic(getProperty(config, property)); + public SortedSet getRegisteredDefinitions() { + return Collections.unmodifiableSortedSet(this.definitions); } /** - * Generates a human consumable description of how the configured ConfigurationValueProvider(s) will - * attempt to set a default value. + * @return the registered {@link ConfigurationDefinition} asssociated with this key. Null if none match. */ - public String describeValueLookupLogic(ConfigurationProperty property) { - List reasons = new ArrayList<>(); - for (ConfigurationValueProvider container : configurationValueProviders) { - reasons.add(container.describeValueLookupLogic(property)); + public ConfigurationDefinition getRegisteredDefinition(String key) { + for (ConfigurationDefinition def : getRegisteredDefinitions()) { + if (def.getKey().equalsIgnoreCase(key)) { + return def; + } + final Set aliasKeys = def.getAliasKeys(); + if (aliasKeys != null && aliasKeys.contains(def.getKey())) { + return def; + } } - return StringUtil.join(reasons, " AND "); - } - - /** - * Convenience method to check if the object types should consider catalog name - * also during comparision (equals(), hashcode() and compareTo()) - * - * @return - */ - public boolean shouldIncludeCatalogInSpecification() { - Boolean includeCatalog = getConfiguration(GlobalConfiguration.class) - .getValue(GlobalConfiguration.INCLUDE_CATALOG_IN_SPECIFICATION, Boolean.class); - return includeCatalog != null ? includeCatalog : false; + return null; } } diff --git a/liquibase-core/src/main/java/liquibase/configuration/ProvidedValue.java b/liquibase-core/src/main/java/liquibase/configuration/ProvidedValue.java new file mode 100644 index 00000000000..35426dd8f2b --- /dev/null +++ b/liquibase-core/src/main/java/liquibase/configuration/ProvidedValue.java @@ -0,0 +1,61 @@ +package liquibase.configuration; + +/** + * Describes a value found from a provider. This is the most basic level at which a configuration value is defined. + */ +public class ProvidedValue { + private final String requestedKey; + private final String actualKey; + private final String sourceDescription; + private final ConfigurationValueProvider provider; + private final Object value; + + public ProvidedValue(String requestedKey, String actualKey, Object value, String sourceDescription, ConfigurationValueProvider provider) { + this.requestedKey = requestedKey; + this.actualKey = actualKey; + this.value = value; + this.sourceDescription = sourceDescription; + this.provider = provider; + } + + /** + * The value found by the provider. + */ + public Object getValue() { + return value; + } + + /** + * The configuration key the code asked the provider for. + * May be different than {@link #getActualKey()} if the provider does fuzzy matching such as case-insensitive lookups or . -> _ conversions etc. + */ + public String getRequestedKey() { + return requestedKey; + } + + /** + * The actual key/source for the value. + * This may be different than {@link #getRequestedKey()} if the provider does fuzzy matching such as case-insensitive lookups or . -> _ conversions etc. + */ + public String getActualKey() { + return actualKey; + } + + /** + * A description of where the value came from. + */ + public String getSourceDescription() { + return sourceDescription; + } + + /** + * The provider for this value + */ + public ConfigurationValueProvider getProvider() { + return provider; + } + + public String describe() { + return sourceDescription + " '" + actualKey + "'"; + } +} diff --git a/liquibase-core/src/main/java/liquibase/configuration/SystemPropertyProvider.java b/liquibase-core/src/main/java/liquibase/configuration/SystemPropertyProvider.java deleted file mode 100644 index 91ffc63a74e..00000000000 --- a/liquibase-core/src/main/java/liquibase/configuration/SystemPropertyProvider.java +++ /dev/null @@ -1,38 +0,0 @@ -package liquibase.configuration; - -import liquibase.util.StringUtil; - -import java.util.Map; -import java.util.Properties; - -/** - * A ConfigurationValueProvider implementation that looks for overriding values in system properties. - * Looks for system properties in the format "NAMESPACE.PROPERTY_NAME". - */ -public class SystemPropertyProvider implements ConfigurationValueProvider { - - @Override - public Object getValue(String namespace, String property) { - String propValue = System.getProperty(namespace +"."+property); - if (StringUtil.isNotEmpty(propValue)) { - return propValue; - } - - // - // Not matching with the actual key then try case insensitive - // - Properties properties = System.getProperties(); - for (Map.Entry entry : properties.entrySet()) { - String key = (String)entry.getKey(); - if (key.equalsIgnoreCase(namespace + "." + property)) { - return entry.getValue(); - } - } - return null; - } - - @Override - public String describeValueLookupLogic(ConfigurationProperty property) { - return "System property '"+property.getNamespace()+"."+property.getName()+"'"; - } -} diff --git a/liquibase-core/src/main/java/liquibase/configuration/core/DeprecatedConfigurationValueProvider.java b/liquibase-core/src/main/java/liquibase/configuration/core/DeprecatedConfigurationValueProvider.java new file mode 100644 index 00000000000..27d8a82abec --- /dev/null +++ b/liquibase-core/src/main/java/liquibase/configuration/core/DeprecatedConfigurationValueProvider.java @@ -0,0 +1,56 @@ +package liquibase.configuration.core; + +import liquibase.configuration.AbstractMapConfigurationValueProvider; +import liquibase.configuration.ConfigurationDefinition; + +import java.util.HashMap; +import java.util.Map; + +/** + * {@link liquibase.configuration.ConfigurationValueProvider} that simulates the behavior from pre-4.4 methods like {@link liquibase.configuration.GlobalConfiguration#setOutputEncoding(String)}. + * It is also useful for integrations that do not yet support a "Scope" style calling of logic. + * The values set in here should override environmental settings like {@link SystemPropertyValueProvider} but is overridden by new-style code using {@link ScopeValueProvider}. + * + * @deprecated + */ +public class DeprecatedConfigurationValueProvider extends AbstractMapConfigurationValueProvider { + + private static final Map data = new HashMap<>(); + + @Override + protected Map getMap() { + return data; + } + + @Override + public int getPrecedence() { + return 350; + } + + /** + * @deprecated + */ + public static void setData(String key, Object value) { + data.put(key, value); + } + + /** + * @deprecated + */ + public static void setData(ConfigurationDefinition configuration, T value) { + data.put(configuration.getKey(), value); + } + + /** + * Clears all data stored in this provider. + * @deprecated + */ + public static void clearData() { + data.clear(); + } + + @Override + protected String getSourceDescription() { + return "Legacy configuration"; + } +} diff --git a/liquibase-core/src/main/java/liquibase/configuration/core/ScopeValueProvider.java b/liquibase-core/src/main/java/liquibase/configuration/core/ScopeValueProvider.java new file mode 100644 index 00000000000..589dc773864 --- /dev/null +++ b/liquibase-core/src/main/java/liquibase/configuration/core/ScopeValueProvider.java @@ -0,0 +1,38 @@ +package liquibase.configuration.core; + +import liquibase.Scope; +import liquibase.configuration.AbstractConfigurationValueProvider; +import liquibase.configuration.ProvidedValue; + +import java.util.Properties; + +/** + * Searches the {@link liquibase.Scope} for the given key. + * Does not perform any key smoothing/translating. + */ +public class ScopeValueProvider extends AbstractConfigurationValueProvider { + + @Override + public int getPrecedence() { + return 400; + } + + @Override + public ProvidedValue getProvidedValue(String key) { + if (key == null) { + return null; + } + + final Object value = Scope.getCurrentScope().get(key, Object.class); + if (value == null) { + return null; + } + + return new ProvidedValue(key, key, value, "Scoped value", this); + } + + protected Properties getSystemProperties() { + return System.getProperties(); + } + +} diff --git a/liquibase-core/src/main/java/liquibase/configuration/core/SystemPropertyValueProvider.java b/liquibase-core/src/main/java/liquibase/configuration/core/SystemPropertyValueProvider.java new file mode 100644 index 00000000000..3859faf2c72 --- /dev/null +++ b/liquibase-core/src/main/java/liquibase/configuration/core/SystemPropertyValueProvider.java @@ -0,0 +1,33 @@ +package liquibase.configuration.core; + +import liquibase.configuration.AbstractConfigurationValueProvider; +import liquibase.configuration.AbstractMapConfigurationValueProvider; +import liquibase.configuration.ConfigurationValueProvider; +import liquibase.configuration.ProvidedValue; +import liquibase.util.StringUtil; + +import java.util.Map; +import java.util.Properties; + +/** + * Searches for the configuration values in the system properties {@link System#getProperties()}. + *

+ * To improve usability, it will search for the given key case insensitively. + */ +public class SystemPropertyValueProvider extends AbstractMapConfigurationValueProvider { + + @Override + public int getPrecedence() { + return 200; + } + + @Override + protected String getSourceDescription() { + return "System property"; + } + + @Override + protected Map getMap() { + return System.getProperties(); + } +} diff --git a/liquibase-core/src/main/java/liquibase/database/AbstractJdbcDatabase.java b/liquibase-core/src/main/java/liquibase/database/AbstractJdbcDatabase.java index 9d89e438400..0113dbb267b 100644 --- a/liquibase-core/src/main/java/liquibase/database/AbstractJdbcDatabase.java +++ b/liquibase-core/src/main/java/liquibase/database/AbstractJdbcDatabase.java @@ -9,9 +9,9 @@ import liquibase.changelog.DatabaseChangeLog; import liquibase.changelog.RanChangeSet; import liquibase.changelog.StandardChangeLogHistoryService; -import liquibase.configuration.ConfigurationProperty; -import liquibase.configuration.GlobalConfiguration; -import liquibase.configuration.LiquibaseConfiguration; +import liquibase.GlobalConfiguration; +import liquibase.configuration.ConfigurationDefinition; +import liquibase.configuration.ConfiguredValue; import liquibase.database.core.OracleDatabase; import liquibase.database.core.PostgresDatabase; import liquibase.database.core.SQLiteDatabase; @@ -623,7 +623,7 @@ public String getDatabaseChangeLogTableName() { return databaseChangeLogTableName; } - return LiquibaseConfiguration.getInstance().getConfiguration(GlobalConfiguration.class).getDatabaseChangeLogTableName(); + return GlobalConfiguration.DATABASECHANGELOG_TABLE_NAME.getCurrentValue(); } @Override @@ -637,7 +637,7 @@ public String getDatabaseChangeLogLockTableName() { return databaseChangeLogLockTableName; } - return LiquibaseConfiguration.getInstance().getConfiguration(GlobalConfiguration.class).getDatabaseChangeLogLockTableName(); + return GlobalConfiguration.DATABASECHANGELOGLOCK_TABLE_NAME.getCurrentValue(); } @Override @@ -651,7 +651,7 @@ public String getLiquibaseTablespaceName() { return liquibaseTablespaceName; } - return LiquibaseConfiguration.getInstance().getConfiguration(GlobalConfiguration.class).getLiquibaseTablespaceName(); + return GlobalConfiguration.LIQUIBASE_TABLESPACE_NAME.getCurrentValue(); } @Override @@ -674,9 +674,9 @@ public String getLiquibaseCatalogName() { return liquibaseCatalogName; } - ConfigurationProperty configuration = LiquibaseConfiguration.getInstance().getProperty(GlobalConfiguration.class, GlobalConfiguration.LIQUIBASE_CATALOG_NAME); - if (configuration.getWasOverridden()) { - return configuration.getValue(String.class); + final String configuredCatalogName = GlobalConfiguration.LIQUIBASE_CATALOG_NAME.getCurrentValue(); + if (configuredCatalogName != null) { + return configuredCatalogName; } return getDefaultCatalogName(); @@ -693,9 +693,9 @@ public String getLiquibaseSchemaName() { return liquibaseSchemaName; } - ConfigurationProperty configuration = LiquibaseConfiguration.getInstance().getProperty(GlobalConfiguration.class, GlobalConfiguration.LIQUIBASE_SCHEMA_NAME); - if (configuration.getWasOverridden()) { - return configuration.getValue(String.class); + final ConfiguredValue configuredValue = GlobalConfiguration.LIQUIBASE_SCHEMA_NAME.getCurrentConfiguredValue(); + if (!ConfigurationDefinition.wasDefaultValueUsed(configuredValue)) { + return configuredValue.getValue(); } return getDefaultSchemaName(); diff --git a/liquibase-core/src/main/java/liquibase/database/core/MSSQLDatabase.java b/liquibase-core/src/main/java/liquibase/database/core/MSSQLDatabase.java index 0fac70df533..e9bbe1c9186 100644 --- a/liquibase-core/src/main/java/liquibase/database/core/MSSQLDatabase.java +++ b/liquibase-core/src/main/java/liquibase/database/core/MSSQLDatabase.java @@ -2,7 +2,7 @@ import liquibase.CatalogAndSchema; import liquibase.Scope; -import liquibase.configuration.LiquibaseConfiguration; +import liquibase.GlobalConfiguration; import liquibase.database.AbstractJdbcDatabase; import liquibase.database.DatabaseConnection; import liquibase.database.OfflineConnection; @@ -377,7 +377,7 @@ public String escapeObjectName(String catalogName, String schemaName, String obj return super.escapeObjectName(objectName, objectType); } - boolean includeCatalog = LiquibaseConfiguration.getInstance().shouldIncludeCatalogInSpecification(); + boolean includeCatalog = GlobalConfiguration.INCLUDE_CATALOG_IN_SPECIFICATION.getCurrentValue(); if ((catalogName != null) && (includeCatalog || !catalogName.equalsIgnoreCase(this.getDefaultCatalogName()))) { return super.escapeObjectName(catalogName, schemaName, objectName, objectType); } else { diff --git a/liquibase-core/src/main/java/liquibase/datatype/core/ClobType.java b/liquibase-core/src/main/java/liquibase/datatype/core/ClobType.java index c0b2d49babb..0ebcb582e4e 100644 --- a/liquibase-core/src/main/java/liquibase/datatype/core/ClobType.java +++ b/liquibase-core/src/main/java/liquibase/datatype/core/ClobType.java @@ -1,8 +1,7 @@ package liquibase.datatype.core; import liquibase.change.core.LoadDataChange; -import liquibase.configuration.GlobalConfiguration; -import liquibase.configuration.LiquibaseConfiguration; +import liquibase.GlobalConfiguration; import liquibase.database.Database; import liquibase.database.core.*; import liquibase.datatype.DataTypeInfo; @@ -44,8 +43,8 @@ public String objectToSql(Object value, Database database) { public DatabaseDataType toDatabaseDataType(Database database) { String originalDefinition = StringUtil.trimToEmpty(getRawDefinition()); if (database instanceof MSSQLDatabase) { - if ((!LiquibaseConfiguration.getInstance().getProperty(GlobalConfiguration.class, GlobalConfiguration - .CONVERT_DATA_TYPES).getValue(Boolean.class) && originalDefinition.toLowerCase(Locale.US).startsWith("text")) + if ((!GlobalConfiguration.CONVERT_DATA_TYPES.getCurrentValue() + && originalDefinition.toLowerCase(Locale.US).startsWith("text")) || originalDefinition.toLowerCase(Locale.US).startsWith("[text]")) { DatabaseDataType type = new DatabaseDataType(database.escapeDataTypeName("varchar")); // If there is additional specification after ntext (e.g. COLLATE), import that. diff --git a/liquibase-core/src/main/java/liquibase/datatype/core/TimestampType.java b/liquibase-core/src/main/java/liquibase/datatype/core/TimestampType.java index 5d92519c1d7..eb040198662 100644 --- a/liquibase-core/src/main/java/liquibase/datatype/core/TimestampType.java +++ b/liquibase-core/src/main/java/liquibase/datatype/core/TimestampType.java @@ -4,8 +4,7 @@ import liquibase.change.core.LoadDataChange; import java.util.Locale; -import liquibase.configuration.GlobalConfiguration; -import liquibase.configuration.LiquibaseConfiguration; +import liquibase.GlobalConfiguration; import liquibase.database.Database; import liquibase.database.core.*; import liquibase.datatype.DataTypeInfo; @@ -67,9 +66,7 @@ public DatabaseDataType toDatabaseDataType(Database database) { return super.toDatabaseDataType(database); } if (database instanceof MSSQLDatabase) { - if (!LiquibaseConfiguration.getInstance() - .getProperty(GlobalConfiguration.class, GlobalConfiguration.CONVERT_DATA_TYPES) - .getValue(Boolean.class) + if (!GlobalConfiguration.CONVERT_DATA_TYPES.getCurrentValue() && originalDefinition.toLowerCase(Locale.US).startsWith("timestamp")) { return new DatabaseDataType(database.escapeDataTypeName("timestamp")); } diff --git a/liquibase-core/src/main/java/liquibase/dbdoc/ChangeLogWriter.java b/liquibase-core/src/main/java/liquibase/dbdoc/ChangeLogWriter.java index 13c3c4c9f17..def4f16277e 100644 --- a/liquibase-core/src/main/java/liquibase/dbdoc/ChangeLogWriter.java +++ b/liquibase-core/src/main/java/liquibase/dbdoc/ChangeLogWriter.java @@ -1,7 +1,6 @@ package liquibase.dbdoc; -import liquibase.configuration.GlobalConfiguration; -import liquibase.configuration.LiquibaseConfiguration; +import liquibase.GlobalConfiguration; import liquibase.resource.ResourceAccessor; import liquibase.util.StreamUtil; @@ -22,7 +21,7 @@ public void writeChangeLog(String changeLog, String physicalFilePath) throws IOE xmlFile.getParentFile().mkdirs(); BufferedWriter changeLogStream = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(xmlFile, - false), LiquibaseConfiguration.getInstance().getConfiguration(GlobalConfiguration.class).getOutputEncoding())); + false), GlobalConfiguration.OUTPUT_ENCODING.getCurrentValue())); try (InputStream stylesheet = resourceAccessor.openStream(null, physicalFilePath)) { if (stylesheet == null) { throw new IOException("Can not find " + changeLog); diff --git a/liquibase-core/src/main/java/liquibase/dbdoc/HTMLListWriter.java b/liquibase-core/src/main/java/liquibase/dbdoc/HTMLListWriter.java index a73fd8a64e5..6a9b99c7167 100644 --- a/liquibase-core/src/main/java/liquibase/dbdoc/HTMLListWriter.java +++ b/liquibase-core/src/main/java/liquibase/dbdoc/HTMLListWriter.java @@ -1,7 +1,6 @@ package liquibase.dbdoc; -import liquibase.configuration.GlobalConfiguration; -import liquibase.configuration.LiquibaseConfiguration; +import liquibase.GlobalConfiguration; import liquibase.util.StringUtil; import java.io.*; @@ -24,7 +23,7 @@ public HTMLListWriter(String title, String filename, String subdir, File outputD } public void writeHTML(SortedSet objects) throws IOException { - Writer fileWriter = new OutputStreamWriter(new FileOutputStream(new File(outputDir, filename)), LiquibaseConfiguration.getInstance().getConfiguration(GlobalConfiguration.class).getOutputEncoding()); + Writer fileWriter = new OutputStreamWriter(new FileOutputStream(new File(outputDir, filename)), GlobalConfiguration.OUTPUT_ENCODING.getCurrentValue()); try { fileWriter.append("\n" + "\n" + "\n"); diff --git a/liquibase-core/src/main/java/liquibase/dbdoc/HTMLWriter.java b/liquibase-core/src/main/java/liquibase/dbdoc/HTMLWriter.java index 3580e676b0f..221a4a1e4b8 100644 --- a/liquibase-core/src/main/java/liquibase/dbdoc/HTMLWriter.java +++ b/liquibase-core/src/main/java/liquibase/dbdoc/HTMLWriter.java @@ -2,8 +2,7 @@ import liquibase.change.Change; import liquibase.changelog.ChangeSet; -import liquibase.configuration.GlobalConfiguration; -import liquibase.configuration.LiquibaseConfiguration; +import liquibase.GlobalConfiguration; import liquibase.database.Database; import liquibase.exception.DatabaseException; import liquibase.exception.DatabaseHistoryException; @@ -30,7 +29,7 @@ public HTMLWriter(File outputDir, Database database) { protected abstract void writeCustomHTML(Writer fileWriter, Object object, List<Change> changes, Database database) throws IOException; private Writer createFileWriter(Object object) throws IOException { - return new OutputStreamWriter(new FileOutputStream(new File(outputDir, DBDocUtil.toFileName(object.toString().toLowerCase()) + ".html")), LiquibaseConfiguration.getInstance().getConfiguration(GlobalConfiguration.class).getOutputEncoding()); + return new OutputStreamWriter(new FileOutputStream(new File(outputDir, DBDocUtil.toFileName(object.toString().toLowerCase()) + ".html")), GlobalConfiguration.OUTPUT_ENCODING.getCurrentValue()); } public void writeHTML(Object object, List<Change> ranChanges, List<Change> changesToRun, String changeLog) throws IOException, DatabaseHistoryException, DatabaseException { diff --git a/liquibase-core/src/main/java/liquibase/diff/compare/core/CatalogComparator.java b/liquibase-core/src/main/java/liquibase/diff/compare/core/CatalogComparator.java index 1a71907561a..e8ef0b79b0f 100644 --- a/liquibase-core/src/main/java/liquibase/diff/compare/core/CatalogComparator.java +++ b/liquibase-core/src/main/java/liquibase/diff/compare/core/CatalogComparator.java @@ -1,7 +1,7 @@ package liquibase.diff.compare.core; import liquibase.CatalogAndSchema; -import liquibase.configuration.LiquibaseConfiguration; +import liquibase.GlobalConfiguration; import liquibase.database.Database; import liquibase.diff.ObjectDifferences; import liquibase.diff.compare.CompareControl; @@ -38,7 +38,7 @@ public boolean isSameObject(DatabaseObject databaseObject1, DatabaseObject datab } // the flag will be set true in multi catalog environments - boolean shouldIncludeCatalog = LiquibaseConfiguration.getInstance().shouldIncludeCatalogInSpecification(); + boolean shouldIncludeCatalog = GlobalConfiguration.INCLUDE_CATALOG_IN_SPECIFICATION.getCurrentValue(); String object1Name; if (!shouldIncludeCatalog && ((Catalog) databaseObject1).isDefault()) { object1Name = null; diff --git a/liquibase-core/src/main/java/liquibase/diff/compare/core/ColumnComparator.java b/liquibase-core/src/main/java/liquibase/diff/compare/core/ColumnComparator.java index 9d889bd4a8d..76c592598c3 100644 --- a/liquibase-core/src/main/java/liquibase/diff/compare/core/ColumnComparator.java +++ b/liquibase-core/src/main/java/liquibase/diff/compare/core/ColumnComparator.java @@ -1,7 +1,6 @@ package liquibase.diff.compare.core; -import liquibase.configuration.GlobalConfiguration; -import liquibase.configuration.LiquibaseConfiguration; +import liquibase.GlobalConfiguration; import liquibase.database.Database; import liquibase.diff.ObjectDifferences; import liquibase.diff.compare.CompareControl; @@ -77,7 +76,7 @@ public ObjectDifferences findDifferences(DatabaseObject databaseObject1, Databas exclude.add("type"); exclude.add("autoIncrementInformation"); - if (!LiquibaseConfiguration.getInstance().getConfiguration(GlobalConfiguration.class).getDiffColumnOrder()) { + if (!GlobalConfiguration.DIFF_COLUMN_ORDER.getCurrentValue()) { exclude.add("order"); } diff --git a/liquibase-core/src/main/java/liquibase/diff/compare/core/SchemaComparator.java b/liquibase-core/src/main/java/liquibase/diff/compare/core/SchemaComparator.java index e123f5e3e52..13c89a715b3 100644 --- a/liquibase-core/src/main/java/liquibase/diff/compare/core/SchemaComparator.java +++ b/liquibase-core/src/main/java/liquibase/diff/compare/core/SchemaComparator.java @@ -1,7 +1,7 @@ package liquibase.diff.compare.core; import liquibase.CatalogAndSchema; -import liquibase.configuration.LiquibaseConfiguration; +import liquibase.GlobalConfiguration; import liquibase.database.Database; import liquibase.diff.ObjectDifferences; import liquibase.diff.compare.CompareControl; @@ -10,7 +10,6 @@ import liquibase.structure.DatabaseObject; import liquibase.structure.core.Catalog; import liquibase.structure.core.Schema; -import liquibase.util.StringUtil; import java.util.Set; @@ -38,7 +37,7 @@ public boolean isSameObject(DatabaseObject databaseObject1, DatabaseObject datab String schemaName2 = null; // the flag will be set true in multi catalog environments - boolean shouldIncludeCatalog = LiquibaseConfiguration.getInstance().shouldIncludeCatalogInSpecification(); + boolean shouldIncludeCatalog = GlobalConfiguration.INCLUDE_CATALOG_IN_SPECIFICATION.getCurrentValue(); if (shouldIncludeCatalog) { Catalog catalog1 = ((Schema) databaseObject1).getCatalog(); Catalog catalog2 = ((Schema) databaseObject2).getCatalog(); diff --git a/liquibase-core/src/main/java/liquibase/diff/output/changelog/DiffToChangeLog.java b/liquibase-core/src/main/java/liquibase/diff/output/changelog/DiffToChangeLog.java index 6add04eeea0..b3fe0ab8510 100644 --- a/liquibase-core/src/main/java/liquibase/diff/output/changelog/DiffToChangeLog.java +++ b/liquibase-core/src/main/java/liquibase/diff/output/changelog/DiffToChangeLog.java @@ -4,8 +4,8 @@ import liquibase.change.Change; import liquibase.change.core.*; import liquibase.changelog.ChangeSet; -import liquibase.configuration.GlobalConfiguration; -import liquibase.configuration.LiquibaseConfiguration; +import liquibase.GlobalConfiguration; +import liquibase.configuration.core.DeprecatedConfigurationValueProvider; import liquibase.database.*; import liquibase.database.core.*; import liquibase.diff.DiffResult; @@ -97,7 +97,7 @@ public void print(String changeLogFile, ChangeLogSerializer changeLogSerializer) File objectsDir = null; if (changeLogFile.toLowerCase().endsWith("sql")) { - System.setProperty("liquibase.pro.sql.inline", "true"); + DeprecatedConfigurationValueProvider.setData("liquibase.pro.sql.inline", "true"); } else if (this.diffResult.getComparisonSnapshot() instanceof EmptyDatabaseSnapshot) { objectsDir = new File(file.getParentFile(), "objects"); } else { @@ -134,9 +134,9 @@ public void run() { } else { Scope.getCurrentScope().getLog(getClass()).info(file + " exists, appending"); ByteArrayOutputStream out = new ByteArrayOutputStream(); - print(new PrintStream(out, true, LiquibaseConfiguration.getInstance().getConfiguration(GlobalConfiguration.class).getOutputEncoding()), changeLogSerializer); + print(new PrintStream(out, true, GlobalConfiguration.OUTPUT_ENCODING.getCurrentValue()), changeLogSerializer); - String xml = new String(out.toByteArray(), LiquibaseConfiguration.getInstance().getConfiguration(GlobalConfiguration.class).getOutputEncoding()); + String xml = new String(out.toByteArray(), GlobalConfiguration.OUTPUT_ENCODING.getCurrentValue()); String innerXml = xml.replaceFirst("(?ms).*<databaseChangeLog[^>]*>", ""); innerXml = innerXml.replaceFirst(DATABASE_CHANGE_LOG_CLOSING_XML_TAG, ""); @@ -161,23 +161,19 @@ public void run() { } } - String lineSeparator = LiquibaseConfiguration.getInstance().getConfiguration(GlobalConfiguration - .class).getOutputLineSeparator(); + String lineSeparator = GlobalConfiguration.OUTPUT_LINE_SEPARATOR.getCurrentValue(); if (foundEndTag) { randomAccessFile.seek(offset); randomAccessFile.writeBytes(" "); - randomAccessFile.write(innerXml.getBytes(LiquibaseConfiguration.getInstance().getConfiguration - (GlobalConfiguration.class).getOutputEncoding())); + randomAccessFile.write(innerXml.getBytes(GlobalConfiguration.OUTPUT_ENCODING.getCurrentValue())); randomAccessFile.writeBytes(lineSeparator); randomAccessFile.writeBytes(DATABASE_CHANGE_LOG_CLOSING_XML_TAG + lineSeparator); } else { randomAccessFile.seek(0); long length = randomAccessFile.length(); randomAccessFile.seek(length); - randomAccessFile.write( - xml.getBytes(LiquibaseConfiguration.getInstance().getConfiguration - (GlobalConfiguration.class).getOutputEncoding())); + randomAccessFile.write(xml.getBytes(GlobalConfiguration.OUTPUT_ENCODING.getCurrentValue())); } } @@ -233,7 +229,7 @@ public void printNew(ChangeLogSerializer changeLogSerializer, File file) throws } try (FileOutputStream stream = new FileOutputStream(file); - PrintStream out = new PrintStream(stream, true, LiquibaseConfiguration.getInstance().getConfiguration(GlobalConfiguration.class).getOutputEncoding())) { + PrintStream out = new PrintStream(stream, true, GlobalConfiguration.OUTPUT_ENCODING.getCurrentValue())) { changeLogSerializer.write(changeSets, out); } } @@ -255,7 +251,7 @@ public List<ChangeSet> generateChangeSets() { DatabaseObjectComparator comparator = new DatabaseObjectComparator(); String created = null; - if (LiquibaseConfiguration.getInstance().getProperty(GlobalConfiguration.class, GlobalConfiguration.GENERATE_CHANGESET_CREATED_VALUES).getValue(Boolean.class)) { + if (GlobalConfiguration.GENERATE_CHANGESET_CREATED_VALUES.getCurrentValue()) { created = new SimpleDateFormat("yyyy-MM-dd HH:mmZ").format(new Date()); } @@ -858,7 +854,7 @@ public void setIdRoot(String idRoot) { protected String generateId(Change[] changes) { String desc = ""; - if (LiquibaseConfiguration.getInstance().getConfiguration(GlobalConfiguration.class).getGeneratedChangeSetIdsContainDescription()) { + if (GlobalConfiguration.GENERATED_CHANGESET_IDS_INCLUDE_DESCRIPTION.getCurrentValue()) { if (!overriddenIdRoot) { //switch timestamp to a shorter string (last 4 digits in base 36 format). Still mostly unique, but shorter since we also now have mostly-unique descriptions of the changes this.idRoot = Long.toString(Long.decode(idRoot), 36); idRoot = idRoot.substring(idRoot.length() - 4); diff --git a/liquibase-core/src/main/java/liquibase/diff/output/changelog/core/MissingDataChangeGenerator.java b/liquibase-core/src/main/java/liquibase/diff/output/changelog/core/MissingDataChangeGenerator.java index 227d4820a8c..a8cb96201fc 100644 --- a/liquibase-core/src/main/java/liquibase/diff/output/changelog/core/MissingDataChangeGenerator.java +++ b/liquibase-core/src/main/java/liquibase/diff/output/changelog/core/MissingDataChangeGenerator.java @@ -3,9 +3,7 @@ import liquibase.change.Change; import liquibase.change.ColumnConfig; import liquibase.change.core.InsertDataChange; -import liquibase.configuration.GlobalConfiguration; -import liquibase.configuration.LiquibaseConfiguration; -import liquibase.database.AbstractJdbcDatabase; +import liquibase.GlobalConfiguration; import liquibase.database.Database; import liquibase.database.core.InformixDatabase; import liquibase.database.jvm.JdbcConnection; @@ -18,7 +16,6 @@ import liquibase.structure.DatabaseObject; import liquibase.structure.core.*; import liquibase.util.JdbcUtils; -import liquibase.util.StringUtil; import java.sql.ResultSet; import java.sql.SQLException; @@ -100,7 +97,7 @@ public Change[] fixMissing(DatabaseObject missingObject, DiffOutputControl outpu column.setValueDate((Date) value); } else if (value instanceof byte[]) { if (referenceDatabase instanceof InformixDatabase) { - column.setValue(new String((byte[]) value, LiquibaseConfiguration.getInstance().getConfiguration(GlobalConfiguration.class).getOutputEncoding())); + column.setValue(new String((byte[]) value, GlobalConfiguration.OUTPUT_ENCODING.getCurrentValue())); } column.setValueComputed(new DatabaseFunction("UNSUPPORTED FOR DIFF: BINARY DATA")); } else { // fall back to simple string diff --git a/liquibase-core/src/main/java/liquibase/diff/output/changelog/core/MissingDataExternalFileChangeGenerator.java b/liquibase-core/src/main/java/liquibase/diff/output/changelog/core/MissingDataExternalFileChangeGenerator.java index 706763bcb78..596c71c0916 100644 --- a/liquibase-core/src/main/java/liquibase/diff/output/changelog/core/MissingDataExternalFileChangeGenerator.java +++ b/liquibase-core/src/main/java/liquibase/diff/output/changelog/core/MissingDataExternalFileChangeGenerator.java @@ -3,8 +3,7 @@ import liquibase.change.Change; import liquibase.change.core.LoadDataChange; import liquibase.change.core.LoadDataColumnConfig; -import liquibase.configuration.GlobalConfiguration; -import liquibase.configuration.LiquibaseConfiguration; +import liquibase.GlobalConfiguration; import liquibase.database.Database; import liquibase.database.jvm.JdbcConnection; import liquibase.diff.output.DiffOutputControl; @@ -89,10 +88,7 @@ public Change[] fixMissing(DatabaseObject missingObject, DiffOutputControl outpu try ( FileOutputStream fileOutputStream = new FileOutputStream(fileName); OutputStreamWriter outputStreamWriter = new OutputStreamWriter( - fileOutputStream, - LiquibaseConfiguration.getInstance().getConfiguration(GlobalConfiguration.class) - .getOutputEncoding() - ); + fileOutputStream, GlobalConfiguration.OUTPUT_ENCODING.getCurrentValue()); CSVWriter outputFile = new CSVWriter(new BufferedWriter(outputStreamWriter)); ) { @@ -146,7 +142,7 @@ public Change[] fixMissing(DatabaseObject missingObject, DiffOutputControl outpu LoadDataChange change = new LoadDataChange(); change.setFile(fileName); - change.setEncoding(LiquibaseConfiguration.getInstance().getConfiguration(GlobalConfiguration.class).getOutputEncoding()); + change.setEncoding(GlobalConfiguration.OUTPUT_ENCODING.getCurrentValue()); if (outputControl.getIncludeCatalog()) { change.setCatalogName(table.getSchema().getCatalogName()); } diff --git a/liquibase-core/src/main/java/liquibase/exception/UnknownConfigurationType.java b/liquibase-core/src/main/java/liquibase/exception/UnknownConfigurationType.java new file mode 100644 index 00000000000..473472d20f8 --- /dev/null +++ b/liquibase-core/src/main/java/liquibase/exception/UnknownConfigurationType.java @@ -0,0 +1,15 @@ +package liquibase.exception; + +public class UnknownConfigurationType extends UnexpectedLiquibaseException { + public UnknownConfigurationType(String message) { + super(message); + } + + public UnknownConfigurationType(String message, Throwable cause) { + super(message, cause); + } + + public UnknownConfigurationType(Throwable cause) { + super(cause); + } +} diff --git a/liquibase-core/src/main/java/liquibase/hub/HubConfiguration.java b/liquibase-core/src/main/java/liquibase/hub/HubConfiguration.java new file mode 100644 index 00000000000..24a471aff93 --- /dev/null +++ b/liquibase-core/src/main/java/liquibase/hub/HubConfiguration.java @@ -0,0 +1,78 @@ +package liquibase.hub; + +import liquibase.Scope; +import liquibase.configuration.ConfigurationDefinition; +import liquibase.configuration.AutoloadedConfigurations; +import liquibase.util.StringUtil; + +import java.util.Arrays; +import java.util.List; +import java.util.logging.Level; + +/** + * Configuration container for global properties. + */ +public class HubConfiguration implements AutoloadedConfigurations { + + public static final ConfigurationDefinition<String> LIQUIBASE_HUB_API_KEY; + public static final ConfigurationDefinition<String> LIQUIBASE_HUB_URL; + public static final ConfigurationDefinition<String> LIQUIBASE_HUB_MODE; + public static final ConfigurationDefinition<Level> LIQUIBASE_HUB_LOGLEVEL; + + static { + ConfigurationDefinition.Builder builder = new ConfigurationDefinition.Builder("liquibase.hub"); + + LIQUIBASE_HUB_API_KEY = builder.define("apiKey", String.class) + .setDescription("Liquibase Hub API key for operations") + .setValueObfuscator(value -> { + if (value == null) { + return null; + } + return value.substring(0, 6) + "************"; + + }) + .build(); + + LIQUIBASE_HUB_URL = builder.define("url", String.class) + .setDescription("Liquibase Hub URL for operations") + .setDefaultValue("https://hub.liquibase.com") + .setValueHandler(value -> { + if (value == null) { + return null; + } + return value.toString().replaceFirst("(https?://[^/]+).*", "$1"); + }) + .build(); + LIQUIBASE_HUB_MODE = builder.define("mode", String.class) + .setDescription("Content to send to Liquibase Hub during operations. Values can be 'all', 'meta', or 'off'") + .setDefaultValue("all") + .build(); + + LIQUIBASE_HUB_LOGLEVEL = builder.define("logLevel", Level.class) + .setDescription("Log level for filtering log messages to send to Liquibase Hub during operations. Values can be any acceptable log level.") + .setDefaultValue(Level.INFO) + .setValueHandler(value -> { + if (value == null) { + return null; + } + + if (value instanceof String) { + final List<String> validValues = Arrays.asList("OFF", "FINE", "WARN", "ERROR", "INFO"); + if (!validValues.contains(((String) value).toUpperCase())) { + Level logLevel = Level.INFO; + try { + logLevel = Level.parse(((String) value).toUpperCase()); + } catch (IllegalArgumentException e) { + String message = "An invalid liquibase.hub.logLevel value of " + value + " detected. Acceptable values are " + StringUtil.join(validValues, ","); + Scope.getCurrentScope().getLog(liquibase.hub.HubConfiguration.class).warning(message); + } + value = logLevel.toString(); + } + + } + + return Level.parse(value.toString()); + }) + .build(); + } +} diff --git a/liquibase-core/src/main/java/liquibase/hub/HubUpdater.java b/liquibase-core/src/main/java/liquibase/hub/HubUpdater.java index 6ca546488ac..fb53e077b2c 100644 --- a/liquibase-core/src/main/java/liquibase/hub/HubUpdater.java +++ b/liquibase-core/src/main/java/liquibase/hub/HubUpdater.java @@ -11,10 +11,9 @@ import liquibase.command.CommandResult; import liquibase.command.core.RegisterChangeLogCommand; import liquibase.command.core.SyncHubCommand; -import liquibase.configuration.ConfigurationProperty; -import liquibase.configuration.GlobalConfiguration; -import liquibase.configuration.HubConfiguration; -import liquibase.configuration.LiquibaseConfiguration; +import liquibase.configuration.ConfigurationDefinition; +import liquibase.configuration.ConfiguredValue; +import liquibase.configuration.core.DeprecatedConfigurationValueProvider; import liquibase.database.Database; import liquibase.database.DatabaseConnection; import liquibase.database.jvm.JdbcConnection; @@ -198,8 +197,7 @@ public void postUpdateHub(Operation updateOperation, BufferedLogService bufferLo // Send the COMPLETE operation event // Capture the Liquibase Hub log level to use for filtering // - HubConfiguration hubConfiguration = LiquibaseConfiguration.getInstance().getConfiguration(HubConfiguration.class); - Level currentLevel = Level.parse(hubConfiguration.getLiquibaseHubLogLevel()); + Level currentLevel = HubConfiguration.LIQUIBASE_HUB_LOGLEVEL.getCurrentValue(); hubService.sendOperationEvent(updateOperation, new OperationEvent() .setEventType("COMPLETE") @@ -260,8 +258,7 @@ public void postUpdateHubExceptionHandling(Operation updateOperation, // // Capture the current log level to use for filtering // - HubConfiguration hubConfiguration = LiquibaseConfiguration.getInstance().getConfiguration(HubConfiguration.class); - Level currentLevel = Level.parse(hubConfiguration.getLiquibaseHubLogLevel()); + Level currentLevel = HubConfiguration.LIQUIBASE_HUB_LOGLEVEL.getCurrentValue(); // // Check to see if the changelog has been deactivated @@ -318,7 +315,7 @@ public boolean hubIsNotAvailable(String changeLogId) { } public void syncHub(String changeLogFile, DatabaseChangeLog databaseChangeLog, UUID hubConnectionId) { - final SyncHubCommand syncHub = (SyncHubCommand) CommandFactory.getInstance().getCommand("syncHub"); + final SyncHubCommand syncHub = (SyncHubCommand) Scope.getCurrentScope().getSingleton(CommandFactory.class).getCommand("syncHub"); syncHub.setChangeLogFile(changeLogFile); syncHub.setUrl(database.getConnection().getURL()); syncHub.setHubConnectionId(hubConnectionId != null ? Objects.toString(hubConnectionId) : null); @@ -327,7 +324,7 @@ public void syncHub(String changeLogFile, DatabaseChangeLog databaseChangeLog, U try { syncHub.configure(Collections.singletonMap("changeLog", databaseChangeLog)); - final CommandResult commandResult = syncHub.execute(); + final CommandResult commandResult = Scope.getCurrentScope().getSingleton(CommandFactory.class).execute(syncHub); if (!commandResult.succeeded) { Scope.getCurrentScope().getLog(getClass()).warning("Liquibase Hub sync failed: " + commandResult.message); } @@ -358,7 +355,6 @@ public void register(String changeLogFile) // // Just return if Hub is off // - HubConfiguration hubConfiguration = LiquibaseConfiguration.getInstance().getConfiguration(HubConfiguration.class); final HubService hubService = Scope.getCurrentScope().getSingleton(HubServiceFactory.class).getService(); if (!hubService.isOnline()) { return; @@ -369,7 +365,7 @@ public void register(String changeLogFile) // 1. We have a key already OR // 2. We have a changeLogId already // - if (!StringUtil.isEmpty(hubConfiguration.getLiquibaseHubApiKey()) || + if (!StringUtil.isEmpty(HubConfiguration.LIQUIBASE_HUB_API_KEY.getCurrentValue()) || changeLog.getChangeLogId() != null) { return; } @@ -462,15 +458,15 @@ public void register(String changeLogFile) // If there is no liquibase.hub.mode setting then add one with value 'all' // Do not update liquibase.hub.mode if it is already set // - ConfigurationProperty hubModeProperty = hubConfiguration.getProperty(HubConfiguration.LIQUIBASE_HUB_MODE); - if (! hubModeProperty.getWasOverridden()) { + ConfiguredValue<String> hubModeProperty = HubConfiguration.LIQUIBASE_HUB_MODE.getCurrentConfiguredValue(); + if (ConfigurationDefinition.wasDefaultValueUsed(hubModeProperty)) { writeToPropertiesFile(defaultsFile, "\nliquibase.hub.mode=all\n"); message = "* Updated properties file " + defaultsFile + " to set liquibase.hub properties"; Scope.getCurrentScope().getUI().sendMessage(message); Scope.getCurrentScope().getLog(getClass()).info(message); } else { message = "* Updated the liquibase.hub.apiKey property."; - String message2 = "The liquibase.hub.mode is already set to " + hubConfiguration.getLiquibaseHubMode() + ". It will not be updated."; + String message2 = "The liquibase.hub.mode is already set to " + hubModeProperty.getValue() + ". It will not be updated."; Scope.getCurrentScope().getUI().sendMessage(message); Scope.getCurrentScope().getUI().sendMessage(message2); Scope.getCurrentScope().getLog(getClass()).warning(message); @@ -484,7 +480,7 @@ public void register(String changeLogFile) message = "* Registering changelog file " + changeLogFile + " with Hub"; Scope.getCurrentScope().getUI().sendMessage(message); Scope.getCurrentScope().getLog(getClass()).info(message); - hubConfiguration.setLiquibaseHubApiKey(registerResponse.getApiKey()); + DeprecatedConfigurationValueProvider.setData(HubConfiguration.LIQUIBASE_HUB_API_KEY, registerResponse.getApiKey()); registerChangeLog(registerResponse.getProjectId(), changeLog, changeLogFile); message = "Great! Your free operation and deployment reports will be available to you after your local Liquibase commands complete."; @@ -500,7 +496,8 @@ public void register(String changeLogFile) "No operations will be reported."; Scope.getCurrentScope().getUI().sendMessage(message); Scope.getCurrentScope().getLog(getClass()).warning(message); - hubConfiguration.setLiquibaseHubApiKey(null); + + System.setProperty(HubConfiguration.LIQUIBASE_HUB_API_KEY.getKey(), null); } } } @@ -509,7 +506,7 @@ public void register(String changeLogFile) // Write the string to a properties file // private void writeToPropertiesFile(File defaultsFile, String stringToWrite) throws IOException { - String encoding = LiquibaseConfiguration.getInstance().getConfiguration(GlobalConfiguration.class).getOutputEncoding(); + String encoding = GlobalConfiguration.OUTPUT_ENCODING.getCurrentValue(); try (RandomAccessFile randomAccessFile = new RandomAccessFile(defaultsFile, "rw")) { randomAccessFile.seek(defaultsFile.length()); randomAccessFile.write(stringToWrite.getBytes(encoding)); @@ -543,7 +540,7 @@ private void registerChangeLog(UUID hubProjectId, DatabaseChangeLog changeLog, S // // Execute registerChangeLog // - CommandResult result = registerChangeLogCommand.execute(); + CommandResult result = Scope.getCurrentScope().getSingleton(CommandFactory.class).execute(registerChangeLogCommand); Scope.getCurrentScope().getUI().sendMessage(result.print()); } diff --git a/liquibase-core/src/main/java/liquibase/hub/core/HttpClient.java b/liquibase-core/src/main/java/liquibase/hub/core/HttpClient.java index 7a8d86371d1..38824f5f4a6 100644 --- a/liquibase-core/src/main/java/liquibase/hub/core/HttpClient.java +++ b/liquibase-core/src/main/java/liquibase/hub/core/HttpClient.java @@ -1,8 +1,8 @@ package liquibase.hub.core; import liquibase.Scope; -import liquibase.configuration.HubConfiguration; -import liquibase.configuration.LiquibaseConfiguration; +import liquibase.configuration.core.DeprecatedConfigurationValueProvider; +import liquibase.hub.HubConfiguration; import liquibase.hub.LiquibaseHubException; import liquibase.hub.LiquibaseHubObjectNotFoundException; import liquibase.hub.LiquibaseHubRedirectException; @@ -90,8 +90,7 @@ protected <T> T doDelete(String url, Class<T> returnType) throws LiquibaseHubExc } private URLConnection openConnection(String url) throws LiquibaseHubException { - HubConfiguration hubConfiguration = LiquibaseConfiguration.getInstance().getConfiguration(HubConfiguration.class); - String apiKey = hubConfiguration.getLiquibaseHubApiKey(); + String apiKey = HubConfiguration.LIQUIBASE_HUB_API_KEY.getCurrentValue(); try { final URLConnection connection = new URL(getHubUrl() + url).openConnection(); @@ -182,8 +181,8 @@ protected <T> T doRequest(String method, String url, Object requestBodyObject, String newHubUrl = connection.getHeaderField("Location"); newHubUrl = newHubUrl.replaceAll(url, ""); Scope.getCurrentScope().getLog(getClass()).info("Redirecting to URL: " + newHubUrl); - HubConfiguration hubConfiguration = LiquibaseConfiguration.getInstance().getConfiguration(HubConfiguration.class); - hubConfiguration.setLiquibaseHubUrl(newHubUrl); + + DeprecatedConfigurationValueProvider.setData(HubConfiguration.LIQUIBASE_HUB_URL, newHubUrl); throw new LiquibaseHubRedirectException(); } } @@ -233,8 +232,7 @@ protected <T> T doRequest(String method, String url, Object requestBodyObject, } public String getHubUrl() { - HubConfiguration hubConfiguration = LiquibaseConfiguration.getInstance().getConfiguration(HubConfiguration.class); - return hubConfiguration.getLiquibaseHubUrl(); + return HubConfiguration.LIQUIBASE_HUB_URL.getCurrentValue(); } diff --git a/liquibase-core/src/main/java/liquibase/hub/core/StandardHubService.java b/liquibase-core/src/main/java/liquibase/hub/core/StandardHubService.java index 28b607c9f02..c809c2d70dc 100644 --- a/liquibase-core/src/main/java/liquibase/hub/core/StandardHubService.java +++ b/liquibase-core/src/main/java/liquibase/hub/core/StandardHubService.java @@ -3,8 +3,7 @@ import liquibase.Scope; import liquibase.changelog.ChangeSet; import liquibase.changelog.RanChangeSet; -import liquibase.configuration.HubConfiguration; -import liquibase.configuration.LiquibaseConfiguration; +import liquibase.hub.HubConfiguration; import liquibase.exception.LiquibaseException; import liquibase.hub.*; import liquibase.hub.model.*; @@ -46,7 +45,7 @@ public int getPriority() { @Override public boolean isOnline() { - return !LiquibaseConfiguration.getInstance().getConfiguration(HubConfiguration.class).getLiquibaseHubMode().equalsIgnoreCase("OFF"); + return !HubConfiguration.LIQUIBASE_HUB_MODE.getCurrentValue().equalsIgnoreCase("OFF"); } public boolean isHubAvailable() { @@ -54,7 +53,7 @@ public boolean isHubAvailable() { final Logger log = Scope.getCurrentScope().getLog(getClass()); final HubServiceFactory hubServiceFactory = Scope.getCurrentScope().getSingleton(HubServiceFactory.class); - if (LiquibaseConfiguration.getInstance().getConfiguration(HubConfiguration.class).getLiquibaseHubMode().equalsIgnoreCase("OFF")) { + if (HubConfiguration.LIQUIBASE_HUB_MODE.getCurrentValue().equalsIgnoreCase("OFF")) { hubServiceFactory.setOfflineReason("property liquibase.hub.mode is 'OFF'. To send data to Liquibase Hub, please set it to \"all\""); this.available = false; } else if (getApiKey() == null) { @@ -71,7 +70,7 @@ public boolean isHubAvailable() { this.organizationId = organization.getId(); } - log.info("Connected to Liquibase Hub with an API Key '" + LiquibaseConfiguration.getInstance().getConfiguration(HubConfiguration.class).getLiquibaseHubApiKeySecureDescription() + "'"); + log.info("Connected to Liquibase Hub with an API Key '" + HubConfiguration.LIQUIBASE_HUB_API_KEY.getCurrentValueObfuscated() + "'"); this.available = true; } catch (LiquibaseHubException e) { if (e.getCause() instanceof ConnectException) { @@ -96,8 +95,7 @@ public boolean isHubAvailable() { } public String getApiKey() { - HubConfiguration hubConfiguration = LiquibaseConfiguration.getInstance().getConfiguration(HubConfiguration.class); - return StringUtil.trimToNull(hubConfiguration.getLiquibaseHubApiKey()); + return StringUtil.trimToNull(HubConfiguration.LIQUIBASE_HUB_API_KEY.getCurrentValue()); } @Override @@ -454,7 +452,7 @@ public OperationEvent sendOperationEvent(Operation operation, OperationEvent ope } if (operationEvent.getOperationEventLog() != null) { - if (!LiquibaseConfiguration.getInstance().getConfiguration(HubConfiguration.class).getLiquibaseHubMode().equalsIgnoreCase("meta")) { + if (!HubConfiguration.LIQUIBASE_HUB_MODE.getCurrentValue().equalsIgnoreCase("meta")) { requestParams.put("logs", operationEvent.getOperationEventLog().getLogMessage()); requestParams.put("logsTimestamp", operationEvent.getOperationEventLog().getTimestampLog()); } @@ -475,7 +473,7 @@ public void sendOperationChangeEvent(OperationChangeEvent operationChangeEvent) String[] generatedSql = null; String logs = null; Date logsTimestamp = operationChangeEvent.getLogsTimestamp(); - if (!LiquibaseConfiguration.getInstance().getConfiguration(HubConfiguration.class).getLiquibaseHubMode().equalsIgnoreCase("meta")) { + if (!HubConfiguration.LIQUIBASE_HUB_MODE.getCurrentValue().equalsIgnoreCase("meta")) { changesetBody = operationChangeEvent.getChangesetBody(); generatedSql = operationChangeEvent.getGeneratedSql(); diff --git a/liquibase-core/src/main/java/liquibase/hub/listener/HubChangeExecListener.java b/liquibase-core/src/main/java/liquibase/hub/listener/HubChangeExecListener.java index 3da46b1a689..8fda0a2d9ae 100644 --- a/liquibase-core/src/main/java/liquibase/hub/listener/HubChangeExecListener.java +++ b/liquibase-core/src/main/java/liquibase/hub/listener/HubChangeExecListener.java @@ -7,8 +7,7 @@ import liquibase.changelog.visitor.AbstractChangeExecListener; import liquibase.changelog.visitor.ChangeExecListener; import liquibase.changelog.visitor.ChangeLogSyncListener; -import liquibase.configuration.HubConfiguration; -import liquibase.configuration.LiquibaseConfiguration; +import liquibase.hub.HubConfiguration; import liquibase.database.Database; import liquibase.exception.LiquibaseException; import liquibase.exception.PreconditionErrorException; @@ -192,10 +191,8 @@ private void updateHubForRollback(ChangeSet changeSet, String operationStatusType, String statusMessage) { if (operation == null) { - HubConfiguration hubConfiguration = LiquibaseConfiguration.getInstance().getConfiguration(HubConfiguration.class); - String apiKey = StringUtil.trimToNull(hubConfiguration.getLiquibaseHubApiKey()); - boolean hubOn = - ! (LiquibaseConfiguration.getInstance().getConfiguration(HubConfiguration.class).getLiquibaseHubMode().equalsIgnoreCase("off")); + String apiKey = StringUtil.trimToNull(HubConfiguration.LIQUIBASE_HUB_API_KEY.getCurrentValue()); + boolean hubOn = !(HubConfiguration.LIQUIBASE_HUB_MODE.getCurrentValue().equalsIgnoreCase("off")); if (apiKey != null && hubOn) { String message = "Hub communication failure.\n" + @@ -316,8 +313,7 @@ private String getCurrentLog() { // // Capture the current log level to use for filtering // - HubConfiguration hubConfiguration = LiquibaseConfiguration.getInstance().getConfiguration(HubConfiguration.class); - Level currentLevel = Level.parse(hubConfiguration.getLiquibaseHubLogLevel()); + Level currentLevel = HubConfiguration.LIQUIBASE_HUB_LOGLEVEL.getCurrentValue(); BufferedLogService bufferedLogService = Scope.getCurrentScope().get(BufferedLogService.class.getName(), BufferedLogService.class); @@ -340,10 +336,8 @@ private void updateHub(ChangeSet changeSet, // If not connected to Hub but we are supposed to be then show message // if (operation == null) { - HubConfiguration hubConfiguration = LiquibaseConfiguration.getInstance().getConfiguration(HubConfiguration.class); - String apiKey = StringUtil.trimToNull(hubConfiguration.getLiquibaseHubApiKey()); - boolean hubOn = - ! (LiquibaseConfiguration.getInstance().getConfiguration(HubConfiguration.class).getLiquibaseHubMode().equalsIgnoreCase("off")); + String apiKey = StringUtil.trimToNull(HubConfiguration.LIQUIBASE_HUB_API_KEY.getCurrentValueObfuscated()); + boolean hubOn = ! (HubConfiguration.LIQUIBASE_HUB_MODE.getCurrentValue().equalsIgnoreCase("off")); if (apiKey != null && hubOn) { String message; if (databaseChangeLog.getChangeLogId() == null) { diff --git a/liquibase-core/src/main/java/liquibase/integration/ant/BaseLiquibaseTask.java b/liquibase-core/src/main/java/liquibase/integration/ant/BaseLiquibaseTask.java index 5be67ece6f0..afee363d4ca 100644 --- a/liquibase-core/src/main/java/liquibase/integration/ant/BaseLiquibaseTask.java +++ b/liquibase-core/src/main/java/liquibase/integration/ant/BaseLiquibaseTask.java @@ -2,7 +2,7 @@ import liquibase.Liquibase; import liquibase.Scope; -import liquibase.configuration.GlobalConfiguration; +import liquibase.GlobalConfiguration; import liquibase.configuration.LiquibaseConfiguration; import liquibase.database.Database; import liquibase.exception.DatabaseException; @@ -135,20 +135,15 @@ protected String getChangeLogFile() { } protected boolean shouldRun() { - LiquibaseConfiguration configuration = LiquibaseConfiguration.getInstance(); - GlobalConfiguration globalConfiguration = configuration.getConfiguration(GlobalConfiguration.class); - if (!globalConfiguration.getShouldRun()) { - log("Liquibase did not run because " + configuration.describeValueLookupLogic(globalConfiguration - .getProperty(GlobalConfiguration.SHOULD_RUN)) + " was set to false", Project.MSG_INFO); + if (!GlobalConfiguration.SHOULD_RUN.getCurrentValue()) { + log("Liquibase did not run because " + GlobalConfiguration.SHOULD_RUN.getKey() + " was set to false", Project.MSG_INFO); return false; } return true; } protected String getDefaultOutputEncoding() { - LiquibaseConfiguration liquibaseConfiguration = LiquibaseConfiguration.getInstance(); - GlobalConfiguration globalConfiguration = liquibaseConfiguration.getConfiguration(GlobalConfiguration.class); - return globalConfiguration.getOutputEncoding(); + return GlobalConfiguration.OUTPUT_ENCODING.getCurrentValue(); } /** diff --git a/liquibase-core/src/main/java/liquibase/integration/commandline/CommandLineUtils.java b/liquibase-core/src/main/java/liquibase/integration/commandline/CommandLineUtils.java index 22eaf33bed7..fad5c5adbde 100644 --- a/liquibase-core/src/main/java/liquibase/integration/commandline/CommandLineUtils.java +++ b/liquibase-core/src/main/java/liquibase/integration/commandline/CommandLineUtils.java @@ -15,7 +15,6 @@ import liquibase.diff.output.ObjectChangeFilter; import liquibase.exception.DatabaseException; import liquibase.exception.LiquibaseException; -import liquibase.logging.LogService; import liquibase.resource.ClassLoaderResourceAccessor; import liquibase.resource.ResourceAccessor; import liquibase.util.LiquibaseUtil; @@ -149,7 +148,7 @@ public static void doDiff(Database referenceDatabase, Database targetDatabase, S public static DiffCommand createDiffCommand(Database referenceDatabase, Database targetDatabase, String snapshotTypes, CompareControl.SchemaComparison[] schemaComparisons, ObjectChangeFilter objectChangeFilter, PrintStream output) { - DiffCommand diffCommand = (DiffCommand) CommandFactory.getInstance().getCommand("diff"); + DiffCommand diffCommand = (DiffCommand) Scope.getCurrentScope().getSingleton(CommandFactory.class).getCommand("diff"); diffCommand .setReferenceDatabase(referenceDatabase) @@ -168,7 +167,7 @@ public static void doDiff(Database referenceDatabase, Database targetDatabase, S Scope.getCurrentScope().getUI().sendMessage(""); Scope.getCurrentScope().getUI().sendMessage(coreBundle.getString("diff.results")); try { - diffCommand.execute(); + Scope.getCurrentScope().getSingleton(CommandFactory.class).execute(diffCommand); } catch (CommandExecutionException e) { throw new LiquibaseException(e); } @@ -194,8 +193,7 @@ public static void doDiffToChangeLog(String changeLogFile, CompareControl.SchemaComparison[] schemaComparisons) throws LiquibaseException, IOException, ParserConfigurationException { - DiffToChangeLogCommand command = (DiffToChangeLogCommand) CommandFactory.getInstance().getCommand - ("diffChangeLog"); + DiffToChangeLogCommand command = (DiffToChangeLogCommand) Scope.getCurrentScope().getSingleton(CommandFactory.class).getCommand("diffChangeLog"); command.setReferenceDatabase(referenceDatabase) .setTargetDatabase(targetDatabase) .setSnapshotTypes(snapshotTypes) @@ -206,7 +204,7 @@ public static void doDiffToChangeLog(String changeLogFile, .setDiffOutputControl(diffOutputControl); try { - command.execute(); + Scope.getCurrentScope().getSingleton(CommandFactory.class).execute(command); } catch (CommandExecutionException e) { throw new LiquibaseException(e); } @@ -233,8 +231,7 @@ public static void doGenerateChangeLog(String changeLogFile, Database originalDa CompareControl compareControl = new CompareControl(comparisons, snapshotTypes); diffOutputControl.setDataDir(dataDir); - GenerateChangeLogCommand command = (GenerateChangeLogCommand) CommandFactory.getInstance().getCommand - ("generateChangeLog"); + GenerateChangeLogCommand command = (GenerateChangeLogCommand) Scope.getCurrentScope().getSingleton(CommandFactory.class).getCommand("generateChangeLog"); command.setReferenceDatabase(originalDatabase) .setSnapshotTypes(snapshotTypes) @@ -246,7 +243,7 @@ public static void doGenerateChangeLog(String changeLogFile, Database originalDa .setContext(context); try { - command.execute(); + Scope.getCurrentScope().getSingleton(CommandFactory.class).execute(command); } catch (CommandExecutionException e) { throw new LiquibaseException(e); } diff --git a/liquibase-core/src/main/java/liquibase/integration/commandline/Main.java b/liquibase-core/src/main/java/liquibase/integration/commandline/Main.java index fa158c332c0..d26322b6c7b 100644 --- a/liquibase-core/src/main/java/liquibase/integration/commandline/Main.java +++ b/liquibase-core/src/main/java/liquibase/integration/commandline/Main.java @@ -9,9 +9,10 @@ import liquibase.command.CommandResult; import liquibase.command.LiquibaseCommand; import liquibase.command.core.*; -import liquibase.configuration.GlobalConfiguration; -import liquibase.configuration.HubConfiguration; +import liquibase.GlobalConfiguration; import liquibase.configuration.LiquibaseConfiguration; +import liquibase.configuration.core.DeprecatedConfigurationValueProvider; +import liquibase.hub.HubConfiguration; import liquibase.database.Database; import liquibase.diff.compare.CompareControl; import liquibase.diff.output.DiffOutputControl; @@ -199,18 +200,6 @@ public Integer run() throws Exception { Main main = new Main(); try { - GlobalConfiguration globalConfiguration = LiquibaseConfiguration.getInstance().getConfiguration - (GlobalConfiguration.class); - - if (!globalConfiguration.getShouldRun()) { - Scope.getCurrentScope().getUI().sendErrorMessage(( - String.format(coreBundle.getString("did.not.run.because.param.was.set.to.false"), - LiquibaseConfiguration.getInstance().describeValueLookupLogic( - globalConfiguration.getProperty(GlobalConfiguration.SHOULD_RUN))))); - return 0; - } - HubConfiguration hubConfiguration = LiquibaseConfiguration.getInstance().getConfiguration(HubConfiguration.class); - if ((args.length == 0) || ((args.length == 1) && ("--" + OPTIONS.HELP).equals(args[0]))) { main.printHelp(System.out); return 0; @@ -336,6 +325,12 @@ public Integer run() throws Exception { Scope.getCurrentScope().getUI().sendMessage(CommandLineUtils.getBanner()); + if (!GlobalConfiguration.SHOULD_RUN.getCurrentValue()) { + Scope.getCurrentScope().getUI().sendErrorMessage(( + String.format(coreBundle.getString("did.not.run.because.param.was.set.to.false"), + GlobalConfiguration.SHOULD_RUN.getCurrentConfiguredValue().getProvidedValue().getActualKey()))); + return 0; + } if (setupNeeded(main)) { List<String> setupMessages = main.checkSetup(); @@ -349,14 +344,14 @@ public Integer run() throws Exception { // Store the Hub API key for later use // if (StringUtil.isNotEmpty(main.liquibaseHubApiKey)) { - hubConfiguration.setLiquibaseHubApiKey(main.liquibaseHubApiKey); + DeprecatedConfigurationValueProvider.setData(HubConfiguration.LIQUIBASE_HUB_API_KEY, main.liquibaseHubApiKey); } // // Store the Hub URL for later use // if (StringUtil.isNotEmpty(main.liquibaseHubUrl)) { - hubConfiguration.setLiquibaseHubUrl(main.liquibaseHubUrl); + DeprecatedConfigurationValueProvider.setData(HubConfiguration.LIQUIBASE_HUB_URL, main.liquibaseHubUrl); } main.applyDefaults(); @@ -405,7 +400,7 @@ public Integer run() throws Exception { } if (isHubEnabled(main.command) && - LiquibaseConfiguration.getInstance().getConfiguration(HubConfiguration.class).getLiquibaseHubApiKey() != null && + HubConfiguration.LIQUIBASE_HUB_API_KEY.getCurrentValue() != null && !Scope.getCurrentScope().getSingleton(HubServiceFactory.class).isOnline()) { ui.sendMessage("WARNING: The command "+main.command+" operations were not synced with your Liquibase Hub account because: " + StringUtil.lowerCaseFirst(Scope.getCurrentScope().getSingleton(HubServiceFactory.class).getOfflineReason())); } @@ -445,8 +440,7 @@ protected static void setLogLevel(LogService logService, java.util.logging.Logge // Set the Liquibase Hub log level if logging is not OFF // if (level != Level.OFF) { - HubConfiguration hubConfiguration = LiquibaseConfiguration.getInstance().getConfiguration(HubConfiguration.class); - hubConfiguration.setLiquibaseHubLogLevel(level.toString()); + DeprecatedConfigurationValueProvider.setData(HubConfiguration.LIQUIBASE_HUB_LOGLEVEL, level); } } @@ -1031,23 +1025,7 @@ protected void parsePropertiesFile(InputStream propertiesInputStream) throws IOE if (((String) entry.getKey()).startsWith("parameter.")) { changeLogParameters.put(((String) entry.getKey()).replaceFirst("^parameter.", ""), entry.getValue()); } else if (((String) entry.getKey()).contains(".")) { - // - // Determine the namespace and value keys - // then set the property value - // - final String[] splitKey = ((String) entry.getKey()).split("\\.", 3); - String namespace=""; - for (int i=0; i < splitKey.length-1; i++) { - if (! namespace.equals("")) { - namespace += "."; - } - namespace += splitKey[i]; - } - String valueKey = splitKey[splitKey.length-1]; - try { - LiquibaseConfiguration.getInstance().getConfiguration(namespace).setValue(valueKey, entry.getValue()); - } - catch (Exception e) { + if (Scope.getCurrentScope().getSingleton(LiquibaseConfiguration.class).getRegisteredDefinition((String) entry.getKey()) == null) { if (strict) { throw new CommandLineParsingException( String.format(coreBundle.getString("parameter.unknown"), entry.getKey()) @@ -1058,6 +1036,9 @@ protected void parsePropertiesFile(InputStream propertiesInputStream) throws IOE ); } } + if (System.getProperty((String) entry.getKey()) == null) { + DeprecatedConfigurationValueProvider.setData((String) entry.getKey(), entry.getValue()); + } } else { Field field = getDeclaredField((String)entry.getKey()); Object currentValue = field.get(this); @@ -1378,15 +1359,14 @@ protected void doMigration() throws Exception { // // Log setting for Hub properties // - HubConfiguration hubConfiguration = LiquibaseConfiguration.getInstance().getConfiguration(HubConfiguration.class); - if (StringUtil.isNotEmpty(hubConfiguration.getLiquibaseHubApiKey())) { - LOG.fine("Liquibase Hub API Key: " + hubConfiguration.getLiquibaseHubApiKeySecureDescription()); + if (StringUtil.isNotEmpty(HubConfiguration.LIQUIBASE_HUB_API_KEY.getCurrentValue())) { + LOG.fine("Liquibase Hub API Key: " + HubConfiguration.LIQUIBASE_HUB_API_KEY.getCurrentValueObfuscated()); } - if (StringUtil.isNotEmpty(hubConfiguration.getLiquibaseHubUrl())) { - LOG.fine("Liquibase Hub URL: " + hubConfiguration.getLiquibaseHubUrl()); + if (StringUtil.isNotEmpty(HubConfiguration.LIQUIBASE_HUB_URL.getCurrentValue())) { + LOG.fine("Liquibase Hub URL: " + HubConfiguration.LIQUIBASE_HUB_URL.getCurrentValue()); } - if (StringUtil.isNotEmpty(hubConfiguration.getLiquibaseHubMode())) { - LOG.fine("Liquibase Hub Mode: " + hubConfiguration.getLiquibaseHubMode()); + if (StringUtil.isNotEmpty(HubConfiguration.LIQUIBASE_HUB_MODE.getCurrentValue())) { + LOG.fine("Liquibase Hub Mode: " + HubConfiguration.LIQUIBASE_HUB_MODE.getCurrentValue()); } // @@ -1449,7 +1429,7 @@ protected void doMigration() throws Exception { // Set the global configuration option based on presence of the dataOutputDirectory // boolean b = dataOutputDirectory != null; - LiquibaseConfiguration.getInstance().getConfiguration(GlobalConfiguration.class).setShouldSnapshotData(b); + DeprecatedConfigurationValueProvider.setData(GlobalConfiguration.SHOULD_SNAPSHOT_DATA, b); ObjectChangeFilter objectChangeFilter = null; CompareControl.ComputedSchemas computedSchemas = CompareControl.computeSchemas( @@ -1489,7 +1469,7 @@ protected void doMigration() throws Exception { System.exit(0); } if (isFormattedDiff()) { - LiquibaseCommand liquibaseCommand = CommandFactory.getInstance().getCommand(COMMANDS.FORMATTED_DIFF); + LiquibaseCommand liquibaseCommand = Scope.getCurrentScope().getSingleton(CommandFactory.class).getCommand(COMMANDS.FORMATTED_DIFF); DiffCommand diffCommand = CommandLineUtils.createDiffCommand( createReferenceDatabaseFromCommandParams(commandParams, fileOpener), database, @@ -1498,7 +1478,7 @@ protected void doMigration() throws Exception { argsMap.put("format", getCommandParam(OPTIONS.FORMAT, "JSON")); argsMap.put("diffCommand", diffCommand); ((AbstractSelfConfiguratingCommand) liquibaseCommand).configure(argsMap); - liquibaseCommand.execute(); + Scope.getCurrentScope().getSingleton(CommandFactory.class).execute(liquibaseCommand); } else { CommandLineUtils.doDiff( createReferenceDatabaseFromCommandParams(commandParams, fileOpener), @@ -1545,38 +1525,37 @@ protected void doMigration() throws Exception { diffOutputControl); return; } else if (COMMANDS.SNAPSHOT.equalsIgnoreCase(command)) { - SnapshotCommand snapshotCommand = (SnapshotCommand) CommandFactory.getInstance() + SnapshotCommand snapshotCommand = (SnapshotCommand) Scope.getCurrentScope().getSingleton(CommandFactory.class) .getCommand(COMMANDS.SNAPSHOT); snapshotCommand.setDatabase(database); snapshotCommand.setSchemas(getSchemaParams(database)); snapshotCommand.setSerializerFormat(getCommandParam(OPTIONS.SNAPSHOT_FORMAT, null)); Writer outputWriter = getOutputWriter(); - String result = snapshotCommand.execute().print(); + String result = Scope.getCurrentScope().getSingleton(CommandFactory.class).execute(snapshotCommand).print(); outputWriter.write(result); outputWriter.flush(); outputWriter.close(); return; } else if (COMMANDS.EXECUTE_SQL.equalsIgnoreCase(command)) { - ExecuteSqlCommand executeSqlCommand = (ExecuteSqlCommand) CommandFactory.getInstance().getCommand( - COMMANDS.EXECUTE_SQL); + ExecuteSqlCommand executeSqlCommand = (ExecuteSqlCommand) Scope.getCurrentScope().getSingleton(CommandFactory.class).getCommand(COMMANDS.EXECUTE_SQL); executeSqlCommand.setDatabase(database); executeSqlCommand.setSql(getCommandParam("sql", null)); executeSqlCommand.setSqlFile(getCommandParam("sqlFile", null)); executeSqlCommand.setDelimiter(getCommandParam("delimiter", ";")); Writer outputWriter = getOutputWriter(); - outputWriter.write(executeSqlCommand.execute().print()); + outputWriter.write(Scope.getCurrentScope().getSingleton(CommandFactory.class).execute(executeSqlCommand).print()); outputWriter.flush(); outputWriter.close(); return; } else if (COMMANDS.SNAPSHOT_REFERENCE.equalsIgnoreCase(command)) { - SnapshotCommand snapshotCommand = (SnapshotCommand) CommandFactory.getInstance() + SnapshotCommand snapshotCommand = (SnapshotCommand) Scope.getCurrentScope().getSingleton(CommandFactory.class) .getCommand(COMMANDS.SNAPSHOT); Database referenceDatabase = createReferenceDatabaseFromCommandParams(commandParams, fileOpener); snapshotCommand.setDatabase(referenceDatabase); snapshotCommand.setSchemas(getSchemaParams(database)); snapshotCommand.setSerializerFormat(getCommandParam(OPTIONS.SNAPSHOT_FORMAT, null)); Writer outputWriter = getOutputWriter(); - outputWriter.write(snapshotCommand.execute().print()); + outputWriter.write(Scope.getCurrentScope().getSingleton(CommandFactory.class).execute(snapshotCommand).print()); outputWriter.flush(); outputWriter.close(); @@ -1650,7 +1629,7 @@ protected void doMigration() throws Exception { Map<String, Object> argsMap = new HashMap<>(); loadChangeSetInfoToMap(argsMap); LiquibaseCommand liquibaseCommand = createLiquibaseCommand(database, liquibase, COMMANDS.ROLLBACK_ONE_CHANGE_SET, argsMap); - liquibaseCommand.execute(); + Scope.getCurrentScope().getSingleton(CommandFactory.class).execute(liquibaseCommand); return; } else if (COMMANDS.ROLLBACK_ONE_CHANGE_SET_SQL.equals(command)) { Writer outputWriter = getOutputWriter(); @@ -1659,7 +1638,7 @@ protected void doMigration() throws Exception { argsMap.put("outputWriter", outputWriter); argsMap.put("force", true); LiquibaseCommand liquibaseCommand = createLiquibaseCommand(database, liquibase, COMMANDS.ROLLBACK_ONE_CHANGE_SET, argsMap); - liquibaseCommand.execute(); + Scope.getCurrentScope().getSingleton(CommandFactory.class).execute(liquibaseCommand); outputWriter.flush(); outputWriter.close(); return; @@ -1667,7 +1646,7 @@ protected void doMigration() throws Exception { Map<String, Object> argsMap = new HashMap<>(); argsMap.put("deploymentId", getCommandParam(OPTIONS.DEPLOYMENT_ID, null)); LiquibaseCommand liquibaseCommand = createLiquibaseCommand(database, liquibase, COMMANDS.ROLLBACK_ONE_UPDATE, argsMap); - liquibaseCommand.execute(); + Scope.getCurrentScope().getSingleton(CommandFactory.class).execute(liquibaseCommand); return; } else if (COMMANDS.ROLLBACK_ONE_UPDATE_SQL.equals(command)) { Writer outputWriter = getOutputWriter(); @@ -1676,7 +1655,7 @@ protected void doMigration() throws Exception { argsMap.put("outputWriter", outputWriter); argsMap.put("force", true); LiquibaseCommand liquibaseCommand = createLiquibaseCommand(database, liquibase, COMMANDS.ROLLBACK_ONE_UPDATE, argsMap); - liquibaseCommand.execute(); + Scope.getCurrentScope().getSingleton(CommandFactory.class).execute(liquibaseCommand); outputWriter.flush(); outputWriter.close(); return; @@ -1685,7 +1664,8 @@ protected void doMigration() throws Exception { DeactivateChangeLogCommand liquibaseCommand = (DeactivateChangeLogCommand)createLiquibaseCommand(database, liquibase, COMMANDS.DEACTIVATE_CHANGELOG, argsMap); liquibaseCommand.setChangeLogFile(changeLogFile); - CommandResult result = liquibaseCommand.execute(); + CommandResult result = Scope.getCurrentScope().getSingleton(CommandFactory.class).execute(liquibaseCommand); + if (result.succeeded) { Scope.getCurrentScope().getUI().sendMessage(result.print()); } else { @@ -1715,7 +1695,7 @@ protected void doMigration() throws Exception { if (hubProjectName != null) { liquibaseCommand.setProjectName(hubProjectName); } - CommandResult result = liquibaseCommand.execute(); + CommandResult result = Scope.getCurrentScope().getSingleton(CommandFactory.class).execute(liquibaseCommand); if (result.succeeded) { Scope.getCurrentScope().getUI().sendMessage(result.print()); @@ -1727,8 +1707,8 @@ protected void doMigration() throws Exception { executeSyncHub(database, liquibase); return; } else if (COMMANDS.DROP_ALL.equals(command)) { - String liquibaseHubApiKey = hubConfiguration.getLiquibaseHubApiKey(); - String hubMode = hubConfiguration.getLiquibaseHubMode(); + String liquibaseHubApiKey = HubConfiguration.LIQUIBASE_HUB_API_KEY.getCurrentValue(); + String hubMode = HubConfiguration.LIQUIBASE_HUB_MODE.getCurrentValue(); if (liquibaseHubApiKey != null && ! hubMode.toLowerCase().equals("off")) { if (hubConnectionId == null && changeLogFile == null) { String warningMessage = @@ -1742,7 +1722,7 @@ protected void doMigration() throws Exception { } } DropAllCommand dropAllCommand = - (DropAllCommand) CommandFactory.getInstance().getCommand(COMMANDS.DROP_ALL); + (DropAllCommand) Scope.getCurrentScope().getSingleton(CommandFactory.class).getCommand(COMMANDS.DROP_ALL); if (hubConnectionId != null) { dropAllCommand.setHubConnectionId(hubConnectionId); } @@ -1750,7 +1730,7 @@ protected void doMigration() throws Exception { dropAllCommand.setDatabase(liquibase.getDatabase()); dropAllCommand.setSchemas(getSchemaParams(database)); dropAllCommand.setChangeLogFile(changeLogFile); - Scope.getCurrentScope().getUI().sendMessage(dropAllCommand.execute().print()); + Scope.getCurrentScope().getUI().sendMessage(Scope.getCurrentScope().getSingleton(CommandFactory.class).execute(dropAllCommand).print()); return; } else if (COMMANDS.STATUS.equalsIgnoreCase(command)) { boolean runVerbose = false; @@ -1924,10 +1904,10 @@ protected void doMigration() throws Exception { } else if (COMMANDS.UPDATE_TESTING_ROLLBACK.equalsIgnoreCase(command)) { liquibase.updateTestingRollback(new Contexts(contexts), new LabelExpression(labels)); } else if (COMMANDS.HISTORY.equalsIgnoreCase(command)) { - HistoryCommand historyCommand = (HistoryCommand) CommandFactory.getInstance().getCommand("history"); + HistoryCommand historyCommand = (HistoryCommand) Scope.getCurrentScope().getSingleton(CommandFactory.class).getCommand("history"); historyCommand.setDatabase(database); historyCommand.setOutputStream(new PrintStream(getOutputStream())); - historyCommand.execute(); + Scope.getCurrentScope().getSingleton(CommandFactory.class).execute(historyCommand); } else { throw new CommandLineParsingException( String.format(coreBundle.getString("command.unknown"), command)); @@ -1957,7 +1937,7 @@ private void executeSyncHub(Database database, Liquibase liquibase) throws Comma liquibaseCommand.setDatabase(database); liquibaseCommand.setChangeLogFile(changeLogFile); liquibaseCommand.setHubProjectId(hubProjectId); - final CommandResult commandResult = liquibaseCommand.execute(); + final CommandResult commandResult = Scope.getCurrentScope().getSingleton(CommandFactory.class).execute(liquibaseCommand); if (commandResult.succeeded) { Scope.getCurrentScope().getUI().sendMessage(commandResult.print()); } else { @@ -2018,7 +1998,7 @@ private LiquibaseCommand createLiquibaseCommand(Database database, Liquibase liq if (this.commandParams.contains("--help")) { argsMap.put("help", true); } - LiquibaseCommand liquibaseCommand = CommandFactory.getInstance().getCommand(commandName); + LiquibaseCommand liquibaseCommand = Scope.getCurrentScope().getSingleton(CommandFactory.class).getCommand(commandName); AbstractSelfConfiguratingCommand configuratingCommand = (AbstractSelfConfiguratingCommand) liquibaseCommand; configuratingCommand.configure(argsMap); return liquibaseCommand; @@ -2129,8 +2109,7 @@ private OutputStream getOutputStream() throws IOException { } private Writer getOutputWriter() throws IOException { - String charsetName = LiquibaseConfiguration.getInstance().getConfiguration(GlobalConfiguration.class) - .getOutputEncoding(); + String charsetName = GlobalConfiguration.OUTPUT_ENCODING.getCurrentValue(); return new OutputStreamWriter(getOutputStream(), charsetName); } diff --git a/liquibase-core/src/main/java/liquibase/integration/servlet/LiquibaseServletListener.java b/liquibase-core/src/main/java/liquibase/integration/servlet/LiquibaseServletListener.java index 42ef6e7d70e..3e8050c67bb 100644 --- a/liquibase-core/src/main/java/liquibase/integration/servlet/LiquibaseServletListener.java +++ b/liquibase-core/src/main/java/liquibase/integration/servlet/LiquibaseServletListener.java @@ -1,13 +1,7 @@ package liquibase.integration.servlet; -import liquibase.Contexts; -import liquibase.LabelExpression; -import liquibase.Liquibase; -import liquibase.Scope; -import liquibase.configuration.ConfigurationProperty; -import liquibase.configuration.ConfigurationValueProvider; -import liquibase.configuration.GlobalConfiguration; -import liquibase.configuration.LiquibaseConfiguration; +import liquibase.*; +import liquibase.configuration.*; import liquibase.database.Database; import liquibase.database.DatabaseFactory; import liquibase.database.core.DerbyDatabase; @@ -20,7 +14,6 @@ import liquibase.util.NetUtil; import liquibase.util.StringUtil; -import javax.naming.Context; import javax.naming.InitialContext; import javax.naming.NamingException; import javax.servlet.ServletContext; @@ -40,7 +33,6 @@ */ public class LiquibaseServletListener implements ServletContextListener { - private static final String JAVA_COMP_ENV = "java:comp/env"; private static final String LIQUIBASE_CHANGELOG = "liquibase.changelog"; private static final String LIQUIBASE_CONTEXTS = "liquibase.contexts"; private static final String LIQUIBASE_LABELS = "liquibase.labels"; @@ -57,7 +49,6 @@ public class LiquibaseServletListener implements ServletContextListener { private String labels; private String defaultSchema; private String hostName; - private ServletValueContainer servletValueContainer; //temporarily saved separately until all lookup moves to liquibaseConfiguration public String getChangeLogFile() { return changeLogFile; @@ -101,23 +92,24 @@ public String getDefaultSchema() { @Override public void contextInitialized(ServletContextEvent servletContextEvent) { ServletContext servletContext = servletContextEvent.getServletContext(); + final LiquibaseConfiguration liquibaseConfiguration = Scope.getCurrentScope().getSingleton(LiquibaseConfiguration.class); + try { this.hostName = NetUtil.getLocalHostName(); - } - catch (Exception e) { + } catch (Exception e) { servletContext.log("Cannot find hostname: " + e.getMessage()); return; } InitialContext ic = null; String failOnError = null; + final ServletConfigurationValueProvider servletConfigurationValueProvider = new ServletConfigurationValueProvider(servletContext, ic); try { ic = new InitialContext(); - servletValueContainer = new ServletValueContainer(servletContext, ic); - LiquibaseConfiguration.getInstance().init(servletValueContainer); + liquibaseConfiguration.registerProvider(servletConfigurationValueProvider); - failOnError = (String) servletValueContainer.getValue(LIQUIBASE_ONERROR_FAIL); + failOnError = (String) liquibaseConfiguration.getCurrentConfiguredValue(LIQUIBASE_ONERROR_FAIL).getValue(); if (checkPreconditions(servletContext, ic)) { executeUpdate(servletContext, ic); } @@ -130,11 +122,13 @@ public void contextInitialized(ServletContextEvent servletContextEvent) { if (ic != null) { try { ic.close(); - } - catch (NamingException e) { + } catch (NamingException e) { // ignore } } + liquibaseConfiguration.removeProvider(servletConfigurationValueProvider); + + } } @@ -147,16 +141,17 @@ public void contextInitialized(ServletContextEvent servletContextEvent) { * </ol> */ private boolean checkPreconditions(ServletContext servletContext, InitialContext ic) { - GlobalConfiguration globalConfiguration = LiquibaseConfiguration.getInstance().getConfiguration(GlobalConfiguration.class); - if (!globalConfiguration.getShouldRun()) { + if (!liquibase.GlobalConfiguration.SHOULD_RUN.getCurrentValue()) { Scope.getCurrentScope().getLog(getClass()).info("Liquibase did not run on " + hostName - + " because "+ LiquibaseConfiguration.getInstance().describeValueLookupLogic(globalConfiguration.getProperty(GlobalConfiguration.SHOULD_RUN)) - + " was set to false"); + + " because " + liquibase.GlobalConfiguration.SHOULD_RUN.getKey() + + " was set to false"); return false; } - String machineIncludes = (String) servletValueContainer.getValue(LIQUIBASE_HOST_INCLUDES); - String machineExcludes = (String) servletValueContainer.getValue(LIQUIBASE_HOST_EXCLUDES); + final LiquibaseConfiguration liquibaseConfiguration = Scope.getCurrentScope().getSingleton(LiquibaseConfiguration.class); + + String machineIncludes = (String) liquibaseConfiguration.getCurrentConfiguredValue(LIQUIBASE_HOST_INCLUDES).getValue(); + String machineExcludes = (String) liquibaseConfiguration.getCurrentConfiguredValue(LIQUIBASE_HOST_EXCLUDES).getValue(); boolean shouldRun = false; if ((machineIncludes == null) && (machineExcludes == null)) { @@ -178,10 +173,11 @@ private boolean checkPreconditions(ServletContext servletContext, InitialContext } } - if (globalConfiguration.getShouldRun() && globalConfiguration.getProperty(GlobalConfiguration.SHOULD_RUN).getWasOverridden()) { + final ConfiguredValue<Boolean> shouldRunValue = liquibase.GlobalConfiguration.SHOULD_RUN.getCurrentConfiguredValue(); + if (liquibase.GlobalConfiguration.SHOULD_RUN.getCurrentValue() && !ConfigurationDefinition.wasDefaultValueUsed(shouldRunValue)) { shouldRun = true; servletContext.log("ignoring " + LIQUIBASE_HOST_INCLUDES + " and " - + LIQUIBASE_HOST_EXCLUDES + ", since " + LiquibaseConfiguration.getInstance().describeValueLookupLogic(globalConfiguration.getProperty(GlobalConfiguration.SHOULD_RUN)) + + LIQUIBASE_HOST_EXCLUDES + ", since " + shouldRunValue.getProvidedValue().describe() + "=true"); } if (!shouldRun) { @@ -197,19 +193,21 @@ private boolean checkPreconditions(ServletContext servletContext, InitialContext */ @java.lang.SuppressWarnings("squid:S2095") private void executeUpdate(ServletContext servletContext, InitialContext ic) throws NamingException, SQLException, LiquibaseException { - setDataSource((String) servletValueContainer.getValue(LIQUIBASE_DATASOURCE)); + final LiquibaseConfiguration liquibaseConfiguration = Scope.getCurrentScope().getSingleton(LiquibaseConfiguration.class); + + setDataSource((String) liquibaseConfiguration.getCurrentConfiguredValue(LIQUIBASE_DATASOURCE).getValue()); if (getDataSource() == null) { throw new RuntimeException("Cannot run Liquibase, " + LIQUIBASE_DATASOURCE + " is not set"); } - setChangeLogFile((String) servletValueContainer.getValue(LIQUIBASE_CHANGELOG)); + setChangeLogFile((String) liquibaseConfiguration.getCurrentConfiguredValue(LIQUIBASE_CHANGELOG).getValue()); if (getChangeLogFile() == null) { throw new RuntimeException("Cannot run Liquibase, " + LIQUIBASE_CHANGELOG + " is not set"); } - setContexts((String) servletValueContainer.getValue(LIQUIBASE_CONTEXTS)); - setLabels((String) servletValueContainer.getValue(LIQUIBASE_LABELS)); - this.defaultSchema = StringUtil.trimToNull((String) servletValueContainer.getValue(LIQUIBASE_SCHEMA_DEFAULT)); + setContexts((String) liquibaseConfiguration.getCurrentConfiguredValue(LIQUIBASE_CONTEXTS).getValue()); + setLabels((String) liquibaseConfiguration.getCurrentConfiguredValue(LIQUIBASE_LABELS).getValue()); + this.defaultSchema = StringUtil.trimToNull((String) liquibaseConfiguration.getCurrentConfiguredValue(LIQUIBASE_SCHEMA_DEFAULT).getValue()); Connection connection = null; Database database = null; @@ -236,7 +234,7 @@ private void executeUpdate(ServletContext servletContext, InitialContext ic) thr while (initParameters.hasMoreElements()) { String name = initParameters.nextElement().trim(); if (name.startsWith(LIQUIBASE_PARAMETER + ".")) { - liquibase.setChangeLogParameter(name.substring(LIQUIBASE_PARAMETER.length() + 1), servletValueContainer.getValue(name)); + liquibase.setChangeLogParameter(name.substring(LIQUIBASE_PARAMETER.length() + 1), liquibaseConfiguration.getCurrentConfiguredValue(name)); } } @@ -244,8 +242,7 @@ private void executeUpdate(ServletContext servletContext, InitialContext ic) thr if (database instanceof DerbyDatabase) { ((DerbyDatabase) database).setShutdownEmbeddedDerby(false); } - } - finally { + } finally { if (liquibase != null) { liquibase.close(); } else if (connection != null) { @@ -258,53 +255,4 @@ private void executeUpdate(ServletContext servletContext, InitialContext ic) thr public void contextDestroyed(ServletContextEvent servletContextEvent) { } - protected class ServletValueContainer implements ConfigurationValueProvider { - - private ServletContext servletContext; - private InitialContext initialContext; - - public ServletValueContainer(ServletContext servletContext, InitialContext initialContext) { - this.servletContext = servletContext; - this.initialContext = initialContext; - } - - @Override - public String describeValueLookupLogic(ConfigurationProperty property) { - return "JNDI, servlet container init parameter, and system property '"+property.getNamespace()+"."+property.getName()+"'"; - } - - @Override - public Object getValue(String namespace, String property) { - return getValue(namespace +"."+property); - } - - /** - * Try to read the value that is stored by the given key from - * <ul> - * <li>JNDI</li> - * <li>the servlet context's init parameters</li> - * <li>system properties</li> - * </ul> - */ - public Object getValue(String prefixAndProperty) { - // Try to get value from JNDI - try { - Context envCtx = (Context) initialContext.lookup(JAVA_COMP_ENV); - String valueFromJndi = (String) envCtx.lookup(prefixAndProperty); - return valueFromJndi; - } - catch (NamingException e) { - // Ignore - } - - // Return the value from the servlet context - String valueFromServletContext = servletContext.getInitParameter(prefixAndProperty); - if (valueFromServletContext != null) { - return valueFromServletContext; - } - - // Otherwise: Return system property - return System.getProperty(prefixAndProperty); - } - } } diff --git a/liquibase-core/src/main/java/liquibase/integration/servlet/ServletConfigurationValueProvider.java b/liquibase-core/src/main/java/liquibase/integration/servlet/ServletConfigurationValueProvider.java new file mode 100644 index 00000000000..926c00c3f34 --- /dev/null +++ b/liquibase-core/src/main/java/liquibase/integration/servlet/ServletConfigurationValueProvider.java @@ -0,0 +1,61 @@ +package liquibase.integration.servlet; + +import liquibase.configuration.ConfigurationValueProvider; +import liquibase.configuration.ProvidedValue; +import org.springframework.util.StringUtils; + +import javax.naming.Context; +import javax.naming.InitialContext; +import javax.naming.NamingException; +import javax.servlet.ServletContext; + +public class ServletConfigurationValueProvider implements ConfigurationValueProvider { + + private static final String JAVA_COMP_ENV = "java:comp/env"; + + @Override + public int getPrecedence() { + return 30; + } + + private final ServletContext servletContext; + private final InitialContext initialContext; + + public ServletConfigurationValueProvider(ServletContext servletContext, InitialContext initialContext) { + this.servletContext = servletContext; + this.initialContext = initialContext; + } + + /** + * Try to read the value that is stored by the given key from + * <ul> + * <li>JNDI</li> + * <li>the servlet context's init parameters</li> + * <li>system properties</li> + * </ul> + */ + @Override + public ProvidedValue getProvidedValue(String key) { + if (initialContext != null) { + // Try to get value from JNDI + try { + Context envCtx = (Context) initialContext.lookup(JAVA_COMP_ENV); + String valueFromJndi = (String) envCtx.lookup(key); + + return new ProvidedValue(key, JAVA_COMP_ENV + "/" + key, valueFromJndi, "JNDI", this); + } catch (NamingException e) { + // Ignore + } + } + + if (servletContext != null) { + // Return the value from the servlet context + String valueFromServletContext = servletContext.getInitParameter(key); + if (valueFromServletContext != null) { + return new ProvidedValue(key, key, valueFromServletContext, "Servlet context", this); + } + } + + return null; + } +} diff --git a/liquibase-core/src/main/java/liquibase/integration/spring/SpringLiquibase.java b/liquibase-core/src/main/java/liquibase/integration/spring/SpringLiquibase.java index 7dccdcdf0f5..c2c2c18ecb6 100644 --- a/liquibase-core/src/main/java/liquibase/integration/spring/SpringLiquibase.java +++ b/liquibase-core/src/main/java/liquibase/integration/spring/SpringLiquibase.java @@ -1,12 +1,7 @@ package liquibase.integration.spring; -import liquibase.Contexts; -import liquibase.LabelExpression; -import liquibase.Liquibase; -import liquibase.Scope; -import liquibase.configuration.ConfigurationProperty; -import liquibase.configuration.GlobalConfiguration; -import liquibase.configuration.LiquibaseConfiguration; +import liquibase.*; +import liquibase.configuration.ConfiguredValue; import liquibase.database.Database; import liquibase.database.DatabaseConnection; import liquibase.database.DatabaseFactory; @@ -252,12 +247,10 @@ public void setTestRollbackOnUpdate(boolean testRollbackOnUpdate) { */ @Override public void afterPropertiesSet() throws LiquibaseException { - ConfigurationProperty shouldRunProperty = LiquibaseConfiguration.getInstance() - .getProperty(GlobalConfiguration.class, GlobalConfiguration.SHOULD_RUN); + final ConfiguredValue<Boolean> shouldRunProperty = GlobalConfiguration.SHOULD_RUN.getCurrentConfiguredValue(); - if (!shouldRunProperty.getValue(Boolean.class)) { - Scope.getCurrentScope().getLog(getClass()).info("Liquibase did not run because " + LiquibaseConfiguration - .getInstance().describeValueLookupLogic(shouldRunProperty) + " was set to false"); + if (!(Boolean) shouldRunProperty.getValue()) { + Scope.getCurrentScope().getLog(getClass()).info("Liquibase did not run because " +shouldRunProperty.getProvidedValue().describe() + " was set to false"); return; } if (!shouldRun) { @@ -287,8 +280,7 @@ private void generateRollbackFile(Liquibase liquibase) throws LiquibaseException try ( FileOutputStream fileOutputStream = new FileOutputStream(rollbackFile); - Writer output = new OutputStreamWriter(fileOutputStream, LiquibaseConfiguration.getInstance() - .getConfiguration(GlobalConfiguration.class).getOutputEncoding()) ) + Writer output = new OutputStreamWriter(fileOutputStream, GlobalConfiguration.OUTPUT_ENCODING.getCurrentValue()) ) { if (tag != null) { diff --git a/liquibase-core/src/main/java/liquibase/license/LicenseServiceFactory.java b/liquibase-core/src/main/java/liquibase/license/LicenseServiceFactory.java index 858d591ec25..29fee1b537e 100644 --- a/liquibase-core/src/main/java/liquibase/license/LicenseServiceFactory.java +++ b/liquibase-core/src/main/java/liquibase/license/LicenseServiceFactory.java @@ -4,19 +4,24 @@ public class LicenseServiceFactory extends AbstractPluginFactory<LicenseService> { - private LicenseServiceFactory() {} + private LicenseServiceFactory() { + } - @Override - protected Class<LicenseService> getPluginClass() { - return LicenseService.class; - } + @Override + protected Class<LicenseService> getPluginClass() { + return LicenseService.class; + } - @Override - protected int getPriority(LicenseService obj, Object... args) { - return obj.getPriority(); - } + @Override + protected int getPriority(LicenseService obj, Object... args) { + return obj.getPriority(); + } - public LicenseService getLicenseService() { - return getPlugin(); - } + public LicenseService getLicenseService() { + return getPlugin(); + } + + public void unregister(LicenseService service) { + this.removeInstance(service); + } } diff --git a/liquibase-core/src/main/java/liquibase/lockservice/StandardLockService.java b/liquibase-core/src/main/java/liquibase/lockservice/StandardLockService.java index 63e8dab4dd1..4204160f89b 100644 --- a/liquibase-core/src/main/java/liquibase/lockservice/StandardLockService.java +++ b/liquibase-core/src/main/java/liquibase/lockservice/StandardLockService.java @@ -2,8 +2,7 @@ import liquibase.Scope; import liquibase.change.Change; -import liquibase.configuration.GlobalConfiguration; -import liquibase.configuration.LiquibaseConfiguration; +import liquibase.GlobalConfiguration; import liquibase.database.Database; import liquibase.database.ObjectQuotingStrategy; import liquibase.database.core.DB2Database; @@ -68,8 +67,7 @@ public Long getChangeLogLockWaitTime() { if (changeLogLockPollRate != null) { return changeLogLockPollRate; } - return LiquibaseConfiguration.getInstance().getConfiguration(GlobalConfiguration.class) - .getDatabaseChangeLogLockWaitTime(); + return GlobalConfiguration.CHANGELOGLOCK_WAIT_TIME.getCurrentValue(); } @Override @@ -81,8 +79,7 @@ public Long getChangeLogLockRecheckTime() { if (changeLogLockRecheckTime != null) { return changeLogLockRecheckTime; } - return LiquibaseConfiguration.getInstance().getConfiguration(GlobalConfiguration.class) - .getDatabaseChangeLogLockPollRate(); + return GlobalConfiguration.CHANGELOGLOCK_POLL_RATE.getCurrentValue(); } @Override diff --git a/liquibase-core/src/main/java/liquibase/logging/core/AbstractLogger.java b/liquibase-core/src/main/java/liquibase/logging/core/AbstractLogger.java index 53fded1f43d..cba68b249dd 100644 --- a/liquibase-core/src/main/java/liquibase/logging/core/AbstractLogger.java +++ b/liquibase-core/src/main/java/liquibase/logging/core/AbstractLogger.java @@ -1,8 +1,8 @@ package liquibase.logging.core; import liquibase.AbstractExtensibleObject; -import liquibase.configuration.GlobalConfiguration; -import liquibase.configuration.LiquibaseConfiguration; +import liquibase.GlobalConfiguration; +import liquibase.exception.UnknownConfigurationType; import liquibase.logging.LogMessageFilter; import liquibase.logging.Logger; @@ -81,7 +81,12 @@ public void debug(String message, Throwable e) { } protected String filterMessage(String message) { - if (filter == null || !LiquibaseConfiguration.getInstance().getConfiguration(GlobalConfiguration.class).getShouldFilterLogMessages()) { + try { + if (filter == null || GlobalConfiguration.FILTER_LOG_MESSAGES == null || !GlobalConfiguration.FILTER_LOG_MESSAGES.getCurrentValue()) { + return message; + } + } catch (UnknownConfigurationType unknownConfigurationType) { + //probably in initial scope bootstrap return message; } return filter.filterMessage(message); diff --git a/liquibase-core/src/main/java/liquibase/logging/core/DefaultLogMessageFilter.java b/liquibase-core/src/main/java/liquibase/logging/core/DefaultLogMessageFilter.java index 9c3766578ae..93e6fa60ed5 100644 --- a/liquibase-core/src/main/java/liquibase/logging/core/DefaultLogMessageFilter.java +++ b/liquibase-core/src/main/java/liquibase/logging/core/DefaultLogMessageFilter.java @@ -1,20 +1,18 @@ package liquibase.logging.core; -import liquibase.Scope; -import liquibase.configuration.HubConfiguration; -import liquibase.configuration.LiquibaseConfiguration; +import liquibase.hub.HubConfiguration; import liquibase.logging.LogMessageFilter; -import liquibase.util.StringUtil; public class DefaultLogMessageFilter implements LogMessageFilter { @Override public String filterMessage(String message) { - final HubConfiguration configuration = LiquibaseConfiguration.getInstance().getConfiguration(HubConfiguration.class); - - final String liquibaseHubApiKey = StringUtil.trimToNull(configuration.getLiquibaseHubApiKey()); + String liquibaseHubApiKey = null; + if (HubConfiguration.LIQUIBASE_HUB_API_KEY != null) { + liquibaseHubApiKey = HubConfiguration.LIQUIBASE_HUB_API_KEY.getCurrentValue(); + } if (liquibaseHubApiKey != null) { - message = message.replace(liquibaseHubApiKey, configuration.getLiquibaseHubApiKeySecureDescription()); + message = message.replace(liquibaseHubApiKey, HubConfiguration.LIQUIBASE_HUB_API_KEY.getCurrentValueObfuscated()); } return message; diff --git a/liquibase-core/src/main/java/liquibase/logging/core/DefaultLoggerConfiguration.java b/liquibase-core/src/main/java/liquibase/logging/core/DefaultLoggerConfiguration.java index 421d80f79a7..3a4a8af1836 100644 --- a/liquibase-core/src/main/java/liquibase/logging/core/DefaultLoggerConfiguration.java +++ b/liquibase-core/src/main/java/liquibase/logging/core/DefaultLoggerConfiguration.java @@ -1,53 +1,20 @@ package liquibase.logging.core; -import liquibase.configuration.AbstractConfigurationContainer; -import liquibase.exception.UnexpectedLiquibaseException; - -import java.util.logging.Level; +import liquibase.configuration.ConfigurationDefinition; +import liquibase.configuration.AutoloadedConfigurations; /** * Configuration container for {@link liquibase.logging.LogService} properties */ -public class DefaultLoggerConfiguration extends AbstractConfigurationContainer { - - public static final String LOG_LEVEL = "level"; +public class DefaultLoggerConfiguration implements AutoloadedConfigurations { - public DefaultLoggerConfiguration() { - super("liquibase.defaultlogger"); + public static ConfigurationDefinition<String> LOG_LEVEL; - getContainer().addProperty(LOG_LEVEL, String.class) + static { + ConfigurationDefinition.Builder builder = new ConfigurationDefinition.Builder("liquibase.defaultlogger"); + LOG_LEVEL = builder.define("level", String.class) .setDescription("Logging level") - .setDefaultValue("INFO"); - } - - public String getLogLevelName() { - return getContainer().getValue(LOG_LEVEL, String.class); - } - - - /** - * Transforms the strings DEBUG, INFO, WARNING, ERROR and OFF (case-insensitive) into the appropriate LogLevel. - * @return a value from the LogLevel enum - */ - public Level getLogLevel() { - String logLevel = getLogLevelName(); - - if ("fine".equalsIgnoreCase(logLevel) || "debug".equalsIgnoreCase(logLevel)) { - return Level.FINE; - } else if ("info".equalsIgnoreCase(logLevel)) { - return Level.INFO; - } else if ("warning".equalsIgnoreCase(logLevel)) { - return Level.WARNING; - } else if ("error".equalsIgnoreCase(logLevel) || "severe".equalsIgnoreCase(logLevel)) { - return Level.SEVERE; - } else if ("off".equalsIgnoreCase(logLevel)) { - return Level.OFF; - } else { - throw new UnexpectedLiquibaseException("Unknown log level: " + logLevel+". Valid levels are: debug, info, warning, error, off"); - } - } - public DefaultLoggerConfiguration setLogLevel(String name) { - getContainer().setValue(LOG_LEVEL, name); - return this; + .setDefaultValue("INFO") + .build(); } } diff --git a/liquibase-core/src/main/java/liquibase/parser/ChangeLogParserCofiguration.java b/liquibase-core/src/main/java/liquibase/parser/ChangeLogParserCofiguration.java deleted file mode 100644 index 917fb6aaead..00000000000 --- a/liquibase-core/src/main/java/liquibase/parser/ChangeLogParserCofiguration.java +++ /dev/null @@ -1,45 +0,0 @@ -package liquibase.parser; - -import liquibase.configuration.AbstractConfigurationContainer; - -/** - * Configuration container for properties applicable to most {@link liquibase.parser.ChangeLogParser} implementations - */ -public class ChangeLogParserCofiguration extends AbstractConfigurationContainer { - - public static final String SUPPORT_PROPERTY_ESCAPING = "supportPropertyEscaping"; - public static final String USE_PROCEDURE_SCHEMA = "useProcedureSchema"; - - public ChangeLogParserCofiguration() { - super("liquibase"); - - getContainer().addProperty(SUPPORT_PROPERTY_ESCAPING, Boolean.class) - .setDescription("Support escaping changelog parameters using a colon. Example: ${:user.name}") - .setDefaultValue(false) - .addAlias("enableEscaping"); - - getContainer().addProperty(USE_PROCEDURE_SCHEMA, Boolean.class) - .setDescription("If set to true (default value), createProcedure tags with a set schemaName will modify the procedure body with the given schema name.") - .setDefaultValue(true); - } - - public boolean getSupportPropertyEscaping() { - return getContainer().getValue(SUPPORT_PROPERTY_ESCAPING, Boolean.class); - } - - public ChangeLogParserCofiguration setSupportPropertyEscaping(boolean support) { - getContainer().setValue(SUPPORT_PROPERTY_ESCAPING, support); - return this; - } - - public boolean getUseProcedureSchema() { - return getContainer().getValue(USE_PROCEDURE_SCHEMA, Boolean.class); - } - - public ChangeLogParserCofiguration setUseProcedureSchema(boolean useSchema) { - getContainer().setValue(USE_PROCEDURE_SCHEMA, useSchema); - return this; - } - - -} diff --git a/liquibase-core/src/main/java/liquibase/parser/ChangeLogParserConfiguration.java b/liquibase-core/src/main/java/liquibase/parser/ChangeLogParserConfiguration.java new file mode 100644 index 00000000000..74646873a11 --- /dev/null +++ b/liquibase-core/src/main/java/liquibase/parser/ChangeLogParserConfiguration.java @@ -0,0 +1,28 @@ +package liquibase.parser; + +import liquibase.configuration.ConfigurationDefinition; +import liquibase.configuration.AutoloadedConfigurations; + +/** + * Configuration container for properties applicable to most {@link liquibase.parser.ChangeLogParser} implementations + */ +public class ChangeLogParserConfiguration implements AutoloadedConfigurations { + + public static final ConfigurationDefinition<Boolean> SUPPORT_PROPERTY_ESCAPING; + public static final ConfigurationDefinition<Boolean> USE_PROCEDURE_SCHEMA; + + static { + ConfigurationDefinition.Builder builder = new ConfigurationDefinition.Builder("liquibase"); + + SUPPORT_PROPERTY_ESCAPING = builder.define("supportPropertyEscaping", Boolean.class) + .setDescription("Support escaping changelog parameters using a colon. Example: ${:user.name}") + .setDefaultValue(false) + .addAliasKey("enableEscaping") + .build(); + + USE_PROCEDURE_SCHEMA = builder.define("useProcedureSchema", Boolean.class) + .setDescription("If set to true (default value), createProcedure tags with a set schemaName will modify the procedure body with the given schema name.") + .setDefaultValue(true) + .build(); + } +} diff --git a/liquibase-core/src/main/java/liquibase/parser/core/yaml/YamlSnapshotParser.java b/liquibase-core/src/main/java/liquibase/parser/core/yaml/YamlSnapshotParser.java index e0eb0ba9d5d..cec42c76a09 100644 --- a/liquibase-core/src/main/java/liquibase/parser/core/yaml/YamlSnapshotParser.java +++ b/liquibase-core/src/main/java/liquibase/parser/core/yaml/YamlSnapshotParser.java @@ -1,7 +1,6 @@ package liquibase.parser.core.yaml; -import liquibase.configuration.GlobalConfiguration; -import liquibase.configuration.LiquibaseConfiguration; +import liquibase.GlobalConfiguration; import liquibase.database.Database; import liquibase.database.DatabaseFactory; import liquibase.database.OfflineConnection; @@ -67,7 +66,7 @@ private Map getParsedYamlFromInputStream(Yaml yaml, InputStream stream) throws L Map parsedYaml; try ( InputStreamReader inputStreamReader = new InputStreamReader( - stream, LiquibaseConfiguration.getInstance().getConfiguration(GlobalConfiguration.class).getOutputEncoding() + stream, GlobalConfiguration.OUTPUT_ENCODING.getCurrentValue() ); ) { parsedYaml = (Map) yaml.load(inputStreamReader); diff --git a/liquibase-core/src/main/java/liquibase/sdk/Main.java b/liquibase-core/src/main/java/liquibase/sdk/Main.java index 350b2eef7fc..56e71ef5fbd 100644 --- a/liquibase-core/src/main/java/liquibase/sdk/Main.java +++ b/liquibase-core/src/main/java/liquibase/sdk/Main.java @@ -1,5 +1,7 @@ package liquibase.sdk; +import liquibase.Scope; +import liquibase.command.CommandFactory; import liquibase.command.LiquibaseCommand; import liquibase.exception.UnexpectedLiquibaseException; import liquibase.sdk.convert.ConvertCommand; @@ -59,7 +61,7 @@ public static void main(String[] args) { throw new UserError("Unknown command: "+main.command); } - command.execute(); + Scope.getCurrentScope().getSingleton(CommandFactory.class).execute(command); main.divider(); main.out("Command executed successfully"); diff --git a/liquibase-core/src/main/java/liquibase/sdk/convert/ConvertCommand.java b/liquibase-core/src/main/java/liquibase/sdk/convert/ConvertCommand.java index 7c3b64caea0..0b4bdc87c67 100644 --- a/liquibase-core/src/main/java/liquibase/sdk/convert/ConvertCommand.java +++ b/liquibase-core/src/main/java/liquibase/sdk/convert/ConvertCommand.java @@ -55,7 +55,7 @@ public void setClasspath(String classpath) { } @Override - protected CommandResult run() throws Exception { + public CommandResult run() throws Exception { List<ResourceAccessor> openers = new ArrayList<>(); openers.add(new FileSystemResourceAccessor()); openers.add(new ClassLoaderResourceAccessor()); diff --git a/liquibase-core/src/main/java/liquibase/sdk/resource/MockResourceAccessor.java b/liquibase-core/src/main/java/liquibase/sdk/resource/MockResourceAccessor.java index 331d3c414c7..23828f2f052 100644 --- a/liquibase-core/src/main/java/liquibase/sdk/resource/MockResourceAccessor.java +++ b/liquibase-core/src/main/java/liquibase/sdk/resource/MockResourceAccessor.java @@ -1,7 +1,6 @@ package liquibase.sdk.resource; -import liquibase.configuration.GlobalConfiguration; -import liquibase.configuration.LiquibaseConfiguration; +import liquibase.GlobalConfiguration; import liquibase.resource.AbstractResourceAccessor; import liquibase.resource.InputStreamList; @@ -28,7 +27,7 @@ public MockResourceAccessor(Map<String, String> contentByFileName) { public InputStreamList openStreams(String relativeTo, String streamPath) throws IOException { InputStream stream = null; if (contentByFileName.containsKey(streamPath)) { - stream = new ByteArrayInputStream(contentByFileName.get(streamPath).getBytes(LiquibaseConfiguration.getInstance().getConfiguration(GlobalConfiguration.class).getOutputEncoding())); + stream = new ByteArrayInputStream(contentByFileName.get(streamPath).getBytes(GlobalConfiguration.OUTPUT_ENCODING.getCurrentValue())); } if (stream == null) { return null; diff --git a/liquibase-core/src/main/java/liquibase/sdk/supplier/resource/ResourceSupplier.java b/liquibase-core/src/main/java/liquibase/sdk/supplier/resource/ResourceSupplier.java index 9902e87d85a..6acc06bb5d6 100644 --- a/liquibase-core/src/main/java/liquibase/sdk/supplier/resource/ResourceSupplier.java +++ b/liquibase-core/src/main/java/liquibase/sdk/supplier/resource/ResourceSupplier.java @@ -3,8 +3,7 @@ import liquibase.Scope; import liquibase.change.ChangeFactory; import liquibase.change.core.CreateProcedureChange; -import liquibase.configuration.GlobalConfiguration; -import liquibase.configuration.LiquibaseConfiguration; +import liquibase.GlobalConfiguration; import liquibase.database.core.HsqlDatabase; import liquibase.resource.AbstractResourceAccessor; import liquibase.resource.InputStreamList; @@ -36,8 +35,7 @@ private static class SimpleResourceAccessor extends AbstractResourceAccessor{ @Override public InputStreamList openStreams(String relativeTo, String streamPath) throws IOException { InputStream stream = null; - String encoding = LiquibaseConfiguration.getInstance().getConfiguration( - GlobalConfiguration.class).getOutputEncoding(); + String encoding = GlobalConfiguration.OUTPUT_ENCODING.getCurrentValue(); if (streamPath.toLowerCase().endsWith("csv")) { stream = new ByteArrayInputStream(USERS_CSV.getBytes(encoding)); } else if (streamPath.toLowerCase().endsWith("my-logic.sql")) { diff --git a/liquibase-core/src/main/java/liquibase/serializer/core/formattedsql/FormattedSqlChangeLogSerializer.java b/liquibase-core/src/main/java/liquibase/serializer/core/formattedsql/FormattedSqlChangeLogSerializer.java index dc7ebae0354..2548f1cb545 100644 --- a/liquibase-core/src/main/java/liquibase/serializer/core/formattedsql/FormattedSqlChangeLogSerializer.java +++ b/liquibase-core/src/main/java/liquibase/serializer/core/formattedsql/FormattedSqlChangeLogSerializer.java @@ -4,8 +4,7 @@ import liquibase.change.Change; import liquibase.changelog.ChangeLogChild; import liquibase.changelog.ChangeSet; -import liquibase.configuration.GlobalConfiguration; -import liquibase.configuration.LiquibaseConfiguration; +import liquibase.GlobalConfiguration; import liquibase.database.Database; import liquibase.database.DatabaseFactory; import liquibase.diff.output.changelog.DiffToChangeLog; @@ -105,7 +104,7 @@ public <T extends ChangeLogChild> void write(List<T> children, OutputStream out) builder.append("\n"); } - out.write(builder.toString().getBytes(LiquibaseConfiguration.getInstance().getConfiguration(GlobalConfiguration.class).getOutputEncoding())); + out.write(builder.toString().getBytes(GlobalConfiguration.OUTPUT_ENCODING.getCurrentValue())); } diff --git a/liquibase-core/src/main/java/liquibase/serializer/core/json/JsonChangeLogSerializer.java b/liquibase-core/src/main/java/liquibase/serializer/core/json/JsonChangeLogSerializer.java index f05a26cb79e..aabfbc95235 100644 --- a/liquibase-core/src/main/java/liquibase/serializer/core/json/JsonChangeLogSerializer.java +++ b/liquibase-core/src/main/java/liquibase/serializer/core/json/JsonChangeLogSerializer.java @@ -1,8 +1,7 @@ package liquibase.serializer.core.json; import liquibase.changelog.ChangeLogChild; -import liquibase.configuration.GlobalConfiguration; -import liquibase.configuration.LiquibaseConfiguration; +import liquibase.GlobalConfiguration; import liquibase.serializer.core.yaml.YamlChangeLogSerializer; import liquibase.util.StringUtil; @@ -16,7 +15,7 @@ public class JsonChangeLogSerializer extends YamlChangeLogSerializer { @Override public <T extends ChangeLogChild> void write(List<T> children, OutputStream out) throws IOException { - BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(out, LiquibaseConfiguration.getInstance().getConfiguration(GlobalConfiguration.class).getOutputEncoding())); + BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(out, GlobalConfiguration.OUTPUT_ENCODING.getCurrentValue())); writer.write("{ \"databaseChangeLog\": [\n"); int i = 0; for (T child : children) { diff --git a/liquibase-core/src/main/java/liquibase/serializer/core/string/StringSnapshotSerializer.java b/liquibase-core/src/main/java/liquibase/serializer/core/string/StringSnapshotSerializer.java index 0b7fce6816a..82a941bce93 100644 --- a/liquibase-core/src/main/java/liquibase/serializer/core/string/StringSnapshotSerializer.java +++ b/liquibase-core/src/main/java/liquibase/serializer/core/string/StringSnapshotSerializer.java @@ -1,7 +1,6 @@ package liquibase.serializer.core.string; -import liquibase.configuration.GlobalConfiguration; -import liquibase.configuration.LiquibaseConfiguration; +import liquibase.GlobalConfiguration; import liquibase.exception.UnexpectedLiquibaseException; import liquibase.serializer.LiquibaseSerializable; import liquibase.serializer.SnapshotSerializer; @@ -149,7 +148,7 @@ private String serializeObject(Map collection, int indent) { @Override public void write(DatabaseSnapshot snapshot, OutputStream out) throws IOException { - out.write(serialize(snapshot, true).getBytes(LiquibaseConfiguration.getInstance().getConfiguration(GlobalConfiguration.class).getOutputEncoding())); + out.write(serialize(snapshot, true).getBytes(GlobalConfiguration.OUTPUT_ENCODING.getCurrentValue())); } @Override diff --git a/liquibase-core/src/main/java/liquibase/serializer/core/string/StringSnapshotSerializerReadable.java b/liquibase-core/src/main/java/liquibase/serializer/core/string/StringSnapshotSerializerReadable.java index 6e722597386..5bff4c45934 100644 --- a/liquibase-core/src/main/java/liquibase/serializer/core/string/StringSnapshotSerializerReadable.java +++ b/liquibase-core/src/main/java/liquibase/serializer/core/string/StringSnapshotSerializerReadable.java @@ -1,7 +1,6 @@ package liquibase.serializer.core.string; -import liquibase.configuration.GlobalConfiguration; -import liquibase.configuration.LiquibaseConfiguration; +import liquibase.GlobalConfiguration; import liquibase.database.Database; import liquibase.exception.UnexpectedLiquibaseException; import liquibase.serializer.LiquibaseSerializable; @@ -221,7 +220,7 @@ private <T> List<T> sort(Collection objects, Comparator<T> comparator) { @Override public void write(DatabaseSnapshot snapshot, OutputStream out) throws IOException { - out.write(serialize(snapshot, true).getBytes(LiquibaseConfiguration.getInstance().getConfiguration(GlobalConfiguration.class).getOutputEncoding())); + out.write(serialize(snapshot, true).getBytes(GlobalConfiguration.OUTPUT_ENCODING.getCurrentValue())); } @Override diff --git a/liquibase-core/src/main/java/liquibase/serializer/core/xml/XMLChangeLogSerializer.java b/liquibase-core/src/main/java/liquibase/serializer/core/xml/XMLChangeLogSerializer.java index e0ebc6df074..e7b61da7009 100644 --- a/liquibase-core/src/main/java/liquibase/serializer/core/xml/XMLChangeLogSerializer.java +++ b/liquibase-core/src/main/java/liquibase/serializer/core/xml/XMLChangeLogSerializer.java @@ -5,8 +5,7 @@ import liquibase.changelog.ChangeLogChild; import liquibase.changelog.ChangeSet; import liquibase.changelog.DatabaseChangeLog; -import liquibase.configuration.GlobalConfiguration; -import liquibase.configuration.LiquibaseConfiguration; +import liquibase.GlobalConfiguration; import liquibase.exception.UnexpectedLiquibaseException; import liquibase.parser.NamespaceDetails; import liquibase.parser.NamespaceDetailsFactory; @@ -168,7 +167,7 @@ public void append(ChangeSet changeSet, File changeLogFile) throws IOException { } else { existingChangeLog = existingChangeLog.replaceFirst("</databaseChangeLog>", serialize(changeSet, true) + "\n</databaseChangeLog>"); - StreamUtil.copy(new ByteArrayInputStream(existingChangeLog.getBytes(LiquibaseConfiguration.getInstance().getConfiguration(GlobalConfiguration.class).getOutputEncoding())), out); + StreamUtil.copy(new ByteArrayInputStream(existingChangeLog.getBytes(GlobalConfiguration.OUTPUT_ENCODING.getCurrentValue())), out); } out.flush(); } diff --git a/liquibase-core/src/main/java/liquibase/serializer/core/yaml/YamlChangeLogSerializer.java b/liquibase-core/src/main/java/liquibase/serializer/core/yaml/YamlChangeLogSerializer.java index 219e3afc9af..428f25a57bb 100644 --- a/liquibase-core/src/main/java/liquibase/serializer/core/yaml/YamlChangeLogSerializer.java +++ b/liquibase-core/src/main/java/liquibase/serializer/core/yaml/YamlChangeLogSerializer.java @@ -2,8 +2,7 @@ import liquibase.changelog.ChangeLogChild; import liquibase.changelog.ChangeSet; -import liquibase.configuration.GlobalConfiguration; -import liquibase.configuration.LiquibaseConfiguration; +import liquibase.GlobalConfiguration; import liquibase.serializer.ChangeLogSerializer; import liquibase.serializer.LiquibaseSerializable; @@ -29,7 +28,7 @@ public <T extends ChangeLogChild> void write(List<T> children, OutputStream out) Map<String, Object> containerMap = new HashMap<>(); containerMap.put("databaseChangeLog", maps); - BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(out, LiquibaseConfiguration.getInstance().getConfiguration(GlobalConfiguration.class).getOutputEncoding())); + BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(out, GlobalConfiguration.OUTPUT_ENCODING.getCurrentValue())); writer.write(yaml.dumpAsMap(containerMap)); writer.write("\n"); writer.flush(); diff --git a/liquibase-core/src/main/java/liquibase/serializer/core/yaml/YamlSnapshotSerializer.java b/liquibase-core/src/main/java/liquibase/serializer/core/yaml/YamlSnapshotSerializer.java index dcbf2edf97e..db46511d645 100644 --- a/liquibase-core/src/main/java/liquibase/serializer/core/yaml/YamlSnapshotSerializer.java +++ b/liquibase-core/src/main/java/liquibase/serializer/core/yaml/YamlSnapshotSerializer.java @@ -1,7 +1,6 @@ package liquibase.serializer.core.yaml; -import liquibase.configuration.GlobalConfiguration; -import liquibase.configuration.LiquibaseConfiguration; +import liquibase.GlobalConfiguration; import liquibase.exception.UnexpectedLiquibaseException; import liquibase.serializer.LiquibaseSerializable; import liquibase.serializer.SnapshotSerializer; @@ -33,7 +32,7 @@ public class YamlSnapshotSerializer extends YamlSerializer implements SnapshotSe @Override public void write(DatabaseSnapshot snapshot, OutputStream out) throws IOException { - BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(out, LiquibaseConfiguration.getInstance().getConfiguration(GlobalConfiguration.class).getOutputEncoding())); + BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(out, GlobalConfiguration.OUTPUT_ENCODING.getCurrentValue())); writer.write(serialize(snapshot, true)); } diff --git a/liquibase-core/src/main/java/liquibase/servicelocator/StandardServiceLocator.java b/liquibase-core/src/main/java/liquibase/servicelocator/StandardServiceLocator.java index eae3d46d067..309bdfa4aa5 100644 --- a/liquibase-core/src/main/java/liquibase/servicelocator/StandardServiceLocator.java +++ b/liquibase-core/src/main/java/liquibase/servicelocator/StandardServiceLocator.java @@ -26,6 +26,7 @@ public <T> List<T> findInstances(Class<T> interfaceType) throws ServiceNotFoundE allInstances.add(service); } catch (Throwable e) { log.info("Cannot load service: "+e.getMessage()); + log.fine(e.getMessage(), e); } } diff --git a/liquibase-core/src/main/java/liquibase/snapshot/DatabaseSnapshot.java b/liquibase-core/src/main/java/liquibase/snapshot/DatabaseSnapshot.java index 4dc20cdc01a..c9d51c700aa 100644 --- a/liquibase-core/src/main/java/liquibase/snapshot/DatabaseSnapshot.java +++ b/liquibase-core/src/main/java/liquibase/snapshot/DatabaseSnapshot.java @@ -2,8 +2,7 @@ import liquibase.CatalogAndSchema; import liquibase.Scope; -import liquibase.configuration.GlobalConfiguration; -import liquibase.configuration.LiquibaseConfiguration; +import liquibase.GlobalConfiguration; import liquibase.database.Database; import liquibase.database.DatabaseConnection; import liquibase.database.OfflineConnection; @@ -613,7 +612,7 @@ public void load(ParsedNode parsedNode, ResourceAccessor resourceAccessor) throw if ((value != null) && ObjectUtil.hasProperty(object, attr)) { if ((value instanceof byte[]) && ObjectUtil.getPropertyType(object, attr).equals(String .class)) { - value = new String((byte[]) value, LiquibaseConfiguration.getInstance().getConfiguration(GlobalConfiguration.class).getOutputEncoding()); + value = new String((byte[]) value, GlobalConfiguration.OUTPUT_ENCODING.getCurrentValue()); } object.setAttribute(attr, null); ObjectUtil.setProperty(object, attr, value); diff --git a/liquibase-core/src/main/java/liquibase/sqlgenerator/core/CreateProcedureGenerator.java b/liquibase-core/src/main/java/liquibase/sqlgenerator/core/CreateProcedureGenerator.java index 845fdb8010a..4262b6f6d64 100644 --- a/liquibase-core/src/main/java/liquibase/sqlgenerator/core/CreateProcedureGenerator.java +++ b/liquibase-core/src/main/java/liquibase/sqlgenerator/core/CreateProcedureGenerator.java @@ -1,11 +1,10 @@ package liquibase.sqlgenerator.core; -import liquibase.configuration.GlobalConfiguration; -import liquibase.configuration.LiquibaseConfiguration; +import liquibase.GlobalConfiguration; import liquibase.database.Database; import liquibase.database.core.*; import liquibase.exception.ValidationErrors; -import liquibase.parser.ChangeLogParserCofiguration; +import liquibase.parser.ChangeLogParserConfiguration; import liquibase.sql.Sql; import liquibase.sql.UnparsedSql; import liquibase.sqlgenerator.SqlGeneratorChain; @@ -42,8 +41,7 @@ public Sql[] generateSql(CreateProcedureStatement statement, Database database, List<Sql> sql = new ArrayList<>(); String schemaName = statement.getSchemaName(); - if ((schemaName == null) && LiquibaseConfiguration.getInstance().getConfiguration(GlobalConfiguration.class) - .getAlwaysOverrideStoredLogicSchema()) { + if ((schemaName == null) && GlobalConfiguration.ALWAYS_OVERRIDE_STORED_LOGIC_SCHEMA.getCurrentValue()) { schemaName = database.getDefaultSchemaName(); } @@ -129,7 +127,7 @@ public static String removeTrailingDelimiter(String procedureText, String endDel */ public static void surroundWithSchemaSets(List<Sql> sql, String schemaName, Database database) { if ((StringUtil.trimToNull(schemaName) != null) && - !LiquibaseConfiguration.getInstance().getProperty(ChangeLogParserCofiguration.class, ChangeLogParserCofiguration.USE_PROCEDURE_SCHEMA).getValue(Boolean.class)) { + !ChangeLogParserConfiguration.USE_PROCEDURE_SCHEMA.getCurrentValue()) { String defaultSchema = database.getDefaultSchemaName(); if (database instanceof OracleDatabase) { sql.add(0, new UnparsedSql("ALTER SESSION SET CURRENT_SCHEMA=" + database.escapeObjectName(schemaName, Schema.class))); @@ -149,7 +147,7 @@ public static String addSchemaToText(String procedureText, String schemaName, St if (schemaName == null) { return procedureText; } - if ((StringUtil.trimToNull(schemaName) != null) && LiquibaseConfiguration.getInstance().getProperty(ChangeLogParserCofiguration.class, ChangeLogParserCofiguration.USE_PROCEDURE_SCHEMA).getValue(Boolean.class)) { + if ((StringUtil.trimToNull(schemaName) != null) && ChangeLogParserConfiguration.USE_PROCEDURE_SCHEMA.getCurrentValue()) { StringClauses parsedSql = SqlParser.parse(procedureText, true, true); StringClauses.ClauseIterator clauseIterator = parsedSql.getClauseIterator(); Object next = "START"; diff --git a/liquibase-core/src/main/java/liquibase/sqlgenerator/core/ReorganizeTableGeneratorDB2.java b/liquibase-core/src/main/java/liquibase/sqlgenerator/core/ReorganizeTableGeneratorDB2.java index 35d862a87e0..5c6e8a81a4c 100644 --- a/liquibase-core/src/main/java/liquibase/sqlgenerator/core/ReorganizeTableGeneratorDB2.java +++ b/liquibase-core/src/main/java/liquibase/sqlgenerator/core/ReorganizeTableGeneratorDB2.java @@ -1,7 +1,6 @@ package liquibase.sqlgenerator.core; -import liquibase.configuration.GlobalConfiguration; -import liquibase.configuration.LiquibaseConfiguration; +import liquibase.GlobalConfiguration; import liquibase.database.Database; import liquibase.database.core.DB2Database; import liquibase.exception.DatabaseException; @@ -33,7 +32,7 @@ public ValidationErrors validate(ReorganizeTableStatement reorganizeTableStateme @Override public Sql[] generateSql(ReorganizeTableStatement statement, Database database, SqlGeneratorChain sqlGeneratorChain) { - if (!LiquibaseConfiguration.getInstance().getProperty(GlobalConfiguration.class, GlobalConfiguration.AUTO_REORG).getValue(Boolean.class)) { + if (!GlobalConfiguration.AUTO_REORG.getCurrentValue()) { return null; } diff --git a/liquibase-core/src/main/java/liquibase/structure/AbstractDatabaseObject.java b/liquibase-core/src/main/java/liquibase/structure/AbstractDatabaseObject.java index c02a108e225..fa439c0cf97 100644 --- a/liquibase-core/src/main/java/liquibase/structure/AbstractDatabaseObject.java +++ b/liquibase-core/src/main/java/liquibase/structure/AbstractDatabaseObject.java @@ -1,6 +1,6 @@ package liquibase.structure; -import liquibase.configuration.LiquibaseConfiguration; +import liquibase.GlobalConfiguration; import liquibase.exception.UnexpectedLiquibaseException; import liquibase.parser.core.ParsedNode; import liquibase.parser.core.ParsedNodeException; @@ -237,6 +237,6 @@ public String toString() { * @return */ public boolean shouldIncludeCatalogInSpecification() { - return LiquibaseConfiguration.getInstance().shouldIncludeCatalogInSpecification(); + return GlobalConfiguration.INCLUDE_CATALOG_IN_SPECIFICATION.getCurrentValue(); } } diff --git a/liquibase-core/src/main/java/liquibase/structure/core/Data.java b/liquibase-core/src/main/java/liquibase/structure/core/Data.java index 7209a7e3a8d..229a2b077b8 100644 --- a/liquibase-core/src/main/java/liquibase/structure/core/Data.java +++ b/liquibase-core/src/main/java/liquibase/structure/core/Data.java @@ -1,7 +1,6 @@ package liquibase.structure.core; -import liquibase.configuration.GlobalConfiguration; -import liquibase.configuration.LiquibaseConfiguration; +import liquibase.GlobalConfiguration; import liquibase.structure.AbstractDatabaseObject; import liquibase.structure.DatabaseObject; @@ -9,7 +8,7 @@ public class Data extends AbstractDatabaseObject { @Override public boolean snapshotByDefault() { - return LiquibaseConfiguration.getInstance().getConfiguration(GlobalConfiguration.class).getShouldSnapshotData(); + return GlobalConfiguration.SHOULD_SNAPSHOT_DATA.getCurrentValue(); } public Table getTable() { diff --git a/liquibase-core/src/main/java/liquibase/ui/ConsoleUIService.java b/liquibase-core/src/main/java/liquibase/ui/ConsoleUIService.java index f5c80d5bd8e..7adce3519f9 100644 --- a/liquibase-core/src/main/java/liquibase/ui/ConsoleUIService.java +++ b/liquibase-core/src/main/java/liquibase/ui/ConsoleUIService.java @@ -2,10 +2,9 @@ import liquibase.AbstractExtensibleObject; import liquibase.Scope; -import liquibase.configuration.ConfigurationProperty; -import liquibase.configuration.GlobalConfiguration; -import liquibase.configuration.LiquibaseConfiguration; -import liquibase.exception.LiquibaseException; +import liquibase.GlobalConfiguration; +import liquibase.configuration.ConfigurationDefinition; +import liquibase.configuration.ConfiguredValue; import liquibase.exception.UnexpectedLiquibaseException; import liquibase.logging.Logger; import liquibase.util.StringUtil; @@ -114,9 +113,9 @@ public <T> T prompt(String prompt, T defaultValue, InputHandler<T> inputHandler, */ protected ConsoleWrapper getConsole() { if (console == null) { - final ConfigurationProperty headless = LiquibaseConfiguration.getInstance().getProperty(GlobalConfiguration.class, GlobalConfiguration.HEADLESS); - boolean headlessConfigValue = headless.getValue(Boolean.class); - boolean wasHeadlessOverridden = headless.getWasOverridden(); + final ConfiguredValue<Boolean> headlessValue = GlobalConfiguration.HEADLESS.getCurrentConfiguredValue(); + boolean headlessConfigValue = headlessValue.getValue(); + boolean wasHeadlessOverridden = !ConfigurationDefinition.wasDefaultValueUsed(headlessValue); final Logger log = Scope.getCurrentScope().getLog(getClass()); diff --git a/liquibase-core/src/main/java/liquibase/util/FileUtil.java b/liquibase-core/src/main/java/liquibase/util/FileUtil.java index 53553d23433..815fe076eb3 100644 --- a/liquibase-core/src/main/java/liquibase/util/FileUtil.java +++ b/liquibase-core/src/main/java/liquibase/util/FileUtil.java @@ -1,9 +1,7 @@ package liquibase.util; import liquibase.Scope; -import liquibase.configuration.GlobalConfiguration; -import liquibase.configuration.LiquibaseConfiguration; -import liquibase.resource.ResourceAccessor; +import liquibase.GlobalConfiguration; import java.io.*; @@ -66,7 +64,7 @@ public static void write(String contents, File file) throws IOException { try ( FileOutputStream output = new FileOutputStream(file); ){ - StreamUtil.copy(new ByteArrayInputStream(contents.getBytes(LiquibaseConfiguration.getInstance().getConfiguration(GlobalConfiguration.class).getOutputEncoding())), output); + StreamUtil.copy(new ByteArrayInputStream(contents.getBytes(GlobalConfiguration.OUTPUT_ENCODING.getCurrentValue())), output); } } diff --git a/liquibase-core/src/main/java/liquibase/util/MD5Util.java b/liquibase-core/src/main/java/liquibase/util/MD5Util.java index b89924b3e16..c5d95096c41 100644 --- a/liquibase-core/src/main/java/liquibase/util/MD5Util.java +++ b/liquibase-core/src/main/java/liquibase/util/MD5Util.java @@ -1,8 +1,7 @@ package liquibase.util; import liquibase.Scope; -import liquibase.configuration.GlobalConfiguration; -import liquibase.configuration.LiquibaseConfiguration; +import liquibase.GlobalConfiguration; import liquibase.exception.UnexpectedLiquibaseException; import java.io.InputStream; @@ -29,7 +28,7 @@ public static String computeMD5(String input) { MessageDigest digest; try { digest = MessageDigest.getInstance("MD5"); - digest.update(input.getBytes(LiquibaseConfiguration.getInstance().getConfiguration(GlobalConfiguration.class).getOutputEncoding())); + digest.update(input.getBytes(GlobalConfiguration.OUTPUT_ENCODING.getCurrentValue())); } catch (Exception e) { throw new UnexpectedLiquibaseException(e); } diff --git a/liquibase-core/src/main/java/liquibase/util/StreamUtil.java b/liquibase-core/src/main/java/liquibase/util/StreamUtil.java index d626f8740a6..d4c48a2ff0e 100644 --- a/liquibase-core/src/main/java/liquibase/util/StreamUtil.java +++ b/liquibase-core/src/main/java/liquibase/util/StreamUtil.java @@ -2,8 +2,7 @@ import liquibase.Scope; import liquibase.changelog.ChangeSet; -import liquibase.configuration.GlobalConfiguration; -import liquibase.configuration.LiquibaseConfiguration; +import liquibase.GlobalConfiguration; import liquibase.resource.ResourceAccessor; import java.io.*; @@ -15,7 +14,7 @@ public class StreamUtil { public static String getLineSeparator() { - return LiquibaseConfiguration.getInstance().getConfiguration(GlobalConfiguration.class).getOutputLineSeparator(); + return GlobalConfiguration.OUTPUT_LINE_SEPARATOR.getCurrentValue(); } public static void copy(InputStream inputStream, OutputStream outputStream) throws IOException { diff --git a/liquibase-core/src/main/java/liquibase/util/StringUtil.java b/liquibase-core/src/main/java/liquibase/util/StringUtil.java index 8dc33ebbdec..2f8e05ba665 100644 --- a/liquibase-core/src/main/java/liquibase/util/StringUtil.java +++ b/liquibase-core/src/main/java/liquibase/util/StringUtil.java @@ -503,6 +503,13 @@ public static String randomIdentifer(int len) { return sb.toString(); } + /** + * Converts a camelCase string to a kabob-case one + */ + public static String toKabobCase(String string) { + return string.replaceAll("([A-Z])", "-$1").toLowerCase(); + } + public interface StringUtilFormatter<Type> { String toString(Type obj); } diff --git a/liquibase-core/src/main/java/liquibase/util/xml/DefaultXmlWriter.java b/liquibase-core/src/main/java/liquibase/util/xml/DefaultXmlWriter.java index 972e6b81493..92c7ba51ece 100644 --- a/liquibase-core/src/main/java/liquibase/util/xml/DefaultXmlWriter.java +++ b/liquibase-core/src/main/java/liquibase/util/xml/DefaultXmlWriter.java @@ -1,7 +1,6 @@ package liquibase.util.xml; -import liquibase.configuration.GlobalConfiguration; -import liquibase.configuration.LiquibaseConfiguration; +import liquibase.GlobalConfiguration; import org.w3c.dom.Document; import javax.xml.transform.OutputKeys; @@ -29,10 +28,10 @@ public void write(Document doc, OutputStream outputStream) throws IOException { Transformer transformer = factory.newTransformer(); transformer.setOutputProperty(OutputKeys.METHOD, "xml"); transformer.setOutputProperty(OutputKeys.INDENT, "yes"); - transformer.setOutputProperty(OutputKeys.ENCODING, LiquibaseConfiguration.getInstance().getConfiguration(GlobalConfiguration.class).getOutputEncoding()); + transformer.setOutputProperty(OutputKeys.ENCODING, GlobalConfiguration.OUTPUT_ENCODING.getCurrentValue()); //need to nest outputStreamWriter to get around JDK 5 bug. See http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6296446 - OutputStreamWriter writer = new OutputStreamWriter(outputStream, LiquibaseConfiguration.getInstance().getConfiguration(GlobalConfiguration.class).getOutputEncoding()); + OutputStreamWriter writer = new OutputStreamWriter(outputStream, GlobalConfiguration.OUTPUT_ENCODING.getCurrentValue()); transformer.transform(new DOMSource(doc), new StreamResult(writer)); writer.flush(); writer.close(); diff --git a/liquibase-core/src/main/resources/META-INF/services/liquibase.configuration.AutoloadedConfigurations b/liquibase-core/src/main/resources/META-INF/services/liquibase.configuration.AutoloadedConfigurations new file mode 100644 index 00000000000..f2b13f158ab --- /dev/null +++ b/liquibase-core/src/main/resources/META-INF/services/liquibase.configuration.AutoloadedConfigurations @@ -0,0 +1,4 @@ +liquibase.GlobalConfiguration +liquibase.hub.HubConfiguration +liquibase.logging.core.DefaultLoggerConfiguration +liquibase.parser.ChangeLogParserConfiguration diff --git a/liquibase-core/src/main/resources/META-INF/services/liquibase.configuration.ConfigurationValueProvider b/liquibase-core/src/main/resources/META-INF/services/liquibase.configuration.ConfigurationValueProvider new file mode 100644 index 00000000000..f4ba760cb72 --- /dev/null +++ b/liquibase-core/src/main/resources/META-INF/services/liquibase.configuration.ConfigurationValueProvider @@ -0,0 +1,3 @@ +liquibase.configuration.core.DeprecatedConfigurationValueProvider +liquibase.configuration.core.SystemPropertyValueProvider +liquibase.configuration.core.ScopeValueProvider diff --git a/liquibase-core/src/test/groovy/liquibase/LiquibaseTest.groovy b/liquibase-core/src/test/groovy/liquibase/LiquibaseTest.groovy index 0e0b55aaa08..1195aba0d15 100644 --- a/liquibase-core/src/test/groovy/liquibase/LiquibaseTest.groovy +++ b/liquibase-core/src/test/groovy/liquibase/LiquibaseTest.groovy @@ -2,13 +2,12 @@ package liquibase import liquibase.changelog.ChangeLogIterator import liquibase.changelog.DatabaseChangeLog -import liquibase.configuration.HubConfiguration -import liquibase.configuration.LiquibaseConfiguration import liquibase.database.Database import liquibase.database.core.MockDatabase import liquibase.database.jvm.JdbcConnection import liquibase.exception.DatabaseException import liquibase.exception.LiquibaseException +import liquibase.hub.HubConfiguration import liquibase.hub.HubService import liquibase.hub.HubServiceFactory import liquibase.hub.core.MockHubService @@ -203,10 +202,12 @@ class LiquibaseTest extends Specification { def "update communicates with hub"() { given: Liquibase liquibase = new Liquibase("com/example/changelog.mock", mockResourceAccessor, mockDatabase) - LiquibaseConfiguration.instance.getConfiguration(HubConfiguration.class).setLiquibaseHubApiKey("API_KEY") when: - liquibase.update("") + Scope.child(HubConfiguration.LIQUIBASE_HUB_API_KEY.getKey(), "API_KEY", { + liquibase.update("") + }) + then: mockHubService.sentObjects.toString() == @@ -223,13 +224,17 @@ class LiquibaseTest extends Specification { when: Liquibase liquibase = new Liquibase("com/example/changelog.mock", mockResourceAccessor, mockDatabase) - LiquibaseConfiguration.instance.getConfiguration(HubConfiguration.class).setLiquibaseHubApiKey(null) - DatabaseChangeLog changeLog = liquibase.getDatabaseChangeLog() + Connection connection = null; + String message = null; def changeLogId = UUID.randomUUID().toString() - changeLog.setChangeLogId(changeLogId) - Connection connection = liquibase.getConnection(changeLog) - List<String> messages = uiService.getMessages() - String message = messages.get(0) + + Scope.child(HubConfiguration.LIQUIBASE_HUB_API_KEY.getKey(), null, { + DatabaseChangeLog changeLog = liquibase.getDatabaseChangeLog() + changeLog.setChangeLogId(changeLogId) + connection = liquibase.getConnection(changeLog) + List<String> messages = uiService.getMessages() + message = messages.get(0) + }) Scope.exit(scopeId) then: @@ -249,12 +254,15 @@ class LiquibaseTest extends Specification { when: Liquibase liquibase = new Liquibase("com/example/changelog.mock", mockResourceAccessor, mockDatabase) - LiquibaseConfiguration.instance.getConfiguration(HubConfiguration.class).setLiquibaseHubApiKey("API_KEY") - DatabaseChangeLog changeLog = liquibase.getDatabaseChangeLog() - changeLog.setChangeLogId(null) - Connection connection = liquibase.getConnection(changeLog) - List<String> messages = uiService.getMessages() - String message = messages.get(0) + Connection connection = null + String message = null + Scope.child(HubConfiguration.LIQUIBASE_HUB_API_KEY.getKey(), "API_KEY", { + DatabaseChangeLog changeLog = liquibase.getDatabaseChangeLog() + changeLog.setChangeLogId(null) + connection = liquibase.getConnection(changeLog) + List<String> messages = uiService.getMessages() + message = messages.get(0) + }) Scope.exit(scopeId) then: diff --git a/liquibase-core/src/test/groovy/liquibase/changelog/ChangeLogRewriterTest.groovy b/liquibase-core/src/test/groovy/liquibase/changelog/ChangeLogRewriterTest.groovy index 915578d98ad..b667a852a1f 100644 --- a/liquibase-core/src/test/groovy/liquibase/changelog/ChangeLogRewriterTest.groovy +++ b/liquibase-core/src/test/groovy/liquibase/changelog/ChangeLogRewriterTest.groovy @@ -99,7 +99,7 @@ class ChangeLogRewriterTest extends Specification { then: !result.success - result.message.matches(".*was not registered due to an error.*Permission denied.*") + result.message.matches(".*was not registered due to an error.*") !matcher.matches() !idMatcher.matches() changeLog.getChangeLogId() == null diff --git a/liquibase-core/src/test/groovy/liquibase/command/core/DropAllCommandTest.groovy b/liquibase-core/src/test/groovy/liquibase/command/core/DropAllCommandTest.groovy index becc0d64f67..d630c9af1a7 100644 --- a/liquibase-core/src/test/groovy/liquibase/command/core/DropAllCommandTest.groovy +++ b/liquibase-core/src/test/groovy/liquibase/command/core/DropAllCommandTest.groovy @@ -2,9 +2,9 @@ package liquibase.command.core import liquibase.Liquibase import liquibase.Scope -import liquibase.configuration.HubConfiguration -import liquibase.configuration.LiquibaseConfiguration +import liquibase.command.CommandResult import liquibase.database.core.MockDatabase +import liquibase.hub.HubConfiguration import liquibase.hub.HubService import liquibase.hub.core.MockHubService import liquibase.logging.core.BufferedLogService @@ -63,23 +63,22 @@ class DropAllCommandTest extends Specification { BufferedLogService bufferLog = new BufferedLogService() Scope.getCurrentScope().getUI() - def hubConfiguration = LiquibaseConfiguration.getInstance().getConfiguration(HubConfiguration.class) - hubConfiguration.setLiquibaseHubApiKey(UUID.randomUUID().toString()) - def command = new DropAllCommand() - JUnitResourceAccessor testResourceAccessor = new JUnitResourceAccessor() - Liquibase liquibase = new Liquibase(outputFile.getName(), testResourceAccessor, new MockDatabase()) - command.setLiquibase(liquibase) - command.setChangeLogFile(outputFile.getName()) - command.setDatabase(new MockDatabase()) - command.setSchemas("") - def result - CompositeLogService compositeLogService = new CompositeLogService(true, bufferLog); - Scope.child(Scope.Attr.logService.name(), compositeLogService, new Scope.ScopedRunner() { - public void run() { + CommandResult result = null + Scope.child(HubConfiguration.LIQUIBASE_HUB_API_KEY.getKey(), UUID.randomUUID().toString(), { + def command = new DropAllCommand() + JUnitResourceAccessor testResourceAccessor = new JUnitResourceAccessor() + Liquibase liquibase = new Liquibase(outputFile.getName(), testResourceAccessor, new MockDatabase()) + command.setLiquibase(liquibase) + command.setChangeLogFile(outputFile.getName()) + command.setDatabase(new MockDatabase()) + command.setSchemas("") + + CompositeLogService compositeLogService = new CompositeLogService(true, bufferLog); + Scope.child(Scope.Attr.logService.name(), compositeLogService, { result = command.run() - } - }); + }) + }) then: result.succeeded diff --git a/liquibase-core/src/test/groovy/liquibase/command/core/RegisterChangeLogCommandTest.groovy b/liquibase-core/src/test/groovy/liquibase/command/core/RegisterChangeLogCommandTest.groovy index 3165b532dac..99c982178c4 100644 --- a/liquibase-core/src/test/groovy/liquibase/command/core/RegisterChangeLogCommandTest.groovy +++ b/liquibase-core/src/test/groovy/liquibase/command/core/RegisterChangeLogCommandTest.groovy @@ -2,7 +2,7 @@ package liquibase.command.core import liquibase.Scope import liquibase.changelog.DatabaseChangeLog -import liquibase.configuration.HubConfiguration +import liquibase.hub.HubConfiguration import liquibase.configuration.LiquibaseConfiguration import liquibase.hub.HubService import liquibase.hub.HubServiceFactory @@ -188,7 +188,6 @@ class RegisterChangeLogCommandTest extends Specification { when: def outputStream = new ByteArrayOutputStream() - def hubConfiguration = LiquibaseConfiguration.getInstance().getConfiguration(HubConfiguration.class) def command = new RegisterChangeLogCommand() command.setChangeLogFile("changelog.xml") DatabaseChangeLog changeLog = new DatabaseChangeLog(".") diff --git a/liquibase-core/src/test/groovy/liquibase/configuration/ConfigurationDefinitionTest.groovy b/liquibase-core/src/test/groovy/liquibase/configuration/ConfigurationDefinitionTest.groovy new file mode 100644 index 00000000000..56de95f0c3f --- /dev/null +++ b/liquibase-core/src/test/groovy/liquibase/configuration/ConfigurationDefinitionTest.groovy @@ -0,0 +1,196 @@ +package liquibase.configuration + +import liquibase.Scope +import spock.lang.Specification +import spock.lang.Unroll + +class ConfigurationDefinitionTest extends Specification { + + def cleanup() { + System.clearProperty("test.property") + } + + @Unroll + def "does not allow invalid keys"() { + when: + new ConfigurationDefinition.Builder(prefix).define(property, String).addAliasKey(alias) + + then: + def e = thrown(IllegalArgumentException) + e.message == expectedMessage + + where: + prefix | property | alias | expectedMessage + "test" | "invalid-key" | "valid" | "Invalid key format: test.invalid-key" + "invalid-prefix" | "invalid-key" | "valid" | "Invalid prefix format: invalid-prefix" + "invalid-prefix" | "validValue" | "valid" | "Invalid prefix format: invalid-prefix" + "validPrefix" | "validValue" | "invalid-alias" | "Invalid alias format: invalid-alias" + } + + def "Can build and register"() { + when: + def definition = new ConfigurationDefinition.Builder("test.canBuild") + .define("testProperty", String) + .setDefaultValue("Default Value") + .setDescription("A description here") + .build() + + then: + assert Scope.currentScope.getSingleton(LiquibaseConfiguration).getRegisteredDefinitions().contains(definition) + definition.key == "test.canBuild.testProperty" + definition.defaultValue == "Default Value" + definition.description == "A description here" + } + + @Unroll + def "getCurrentValueDetails"() { + when: + def definition = new ConfigurationDefinition.Builder("test") + .define(key, String) + .addAliasKey("other") + .setDefaultValue(defaultValue) + .buildTemporary() + + System.setProperty("test.currentValue", "From from system") + System.setProperty("test.other", "Alias set in system") + def currentValue = Scope.child(["test.currentValue": "From scope"], new Scope.ScopedRunnerWithReturn<ConfiguredValue>() { + @Override + ConfiguredValue run() throws Exception { + return definition.getCurrentConfiguredValue() + } + }) + + then: + currentValue.value == expectedValue + currentValue.getProvidedValue().describe() == expectedSource + ConfigurationDefinition.wasDefaultValueUsed(currentValue) == defaultValueUsed + + where: + key | defaultValue | expectedValue | expectedSource | defaultValueUsed + "currentValue" | "Default Value" | "From scope" | "Scoped value 'test.currentValue'" | false + "unsetValue" | "Configured Default" | "Configured Default" | "Default value 'test.unsetValue'" | true + "unsetValue" | null | null | "No configuration or default value found 'test.unsetValue'" | false + + } + + @Unroll + def "getCurrentValueDetails for aliases"() { + when: + def definition = new ConfigurationDefinition.Builder("test") + .define("actual", String) + .addAliasKey("other.prefix.key") + .addAliasKey("other") + .buildTemporary() + + def currentValue = Scope.child([(key): "From Scope"], new Scope.ScopedRunnerWithReturn<ConfiguredValue>() { + @Override + ConfiguredValue run() throws Exception { + return definition.getCurrentConfiguredValue() + } + }) + + then: + currentValue.value == expected + + where: + key | expected + "test.actual" | "From Scope" + "other.prefix.key" | "From Scope" + "other" | "From Scope" + + } + + def "getValueObfuscated"() { + when: + def obfuscated = new ConfigurationDefinition.Builder("test") + .define("obfuscated", String) + .setValueObfuscator(new ConfigurationValueObfuscator<String>() { + @Override + String obfuscate(String value) { + return "OBFUSCATED " + value + } + }) + .buildTemporary() + + def plainText = new ConfigurationDefinition.Builder("test") + .define("obfuscated", String) + .buildTemporary() + + def obfuscatedOutput = Scope.child(["test.obfuscated": input], new Scope.ScopedRunnerWithReturn<String>() { + @Override + String run() throws Exception { + return obfuscated.getCurrentValueObfuscated() + } + }) + + def plainOutput = Scope.child(["test.obfuscated": input], new Scope.ScopedRunnerWithReturn<String>() { + @Override + String run() throws Exception { + return plainText.getCurrentValueObfuscated() + } + }) + + then: + obfuscatedOutput == expected + plainOutput == expectedPlain + + where: + input | expected | expectedPlain + "value" | "OBFUSCATED value" | "value" + null | "OBFUSCATED null" | null + } + + def convertValues() { + when: + def definition = new ConfigurationDefinition.Builder("test") + .define("property", Boolean) + .buildTemporary() + + System.setProperty("test.property", "true") + + then: + definition.getCurrentConfiguredValue().getValue() == Boolean.TRUE + + } + + def equalsAndHash() { + when: + def definition1 = new ConfigurationDefinition.Builder("test") + .define("property1", Boolean) + .buildTemporary() + + def definition2 = new ConfigurationDefinition.Builder("test") + .define("property2", Boolean) + .buildTemporary() + + def dupeDefinition1 = new ConfigurationDefinition.Builder("test") + .define("property1", Boolean) + .buildTemporary() + + then: + definition1.equals(definition1) + definition1.hashCode() == definition1.hashCode() + + !definition1.equals(definition2) + definition1.hashCode() != definition2.hashCode() + + definition1.equals(dupeDefinition1) + definition1.hashCode() == dupeDefinition1.hashCode() + + } + + @Unroll + def equalsKey() { + expect: + liquibase.GlobalConfiguration.SHOULD_RUN.equalsKey(input) == expected + + where: + input | expected + "liquibase.shouldRun" | true + "liquibase.otherValue" | false + "liquibase.SHOULDRUN" | true + "should.run" | true + "SHOULD.RUN" | true + null | false + } +} diff --git a/liquibase-core/src/test/groovy/liquibase/configuration/ConfigurationPropertyTest.groovy b/liquibase-core/src/test/groovy/liquibase/configuration/ConfigurationPropertyTest.groovy new file mode 100644 index 00000000000..6aef30a01cc --- /dev/null +++ b/liquibase-core/src/test/groovy/liquibase/configuration/ConfigurationPropertyTest.groovy @@ -0,0 +1,55 @@ +package liquibase.configuration + +import liquibase.configuration.core.DeprecatedConfigurationValueProvider +import spock.lang.Specification + +class ConfigurationPropertyTest extends Specification { + + def "setup"() { + DeprecatedConfigurationValueProvider.clearData() + } + + def "cleanup"() { + DeprecatedConfigurationValueProvider.clearData() + } + + def "Works correctly"() { + when: + def builder = new ConfigurationDefinition.Builder("test").define("property", String) + def property = new ConfigurationProperty("test", builder) + .addAlias("test.other.property") + .setDescription("test property desc") + + then: + property.getNamespace() == "test" + property.getName() == "property" + property.getType() == String + property.getDescription() == "test property desc" + property.getValue() == null + + when: + property.setDefaultValue("default value") + then: + property.getDefaultValue() == "default value" + property.getValue() == "default value" + !property.getWasOverridden() + + when: + DeprecatedConfigurationValueProvider.setData("test.property", "set value") + then: + property.getValue(String) == "set value" + property.getWasOverridden() + + + when: + property.setValue("other value") + then: + property.getValue() == "other value" + + when: + DeprecatedConfigurationValueProvider.clearData() + DeprecatedConfigurationValueProvider.setData("test.other.property", "alias value") + then: + property.getValue() == "alias value" + } +} diff --git a/liquibase-core/src/test/groovy/liquibase/configuration/ConfiguredValueTest.groovy b/liquibase-core/src/test/groovy/liquibase/configuration/ConfiguredValueTest.groovy new file mode 100644 index 00000000000..60e2b273767 --- /dev/null +++ b/liquibase-core/src/test/groovy/liquibase/configuration/ConfiguredValueTest.groovy @@ -0,0 +1,51 @@ +package liquibase.configuration + +import liquibase.configuration.core.ScopeValueProvider +import liquibase.configuration.core.SystemPropertyValueProvider +import spock.lang.Specification + +class ConfiguredValueTest extends Specification { + + def "empty"() { + when: + def configuredValue = new ConfiguredValue("requested.key") + + then: + !configuredValue.found() + configuredValue.getValue() == null + configuredValue.getProvidedValues()*.describe() == ["No configuration or default value found 'requested.key'"] + configuredValue.getProvidedValue().describe() == "No configuration or default value found 'requested.key'" + } + + def "one override"() { + when: + def configuredValue = new ConfiguredValue() + configuredValue.override(new ProvidedValue("requested.key", "actual.key", "value", "first override", new SystemPropertyValueProvider())) + + then: + configuredValue.found() + configuredValue.getValue() == "value" + configuredValue.getProvidedValue().describe() == "first override 'actual.key'" + configuredValue.getProvidedValue().requestedKey == "requested.key" + configuredValue.getProvidedValue().actualKey == "actual.key" + configuredValue.getProvidedValues()*.describe() == ["first override 'actual.key'"] + configuredValue.getProvidedValues()*.provider*.class.name == [SystemPropertyValueProvider.name] + } + + def "two overrides"() { + when: + def configuredValue = new ConfiguredValue() + configuredValue.override(new ProvidedValue("requested.key", "actual.key", "value", "first override", new SystemPropertyValueProvider())) + configuredValue.override(new ProvidedValue("requested.key", "other.actual.key", "second value", "second override", new ScopeValueProvider())) + + then: + configuredValue.found() + configuredValue.getValue() == "second value" + configuredValue.getProvidedValue().describe() == "second override 'other.actual.key'" + configuredValue.getProvidedValue().requestedKey == "requested.key" + configuredValue.getProvidedValue().actualKey == "other.actual.key" + configuredValue.getProvidedValues()*.provider*.class.name == [ScopeValueProvider.name, SystemPropertyValueProvider.name] + configuredValue.getProvidedValues()*.describe() == ["second override 'other.actual.key'", "first override 'actual.key'"] + } + +} diff --git a/liquibase-core/src/test/groovy/liquibase/configuration/DeprecatedConfigurationCodeTest.groovy b/liquibase-core/src/test/groovy/liquibase/configuration/DeprecatedConfigurationCodeTest.groovy new file mode 100644 index 00000000000..da50be35f4c --- /dev/null +++ b/liquibase-core/src/test/groovy/liquibase/configuration/DeprecatedConfigurationCodeTest.groovy @@ -0,0 +1,75 @@ +package liquibase.configuration + +import liquibase.configuration.core.DeprecatedConfigurationValueProvider +import spock.lang.Specification + +/** + * Test deprecated styles of code to ensure we are API compatible with them. + * Be liberal with type casts so ensure we are using the correct APIs + */ +class DeprecatedConfigurationCodeTest extends Specification { + + def "cleanup"() { + DeprecatedConfigurationValueProvider.clearData() + } + + def "4_3 getter style configuration lookup"() { + expect: + LiquibaseConfiguration.getInstance().getConfiguration(GlobalConfiguration.class).getOutputEncoding() == "UTF-8" + } + + def "4_3 setter style configuration setting"() { + when: + def config = LiquibaseConfiguration.getInstance().getConfiguration(GlobalConfiguration.class) + + config.setOutputEncoding("ASCII") + + then: + config.getOutputEncoding() == "ASCII" + + when: + DeprecatedConfigurationValueProvider.clearData() + + then: + config.getOutputEncoding() == "UTF-8" + } + + def "4_3 ConfigurationContainer custom implementations"() { + when: + def config = LiquibaseConfiguration.getInstance().getConfiguration(DeprecatedConfigurationConfig.class) + def property = (ConfigurationProperty) config.getProperty(DeprecatedConfigurationConfig.TEST_PROPERTY) + + then: + config.getProperties()*.getName() == ["testProperty"] + property.description == "A test property" + property.getValue() == "default value" + !property.getWasOverridden() + } + + private static class DeprecatedConfigurationConfig extends AbstractConfigurationContainer { + + private static final String TEST_PROPERTY = "testProperty" + + DeprecatedConfigurationConfig() { + super("test"); + + getContainer().addProperty(TEST_PROPERTY, String.class) + .setDescription("A test property") + .setDefaultValue("default value") + .addAlias("mock.property"); + } + + /** + * Should Liquibase execute + */ + boolean getTestProperty() { + return getContainer().getValue(TEST_PROPERTY, Boolean.class); + } + + DeprecatedConfigurationConfig setTestProperty(boolean value) { + getContainer().setValue(TEST_PROPERTY, value); + return this; + } + } + +} diff --git a/liquibase-core/src/test/groovy/liquibase/configuration/GlobalConfigurationTest.groovy b/liquibase-core/src/test/groovy/liquibase/configuration/GlobalConfigurationTest.groovy new file mode 100644 index 00000000000..47aaed9851b --- /dev/null +++ b/liquibase-core/src/test/groovy/liquibase/configuration/GlobalConfigurationTest.groovy @@ -0,0 +1,12 @@ +package liquibase.configuration + +import spock.lang.Specification + +class GlobalConfigurationTest extends Specification { + + def "string properties are set correctly"() { + expect: + assert GlobalConfiguration.HEADLESS == "liquibase.headless" + assert GlobalConfiguration.SHOULD_RUN == "liquibase.shouldRun" + } +} diff --git a/liquibase-core/src/test/groovy/liquibase/configuration/LiquibaseConfigurationTest.groovy b/liquibase-core/src/test/groovy/liquibase/configuration/LiquibaseConfigurationTest.groovy new file mode 100644 index 00000000000..2e82ede3762 --- /dev/null +++ b/liquibase-core/src/test/groovy/liquibase/configuration/LiquibaseConfigurationTest.groovy @@ -0,0 +1,65 @@ +package liquibase.configuration + +import liquibase.Scope +import spock.lang.Specification + +class LiquibaseConfigurationTest extends Specification { + + def "getCurrentConfiguredValue"() { + when: + System.setProperty("test.currentValue", "From system") + def currentValue = Scope.child(["test.currentValue": "From scope"], new Scope.ScopedRunnerWithReturn<ConfiguredValue>() { + @Override + ConfiguredValue run() throws Exception { + return Scope.currentScope.getSingleton(LiquibaseConfiguration).getCurrentConfiguredValue("test.currentValue") + } + }) + + then: + currentValue.value == "From scope" + currentValue.providedValues*.describe() == ["Scoped value 'test.currentValue'", "System property 'test.currentValue'"] + } + + def "getCurrentConfiguredValue with no value found"() { + when: + def currentValue = Scope.currentScope.getSingleton(LiquibaseConfiguration).getCurrentConfiguredValue("test.unknownValue") + + then: + currentValue != null + currentValue.getValue() == null + currentValue.getProvidedValue().sourceDescription == "No configuration or default value found" + currentValue.getProvidedValue().requestedKey == "test.unknownValue" + currentValue.getProvidedValue().provider != null + } + + + def "autoRegisters and sorts providers"() { + expect: + Scope.getCurrentScope().getSingleton(LiquibaseConfiguration).configurationValueProviders*.getClass()*.getName().contains("liquibase.configuration.core.SystemPropertyValueProvider") + } + + def "autoRegisters definitions"() { + expect: + Scope.getCurrentScope().getSingleton(LiquibaseConfiguration).getRegisteredDefinitions().size() > 10 + } + + def "getRegisteredDefinition for a key"() { + when: + def definition = Scope.getCurrentScope().getSingleton(LiquibaseConfiguration).getRegisteredDefinition("liquibase.shouldRun") + + then: + definition.key == "liquibase.shouldRun" + definition.description == "Should Liquibase commands execute" + + } + + def "getRegisteredDefinition for an unknown key"() { + when: + def definition = Scope.getCurrentScope().getSingleton(LiquibaseConfiguration).getRegisteredDefinition("test.invalid") + + then: + definition == null + + } + +} diff --git a/liquibase-core/src/test/groovy/liquibase/configuration/ProvidedValueTest.groovy b/liquibase-core/src/test/groovy/liquibase/configuration/ProvidedValueTest.groovy new file mode 100644 index 00000000000..a77716798db --- /dev/null +++ b/liquibase-core/src/test/groovy/liquibase/configuration/ProvidedValueTest.groovy @@ -0,0 +1,12 @@ +package liquibase.configuration + +import liquibase.configuration.core.SystemPropertyValueProvider +import spock.lang.Specification + +class ProvidedValueTest extends Specification { + + def describe() { + expect: + new ProvidedValue("requested.key", "actual.key", "value", "test source", new SystemPropertyValueProvider()).describe() == "test source 'actual.key'" + } +} diff --git a/liquibase-core/src/test/groovy/liquibase/configuration/core/DeprecatedConfigurationValueProviderTest.groovy b/liquibase-core/src/test/groovy/liquibase/configuration/core/DeprecatedConfigurationValueProviderTest.groovy new file mode 100644 index 00000000000..37b68ef3412 --- /dev/null +++ b/liquibase-core/src/test/groovy/liquibase/configuration/core/DeprecatedConfigurationValueProviderTest.groovy @@ -0,0 +1,22 @@ +package liquibase.configuration.core + +import spock.lang.Specification + +class DeprecatedConfigurationValueProviderTest extends Specification { + + def "can set and clear values"() { + when: + DeprecatedConfigurationValueProvider.setData("test.key", "test value") + + then: + new DeprecatedConfigurationValueProvider().getProvidedValue("test.key").getValue() == "test value" + new DeprecatedConfigurationValueProvider().getProvidedValue("invalid.key") == null + + when: + DeprecatedConfigurationValueProvider.clearData() + + then: + new DeprecatedConfigurationValueProvider().getProvidedValue("test.key") == null + + } +} diff --git a/liquibase-core/src/test/groovy/liquibase/configuration/core/MapConfigurationValueProviderTest.groovy b/liquibase-core/src/test/groovy/liquibase/configuration/core/MapConfigurationValueProviderTest.groovy new file mode 100644 index 00000000000..df513748fa5 --- /dev/null +++ b/liquibase-core/src/test/groovy/liquibase/configuration/core/MapConfigurationValueProviderTest.groovy @@ -0,0 +1,67 @@ +package liquibase.configuration.core + +import liquibase.configuration.AbstractMapConfigurationValueProvider +import spock.lang.Specification +import spock.lang.Unroll + +/** + * Tests the base {@link AbstractMapConfigurationValueProvider} logic. Can't call this + * AbstractMapConfigurationValueProviderTest or maven won't pick it up + */ +class MapConfigurationValueProviderTest extends Specification { + + def "empty values count as not set"() { + when: + def provider = new MapConfigurationValueProvider(["empty.property":""]) + + then: + provider.getProvidedValue("empty.property") == null + provider.getProvidedValue("empty-property") == null + } + + @Unroll + def "keyMatches"() { + expect: + new MapConfigurationValueProvider([:]).keyMatches(wantedKey, storedKey) == matches + + where: + wantedKey | storedKey | matches + "single" | "single" | true + "single" | "SINGLE" | true + "single" | "SiNglE" | true + "parent.child" | "parent.child" | true + "parent.child" | "PARENT.Child" | true + "parent.child" | "PARENT-Child" | false + "parent.child" | "PARENT_Child" | false + "parent.bothChildren" | "Parent.BothChildren" | true + "parent.bothChildren" | "parent.both-children" | true + "parent.bothChildren" | "parent.both_children" | false + "single" | "invalid" | false + "parent.child" | "parent" | false + } + + static class MapConfigurationValueProvider extends AbstractMapConfigurationValueProvider { + + private final Map<?, ?> map + + MapConfigurationValueProvider(Map<?, ?> map) { + this.map = map + } + + @Override + int getPrecedence() { + return -1 + } + + @Override + protected String getSourceDescription() { + return "Test map" + } + + @Override + protected Map<?, ?> getMap() { + return map + } + } + +} diff --git a/liquibase-core/src/test/groovy/liquibase/configuration/core/ScopeValueProviderTest.groovy b/liquibase-core/src/test/groovy/liquibase/configuration/core/ScopeValueProviderTest.groovy new file mode 100644 index 00000000000..facd49a0bed --- /dev/null +++ b/liquibase-core/src/test/groovy/liquibase/configuration/core/ScopeValueProviderTest.groovy @@ -0,0 +1,56 @@ +package liquibase.configuration.core + +import liquibase.Scope +import liquibase.configuration.ProvidedValue +import spock.lang.Specification +import spock.lang.Unroll + +class ScopeValueProviderTest extends Specification { + + + @Unroll + def "GetValue"() { + when: + def env = [ + "lower" : "saw lower", + "lower_underscore": "saw lower underscore", + "lower.dot" : "saw lower dot", + "lower_under.dot" : "saw lower word dot", + "UPPER" : "saw upper", + "UPPER_UNDERSCORE": "saw upper underscore", + "UPPER.DOT" : "saw upper dot", + "UPPER_UNDER_DOT" : "saw under dot", + ] + + def passedKey = key + ProvidedValue foundValue = Scope.child(env, new Scope.ScopedRunnerWithReturn<ProvidedValue>() { + @Override + ProvidedValue run() throws Exception { + new ScopeValueProvider().getProvidedValue(passedKey) + } + }) + + then: + if (foundValue == null) { + assert expectedValue == null + } else { + assert foundValue.value == expectedValue + assert foundValue.describe() == expectedSource + } + + + where: + key | expectedValue | expectedSource + "lower" | "saw lower" | "Scoped value 'lower'" + "LOWER" | null | null + "upper" | null | null + "UPPER" | "saw upper" | "Scoped value 'UPPER'" + "lower.underscore" | null | null + "upper.dot" | null | null + "UPPER.DOT" | "saw upper dot" | "Scoped value 'UPPER.DOT'" + "LOWER.UNDER.dot" | null | null + "LOWER_UNDER_DOT" | null | null + "invalid" | null | null + null | null | null + } +} diff --git a/liquibase-core/src/test/groovy/liquibase/configuration/core/SystemPropertyValueProviderTest.groovy b/liquibase-core/src/test/groovy/liquibase/configuration/core/SystemPropertyValueProviderTest.groovy new file mode 100644 index 00000000000..ba048c98de7 --- /dev/null +++ b/liquibase-core/src/test/groovy/liquibase/configuration/core/SystemPropertyValueProviderTest.groovy @@ -0,0 +1,14 @@ +package liquibase.configuration.core + + +import spock.lang.Specification +import spock.lang.Unroll + +class SystemPropertyValueProviderTest extends Specification { + + @Unroll + def "getProvidedValue"() { + expect: + new SystemPropertyValueProvider().getProvidedValue("USER.NAME").getValue() == System.getProperty("user.name") + } +} diff --git a/liquibase-core/src/test/groovy/liquibase/configuration/HubConfigurationTest.groovy b/liquibase-core/src/test/groovy/liquibase/hub/HubConfigurationTest.groovy similarity index 73% rename from liquibase-core/src/test/groovy/liquibase/configuration/HubConfigurationTest.groovy rename to liquibase-core/src/test/groovy/liquibase/hub/HubConfigurationTest.groovy index 9a021f2be6e..b3a8c26a3ca 100644 --- a/liquibase-core/src/test/groovy/liquibase/configuration/HubConfigurationTest.groovy +++ b/liquibase-core/src/test/groovy/liquibase/hub/HubConfigurationTest.groovy @@ -1,6 +1,6 @@ -package liquibase.configuration - +package liquibase.hub +import liquibase.Scope import spock.lang.Specification import spock.lang.Unroll @@ -9,10 +9,15 @@ class HubConfigurationTest extends Specification { @Unroll def "setHubUrl cleans up input"() { when: - def config = new HubConfiguration().setLiquibaseHubUrl(input) + def output = Scope.child([(HubConfiguration.LIQUIBASE_HUB_URL.key): input], new Scope.ScopedRunnerWithReturn<String>() { + @Override + String run() throws Exception { + return HubConfiguration.LIQUIBASE_HUB_URL.getCurrentValue() + } + }) then: - config.getLiquibaseHubUrl() == expected + output == expected where: input | expected @@ -29,12 +34,4 @@ class HubConfigurationTest extends Specification { "http://localhost:8080" | "http://localhost:8080" } - def setGetHubApiKey() { - when: - def config = new HubConfiguration().setLiquibaseHubApiKey("this_is_a_hub_key") - - then: - config.getLiquibaseHubApiKey() == "this_is_a_hub_key" - } - } diff --git a/liquibase-core/src/test/groovy/liquibase/hub/core/StandardHubServiceTest.groovy b/liquibase-core/src/test/groovy/liquibase/hub/core/StandardHubServiceTest.groovy index e600bc9bc86..4394d4a0892 100644 --- a/liquibase-core/src/test/groovy/liquibase/hub/core/StandardHubServiceTest.groovy +++ b/liquibase-core/src/test/groovy/liquibase/hub/core/StandardHubServiceTest.groovy @@ -1,7 +1,7 @@ package liquibase.hub.core -import liquibase.configuration.HubConfiguration -import liquibase.configuration.LiquibaseConfiguration +import liquibase.Scope +import liquibase.hub.HubConfiguration import liquibase.hub.model.Connection import liquibase.hub.model.OperationChangeEvent import liquibase.hub.model.Project @@ -12,10 +12,6 @@ class StandardHubServiceTest extends Specification { private static testUuid = UUID.fromString("3b8b6f80-1194-4a70-8cf2-30f33fd0433e") - def cleanup() { - LiquibaseConfiguration.getInstance().getConfiguration(HubConfiguration.class).setLiquibaseHubMode("all") - } - @Unroll def "toSearchString"() { expect: @@ -51,36 +47,39 @@ class StandardHubServiceTest extends Specification { def operationId = UUID.randomUUID() when: - LiquibaseConfiguration.getInstance().getConfiguration(HubConfiguration.class).setLiquibaseHubMode(mode) - - def mockHttpClient = new MockHttpClient([ - "GET /api/v1/organizations" : MockHttpClient.createListResponse([ - id : orgId.toString(), - name: "Mock Org" - ]), - ("POST /api/v1/organizations/$orgId/projects/$projectId/operations/$operationId/change-events" as String): null, - ]) - - def service = new StandardHubService( - http: mockHttpClient - ) - - def event = new OperationChangeEvent( - eventType: "update", - changesetId: "1", - project: [ - id: projectId, - ], - operation: [ - id: operationId, - ], - changesetAuthor: "tester", - generatedSql: ["select sql here"], - changesetBody: "{ body }" - ) - service.sendOperationChangeEvent(event) - - def seenRequestBody = mockHttpClient.getRequestBody("POST /api/v1/organizations/$orgId/projects/$projectId/operations/$operationId/change-events") + def seenRequestBody + + Scope.child([(HubConfiguration.LIQUIBASE_HUB_MODE.getKey()): mode], { + + def mockHttpClient = new MockHttpClient([ + "GET /api/v1/organizations" : MockHttpClient.createListResponse([ + id : orgId.toString(), + name: "Mock Org" + ]), + ("POST /api/v1/organizations/$orgId/projects/$projectId/operations/$operationId/change-events" as String): null, + ]) + + def service = new StandardHubService( + http: mockHttpClient + ) + + def event = new OperationChangeEvent( + eventType: "update", + changesetId: "1", + project: [ + id: projectId, + ], + operation: [ + id: operationId, + ], + changesetAuthor: "tester", + generatedSql: ["select sql here"], + changesetBody: "{ body }" + ) + service.sendOperationChangeEvent(event) + + seenRequestBody = mockHttpClient.getRequestBody("POST /api/v1/organizations/$orgId/projects/$projectId/operations/$operationId/change-events") + } as Scope.ScopedRunner) then: seenRequestBody.changesetBody == (mode == "meta" ? null : "{ body }") diff --git a/liquibase-core/src/test/groovy/liquibase/parser/core/formattedsql/FormattedSqlChangeLogParserTest.groovy b/liquibase-core/src/test/groovy/liquibase/parser/core/formattedsql/FormattedSqlChangeLogParserTest.groovy index 5a15fdd4d61..a0570a70b40 100644 --- a/liquibase-core/src/test/groovy/liquibase/parser/core/formattedsql/FormattedSqlChangeLogParserTest.groovy +++ b/liquibase-core/src/test/groovy/liquibase/parser/core/formattedsql/FormattedSqlChangeLogParserTest.groovy @@ -90,14 +90,6 @@ select 1 "select 1;" - def setup() { - LiquibaseConfiguration.getInstance().reset() - } - - def cleanup() { - LiquibaseConfiguration.getInstance().reset() - } - def supports() throws Exception { expect: assert new MockFormattedSqlChangeLogParser(VALID_CHANGELOG).supports("asdf.sql", new JUnitResourceAccessor()) diff --git a/liquibase-core/src/test/groovy/liquibase/parser/core/xml/XMLChangeLogSAXParser_RealFile_Test.groovy b/liquibase-core/src/test/groovy/liquibase/parser/core/xml/XMLChangeLogSAXParser_RealFile_Test.groovy index 1e05d0092cb..cbe9584a23d 100644 --- a/liquibase-core/src/test/groovy/liquibase/parser/core/xml/XMLChangeLogSAXParser_RealFile_Test.groovy +++ b/liquibase-core/src/test/groovy/liquibase/parser/core/xml/XMLChangeLogSAXParser_RealFile_Test.groovy @@ -43,10 +43,6 @@ public class XMLChangeLogSAXParser_RealFile_Test extends Specification { @Shared resourceSupplier = new ResourceSupplier() - def before() { - LiquibaseConfiguration.getInstance().reset(); - } - def "namespace configured correctly"() { expect: assert new XMLChangeLogSAXParser().saxParserFactory.isNamespaceAware() diff --git a/liquibase-core/src/test/groovy/liquibase/sqlgenerator/core/CreateProcedureGeneratorTest.groovy b/liquibase-core/src/test/groovy/liquibase/sqlgenerator/core/CreateProcedureGeneratorTest.groovy index b33962a95f8..4db63dad73c 100644 --- a/liquibase-core/src/test/groovy/liquibase/sqlgenerator/core/CreateProcedureGeneratorTest.groovy +++ b/liquibase-core/src/test/groovy/liquibase/sqlgenerator/core/CreateProcedureGeneratorTest.groovy @@ -1,11 +1,8 @@ package liquibase.sqlgenerator.core -import liquibase.configuration.LiquibaseConfiguration + import liquibase.database.core.MSSQLDatabase import liquibase.database.core.OracleDatabase -import liquibase.parser.ChangeLogParserCofiguration -import liquibase.sqlgenerator.SqlGeneratorFactory -import liquibase.statement.core.CreateProcedureStatement import spock.lang.Specification import spock.lang.Unroll diff --git a/liquibase-core/src/test/java/liquibase/changelog/ChangeLogParametersTest.java b/liquibase-core/src/test/java/liquibase/changelog/ChangeLogParametersTest.java index 3e8f137d13c..278d59b2e6a 100644 --- a/liquibase-core/src/test/java/liquibase/changelog/ChangeLogParametersTest.java +++ b/liquibase-core/src/test/java/liquibase/changelog/ChangeLogParametersTest.java @@ -3,9 +3,7 @@ import liquibase.ContextExpression; import liquibase.Contexts; import liquibase.Labels; -import liquibase.configuration.LiquibaseConfiguration; import liquibase.database.core.H2Database; -import org.junit.Before; import org.junit.Test; import static org.junit.Assert.assertEquals; @@ -14,11 +12,6 @@ public class ChangeLogParametersTest { - @Before - public void before() { - LiquibaseConfiguration.getInstance().reset(); - } - @Test public void setParameterValue_doubleSet() { ChangeLogParameters changeLogParameters = new ChangeLogParameters(); diff --git a/liquibase-core/src/test/java/liquibase/changelog/ExpressionExpanderTest.java b/liquibase-core/src/test/java/liquibase/changelog/ExpressionExpanderTest.java index cb3fc6330bd..f350c923ec2 100644 --- a/liquibase-core/src/test/java/liquibase/changelog/ExpressionExpanderTest.java +++ b/liquibase-core/src/test/java/liquibase/changelog/ExpressionExpanderTest.java @@ -1,21 +1,22 @@ package liquibase.changelog; -import liquibase.configuration.LiquibaseConfiguration; -import liquibase.parser.ChangeLogParserCofiguration; +import liquibase.Scope; +import liquibase.parser.ChangeLogParserConfiguration; import org.junit.Before; import org.junit.Test; +import java.util.Collections; + import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNull; public class ExpressionExpanderTest { - + private ChangeLogParameters.ExpressionExpander handler; private ChangeLogParameters changeLogParameters; @Before public void setup() { - LiquibaseConfiguration.getInstance().reset(); changeLogParameters = new ChangeLogParameters(); this.handler = new ChangeLogParameters.ExpressionExpander(changeLogParameters); } @@ -53,69 +54,80 @@ public void expandExpressions_nomatchExpression() { assertEquals("A string no expressions ${notset} set", handler.expandExpressions("A string no expressions ${notset} set", null)); assertEquals("A string no expressions ${notset.orParams} set", handler.expandExpressions("A string no expressions ${notset.orParams} set", null)); } - + @Test - public void expandExpressions_escapedSimple() { - LiquibaseConfiguration.getInstance().getConfiguration(ChangeLogParserCofiguration.class).setSupportPropertyEscaping(true); - this.handler = new ChangeLogParameters.ExpressionExpander(changeLogParameters); - - assertEquals("${user.name}", handler.expandExpressions("${:user.name}", null)); + public void expandExpressions_escapedSimple() throws Exception { + Scope.child(Collections.singletonMap(ChangeLogParserConfiguration.SUPPORT_PROPERTY_ESCAPING.getKey(), true), () -> { + this.handler = new ChangeLogParameters.ExpressionExpander(changeLogParameters); + + assertEquals("${user.name}", handler.expandExpressions("${:user.name}", null)); + }); } - + @Test - public void expandExpressions_escapedNonGreedy() { - LiquibaseConfiguration.getInstance().getConfiguration(ChangeLogParserCofiguration.class).setSupportPropertyEscaping(true); - this.handler = new ChangeLogParameters.ExpressionExpander(changeLogParameters); - - assertEquals("${user.name}${user.name}", handler.expandExpressions("${:user.name}${:user.name}", null)); + public void expandExpressions_escapedNonGreedy() throws Exception { + Scope.child(Collections.singletonMap(ChangeLogParserConfiguration.SUPPORT_PROPERTY_ESCAPING.getKey(), true), () -> { + + this.handler = new ChangeLogParameters.ExpressionExpander(changeLogParameters); + + assertEquals("${user.name}${user.name}", handler.expandExpressions("${:user.name}${:user.name}", null)); + }); } - + @Test - public void expandExpressions_escapedMultipleSimple() { - LiquibaseConfiguration.getInstance().getConfiguration(ChangeLogParserCofiguration.class).setSupportPropertyEscaping(true); - this.handler = new ChangeLogParameters.ExpressionExpander(changeLogParameters); - - assertEquals("${user.name} and ${user.name} are literals", - handler.expandExpressions("${:user.name} and ${:user.name} are literals", null)); + public void expandExpressions_escapedMultipleSimple() throws Exception { + Scope.child(Collections.singletonMap(ChangeLogParserConfiguration.SUPPORT_PROPERTY_ESCAPING.getKey(), true), () -> { + + this.handler = new ChangeLogParameters.ExpressionExpander(changeLogParameters); + + assertEquals("${user.name} and ${user.name} are literals", + handler.expandExpressions("${:user.name} and ${:user.name} are literals", null)); + }); } - + @Test - public void expandExpressions_escapedMultipleComplex() { - LiquibaseConfiguration.getInstance().getConfiguration(ChangeLogParserCofiguration.class).setSupportPropertyEscaping(true); - this.handler = new ChangeLogParameters.ExpressionExpander(changeLogParameters); - - assertEquals("${user.name} and ${user.name} are literals but this isn't: " + System.getProperty("user.name"), - handler.expandExpressions("${:user.name} and ${:user.name} are literals but this isn't: ${user.name}", null)); + public void expandExpressions_escapedMultipleComplex() throws Exception { + Scope.child(Collections.singletonMap(ChangeLogParserConfiguration.SUPPORT_PROPERTY_ESCAPING.getKey(), true), () -> { + this.handler = new ChangeLogParameters.ExpressionExpander(changeLogParameters); + + assertEquals("${user.name} and ${user.name} are literals but this isn't: " + System.getProperty("user.name"), + handler.expandExpressions("${:user.name} and ${:user.name} are literals but this isn't: ${user.name}", null)); + }); } - + @Test - public void expandExpressions_escapedBeforeVariable() { - LiquibaseConfiguration.getInstance().getConfiguration(ChangeLogParserCofiguration.class).setSupportPropertyEscaping(true); - this.handler = new ChangeLogParameters.ExpressionExpander(changeLogParameters); - - assertEquals("${user.name} is a literal, " + System.getProperty("user.name") + " is a variable", - handler.expandExpressions("${:user.name} is a literal, ${user.name} is a variable", null)); + public void expandExpressions_escapedBeforeVariable() throws Exception { + Scope.child(Collections.singletonMap(ChangeLogParserConfiguration.SUPPORT_PROPERTY_ESCAPING.getKey(), true), () -> { + + this.handler = new ChangeLogParameters.ExpressionExpander(changeLogParameters); + + assertEquals("${user.name} is a literal, " + System.getProperty("user.name") + " is a variable", + handler.expandExpressions("${:user.name} is a literal, ${user.name} is a variable", null)); + }); } - + @Test - public void expandExpressions_escapedAfterVariable() { - LiquibaseConfiguration.getInstance().getConfiguration(ChangeLogParserCofiguration.class).setSupportPropertyEscaping(true); - this.handler = new ChangeLogParameters.ExpressionExpander(changeLogParameters); - - assertEquals(System.getProperty("user.name") + " is a variable, ${user.name} is a literal", - handler.expandExpressions("${user.name} is a variable, ${:user.name} is a literal", null)); + public void expandExpressions_escapedAfterVariable() throws Exception { + Scope.child(Collections.singletonMap(ChangeLogParserConfiguration.SUPPORT_PROPERTY_ESCAPING.getKey(), true), () -> { + this.handler = new ChangeLogParameters.ExpressionExpander(changeLogParameters); + + assertEquals(System.getProperty("user.name") + " is a variable, ${user.name} is a literal", + handler.expandExpressions("${user.name} is a variable, ${:user.name} is a literal", null)); + }); } - + @Test - public void expandExpressions_escapedMultipleComplexVariant() { - changeLogParameters.set("a", "Value A"); - changeLogParameters.set("b", "Value B"); - - LiquibaseConfiguration.getInstance().getConfiguration(ChangeLogParserCofiguration.class).setSupportPropertyEscaping(true); - this.handler = new ChangeLogParameters.ExpressionExpander(changeLogParameters); - - assertEquals("Value A is a variable, ${a} and ${b} are literals but this isn't: Value B", - handler.expandExpressions("${a} is a variable, ${:a} and ${:b} are literals but this isn't: ${b}", null)); + public void expandExpressions_escapedMultipleComplexVariant() throws Exception { + changeLogParameters.set("a", "Value A"); + changeLogParameters.set("b", "Value B"); + + Scope.child(Collections.singletonMap(ChangeLogParserConfiguration.SUPPORT_PROPERTY_ESCAPING.getKey(), true), () -> { + + this.handler = new ChangeLogParameters.ExpressionExpander(changeLogParameters); + + assertEquals("Value A is a variable, ${a} and ${b} are literals but this isn't: Value B", + handler.expandExpressions("${a} is a variable, ${:a} and ${:b} are literals but this isn't: ${b}", null)); + }); } } diff --git a/liquibase-core/src/test/java/liquibase/configuration/ContextTest.java b/liquibase-core/src/test/java/liquibase/configuration/ContextTest.java deleted file mode 100644 index 9a9fdd47f7d..00000000000 --- a/liquibase-core/src/test/java/liquibase/configuration/ContextTest.java +++ /dev/null @@ -1,63 +0,0 @@ -package liquibase.configuration; - -import junit.framework.TestCase; -import liquibase.exception.UnexpectedLiquibaseException; -import org.junit.Before; -import org.junit.Test; - -import static junit.framework.TestCase.assertNull; -import static org.junit.Assert.assertEquals; - -public class ContextTest { - - private AbstractConfigurationContainer exampleConfiguration; - - @Before - public void before() { - System.clearProperty("liquibase.example.propertyBooleanNoDefault"); - System.clearProperty("liquibase.example.propertyBooleanDefaultFalse"); - System.clearProperty("liquibase.example.property.default.true"); - - exampleConfiguration = new ExampleContext(); - exampleConfiguration.init(new SystemPropertyProvider()); - } - - @Test - public void getValue() { - assertNull(exampleConfiguration.getContainer().getValue("propertyBooleanNoDefault", Boolean.class)); - assertEquals(Boolean.TRUE, exampleConfiguration.getContainer().getValue("propertyBooleanDefaultTrue", Boolean.class)); - assertEquals(Boolean.FALSE, exampleConfiguration.getContainer().getValue("propertyBooleanDefaultFalse", Boolean.class)); - - } - - @Test(expected = IllegalArgumentException.class) - public void setValue_wrongType() { - exampleConfiguration.getContainer().setValue("propertyIntegerDefaultOne", "a"); - } - - @Test - public void getValue_defaultFromSystemProperties() { - System.setProperty("liquibase.example.propertyBooleanNoDefault", "true"); - System.setProperty("liquibase.example.propertyBooleanDefaultFalse", "true"); - System.setProperty("liquibase.example.property.default.true", "false"); - ExampleContext exampleContext = new ExampleContext(); - exampleContext.init(new SystemPropertyProvider()); - - TestCase.assertEquals(Boolean.TRUE, exampleContext.getContainer().getValue("propertyBooleanNoDefault", Boolean.class)); - TestCase.assertEquals(Boolean.TRUE, exampleContext.getContainer().getValue("propertyBooleanDefaultFalse", Boolean.class)); - TestCase.assertEquals(Boolean.FALSE, exampleContext.getContainer().getValue("propertyBooleanDefaultTrue", Boolean.class)); - } - - private static class ExampleContext extends AbstractConfigurationContainer { - private ExampleContext() { - super("liquibase.example"); - - getContainer().addProperty("propertyBooleanNoDefault", Boolean.class).setDescription("An example boolean property with no default"); - getContainer().addProperty("propertyBooleanDefaultTrue", Boolean.class).setDefaultValue(true).addAlias("property.default.true"); - getContainer().addProperty("propertyBooleanDefaultFalse", Boolean.class).setDefaultValue(false); - getContainer().addProperty("propertyIntegerDefaultOne", Integer.class).setDefaultValue(1); - } - } - - -} diff --git a/liquibase-core/src/test/java/liquibase/configuration/LiquibaseConfigurationTest.java b/liquibase-core/src/test/java/liquibase/configuration/LiquibaseConfigurationTest.java deleted file mode 100644 index 85b6382c71f..00000000000 --- a/liquibase-core/src/test/java/liquibase/configuration/LiquibaseConfigurationTest.java +++ /dev/null @@ -1,20 +0,0 @@ -package liquibase.configuration; - -import org.junit.Assert; -import org.junit.Test; - -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertSame; - -public class LiquibaseConfigurationTest { - - @Test - public void getContext_defaultSetup() { - LiquibaseConfiguration liquibaseConfiguration = LiquibaseConfiguration.getInstance(); - GlobalConfiguration globalConfiguration = liquibaseConfiguration.getConfiguration(GlobalConfiguration.class); - - assertNotNull(globalConfiguration); - - assertSame("Multiple calls to getConfiguration should return the same instance", globalConfiguration, liquibaseConfiguration.getConfiguration(GlobalConfiguration.class)); - } -} diff --git a/liquibase-core/src/test/java/liquibase/datatype/ClobTypeTest.java b/liquibase-core/src/test/java/liquibase/datatype/ClobTypeTest.java index 8842f49b09b..084307f0fee 100644 --- a/liquibase-core/src/test/java/liquibase/datatype/ClobTypeTest.java +++ b/liquibase-core/src/test/java/liquibase/datatype/ClobTypeTest.java @@ -1,101 +1,72 @@ package liquibase.datatype; -import liquibase.configuration.GlobalConfiguration; -import liquibase.configuration.LiquibaseConfiguration; +import liquibase.Scope; +import liquibase.GlobalConfiguration; import liquibase.database.core.MSSQLDatabase; import liquibase.datatype.core.ClobType; -import org.junit.After; -import org.junit.Before; import org.junit.Test; import static org.junit.Assert.assertEquals; public class ClobTypeTest { - @Before - public void prepare() { - LiquibaseConfiguration.getInstance().reset(); - } - - @After - public void reset() { - LiquibaseConfiguration.getInstance().reset(); - } @Test - public void mssqlTextToVarcharTest() { - LiquibaseConfiguration.getInstance() - .getConfiguration(GlobalConfiguration.class) - .getProperty(GlobalConfiguration.CONVERT_DATA_TYPES) - .setValue(Boolean.TRUE); - - ClobType ct = new ClobType(); - ct.finishInitialization("Text"); - DatabaseDataType dbType = ct.toDatabaseDataType(new MSSQLDatabase()); - assertEquals("varchar (max)", dbType.getType()); + public void mssqlTextToVarcharTest() throws Exception { + Scope.child(GlobalConfiguration.CONVERT_DATA_TYPES.getKey(), true, () -> { + ClobType ct = new ClobType(); + ct.finishInitialization("Text"); + DatabaseDataType dbType = ct.toDatabaseDataType(new MSSQLDatabase()); + assertEquals("varchar (max)", dbType.getType()); + }); } @Test - public void mssqlEscapedTextToVarcharTest() { - LiquibaseConfiguration.getInstance() - .getConfiguration(GlobalConfiguration.class) - .getProperty(GlobalConfiguration.CONVERT_DATA_TYPES) - .setValue(Boolean.TRUE); - - ClobType ct = new ClobType(); - ct.finishInitialization("[Text]"); - DatabaseDataType dbType = ct.toDatabaseDataType(new MSSQLDatabase()); - assertEquals("varchar (max)", dbType.getType()); + public void mssqlEscapedTextToVarcharTest() throws Exception { + Scope.child(GlobalConfiguration.CONVERT_DATA_TYPES.getKey(), true, () -> { + ClobType ct = new ClobType(); + ct.finishInitialization("[Text]"); + DatabaseDataType dbType = ct.toDatabaseDataType(new MSSQLDatabase()); + assertEquals("varchar (max)", dbType.getType()); + }); } @Test - public void mssqlTextToVarcharNoConvertTest() { - LiquibaseConfiguration.getInstance() - .getConfiguration(GlobalConfiguration.class) - .getProperty(GlobalConfiguration.CONVERT_DATA_TYPES) - .setValue(Boolean.FALSE); - - ClobType ct = new ClobType(); - ct.finishInitialization("Text"); - DatabaseDataType dbType = ct.toDatabaseDataType(new MSSQLDatabase()); - assertEquals("varchar (max)", dbType.getType()); + public void mssqlTextToVarcharNoConvertTest() throws Exception { + Scope.child(GlobalConfiguration.CONVERT_DATA_TYPES.getKey(), false, () -> { + ClobType ct = new ClobType(); + ct.finishInitialization("Text"); + DatabaseDataType dbType = ct.toDatabaseDataType(new MSSQLDatabase()); + assertEquals("varchar (max)", dbType.getType()); + }); } @Test - public void mssqlNTextToNVarcharNoConvertTest() { - LiquibaseConfiguration.getInstance() - .getConfiguration(GlobalConfiguration.class) - .getProperty(GlobalConfiguration.CONVERT_DATA_TYPES) - .setValue(Boolean.FALSE); - - ClobType ct = new ClobType(); - ct.finishInitialization("NText"); - DatabaseDataType dbType = ct.toDatabaseDataType(new MSSQLDatabase()); - assertEquals("nvarchar (max)", dbType.getType()); + public void mssqlNTextToNVarcharNoConvertTest() throws Exception { + Scope.child(GlobalConfiguration.CONVERT_DATA_TYPES.getKey(), false, () -> { + ClobType ct = new ClobType(); + ct.finishInitialization("NText"); + DatabaseDataType dbType = ct.toDatabaseDataType(new MSSQLDatabase()); + assertEquals("nvarchar (max)", dbType.getType()); + }); } @Test - public void mssqlEscapedTextToVarcharNoConvertTest() { - LiquibaseConfiguration.getInstance() - .getConfiguration(GlobalConfiguration.class) - .getProperty(GlobalConfiguration.CONVERT_DATA_TYPES) - .setValue(Boolean.FALSE); - - ClobType ct = new ClobType(); - ct.finishInitialization("[Text]"); - DatabaseDataType dbType = ct.toDatabaseDataType(new MSSQLDatabase()); - assertEquals("varchar (max)", dbType.getType()); + public void mssqlEscapedTextToVarcharNoConvertTest() throws Exception { + Scope.child(GlobalConfiguration.CONVERT_DATA_TYPES.getKey(), false, () -> { + ClobType ct = new ClobType(); + ct.finishInitialization("[Text]"); + DatabaseDataType dbType = ct.toDatabaseDataType(new MSSQLDatabase()); + assertEquals("varchar (max)", dbType.getType()); + }); } @Test - public void mssqlEscapedNTextToNVarcharNoConvertTest() { - LiquibaseConfiguration.getInstance() - .getConfiguration(GlobalConfiguration.class) - .getProperty(GlobalConfiguration.CONVERT_DATA_TYPES) - .setValue(Boolean.FALSE); - - ClobType ct = new ClobType(); - ct.finishInitialization("[NText]"); - DatabaseDataType dbType = ct.toDatabaseDataType(new MSSQLDatabase()); - assertEquals("nvarchar (max)", dbType.getType()); + public void mssqlEscapedNTextToNVarcharNoConvertTest() throws Exception { + Scope.child(GlobalConfiguration.CONVERT_DATA_TYPES.getKey(), false, () -> { + ClobType ct = new ClobType(); + ct.finishInitialization("[NText]"); + DatabaseDataType dbType = ct.toDatabaseDataType(new MSSQLDatabase()); + assertEquals("nvarchar (max)", dbType.getType()); + }); } } diff --git a/liquibase-core/src/test/java/liquibase/integration/ant/AbstractAntTaskTest.java b/liquibase-core/src/test/java/liquibase/integration/ant/AbstractAntTaskTest.java index f119e0ea8fa..b6e32cf4c88 100644 --- a/liquibase-core/src/test/java/liquibase/integration/ant/AbstractAntTaskTest.java +++ b/liquibase-core/src/test/java/liquibase/integration/ant/AbstractAntTaskTest.java @@ -2,8 +2,7 @@ import liquibase.Scope; import liquibase.TestScopeManager; -import liquibase.configuration.GlobalConfiguration; -import liquibase.configuration.LiquibaseConfiguration; +import liquibase.GlobalConfiguration; import org.junit.BeforeClass; import java.io.UnsupportedEncodingException; @@ -22,7 +21,7 @@ protected static void setProperties() { final String resourceName = "/" + name.replace('.', '/') + ".class"; String absoluteFilePath = BaseLiquibaseTask.class.getResource(resourceName).getFile(); try { - absoluteFilePath = URLDecoder.decode(absoluteFilePath, LiquibaseConfiguration.getInstance().getConfiguration(GlobalConfiguration.class).getOutputEncoding()); + absoluteFilePath = URLDecoder.decode(absoluteFilePath, GlobalConfiguration.OUTPUT_ENCODING.getCurrentValue()); } catch (UnsupportedEncodingException e) { throw new RuntimeException("Missing UTF-8 encoding in JVM.", e); } @@ -35,7 +34,7 @@ protected static void setProperties() { final String testResourceName = "/" + testClassName.replace('.', '/') + ".class"; String testAbsoluteFilePath = AbstractAntTaskTest.class.getResource(testResourceName).getFile(); try { - testAbsoluteFilePath = URLDecoder.decode(testAbsoluteFilePath, LiquibaseConfiguration.getInstance().getConfiguration(GlobalConfiguration.class).getOutputEncoding()); + testAbsoluteFilePath = URLDecoder.decode(testAbsoluteFilePath, GlobalConfiguration.OUTPUT_ENCODING.getCurrentValue()); } catch (UnsupportedEncodingException e) { throw new RuntimeException("Missing UTF-8 encoding in JVM.", e); } diff --git a/liquibase-core/src/test/java/liquibase/integration/commandline/MainTest.java b/liquibase-core/src/test/java/liquibase/integration/commandline/MainTest.java old mode 100755 new mode 100644 index 3a40da1e757..34351daa804 --- a/liquibase-core/src/test/java/liquibase/integration/commandline/MainTest.java +++ b/liquibase-core/src/test/java/liquibase/integration/commandline/MainTest.java @@ -1,12 +1,14 @@ package liquibase.integration.commandline; -import liquibase.configuration.GlobalConfiguration; -import liquibase.configuration.LiquibaseConfiguration; +import liquibase.GlobalConfiguration; +import liquibase.Scope; import liquibase.exception.CommandLineParsingException; +import liquibase.parser.ChangeLogParserConfiguration; import liquibase.util.StringUtil; import org.junit.Assert; import org.junit.Test; +import java.util.Collections; import java.util.Properties; import java.util.Arrays; import java.util.List; @@ -85,7 +87,7 @@ public MainTest() throws Exception { // snapshotCommandResult = PowerMockito.mock(SnapshotCommand.SnapshotCommandResult.class); // // // Do not do actual database snapshots. -// when(CommandFactory.getInstance()).thenReturn(commandFactory); +// when(Scope.getCurrentScope().getSingleton(CommandFactory.class)).thenReturn(commandFactory); // when(commandFactory.getCommand("snapshot")).thenReturn(snapshotCommand); // when(snapshotCommand.execute()).thenReturn(snapshotCommandResult); // when(snapshotCommandResult.print()).thenReturn("<?xml version=\"1.0\" encoding=\"UTF-8\"?>..."); @@ -131,12 +133,11 @@ public void startWithoutParameters() throws Exception { @Test public void globalConfigurationSaysDoNotRun() throws Exception { - LiquibaseConfiguration.getInstance().getConfiguration(GlobalConfiguration.class) - .setValue("shouldRun", false); - int errorLevel = Main.run(new String[0]); - LiquibaseConfiguration.getInstance().getConfiguration(GlobalConfiguration.class) - .setValue("shouldRun", true); - assertEquals(errorLevel, 0); // If it SHOULD run, and we would call without parameters, we would get -1 + Scope.child(Collections.singletonMap(GlobalConfiguration.SHOULD_RUN.getKey(), false), () -> { + + int errorLevel = Main.run(new String[0]); + assertEquals(errorLevel, 0); // If it SHOULD run, and we would call without parameters, we would get -1 + }); } // @Test diff --git a/liquibase-core/src/test/java/liquibase/integration/servlet/LiquibaseServletListenerTest.java b/liquibase-core/src/test/java/liquibase/integration/servlet/LiquibaseServletListenerTest.java index 12e3003b463..9641915db04 100644 --- a/liquibase-core/src/test/java/liquibase/integration/servlet/LiquibaseServletListenerTest.java +++ b/liquibase-core/src/test/java/liquibase/integration/servlet/LiquibaseServletListenerTest.java @@ -69,6 +69,9 @@ public void setUp() throws Exception { } public void testShouldNotShutEmbeddedDerbyDown() throws Exception { + if (dataSource == null) { + return; + } try (Connection pooled = dataSource.getConnection()) { servletListener.contextInitialized(new ServletContextEvent(servletContext)); assertEquals("connection.closed", false, pooled.isClosed()); diff --git a/liquibase-integration-tests/src/test/groovy/liquibase/hub/StandardHubServiceTest.groovy b/liquibase-integration-tests/src/test/groovy/liquibase/hub/StandardHubServiceTest.groovy index 960f1b8e56d..a23ff624f97 100644 --- a/liquibase-integration-tests/src/test/groovy/liquibase/hub/StandardHubServiceTest.groovy +++ b/liquibase-integration-tests/src/test/groovy/liquibase/hub/StandardHubServiceTest.groovy @@ -1,6 +1,6 @@ package liquibase.hub -import liquibase.configuration.HubConfiguration +import liquibase.Scope import liquibase.configuration.LiquibaseConfiguration import liquibase.hub.core.StandardHubService import liquibase.hub.model.Connection @@ -17,6 +17,8 @@ class StandardHubServiceTest extends Specification { private UUID knownProjectId = UUID.fromString("ce1a237e-e005-4288-a243-4856823a25a6") private UUID knownConnectionId = UUID.fromString("d92e6505-cd0f-4e91-bb66-b12e6a285184") + private String testScopeId + def setup() { if (integrationTestProperties == null) { integrationTestProperties = new Properties() @@ -27,11 +29,10 @@ class StandardHubServiceTest extends Specification { integrationTestProperties.load(localFileStream) } - def hubApiKey = integrationTestProperties.get("integration.test.hub.apikey") - def hubUrl = integrationTestProperties.get("integration.test.hub.url") - HubConfiguration hubConfiguration = LiquibaseConfiguration.getInstance().getConfiguration(HubConfiguration.class) - hubConfiguration.setLiquibaseHubApiKey(hubApiKey) - hubConfiguration.setLiquibaseHubUrl(hubUrl) + testScopeId = Scope.enter([ + (HubConfiguration.LIQUIBASE_HUB_API_KEY.getKey()):integrationTestProperties.get("integration.test.hub.apikey"), + (HubConfiguration.LIQUIBASE_HUB_URL.getKey()):integrationTestProperties.get("integration.test.hub.url"), + ]) } @@ -39,6 +40,10 @@ class StandardHubServiceTest extends Specification { assumeTrue("Liquibase Hub is not available for testing", hubService.isHubAvailable()) } + def cleanup() { + Scope.exit(testScopeId) + } + def getMe() { when: def hubUser = integrationTestProperties.get("integration.test.hub.userName") diff --git a/liquibase-integration-tests/src/test/java/liquibase/dbtest/AbstractIntegrationTest.java b/liquibase-integration-tests/src/test/java/liquibase/dbtest/AbstractIntegrationTest.java index 4d4c74b795a..d6267500940 100644 --- a/liquibase-integration-tests/src/test/java/liquibase/dbtest/AbstractIntegrationTest.java +++ b/liquibase-integration-tests/src/test/java/liquibase/dbtest/AbstractIntegrationTest.java @@ -3,8 +3,6 @@ import liquibase.*; import liquibase.changelog.ChangeLogHistoryServiceFactory; import liquibase.changelog.ChangeSet; -import liquibase.configuration.HubConfiguration; -import liquibase.configuration.LiquibaseConfiguration; import liquibase.database.Database; import liquibase.database.DatabaseConnection; import liquibase.database.DatabaseFactory; @@ -24,6 +22,7 @@ import liquibase.exception.ValidationFailedException; import liquibase.executor.Executor; import liquibase.executor.ExecutorService; +import liquibase.hub.HubConfiguration; import liquibase.listener.SqlListener; import liquibase.lockservice.LockService; import liquibase.lockservice.LockServiceFactory; @@ -130,11 +129,9 @@ protected AbstractIntegrationTest(String changelogDir, Database dbms) throws Exc String testHubApiKey = integrationTestProperties.getProperty("integration.test.hub.apiKey"); if (testHubApiKey != null) { - HubConfiguration hubConfiguration = - LiquibaseConfiguration.getInstance().getConfiguration(HubConfiguration.class); - hubConfiguration.setLiquibaseHubApiKey(testHubApiKey); + System.setProperty(HubConfiguration.LIQUIBASE_HUB_API_KEY.getKey(), testHubApiKey); String testHubUrl = integrationTestProperties.getProperty("integration.test.hub.url"); - hubConfiguration.setLiquibaseHubUrl(testHubUrl); + System.setProperty(HubConfiguration.LIQUIBASE_HUB_URL.getKey(), testHubUrl); } Scope.setScopeManager(new TestScopeManager()); } diff --git a/liquibase-maven-plugin/src/main/java/org/liquibase/maven/plugins/AbstractLiquibaseChangeLogMojo.java b/liquibase-maven-plugin/src/main/java/org/liquibase/maven/plugins/AbstractLiquibaseChangeLogMojo.java index 843768de7e3..8b8175dc07a 100644 --- a/liquibase-maven-plugin/src/main/java/org/liquibase/maven/plugins/AbstractLiquibaseChangeLogMojo.java +++ b/liquibase-maven-plugin/src/main/java/org/liquibase/maven/plugins/AbstractLiquibaseChangeLogMojo.java @@ -4,10 +4,10 @@ import liquibase.Liquibase; import liquibase.Scope; -import liquibase.configuration.HubConfiguration; -import liquibase.configuration.LiquibaseConfiguration; +import liquibase.configuration.core.DeprecatedConfigurationValueProvider; import liquibase.database.Database; import liquibase.exception.LiquibaseException; +import liquibase.hub.HubConfiguration; import liquibase.resource.ClassLoaderResourceAccessor; import liquibase.resource.CompositeResourceAccessor; import liquibase.resource.FileSystemResourceAccessor; @@ -108,15 +108,14 @@ protected void performLiquibaseTask(Liquibase liquibase) throws LiquibaseExcepti // // Store the Hub API key and URL for later use // - HubConfiguration hubConfiguration = LiquibaseConfiguration.getInstance().getConfiguration(HubConfiguration.class); if (StringUtil.isNotEmpty(hubApiKey)) { - hubConfiguration.setLiquibaseHubApiKey(hubApiKey); + DeprecatedConfigurationValueProvider.setData(HubConfiguration.LIQUIBASE_HUB_API_KEY, hubApiKey); } if (StringUtil.isNotEmpty(hubUrl)) { - hubConfiguration.setLiquibaseHubUrl(hubUrl); + DeprecatedConfigurationValueProvider.setData(HubConfiguration.LIQUIBASE_HUB_URL.getKey(), hubUrl); } if (StringUtil.isNotEmpty(hubMode)) { - hubConfiguration.setLiquibaseHubMode(hubMode); + DeprecatedConfigurationValueProvider.setData(HubConfiguration.LIQUIBASE_HUB_MODE.getKey(), hubMode); } } diff --git a/liquibase-maven-plugin/src/main/java/org/liquibase/maven/plugins/AbstractLiquibaseMojo.java b/liquibase-maven-plugin/src/main/java/org/liquibase/maven/plugins/AbstractLiquibaseMojo.java index b4db3c4ae28..35ac3bfc354 100644 --- a/liquibase-maven-plugin/src/main/java/org/liquibase/maven/plugins/AbstractLiquibaseMojo.java +++ b/liquibase-maven-plugin/src/main/java/org/liquibase/maven/plugins/AbstractLiquibaseMojo.java @@ -2,8 +2,7 @@ import liquibase.Liquibase; import liquibase.Scope; -import liquibase.configuration.GlobalConfiguration; -import liquibase.configuration.LiquibaseConfiguration; +import liquibase.GlobalConfiguration; import liquibase.database.Database; import liquibase.exception.DatabaseException; import liquibase.exception.LiquibaseException; @@ -295,7 +294,7 @@ protected boolean hasProLicense() { protected Writer getOutputWriter(final File outputFile) throws IOException { if (outputFileEncoding == null) { getLog().info("Char encoding not set! The created file will be system dependent!"); - return new OutputStreamWriter(new FileOutputStream(outputFile), LiquibaseConfiguration.getInstance().getConfiguration(GlobalConfiguration.class).getOutputEncoding()); + return new OutputStreamWriter(new FileOutputStream(outputFile), GlobalConfiguration.OUTPUT_ENCODING.getCurrentValue()); } getLog().debug("Writing output file with [" + outputFileEncoding + "] file encoding."); return new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outputFile), outputFileEncoding)); @@ -318,11 +317,8 @@ public void execute() throws MojoExecutionException, MojoFailureException { processSystemProperties(); - LiquibaseConfiguration liquibaseConfiguration = LiquibaseConfiguration.getInstance(); - - if (!liquibaseConfiguration.getConfiguration(GlobalConfiguration.class).getShouldRun()) { - getLog().info("Liquibase did not run because " + liquibaseConfiguration.describeValueLookupLogic - (GlobalConfiguration.class, GlobalConfiguration.SHOULD_RUN) + " was set to false"); + if (!GlobalConfiguration.SHOULD_RUN.getCurrentValue()) { + getLog().info("Liquibase did not run because " + GlobalConfiguration.SHOULD_RUN.getKey() + " was set to false"); return; } if (skip) { diff --git a/liquibase-maven-plugin/src/main/java/org/liquibase/maven/plugins/LiquibaseDatabaseDiff.java b/liquibase-maven-plugin/src/main/java/org/liquibase/maven/plugins/LiquibaseDatabaseDiff.java index 7625201260d..555157a70d3 100644 --- a/liquibase-maven-plugin/src/main/java/org/liquibase/maven/plugins/LiquibaseDatabaseDiff.java +++ b/liquibase-maven-plugin/src/main/java/org/liquibase/maven/plugins/LiquibaseDatabaseDiff.java @@ -4,6 +4,7 @@ import liquibase.CatalogAndSchema; import liquibase.Liquibase; +import liquibase.Scope; import liquibase.command.*; import liquibase.command.core.DiffCommand; import liquibase.database.Database; @@ -249,7 +250,7 @@ protected void performLiquibaseTask(Liquibase liquibase) throws LiquibaseExcepti } else { PrintStream printStream = createPrintStream(); if (isFormattedDiff()) { - LiquibaseCommand liquibaseCommand = CommandFactory.getInstance().getCommand("formattedDiff"); + LiquibaseCommand liquibaseCommand = Scope.getCurrentScope().getSingleton(CommandFactory.class).getCommand("formattedDiff"); DiffCommand diffCommand = CommandLineUtils.createDiffCommand(referenceDatabase, db, StringUtil.trimToNull(diffTypes), schemaComparisons, objectChangeFilter, printStream); @@ -258,7 +259,7 @@ protected void performLiquibaseTask(Liquibase liquibase) throws LiquibaseExcepti argsMap.put("diffCommand", diffCommand); ((AbstractSelfConfiguratingCommand) liquibaseCommand).configure(argsMap); try { - CommandResult result = liquibaseCommand.execute(); + CommandResult result = Scope.getCurrentScope().getSingleton(CommandFactory.class).execute(liquibaseCommand); if (!result.succeeded) { throw new LiquibaseException(result.message); } diff --git a/liquibase-maven-plugin/src/main/java/org/liquibase/maven/plugins/LiquibaseDeactivateChangeLogMojo.java b/liquibase-maven-plugin/src/main/java/org/liquibase/maven/plugins/LiquibaseDeactivateChangeLogMojo.java index 9745317bbfa..bdf960fe1b1 100644 --- a/liquibase-maven-plugin/src/main/java/org/liquibase/maven/plugins/LiquibaseDeactivateChangeLogMojo.java +++ b/liquibase-maven-plugin/src/main/java/org/liquibase/maven/plugins/LiquibaseDeactivateChangeLogMojo.java @@ -30,8 +30,7 @@ protected void performLiquibaseTask(Liquibase liquibase) throws LiquibaseException { super.performLiquibaseTask(liquibase); Database database = liquibase.getDatabase(); - DeactivateChangeLogCommand deactivateChangeLogCommand = - (DeactivateChangeLogCommand) CommandFactory.getInstance().getCommand("deactivateChangeLog"); + DeactivateChangeLogCommand deactivateChangeLogCommand = (DeactivateChangeLogCommand) Scope.getCurrentScope().getSingleton(CommandFactory.class).getCommand("deactivateChangeLog"); deactivateChangeLogCommand.setChangeLogFile(changeLogFile); Map<String, Object> argsMap = new HashMap<>(); argsMap.put("changeLogFile", changeLogFile); @@ -40,7 +39,7 @@ protected void performLiquibaseTask(Liquibase liquibase) argsMap.put("changeLog", liquibase.getDatabaseChangeLog()); deactivateChangeLogCommand.configure(argsMap); try { - CommandResult result = deactivateChangeLogCommand.execute(); + CommandResult result = Scope.getCurrentScope().getSingleton(CommandFactory.class).execute(deactivateChangeLogCommand); if (result.succeeded) { Scope.getCurrentScope().getUI().sendMessage(result.print()); } else { diff --git a/liquibase-maven-plugin/src/main/java/org/liquibase/maven/plugins/LiquibaseDropAll.java b/liquibase-maven-plugin/src/main/java/org/liquibase/maven/plugins/LiquibaseDropAll.java index 1a81afbbb06..8e56fae897a 100644 --- a/liquibase-maven-plugin/src/main/java/org/liquibase/maven/plugins/LiquibaseDropAll.java +++ b/liquibase-maven-plugin/src/main/java/org/liquibase/maven/plugins/LiquibaseDropAll.java @@ -2,10 +2,8 @@ import liquibase.CatalogAndSchema; import liquibase.Liquibase; -import liquibase.configuration.HubConfiguration; -import liquibase.configuration.LiquibaseConfiguration; +import liquibase.hub.HubConfiguration; import liquibase.exception.LiquibaseException; -import liquibase.exception.UnexpectedLiquibaseException; import org.apache.maven.plugin.MojoFailureException; import java.util.ArrayList; @@ -45,9 +43,8 @@ protected void checkRequiredParametersAreSpecified() throws MojoFailureException // // Override because changeLogFile is not required // - HubConfiguration hubConfiguration = LiquibaseConfiguration.getInstance().getConfiguration(HubConfiguration.class); - String liquibaseHubApiKey = hubConfiguration.getLiquibaseHubApiKey(); - String hubMode = hubConfiguration.getLiquibaseHubMode(); + String liquibaseHubApiKey = HubConfiguration.LIQUIBASE_HUB_API_KEY.getCurrentValue(); + String hubMode = HubConfiguration.LIQUIBASE_HUB_MODE.getCurrentValue(); if (liquibaseHubApiKey != null && ! hubMode.toLowerCase().equals("off")) { if (hubConnectionId == null && changeLogFile == null) { String errorMessage = diff --git a/liquibase-maven-plugin/src/main/java/org/liquibase/maven/plugins/LiquibaseGenerateChangeLogMojo.java b/liquibase-maven-plugin/src/main/java/org/liquibase/maven/plugins/LiquibaseGenerateChangeLogMojo.java index 2f46f1f527e..ff0e5aa43d9 100644 --- a/liquibase-maven-plugin/src/main/java/org/liquibase/maven/plugins/LiquibaseGenerateChangeLogMojo.java +++ b/liquibase-maven-plugin/src/main/java/org/liquibase/maven/plugins/LiquibaseGenerateChangeLogMojo.java @@ -1,8 +1,8 @@ package org.liquibase.maven.plugins; +import liquibase.GlobalConfiguration; import liquibase.Liquibase; -import liquibase.configuration.GlobalConfiguration; -import liquibase.configuration.LiquibaseConfiguration; +import liquibase.Scope; import liquibase.database.Database; import liquibase.diff.output.DiffOutputControl; import liquibase.diff.output.StandardObjectChangeFilter; @@ -13,9 +13,6 @@ import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugin.MojoFailureException; -import javax.xml.parsers.ParserConfigurationException; -import java.io.IOException; - /** * <p>Generates a changelog based on the current database schema. Typically used when * beginning to use Liquibase on an existing project and database schema.</p> @@ -117,13 +114,12 @@ protected void performLiquibaseTask(Liquibase liquibase) // Set the global configuration option based on presence of the dataOutputDirectory // boolean b = dataDir != null; - LiquibaseConfiguration.getInstance().getConfiguration(GlobalConfiguration.class).setShouldSnapshotData(b); - - CommandLineUtils.doGenerateChangeLog(outputChangeLogFile, database, defaultCatalogName, defaultSchemaName, StringUtil.trimToNull(diffTypes), - StringUtil.trimToNull(changeSetAuthor), StringUtil.trimToNull(changeSetContext), StringUtil.trimToNull(dataDir), diffOutputControl); - getLog().info("Output written to Change Log file, " + outputChangeLogFile); - } - catch (IOException | ParserConfigurationException e) { + Scope.child(GlobalConfiguration.SHOULD_SNAPSHOT_DATA.getKey(), b, () -> { + CommandLineUtils.doGenerateChangeLog(outputChangeLogFile, database, defaultCatalogName, defaultSchemaName, StringUtil.trimToNull(diffTypes), + StringUtil.trimToNull(changeSetAuthor), StringUtil.trimToNull(changeSetContext), StringUtil.trimToNull(dataDir), diffOutputControl); + getLog().info("Output written to Change Log file, " + outputChangeLogFile); + }); + } catch (Exception e) { throw new LiquibaseException(e); } } diff --git a/liquibase-maven-plugin/src/main/java/org/liquibase/maven/plugins/LiquibaseHistoryMojo.java b/liquibase-maven-plugin/src/main/java/org/liquibase/maven/plugins/LiquibaseHistoryMojo.java index 812a768c921..4fe1eec0187 100644 --- a/liquibase-maven-plugin/src/main/java/org/liquibase/maven/plugins/LiquibaseHistoryMojo.java +++ b/liquibase-maven-plugin/src/main/java/org/liquibase/maven/plugins/LiquibaseHistoryMojo.java @@ -1,6 +1,7 @@ package org.liquibase.maven.plugins; import liquibase.Liquibase; +import liquibase.Scope; import liquibase.command.CommandExecutionException; import liquibase.command.CommandFactory; import liquibase.command.CommandResult; @@ -17,11 +18,11 @@ public class LiquibaseHistoryMojo extends AbstractLiquibaseMojo { @Override protected void performLiquibaseTask(Liquibase liquibase) throws LiquibaseException { - HistoryCommand historyCommand = (HistoryCommand) CommandFactory.getInstance().getCommand("history"); + HistoryCommand historyCommand = (HistoryCommand) Scope.getCurrentScope().getSingleton(CommandFactory.class).getCommand("history"); historyCommand.setDatabase(getLiquibase().getDatabase()); try { - CommandResult result = historyCommand.execute(); + CommandResult result = Scope.getCurrentScope().getSingleton(CommandFactory.class).execute(historyCommand); if (!result.succeeded) { throw new LiquibaseException(result.message); } diff --git a/liquibase-maven-plugin/src/main/java/org/liquibase/maven/plugins/LiquibaseRegisterChangeLogMojo.java b/liquibase-maven-plugin/src/main/java/org/liquibase/maven/plugins/LiquibaseRegisterChangeLogMojo.java index d9f0d29746a..ceaa636ebfe 100644 --- a/liquibase-maven-plugin/src/main/java/org/liquibase/maven/plugins/LiquibaseRegisterChangeLogMojo.java +++ b/liquibase-maven-plugin/src/main/java/org/liquibase/maven/plugins/LiquibaseRegisterChangeLogMojo.java @@ -59,7 +59,7 @@ protected void performLiquibaseTask(Liquibase liquibase) super.performLiquibaseTask(liquibase); Database database = liquibase.getDatabase(); RegisterChangeLogCommand registerChangeLog = - (RegisterChangeLogCommand) CommandFactory.getInstance().getCommand("registerChangeLog"); + (RegisterChangeLogCommand) Scope.getCurrentScope().getSingleton(CommandFactory.class).getCommand("registerChangeLog"); registerChangeLog.setChangeLogFile(changeLogFile); if (hubProjectId != null) { registerChangeLog.setHubProjectId(UUID.fromString(hubProjectId)); @@ -72,7 +72,7 @@ protected void performLiquibaseTask(Liquibase liquibase) argsMap.put("changeLog", liquibase.getDatabaseChangeLog()); registerChangeLog.configure(argsMap); try { - CommandResult result = registerChangeLog.execute(); + CommandResult result = Scope.getCurrentScope().getSingleton(CommandFactory.class).execute(registerChangeLog); if (result.succeeded) { Scope.getCurrentScope().getUI().sendMessage(result.print()); } else { diff --git a/liquibase-maven-plugin/src/main/java/org/liquibase/maven/plugins/LiquibaseReportStatusMojo.java b/liquibase-maven-plugin/src/main/java/org/liquibase/maven/plugins/LiquibaseReportStatusMojo.java index 2c59f167c53..9bb57b744df 100644 --- a/liquibase-maven-plugin/src/main/java/org/liquibase/maven/plugins/LiquibaseReportStatusMojo.java +++ b/liquibase-maven-plugin/src/main/java/org/liquibase/maven/plugins/LiquibaseReportStatusMojo.java @@ -3,8 +3,7 @@ import liquibase.Contexts; import liquibase.LabelExpression; import liquibase.Liquibase; -import liquibase.configuration.GlobalConfiguration; -import liquibase.configuration.LiquibaseConfiguration; +import liquibase.GlobalConfiguration; import liquibase.exception.LiquibaseException; import liquibase.exception.UnexpectedLiquibaseException; @@ -23,7 +22,7 @@ public class LiquibaseReportStatusMojo extends AbstractLiquibaseChangeLogMojo { protected void performLiquibaseTask(Liquibase liquibase) throws LiquibaseException { try { - liquibase.reportStatus(true, new Contexts(contexts), new LabelExpression(labels), new OutputStreamWriter(System.out, LiquibaseConfiguration.getInstance().getConfiguration(GlobalConfiguration.class).getOutputEncoding())); + liquibase.reportStatus(true, new Contexts(contexts), new LabelExpression(labels), new OutputStreamWriter(System.out, GlobalConfiguration.OUTPUT_ENCODING.getCurrentValue())); } catch (UnsupportedEncodingException e) { throw new UnexpectedLiquibaseException(e); } diff --git a/liquibase-maven-plugin/src/main/java/org/liquibase/maven/plugins/LiquibaseRollbackOneChangeSetMojo.java b/liquibase-maven-plugin/src/main/java/org/liquibase/maven/plugins/LiquibaseRollbackOneChangeSetMojo.java index 5cebc273c34..d4de3843cf8 100644 --- a/liquibase-maven-plugin/src/main/java/org/liquibase/maven/plugins/LiquibaseRollbackOneChangeSetMojo.java +++ b/liquibase-maven-plugin/src/main/java/org/liquibase/maven/plugins/LiquibaseRollbackOneChangeSetMojo.java @@ -1,6 +1,7 @@ package org.liquibase.maven.plugins; import liquibase.Liquibase; +import liquibase.Scope; import liquibase.changelog.ChangeLogParameters; import liquibase.command.*; import liquibase.database.Database; @@ -97,7 +98,7 @@ protected void performLiquibaseTask(Liquibase liquibase) throws LiquibaseExcepti "The command 'rollbackOneChangeSet' requires a Liquibase Pro License, available at http://www.liquibase.org/download or sales@liquibase.com."); } Database database = liquibase.getDatabase(); - LiquibaseCommand liquibaseCommand = (CommandFactory.getInstance().getCommand("rollbackOneChangeSet")); + LiquibaseCommand liquibaseCommand = (Scope.getCurrentScope().getSingleton(CommandFactory.class).getCommand("rollbackOneChangeSet")); AbstractSelfConfiguratingCommand configuratingCommand = (AbstractSelfConfiguratingCommand)liquibaseCommand; Map<String, Object> argsMap = getCommandArgsObjectMap(liquibase); ChangeLogParameters clp = new ChangeLogParameters(database); @@ -109,7 +110,7 @@ protected void performLiquibaseTask(Liquibase liquibase) throws LiquibaseExcepti argsMap.put("liquibase", liquibase); configuratingCommand.configure(argsMap); try { - final CommandResult execute = liquibaseCommand.execute(); + final CommandResult execute = Scope.getCurrentScope().getSingleton(CommandFactory.class).execute(liquibaseCommand); if (!execute.succeeded) { throw new LiquibaseException(execute.message); } diff --git a/liquibase-maven-plugin/src/main/java/org/liquibase/maven/plugins/LiquibaseRollbackOneChangeSetSQL.java b/liquibase-maven-plugin/src/main/java/org/liquibase/maven/plugins/LiquibaseRollbackOneChangeSetSQL.java index 7f6adc151da..458a8a7b40d 100644 --- a/liquibase-maven-plugin/src/main/java/org/liquibase/maven/plugins/LiquibaseRollbackOneChangeSetSQL.java +++ b/liquibase-maven-plugin/src/main/java/org/liquibase/maven/plugins/LiquibaseRollbackOneChangeSetSQL.java @@ -4,8 +4,7 @@ import liquibase.Scope; import liquibase.changelog.ChangeLogParameters; import liquibase.command.*; -import liquibase.configuration.GlobalConfiguration; -import liquibase.configuration.LiquibaseConfiguration; +import liquibase.GlobalConfiguration; import liquibase.database.Database; import liquibase.exception.LiquibaseException; import org.apache.maven.plugin.MojoExecutionException; @@ -106,7 +105,7 @@ protected void performLiquibaseTask(Liquibase liquibase) throws LiquibaseExcepti "The command 'rollbackOneChangeSetSQL' requires a Liquibase Pro License, available at http://www.liquibase.org/download or sales@liquibase.com."); } Database database = liquibase.getDatabase(); - LiquibaseCommand liquibaseCommand = (CommandFactory.getInstance().getCommand("rollbackOneChangeSet")); + LiquibaseCommand liquibaseCommand = (Scope.getCurrentScope().getSingleton(CommandFactory.class).getCommand("rollbackOneChangeSet")); AbstractSelfConfiguratingCommand configuratingCommand = (AbstractSelfConfiguratingCommand)liquibaseCommand; Map<String, Object> argsMap = getCommandArgsObjectMap(liquibase); ChangeLogParameters clp = new ChangeLogParameters(database); @@ -122,7 +121,7 @@ protected void performLiquibaseTask(Liquibase liquibase) throws LiquibaseExcepti argsMap.put("liquibase", liquibase); configuratingCommand.configure(argsMap); try { - CommandResult result = liquibaseCommand.execute(); + CommandResult result = Scope.getCurrentScope().getSingleton(CommandFactory.class).execute(liquibaseCommand); if (!result.succeeded) { throw new LiquibaseException(result.message); } @@ -163,8 +162,7 @@ private void closeOutputWriter(Writer outputWriter) throws IOException { } private Writer createOutputWriter() throws IOException { - String charsetName = LiquibaseConfiguration.getInstance().getConfiguration(GlobalConfiguration.class) - .getOutputEncoding(); + String charsetName = GlobalConfiguration.OUTPUT_ENCODING.getCurrentValue(); return new OutputStreamWriter(getOutputStream(), charsetName); } diff --git a/liquibase-maven-plugin/src/main/java/org/liquibase/maven/plugins/LiquibaseRollbackOneUpdateMojo.java b/liquibase-maven-plugin/src/main/java/org/liquibase/maven/plugins/LiquibaseRollbackOneUpdateMojo.java index 473f03f255f..504f4aff699 100644 --- a/liquibase-maven-plugin/src/main/java/org/liquibase/maven/plugins/LiquibaseRollbackOneUpdateMojo.java +++ b/liquibase-maven-plugin/src/main/java/org/liquibase/maven/plugins/LiquibaseRollbackOneUpdateMojo.java @@ -1,6 +1,7 @@ package org.liquibase.maven.plugins; import liquibase.Liquibase; +import liquibase.Scope; import liquibase.changelog.ChangeLogParameters; import liquibase.command.*; import liquibase.database.Database; @@ -63,7 +64,7 @@ protected void performLiquibaseTask(Liquibase liquibase) throws LiquibaseExcepti "The command 'rollbackOneUpdate' requires a Liquibase Pro License, available at http://www.liquibase.org/download or sales@liquibase.com."); } Database database = liquibase.getDatabase(); - LiquibaseCommand liquibaseCommand = (CommandFactory.getInstance().getCommand("rollbackOneUpdate")); + LiquibaseCommand liquibaseCommand = (Scope.getCurrentScope().getSingleton(CommandFactory.class).getCommand("rollbackOneUpdate")); AbstractSelfConfiguratingCommand configuratingCommand = (AbstractSelfConfiguratingCommand)liquibaseCommand; Map<String, Object> argsMap = getCommandArgsObjectMap(liquibase); ChangeLogParameters clp = new ChangeLogParameters(database); @@ -75,7 +76,7 @@ protected void performLiquibaseTask(Liquibase liquibase) throws LiquibaseExcepti argsMap.put("liquibase", liquibase); configuratingCommand.configure(argsMap); try { - CommandResult result = liquibaseCommand.execute(); + CommandResult result = Scope.getCurrentScope().getSingleton(CommandFactory.class).execute(liquibaseCommand); if (!result.succeeded) { throw new LiquibaseException(result.message); } } diff --git a/liquibase-maven-plugin/src/main/java/org/liquibase/maven/plugins/LiquibaseRollbackOneUpdateSQL.java b/liquibase-maven-plugin/src/main/java/org/liquibase/maven/plugins/LiquibaseRollbackOneUpdateSQL.java index 4e11c38ad34..c752bb9d33c 100644 --- a/liquibase-maven-plugin/src/main/java/org/liquibase/maven/plugins/LiquibaseRollbackOneUpdateSQL.java +++ b/liquibase-maven-plugin/src/main/java/org/liquibase/maven/plugins/LiquibaseRollbackOneUpdateSQL.java @@ -4,8 +4,7 @@ import liquibase.Scope; import liquibase.changelog.ChangeLogParameters; import liquibase.command.*; -import liquibase.configuration.GlobalConfiguration; -import liquibase.configuration.LiquibaseConfiguration; +import liquibase.GlobalConfiguration; import liquibase.database.Database; import liquibase.exception.LiquibaseException; import org.apache.maven.plugin.MojoExecutionException; @@ -75,7 +74,7 @@ protected void performLiquibaseTask(Liquibase liquibase) throws LiquibaseExcepti "The command 'rollbackOneUpdateSQL' requires a Liquibase Pro License, available at http://www.liquibase.org/download or sales@liquibase.com."); } Database database = liquibase.getDatabase(); - LiquibaseCommand liquibaseCommand = (CommandFactory.getInstance().getCommand("rollbackOneUpdate")); + LiquibaseCommand liquibaseCommand = (Scope.getCurrentScope().getSingleton(CommandFactory.class).getCommand("rollbackOneUpdate")); AbstractSelfConfiguratingCommand configuratingCommand = (AbstractSelfConfiguratingCommand)liquibaseCommand; Map<String, Object> argsMap = getCommandArgsObjectMap(liquibase); Writer outputWriter = null; @@ -95,7 +94,7 @@ protected void performLiquibaseTask(Liquibase liquibase) throws LiquibaseExcepti argsMap.put("liquibase", liquibase); configuratingCommand.configure(argsMap); try { - CommandResult result = liquibaseCommand.execute(); + CommandResult result = Scope.getCurrentScope().getSingleton(CommandFactory.class).execute(liquibaseCommand); if (!result.succeeded) { throw new LiquibaseException(result.message); } } @@ -121,8 +120,7 @@ private void closeOutputWriter(Writer outputWriter) throws IOException { } private Writer createOutputWriter() throws IOException { - String charsetName = LiquibaseConfiguration.getInstance().getConfiguration(GlobalConfiguration.class) - .getOutputEncoding(); + String charsetName = GlobalConfiguration.OUTPUT_ENCODING.getCurrentValue(); return new OutputStreamWriter(getOutputStream(), charsetName); } diff --git a/liquibase-maven-plugin/src/main/java/org/liquibase/maven/plugins/LiquibaseSyncHubMojo.java b/liquibase-maven-plugin/src/main/java/org/liquibase/maven/plugins/LiquibaseSyncHubMojo.java index c80dcd6fdd1..a3de70db402 100644 --- a/liquibase-maven-plugin/src/main/java/org/liquibase/maven/plugins/LiquibaseSyncHubMojo.java +++ b/liquibase-maven-plugin/src/main/java/org/liquibase/maven/plugins/LiquibaseSyncHubMojo.java @@ -3,6 +3,7 @@ import liquibase.Contexts; import liquibase.LabelExpression; import liquibase.Liquibase; +import liquibase.Scope; import liquibase.changelog.ChangeLogParameters; import liquibase.command.*; import liquibase.command.core.SyncHubCommand; @@ -53,7 +54,7 @@ protected void performLiquibaseTask(Liquibase liquibase) throws LiquibaseException { super.performLiquibaseTask(liquibase); Database database = liquibase.getDatabase(); - SyncHubCommand syncHub = (SyncHubCommand) CommandFactory.getInstance().getCommand("syncHub"); + SyncHubCommand syncHub = (SyncHubCommand) Scope.getCurrentScope().getSingleton(CommandFactory.class).getCommand("syncHub"); syncHub.setChangeLogFile(changeLogFile); syncHub.setUrl(database.getConnection().getURL()); syncHub.setHubConnectionId(hubConnectionId); @@ -61,7 +62,7 @@ protected void performLiquibaseTask(Liquibase liquibase) syncHub.setDatabase(database); syncHub.setFailIfOnline(false); try { - CommandResult result = syncHub.execute(); + CommandResult result = Scope.getCurrentScope().getSingleton(CommandFactory.class).execute(syncHub); if (!result.succeeded) { throw new LiquibaseException(result.message); } diff --git a/pom.xml b/pom.xml index 02b0a7dbaf3..06f7a24ed6c 100644 --- a/pom.xml +++ b/pom.xml @@ -16,6 +16,7 @@ <modules> <module>liquibase-core</module> + <module>liquibase-cli</module> <module>liquibase-maven-plugin</module> <module>liquibase-cdi</module> <module>liquibase-integration-tests</module>