Skip to content

Commit

Permalink
Merge pull request #1776 from liquibase/LB-1222
Browse files Browse the repository at this point in the history
Refactor LiquibaseConfiguration API
  • Loading branch information
nvoxland committed Apr 22, 2021
2 parents 36b5ed6 + f36374c commit 256675b
Show file tree
Hide file tree
Showing 152 changed files with 2,911 additions and 1,639 deletions.
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
}
Expand Down
Expand Up @@ -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) {
Expand Down
20 changes: 20 additions & 0 deletions liquibase-cli/pom.xml
@@ -0,0 +1,20 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<parent>
<groupId>org.liquibase</groupId>
<artifactId>liquibase-base-module</artifactId>
<version>${liquibase.version}</version>
<relativePath>../base-module.pom.xml</relativePath>
</parent>

<description>Liquibase CLI interface</description>

<artifactId>liquibase-cli</artifactId>

<dependencies>

</dependencies>

</project>
@@ -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<ConfigurationDefinition> definitions = Scope.getCurrentScope().getSingleton(LiquibaseConfiguration.class).getRegisteredDefinitions();
for (ConfigurationDefinition def : definitions) {
System.out.println("See " + def.getKey() + " = " + def.getCurrentValue() + " -- " + def.getDescription());
}
}
}
145 changes: 145 additions & 0 deletions 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<Boolean> SHOULD_RUN;
public static final ConfigurationDefinition<String> DATABASECHANGELOG_TABLE_NAME;
public static final ConfigurationDefinition<String> DATABASECHANGELOGLOCK_TABLE_NAME;
public static final ConfigurationDefinition<String> LIQUIBASE_TABLESPACE_NAME;
public static final ConfigurationDefinition<String> LIQUIBASE_CATALOG_NAME;
public static final ConfigurationDefinition<String> LIQUIBASE_SCHEMA_NAME;
public static final ConfigurationDefinition<String> OUTPUT_LINE_SEPARATOR;
public static final ConfigurationDefinition<String> OUTPUT_ENCODING;
public static final ConfigurationDefinition<Long> CHANGELOGLOCK_WAIT_TIME;
public static final ConfigurationDefinition<Long> CHANGELOGLOCK_POLL_RATE;
public static final ConfigurationDefinition<Boolean> CONVERT_DATA_TYPES;
public static final ConfigurationDefinition<Boolean> GENERATE_CHANGESET_CREATED_VALUES;
public static final ConfigurationDefinition<Boolean> AUTO_REORG;
public static final ConfigurationDefinition<Boolean> DIFF_COLUMN_ORDER;
public static final ConfigurationDefinition<Boolean> ALWAYS_OVERRIDE_STORED_LOGIC_SCHEMA;
public static final ConfigurationDefinition<Boolean> GENERATED_CHANGESET_IDS_INCLUDE_DESCRIPTION;
public static final ConfigurationDefinition<Boolean> INCLUDE_CATALOG_IN_SPECIFICATION;
public static final ConfigurationDefinition<Boolean> SHOULD_SNAPSHOT_DATA;
public static final ConfigurationDefinition<Boolean> FILTER_LOG_MESSAGES;
public static final ConfigurationDefinition<Boolean> 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();
}
}
18 changes: 7 additions & 11 deletions liquibase-core/src/main/java/liquibase/Liquibase.java
Expand Up @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -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);
Expand All @@ -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.";
Expand Down Expand Up @@ -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);
}
Expand Down
12 changes: 8 additions & 4 deletions 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;
Expand Down Expand Up @@ -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");
Expand Down Expand Up @@ -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<String, Object> scopeValues) {
Expand Down
1 change: 0 additions & 1 deletion liquibase-core/src/main/java/liquibase/ScopeManager.java
Expand Up @@ -2,7 +2,6 @@

public abstract class ScopeManager {


public abstract Scope getCurrentScope();

protected abstract void setCurrentScope(Scope scope);
Expand Down
Expand Up @@ -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;
Expand Down Expand Up @@ -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())
);
}

Expand Down Expand Up @@ -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);
}
Expand Down
Expand Up @@ -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.*;
Expand Down Expand Up @@ -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));
Expand Down
Expand Up @@ -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;
Expand Down Expand Up @@ -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));
Expand Down

0 comments on commit 256675b

Please sign in to comment.