From d9b7e4b8c28161c11d1bf938bad8be10a47e8cca Mon Sep 17 00:00:00 2001 From: Steven Massaro Date: Wed, 15 Jun 2022 08:58:31 -0400 Subject: [PATCH 01/10] make base license message public (DAT-10584) (#2941) --- .../src/main/java/liquibase/license/LicenseServiceUtils.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/liquibase-core/src/main/java/liquibase/license/LicenseServiceUtils.java b/liquibase-core/src/main/java/liquibase/license/LicenseServiceUtils.java index 9b183a2e2dd..3ac79191417 100644 --- a/liquibase-core/src/main/java/liquibase/license/LicenseServiceUtils.java +++ b/liquibase-core/src/main/java/liquibase/license/LicenseServiceUtils.java @@ -12,7 +12,7 @@ public class LicenseServiceUtils { public static final String TRIAL_LICENSE_URL = "https://liquibase.com/trial"; - private static final String BASE_INVALID_LICENSE_MESSAGE = "Using '%s' requires a valid Liquibase Pro or Labs license. Get a free license key at " + TRIAL_LICENSE_URL + "."; + public static final String BASE_INVALID_LICENSE_MESSAGE = "Using '%s' requires a valid Liquibase Pro or Labs license. Get a free license key at " + TRIAL_LICENSE_URL + "."; /** * Check for a Liquibase Pro License. From 6a76491053d9edf63b4139a96d7ff0354a1ae058 Mon Sep 17 00:00:00 2001 From: Steven Massaro Date: Thu, 16 Jun 2022 10:19:44 -0500 Subject: [PATCH 02/10] make BASE_INVALID_LICENSE_MESSAGE variable private --- .../src/main/java/liquibase/license/LicenseServiceUtils.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/liquibase-core/src/main/java/liquibase/license/LicenseServiceUtils.java b/liquibase-core/src/main/java/liquibase/license/LicenseServiceUtils.java index 3ac79191417..9b183a2e2dd 100644 --- a/liquibase-core/src/main/java/liquibase/license/LicenseServiceUtils.java +++ b/liquibase-core/src/main/java/liquibase/license/LicenseServiceUtils.java @@ -12,7 +12,7 @@ public class LicenseServiceUtils { public static final String TRIAL_LICENSE_URL = "https://liquibase.com/trial"; - public static final String BASE_INVALID_LICENSE_MESSAGE = "Using '%s' requires a valid Liquibase Pro or Labs license. Get a free license key at " + TRIAL_LICENSE_URL + "."; + private static final String BASE_INVALID_LICENSE_MESSAGE = "Using '%s' requires a valid Liquibase Pro or Labs license. Get a free license key at " + TRIAL_LICENSE_URL + "."; /** * Check for a Liquibase Pro License. From 0418087a5c0f43bcaea77eb9bad52e1356a0737f Mon Sep 17 00:00:00 2001 From: Wesley willard Date: Wed, 22 Jun 2022 11:19:41 -0500 Subject: [PATCH 03/10] Added testing framework modifications for flow DAT 10586 (#2981) Co-authored-by: Steven Massaro --- .../testing/command/CommandTests.groovy | 3 ++ .../setup/SetupModifyDbCredentials.groovy | 31 +++++++++++++++++++ 2 files changed, 34 insertions(+) create mode 100644 liquibase-extension-testing/src/main/groovy/liquibase/extension/testing/setup/SetupModifyDbCredentials.groovy diff --git a/liquibase-extension-testing/src/main/groovy/liquibase/extension/testing/command/CommandTests.groovy b/liquibase-extension-testing/src/main/groovy/liquibase/extension/testing/command/CommandTests.groovy index cedc7f2dd68..9138511ec78 100644 --- a/liquibase-extension-testing/src/main/groovy/liquibase/extension/testing/command/CommandTests.groovy +++ b/liquibase-extension-testing/src/main/groovy/liquibase/extension/testing/command/CommandTests.groovy @@ -1105,6 +1105,9 @@ Long Description: ${commandDefinition.getLongDescription() ?: "NOT SET"} this.setups.add(new SetupModifyTextFile(textFile, originalString, newString)) } + void modifyDbCredentials(File textFile) { + this.setups.add(new SetupModifyDbCredentials(textFile)) + } private void validate() throws IllegalArgumentException { } diff --git a/liquibase-extension-testing/src/main/groovy/liquibase/extension/testing/setup/SetupModifyDbCredentials.groovy b/liquibase-extension-testing/src/main/groovy/liquibase/extension/testing/setup/SetupModifyDbCredentials.groovy new file mode 100644 index 00000000000..07991b5cded --- /dev/null +++ b/liquibase-extension-testing/src/main/groovy/liquibase/extension/testing/setup/SetupModifyDbCredentials.groovy @@ -0,0 +1,31 @@ +package liquibase.extension.testing.setup + +import liquibase.util.FileUtil + +/** + * + * This class allows modification of a text file to + * replace tokens with the actual database credential + * as specified in the environment + * + */ +class SetupModifyDbCredentials extends TestSetup { + + private static final String URL = "_URL_" + private static final String USERNAME = "_USERNAME_" + private static final String PASSWORD = "_PASSWORD_" + private final File textFile + + SetupModifyDbCredentials(File textFile) { + this.textFile = textFile + } + + @Override + void setup(TestSetupEnvironment testSetupEnvironment) throws Exception { + String contents = FileUtil.getContents(textFile) + contents = contents.replaceAll(URL, testSetupEnvironment.url) + contents = contents.replaceAll(USERNAME, testSetupEnvironment.username) + contents = contents.replaceAll(PASSWORD, testSetupEnvironment.password) + FileUtil.write(contents, textFile) + } +} \ No newline at end of file From 5aacdb4ee9cf1eccd0ec696457afebfc09c27e60 Mon Sep 17 00:00:00 2001 From: Steven Massaro Date: Wed, 22 Jun 2022 12:22:35 -0400 Subject: [PATCH 04/10] general changes to support flow file validation (DAT-10588) (#2986) add createIfNull(Map) method to CollectionUtil expose separate validate() method in CommandScope add constructor to CommandValidationException(Throwable) --- .../java/liquibase/command/CommandScope.java | 16 +++++++++++----- .../exception/CommandValidationException.java | 4 ++++ .../main/java/liquibase/util/CollectionUtil.java | 13 ++++++++++++- 3 files changed, 27 insertions(+), 6 deletions(-) diff --git a/liquibase-core/src/main/java/liquibase/command/CommandScope.java b/liquibase-core/src/main/java/liquibase/command/CommandScope.java index 8b300bbce32..4e7b2bc16c2 100644 --- a/liquibase-core/src/main/java/liquibase/command/CommandScope.java +++ b/liquibase-core/src/main/java/liquibase/command/CommandScope.java @@ -3,6 +3,7 @@ import liquibase.Scope; import liquibase.configuration.*; import liquibase.exception.CommandExecutionException; +import liquibase.exception.CommandValidationException; import liquibase.util.StringUtil; import java.io.OutputStream; @@ -131,11 +132,7 @@ public CommandScope setOutput(OutputStream outputStream) { return this; } - /** - * Executes the command in this scope, and returns the results. - */ - public CommandResults execute() throws CommandExecutionException { - CommandResultsBuilder resultsBuilder = new CommandResultsBuilder(this, outputStream); + public void validate() throws CommandValidationException { for (ConfigurationValueProvider provider : Scope.getCurrentScope().getSingleton(LiquibaseConfiguration.class).getProviders()) { provider.validate(this); } @@ -151,6 +148,15 @@ public CommandResults execute() throws CommandExecutionException { for (CommandStep step : pipeline) { step.validate(this); } + } + + /** + * Executes the command in this scope, and returns the results. + */ + public CommandResults execute() throws CommandExecutionException { + CommandResultsBuilder resultsBuilder = new CommandResultsBuilder(this, outputStream); + final List pipeline = commandDefinition.getPipeline(); + validate(); try { for (CommandStep command : pipeline) { command.run(resultsBuilder); diff --git a/liquibase-core/src/main/java/liquibase/exception/CommandValidationException.java b/liquibase-core/src/main/java/liquibase/exception/CommandValidationException.java index cd78ced0d04..acf80bfb104 100644 --- a/liquibase-core/src/main/java/liquibase/exception/CommandValidationException.java +++ b/liquibase-core/src/main/java/liquibase/exception/CommandValidationException.java @@ -13,6 +13,10 @@ public CommandValidationException(String message) { super(message); } + public CommandValidationException(Throwable cause) { + super(cause); + } + public CommandValidationException(String argument, String message, Throwable cause) { super(buildMessage(argument, message), cause); } diff --git a/liquibase-core/src/main/java/liquibase/util/CollectionUtil.java b/liquibase-core/src/main/java/liquibase/util/CollectionUtil.java index f89bb8dabfc..a03b624fd8d 100644 --- a/liquibase-core/src/main/java/liquibase/util/CollectionUtil.java +++ b/liquibase-core/src/main/java/liquibase/util/CollectionUtil.java @@ -78,7 +78,7 @@ public static T[] createIfNull(T[] arguments) { } /** - * Returns a new empty set if the passed array is null. + * Returns a new empty set if the passed set is null. */ public static Set createIfNull(Set currentValue) { if (currentValue == null) { @@ -88,6 +88,17 @@ public static Set createIfNull(Set currentValue) { } } + /** + * Returns a new empty map if the passed map is null. + */ + public static Map createIfNull(Map currentValue) { + if (currentValue == null) { + return new HashMap<>(); + } else { + return currentValue; + } + } + /** * Converts a set of nested maps (like from yaml/json) into a flat map with dot-separated properties */ From 37c55062ef6e779cbd31fa846e58cbe842a0247e Mon Sep 17 00:00:00 2001 From: Steven Massaro Date: Thu, 23 Jun 2022 13:47:26 -0500 Subject: [PATCH 05/10] do not allow commands to close the top level output stream --- .../java/liquibase/command/CommandScope.java | 8 ++++++- .../liquibase/io/UnclosableOutputStream.java | 23 +++++++++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) create mode 100644 liquibase-core/src/main/java/liquibase/io/UnclosableOutputStream.java diff --git a/liquibase-core/src/main/java/liquibase/command/CommandScope.java b/liquibase-core/src/main/java/liquibase/command/CommandScope.java index 4e7b2bc16c2..2d910761973 100644 --- a/liquibase-core/src/main/java/liquibase/command/CommandScope.java +++ b/liquibase-core/src/main/java/liquibase/command/CommandScope.java @@ -4,6 +4,7 @@ import liquibase.configuration.*; import liquibase.exception.CommandExecutionException; import liquibase.exception.CommandValidationException; +import liquibase.io.UnclosableOutputStream; import liquibase.util.StringUtil; import java.io.OutputStream; @@ -40,7 +41,12 @@ public class CommandScope { * Creates a new scope for the given command. */ public CommandScope(String... commandName) throws CommandExecutionException { - setOutput(System.out); + /* + This is an UncloseableOutputStream because we do not want individual command steps to inadvertently (or + intentionally) close the System.out OutputStream. Closing System.out renders it unusable for other command + steps which expect it to still be open. + */ + setOutput(new UnclosableOutputStream(System.out)); final CommandFactory commandFactory = Scope.getCurrentScope().getSingleton(CommandFactory.class); diff --git a/liquibase-core/src/main/java/liquibase/io/UnclosableOutputStream.java b/liquibase-core/src/main/java/liquibase/io/UnclosableOutputStream.java new file mode 100644 index 00000000000..1473f97f456 --- /dev/null +++ b/liquibase-core/src/main/java/liquibase/io/UnclosableOutputStream.java @@ -0,0 +1,23 @@ +package liquibase.io; + +import java.io.FilterOutputStream; +import java.io.IOException; +import java.io.OutputStream; + +/** + * This class is a wrapper around OutputStreams, and makes them impossible for callers to close. + */ +public class UnclosableOutputStream extends FilterOutputStream { + public UnclosableOutputStream(OutputStream out) { + super(out); + } + + /** + * This method does not actually close the underlying stream, but rather only flushes it. Callers should not be + * closing the stream they are given. + */ + @Override + public void close() throws IOException { + out.flush(); + } +} From 137a92a11b7c94213822c2ea28344fa0a6514a11 Mon Sep 17 00:00:00 2001 From: Steven Massaro Date: Thu, 23 Jun 2022 13:59:49 -0500 Subject: [PATCH 06/10] create the UnclosableOutputStream in the setOutput method --- .../main/java/liquibase/command/CommandScope.java | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/liquibase-core/src/main/java/liquibase/command/CommandScope.java b/liquibase-core/src/main/java/liquibase/command/CommandScope.java index 2d910761973..46f53133516 100644 --- a/liquibase-core/src/main/java/liquibase/command/CommandScope.java +++ b/liquibase-core/src/main/java/liquibase/command/CommandScope.java @@ -41,12 +41,7 @@ public class CommandScope { * Creates a new scope for the given command. */ public CommandScope(String... commandName) throws CommandExecutionException { - /* - This is an UncloseableOutputStream because we do not want individual command steps to inadvertently (or - intentionally) close the System.out OutputStream. Closing System.out renders it unusable for other command - steps which expect it to still be open. - */ - setOutput(new UnclosableOutputStream(System.out)); + setOutput(System.out); final CommandFactory commandFactory = Scope.getCurrentScope().getSingleton(CommandFactory.class); @@ -133,7 +128,12 @@ public T getArgumentValue(CommandArgumentDefinition argument) { * Think "what would be piped out", not "what the user is told about what is happening". */ public CommandScope setOutput(OutputStream outputStream) { - this.outputStream = outputStream; + /* + This is an UncloseableOutputStream because we do not want individual command steps to inadvertently (or + intentionally) close the System.out OutputStream. Closing System.out renders it unusable for other command + steps which expect it to still be open. + */ + this.outputStream = new UnclosableOutputStream(outputStream); return this; } From e62f0d98e3c379ef5ee8d766dd7ab229fef01141 Mon Sep 17 00:00:00 2001 From: Wesley Willard Date: Thu, 23 Jun 2022 17:46:22 -0500 Subject: [PATCH 07/10] Sonar lint cleanup --- .../src/main/java/liquibase/io/UnclosableOutputStream.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/liquibase-core/src/main/java/liquibase/io/UnclosableOutputStream.java b/liquibase-core/src/main/java/liquibase/io/UnclosableOutputStream.java index 1473f97f456..8357d4d7977 100644 --- a/liquibase-core/src/main/java/liquibase/io/UnclosableOutputStream.java +++ b/liquibase-core/src/main/java/liquibase/io/UnclosableOutputStream.java @@ -12,6 +12,11 @@ public UnclosableOutputStream(OutputStream out) { super(out); } + @Override + public void write(byte[] b, int off, int len) throws IOException { + out.write(b, off, len); + } + /** * This method does not actually close the underlying stream, but rather only flushes it. Callers should not be * closing the stream they are given. From ab3862f87ea0589c8e36b06bb5fd3b9cc0a0276d Mon Sep 17 00:00:00 2001 From: Wesley Willard Date: Fri, 24 Jun 2022 10:51:55 -0500 Subject: [PATCH 08/10] Moved UnclosableOutputStream class into CommandScope and made it private Do not create if output stream is null DAT-10419 --- .../java/liquibase/command/CommandScope.java | 36 ++++++++++++++++--- .../liquibase/io/UnclosableOutputStream.java | 28 --------------- 2 files changed, 32 insertions(+), 32 deletions(-) delete mode 100644 liquibase-core/src/main/java/liquibase/io/UnclosableOutputStream.java diff --git a/liquibase-core/src/main/java/liquibase/command/CommandScope.java b/liquibase-core/src/main/java/liquibase/command/CommandScope.java index 46f53133516..895d9580fca 100644 --- a/liquibase-core/src/main/java/liquibase/command/CommandScope.java +++ b/liquibase-core/src/main/java/liquibase/command/CommandScope.java @@ -4,9 +4,10 @@ import liquibase.configuration.*; import liquibase.exception.CommandExecutionException; import liquibase.exception.CommandValidationException; -import liquibase.io.UnclosableOutputStream; import liquibase.util.StringUtil; +import java.io.FilterOutputStream; +import java.io.IOException; import java.io.OutputStream; import java.util.*; @@ -129,11 +130,15 @@ public T getArgumentValue(CommandArgumentDefinition argument) { */ public CommandScope setOutput(OutputStream outputStream) { /* - This is an UncloseableOutputStream because we do not want individual command steps to inadvertently (or + This is an UnclosableOutputStream because we do not want individual command steps to inadvertently (or intentionally) close the System.out OutputStream. Closing System.out renders it unusable for other command - steps which expect it to still be open. + steps which expect it to still be open. If the passed OutputStream is null then we do not create it. */ - this.outputStream = new UnclosableOutputStream(outputStream); + if (outputStream != null) { + this.outputStream = new UnclosableOutputStream(outputStream); + } else { + this.outputStream = null; + } return this; } @@ -203,6 +208,29 @@ private ConfigurationDefinition createConfigurationDefinition(CommandArgu .buildTemporary(); } + /** + * This class is a wrapper around OutputStreams, and makes them impossible for callers to close. + */ + private static class UnclosableOutputStream extends FilterOutputStream { + public UnclosableOutputStream(OutputStream out) { + super(out); + } + + @Override + public void write(byte[] b, int off, int len) throws IOException { + out.write(b, off, len); + } + + /** + * This method does not actually close the underlying stream, but rather only flushes it. Callers should not be + * closing the stream they are given. + */ + @Override + public void close() throws IOException { + out.flush(); + } + } + private class CommandScopeValueProvider extends AbstractMapConfigurationValueProvider { @Override diff --git a/liquibase-core/src/main/java/liquibase/io/UnclosableOutputStream.java b/liquibase-core/src/main/java/liquibase/io/UnclosableOutputStream.java deleted file mode 100644 index 8357d4d7977..00000000000 --- a/liquibase-core/src/main/java/liquibase/io/UnclosableOutputStream.java +++ /dev/null @@ -1,28 +0,0 @@ -package liquibase.io; - -import java.io.FilterOutputStream; -import java.io.IOException; -import java.io.OutputStream; - -/** - * This class is a wrapper around OutputStreams, and makes them impossible for callers to close. - */ -public class UnclosableOutputStream extends FilterOutputStream { - public UnclosableOutputStream(OutputStream out) { - super(out); - } - - @Override - public void write(byte[] b, int off, int len) throws IOException { - out.write(b, off, len); - } - - /** - * This method does not actually close the underlying stream, but rather only flushes it. Callers should not be - * closing the stream they are given. - */ - @Override - public void close() throws IOException { - out.flush(); - } -} From 2d6c3b0a55dd6a646b2eabb77cd9041573a53a8e Mon Sep 17 00:00:00 2001 From: Steven Massaro Date: Wed, 13 Jul 2022 12:20:27 -0400 Subject: [PATCH 09/10] add liquibase flow and flow.validate goals to maven plugin (DAT-10576) (#3015) Add a flow and flow.validate goal to the maven plugin. Also, add class check before casting in Main.java. --- .../integration/commandline/Main.java | 6 ++- .../plugins/AbstractLiquibaseFlowMojo.java | 50 +++++++++++++++++++ .../maven/plugins/LiquibaseFlowMojo.java | 14 ++++++ .../plugins/LiquibaseFlowValidateMojo.java | 13 +++++ 4 files changed, 81 insertions(+), 2 deletions(-) create mode 100644 liquibase-maven-plugin/src/main/java/org/liquibase/maven/plugins/AbstractLiquibaseFlowMojo.java create mode 100644 liquibase-maven-plugin/src/main/java/org/liquibase/maven/plugins/LiquibaseFlowMojo.java create mode 100644 liquibase-maven-plugin/src/main/java/org/liquibase/maven/plugins/LiquibaseFlowValidateMojo.java 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 054e8dd600c..bac4888f687 100644 --- a/liquibase-core/src/main/java/liquibase/integration/commandline/Main.java +++ b/liquibase-core/src/main/java/liquibase/integration/commandline/Main.java @@ -288,8 +288,10 @@ public Integer run() throws Exception { java.util.logging.Logger liquibaseLogger = java.util.logging.Logger.getLogger("liquibase"); liquibaseLogger.setParent(rootLogger); - final JavaLogService logService = (JavaLogService) Scope.getCurrentScope().get(Scope.Attr.logService, LogService.class); - logService.setParent(liquibaseLogger); + LogService logService = Scope.getCurrentScope().get(Scope.Attr.logService, LogService.class); + if (logService instanceof JavaLogService) { + ((JavaLogService) logService).setParent(liquibaseLogger); + } if (main.logLevel == null) { String defaultLogLevel = System.getProperty("liquibase.log.level"); diff --git a/liquibase-maven-plugin/src/main/java/org/liquibase/maven/plugins/AbstractLiquibaseFlowMojo.java b/liquibase-maven-plugin/src/main/java/org/liquibase/maven/plugins/AbstractLiquibaseFlowMojo.java new file mode 100644 index 00000000000..286dc67b2d3 --- /dev/null +++ b/liquibase-maven-plugin/src/main/java/org/liquibase/maven/plugins/AbstractLiquibaseFlowMojo.java @@ -0,0 +1,50 @@ +package org.liquibase.maven.plugins; + +import liquibase.Liquibase; +import liquibase.command.CommandScope; +import liquibase.exception.CommandExecutionException; +import liquibase.exception.LiquibaseException; +import org.liquibase.maven.property.PropertyElement; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; + +public abstract class AbstractLiquibaseFlowMojo extends AbstractLiquibaseMojo { + /** + * Specifies the flowFile to use. If not specified, the default + * checks will be used and no file will be created. + * + * @parameter property="liquibase.flowFile" + */ + @PropertyElement + protected String flowFile; + + /** + * @parameter property="liquibase.outputFile" + */ + @PropertyElement + protected File outputFile; + + @Override + public boolean databaseConnectionRequired() { + return false; + } + + @Override + protected void performLiquibaseTask(Liquibase liquibase) throws LiquibaseException { + CommandScope liquibaseCommand = new CommandScope(getCommandName()); + liquibaseCommand.addArgumentValue("flowFile", flowFile); + liquibaseCommand.addArgumentValue("flowIntegration", "maven"); + if (outputFile != null) { + try { + liquibaseCommand.setOutput(new FileOutputStream(outputFile)); + } catch (FileNotFoundException e) { + throw new CommandExecutionException(e); + } + } + liquibaseCommand.execute(); + } + + public abstract String[] getCommandName(); +} diff --git a/liquibase-maven-plugin/src/main/java/org/liquibase/maven/plugins/LiquibaseFlowMojo.java b/liquibase-maven-plugin/src/main/java/org/liquibase/maven/plugins/LiquibaseFlowMojo.java new file mode 100644 index 00000000000..87e19d3613a --- /dev/null +++ b/liquibase-maven-plugin/src/main/java/org/liquibase/maven/plugins/LiquibaseFlowMojo.java @@ -0,0 +1,14 @@ +package org.liquibase.maven.plugins; + +/** + * Run a series of commands contained in one or more stages, as configured in a liquibase flow-file. + * + * @goal flow + */ +public class LiquibaseFlowMojo extends AbstractLiquibaseFlowMojo { + + @Override + public String[] getCommandName() { + return new String[]{"flow"}; + } +} diff --git a/liquibase-maven-plugin/src/main/java/org/liquibase/maven/plugins/LiquibaseFlowValidateMojo.java b/liquibase-maven-plugin/src/main/java/org/liquibase/maven/plugins/LiquibaseFlowValidateMojo.java new file mode 100644 index 00000000000..043674ebf5c --- /dev/null +++ b/liquibase-maven-plugin/src/main/java/org/liquibase/maven/plugins/LiquibaseFlowValidateMojo.java @@ -0,0 +1,13 @@ +package org.liquibase.maven.plugins; + +/** + * Validate a series of commands contained in one or more stages, as configured in a liquibase flow-file. + * + * @goal flow.validate + */ +public class LiquibaseFlowValidateMojo extends AbstractLiquibaseFlowMojo{ + @Override + public String[] getCommandName() { + return new String[]{"flow", "validate"}; + } +} From 39a6cf7f6f988fe93be1033cdbae9786e24e7b66 Mon Sep 17 00:00:00 2001 From: Steven Massaro Date: Wed, 27 Jul 2022 08:45:05 -0500 Subject: [PATCH 10/10] allow passing any arguments to flow commands from maven plugin (DAT-10944) (#3103) Add a flowCommandArguments Map to the mojo definition for flow and flow.validate maven goals. The arguments will be passed to every command that is run in flow. --- .../plugins/AbstractLiquibaseFlowMojo.java | 17 ++++++++ .../FlowCommandArgumentValueProvider.java | 41 +++++++++++++++++++ 2 files changed, 58 insertions(+) create mode 100644 liquibase-maven-plugin/src/main/java/org/liquibase/maven/provider/FlowCommandArgumentValueProvider.java diff --git a/liquibase-maven-plugin/src/main/java/org/liquibase/maven/plugins/AbstractLiquibaseFlowMojo.java b/liquibase-maven-plugin/src/main/java/org/liquibase/maven/plugins/AbstractLiquibaseFlowMojo.java index 286dc67b2d3..91fab049793 100644 --- a/liquibase-maven-plugin/src/main/java/org/liquibase/maven/plugins/AbstractLiquibaseFlowMojo.java +++ b/liquibase-maven-plugin/src/main/java/org/liquibase/maven/plugins/AbstractLiquibaseFlowMojo.java @@ -1,14 +1,18 @@ package org.liquibase.maven.plugins; import liquibase.Liquibase; +import liquibase.Scope; import liquibase.command.CommandScope; +import liquibase.configuration.LiquibaseConfiguration; import liquibase.exception.CommandExecutionException; import liquibase.exception.LiquibaseException; import org.liquibase.maven.property.PropertyElement; +import org.liquibase.maven.provider.FlowCommandArgumentValueProvider; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; +import java.util.Map; public abstract class AbstractLiquibaseFlowMojo extends AbstractLiquibaseMojo { /** @@ -26,6 +30,15 @@ public abstract class AbstractLiquibaseFlowMojo extends AbstractLiquibaseMojo { @PropertyElement protected File outputFile; + /** + * Arbitrary map of parameters that the underlying liquibase command will use. These arguments will be passed + * verbatim to the underlying liquibase command that is being run. + * + * @parameter property="flowCommandArguments" + */ + @PropertyElement + protected Map flowCommandArguments; + @Override public boolean databaseConnectionRequired() { return false; @@ -36,6 +49,10 @@ protected void performLiquibaseTask(Liquibase liquibase) throws LiquibaseExcepti CommandScope liquibaseCommand = new CommandScope(getCommandName()); liquibaseCommand.addArgumentValue("flowFile", flowFile); liquibaseCommand.addArgumentValue("flowIntegration", "maven"); + if (flowCommandArguments != null) { + FlowCommandArgumentValueProvider flowCommandArgumentValueProvider = new FlowCommandArgumentValueProvider(flowCommandArguments); + Scope.getCurrentScope().getSingleton(LiquibaseConfiguration.class).registerProvider(flowCommandArgumentValueProvider); + } if (outputFile != null) { try { liquibaseCommand.setOutput(new FileOutputStream(outputFile)); diff --git a/liquibase-maven-plugin/src/main/java/org/liquibase/maven/provider/FlowCommandArgumentValueProvider.java b/liquibase-maven-plugin/src/main/java/org/liquibase/maven/provider/FlowCommandArgumentValueProvider.java new file mode 100644 index 00000000000..b7f57b78761 --- /dev/null +++ b/liquibase-maven-plugin/src/main/java/org/liquibase/maven/provider/FlowCommandArgumentValueProvider.java @@ -0,0 +1,41 @@ +package org.liquibase.maven.provider; + +import liquibase.configuration.AbstractMapConfigurationValueProvider; + +import java.util.Map; + +public class FlowCommandArgumentValueProvider extends AbstractMapConfigurationValueProvider { + + private final Map args; + + public FlowCommandArgumentValueProvider(Map args) { + this.args = args; + } + + @Override + public int getPrecedence() { + return 250; + } + + @Override + protected Map getMap() { + return args; + } + + @Override + protected String getSourceDescription() { + return "Arguments provided through maven when invoking flow or flow.validate maven goals"; + } + + @Override + protected boolean keyMatches(String wantedKey, String storedKey) { + if (super.keyMatches(wantedKey, storedKey)) { + return true; + } + if (wantedKey.startsWith("liquibase.command.")) { + return super.keyMatches(wantedKey.replaceFirst("^liquibase\\.command\\.", ""), storedKey); + } + + return super.keyMatches(wantedKey.replaceFirst("^liquibase\\.", ""), storedKey); + } +}