diff --git a/driver-wrappers/mongodb-springdata-v2-wrapper/pom.xml b/driver-wrappers/mongodb-springdata-v2-wrapper/pom.xml
new file mode 100644
index 0000000..c21b0c2
--- /dev/null
+++ b/driver-wrappers/mongodb-springdata-v2-wrapper/pom.xml
@@ -0,0 +1,87 @@
+
+
+
+ driver-wrappers
+ io.mongock
+ 5.0.28-SNAPSHOT
+
+ 4.0.0
+
+ mongodb-springdata-v2-wrapper
+
+
+ 4.3.3
+ 4.4.1
+ 2.6.3
+
+
+
+
+ io.mongock
+ mongock-cli-util
+ ${project.version}
+
+
+
+ io.mongock
+ mongodb-springdata-v2-driver
+ ${mongock.community.version}
+
+
+
+
+ org.springframework.data
+ spring-data-mongodb
+ 2.2.13.RELEASE
+
+
+ org.mongodb
+ mongodb-driver-sync
+ 3.11.2
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+
+ ${java.version}
+ ${java.version}
+
+
+
+
+ org.apache.maven.plugins
+ maven-shade-plugin
+
+
+
+ shade
+
+
+ false
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/driver-wrappers/mongodb-springdata-v2-wrapper/src/main/java/io/mongock/driver/cli/wrapper/mongodb/springdata/v2/DateToZonedDateTimeConverter.java b/driver-wrappers/mongodb-springdata-v2-wrapper/src/main/java/io/mongock/driver/cli/wrapper/mongodb/springdata/v2/DateToZonedDateTimeConverter.java
new file mode 100644
index 0000000..e350afb
--- /dev/null
+++ b/driver-wrappers/mongodb-springdata-v2-wrapper/src/main/java/io/mongock/driver/cli/wrapper/mongodb/springdata/v2/DateToZonedDateTimeConverter.java
@@ -0,0 +1,19 @@
+package io.mongock.driver.cli.wrapper.mongodb.springdata.v2;
+
+import org.springframework.core.convert.converter.Converter;
+import org.springframework.data.convert.ReadingConverter;
+
+import java.time.ZoneId;
+import java.time.ZonedDateTime;
+import java.util.Date;
+
+@ReadingConverter
+public enum DateToZonedDateTimeConverter implements Converter {
+ INSTANCE;
+
+ @Override
+ public ZonedDateTime convert(Date source) {
+ return source == null ? null : ZonedDateTime.ofInstant(source.toInstant(), ZoneId.systemDefault());
+
+ }
+}
diff --git a/driver-wrappers/mongodb-springdata-v2-wrapper/src/main/java/io/mongock/driver/cli/wrapper/mongodb/springdata/v2/SpringDataMongoV2DriverProvider.java b/driver-wrappers/mongodb-springdata-v2-wrapper/src/main/java/io/mongock/driver/cli/wrapper/mongodb/springdata/v2/SpringDataMongoV2DriverProvider.java
new file mode 100644
index 0000000..ecc348d
--- /dev/null
+++ b/driver-wrappers/mongodb-springdata-v2-wrapper/src/main/java/io/mongock/driver/cli/wrapper/mongodb/springdata/v2/SpringDataMongoV2DriverProvider.java
@@ -0,0 +1,57 @@
+package io.mongock.driver.cli.wrapper.mongodb.springdata.v2;
+
+import com.mongodb.client.MongoClient;
+import com.mongodb.client.MongoClients;
+import io.mongock.cli.util.CliConfiguration;
+import io.mongock.cli.util.ConnectionDriverProvider;
+import io.mongock.driver.api.driver.ConnectionDriver;
+import io.mongock.driver.mongodb.springdata.v2.SpringDataMongoV2Driver;
+import org.springframework.core.convert.converter.Converter;
+import org.springframework.data.mongodb.core.MongoTemplate;
+import org.springframework.data.mongodb.core.convert.MappingMongoConverter;
+import org.springframework.data.mongodb.core.convert.MongoCustomConversions;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class SpringDataMongoV2DriverProvider implements ConnectionDriverProvider {
+
+
+ @Override
+ public ConnectionDriver getDriver(CliConfiguration configuration) {
+
+
+ MongoTemplate mongoTemplate = getMongoTemplate(configuration.getDatabaseUrl(), configuration.getDatabaseName());
+
+ // Driver
+ SpringDataMongoV2Driver driver = SpringDataMongoV2Driver.withDefaultLock(mongoTemplate);
+ driver.enableTransaction();
+
+ return driver;
+ }
+
+ /**
+ * Main MongoTemplate for Mongock to work.
+ */
+ private static MongoTemplate getMongoTemplate(String connectionString, String dbName) {
+
+ MongoClient mongoClient = MongoClients.create(connectionString);
+ MongoTemplate mongoTemplate = new MongoTemplate(mongoClient, dbName);
+
+ // Custom converters to map ZonedDateTime.
+ MappingMongoConverter mongoMapping = (MappingMongoConverter) mongoTemplate.getConverter();
+ mongoMapping.setCustomConversions(customConversions());
+ mongoMapping.afterPropertiesSet();
+
+ return mongoTemplate;
+ }
+
+
+ private static MongoCustomConversions customConversions() {
+ List> converters = new ArrayList<>();
+ converters.add(DateToZonedDateTimeConverter.INSTANCE);
+ converters.add(ZonedDateTimeToDateConverter.INSTANCE);
+ return new MongoCustomConversions(converters);
+ }
+
+}
diff --git a/driver-wrappers/mongodb-springdata-v2-wrapper/src/main/java/io/mongock/driver/cli/wrapper/mongodb/springdata/v2/ZonedDateTimeToDateConverter.java b/driver-wrappers/mongodb-springdata-v2-wrapper/src/main/java/io/mongock/driver/cli/wrapper/mongodb/springdata/v2/ZonedDateTimeToDateConverter.java
new file mode 100644
index 0000000..c2edd95
--- /dev/null
+++ b/driver-wrappers/mongodb-springdata-v2-wrapper/src/main/java/io/mongock/driver/cli/wrapper/mongodb/springdata/v2/ZonedDateTimeToDateConverter.java
@@ -0,0 +1,17 @@
+package io.mongock.driver.cli.wrapper.mongodb.springdata.v2;
+
+import org.springframework.core.convert.converter.Converter;
+import org.springframework.data.convert.WritingConverter;
+
+import java.time.ZonedDateTime;
+import java.util.Date;
+
+@WritingConverter
+public enum ZonedDateTimeToDateConverter implements Converter {
+ INSTANCE;
+
+ @Override
+ public Date convert(ZonedDateTime source) {
+ return source == null ? null : Date.from(source.toInstant());
+ }
+}
diff --git a/driver-wrappers/mongodb-springdata-v3-wrapper/pom.xml b/driver-wrappers/mongodb-springdata-v3-wrapper/pom.xml
new file mode 100644
index 0000000..791097d
--- /dev/null
+++ b/driver-wrappers/mongodb-springdata-v3-wrapper/pom.xml
@@ -0,0 +1,87 @@
+
+
+
+ driver-wrappers
+ io.mongock
+ 5.0.28-SNAPSHOT
+
+ 4.0.0
+
+ mongodb-springdata-v3-wrapper
+
+
+ 4.3.3
+ 4.4.1
+ 2.6.3
+
+
+
+
+
+ io.mongock
+ mongock-cli-util
+ ${project.version}
+
+
+
+
+ io.mongock
+ mongodb-springdata-v3-driver
+ ${mongock.community.version}
+
+
+
+
+
+ org.mongodb
+ mongodb-driver-sync
+ 4.4.1
+
+
+ org.springframework.data
+ spring-data-mongodb
+ 3.3.1
+
+
+
+
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+
+ ${java.version}
+ ${java.version}
+
+
+
+
+ org.apache.maven.plugins
+ maven-shade-plugin
+
+
+
+ shade
+
+
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/driver-wrappers/mongodb-springdata-v3-wrapper/src/main/java/io/mongock/driver/cli/wrapper/mongodb/springdata/v3/DateToZonedDateTimeConverter.java b/driver-wrappers/mongodb-springdata-v3-wrapper/src/main/java/io/mongock/driver/cli/wrapper/mongodb/springdata/v3/DateToZonedDateTimeConverter.java
new file mode 100644
index 0000000..6351aa8
--- /dev/null
+++ b/driver-wrappers/mongodb-springdata-v3-wrapper/src/main/java/io/mongock/driver/cli/wrapper/mongodb/springdata/v3/DateToZonedDateTimeConverter.java
@@ -0,0 +1,19 @@
+package io.mongock.driver.cli.wrapper.mongodb.springdata.v3;
+
+import org.springframework.core.convert.converter.Converter;
+import org.springframework.data.convert.ReadingConverter;
+
+import java.time.ZoneId;
+import java.time.ZonedDateTime;
+import java.util.Date;
+
+@ReadingConverter
+public enum DateToZonedDateTimeConverter implements Converter {
+ INSTANCE;
+
+ @Override
+ public ZonedDateTime convert(Date source) {
+ return source == null ? null : ZonedDateTime.ofInstant(source.toInstant(), ZoneId.systemDefault());
+
+ }
+}
diff --git a/driver-wrappers/mongodb-springdata-v3-wrapper/src/main/java/io/mongock/driver/cli/wrapper/mongodb/springdata/v3/SpringDataMongoV3DriverProvider.java b/driver-wrappers/mongodb-springdata-v3-wrapper/src/main/java/io/mongock/driver/cli/wrapper/mongodb/springdata/v3/SpringDataMongoV3DriverProvider.java
new file mode 100644
index 0000000..4a028ce
--- /dev/null
+++ b/driver-wrappers/mongodb-springdata-v3-wrapper/src/main/java/io/mongock/driver/cli/wrapper/mongodb/springdata/v3/SpringDataMongoV3DriverProvider.java
@@ -0,0 +1,59 @@
+package io.mongock.driver.cli.wrapper.mongodb.springdata.v3;
+
+import com.mongodb.client.MongoClient;
+import com.mongodb.client.MongoClients;
+import io.mongock.cli.util.CliConfiguration;
+import io.mongock.cli.util.ConnectionDriverProvider;
+import io.mongock.driver.api.driver.ConnectionDriver;
+import io.mongock.driver.mongodb.springdata.v3.SpringDataMongoV3Driver;
+import org.springframework.core.convert.converter.Converter;
+import org.springframework.data.mongodb.core.MongoTemplate;
+import org.springframework.data.mongodb.core.convert.MappingMongoConverter;
+import org.springframework.data.mongodb.core.convert.MongoCustomConversions;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class SpringDataMongoV3DriverProvider implements ConnectionDriverProvider {
+
+
+ @Override
+ public ConnectionDriver getDriver(CliConfiguration configuration) {
+
+
+ MongoTemplate mongoTemplate = getMongoTemplate(configuration.getDatabaseUrl(), configuration.getDatabaseName());
+
+ // Driver
+ SpringDataMongoV3Driver driver = SpringDataMongoV3Driver.withDefaultLock(mongoTemplate);
+ driver.enableTransaction();
+
+ return driver;
+ }
+
+ /**
+ * Main MongoTemplate for Mongock to work.
+ */
+ private static MongoTemplate getMongoTemplate(String connectionString, String dbName) {
+
+ MongoClient mongoClient = MongoClients.create(connectionString);
+ MongoTemplate mongoTemplate = new MongoTemplate(mongoClient, dbName);
+
+ // Custom converters to map ZonedDateTime.
+ MappingMongoConverter mongoMapping = (MappingMongoConverter) mongoTemplate.getConverter();
+ mongoMapping.setCustomConversions(customConversions());
+ mongoMapping.afterPropertiesSet();
+
+ return mongoTemplate;
+ }
+
+
+
+ private static MongoCustomConversions customConversions() {
+ List> converters = new ArrayList<>();
+ converters.add(DateToZonedDateTimeConverter.INSTANCE);
+ converters.add(ZonedDateTimeToDateConverter.INSTANCE);
+ return new MongoCustomConversions(converters);
+ }
+
+
+}
diff --git a/driver-wrappers/mongodb-springdata-v3-wrapper/src/main/java/io/mongock/driver/cli/wrapper/mongodb/springdata/v3/ZonedDateTimeToDateConverter.java b/driver-wrappers/mongodb-springdata-v3-wrapper/src/main/java/io/mongock/driver/cli/wrapper/mongodb/springdata/v3/ZonedDateTimeToDateConverter.java
new file mode 100644
index 0000000..3158965
--- /dev/null
+++ b/driver-wrappers/mongodb-springdata-v3-wrapper/src/main/java/io/mongock/driver/cli/wrapper/mongodb/springdata/v3/ZonedDateTimeToDateConverter.java
@@ -0,0 +1,17 @@
+package io.mongock.driver.cli.wrapper.mongodb.springdata.v3;
+
+import org.springframework.core.convert.converter.Converter;
+import org.springframework.data.convert.WritingConverter;
+
+import java.time.ZonedDateTime;
+import java.util.Date;
+
+@WritingConverter
+public enum ZonedDateTimeToDateConverter implements Converter {
+ INSTANCE;
+
+ @Override
+ public Date convert(ZonedDateTime source) {
+ return source == null ? null : Date.from(source.toInstant());
+ }
+}
diff --git a/driver-wrappers/pom.xml b/driver-wrappers/pom.xml
new file mode 100644
index 0000000..cdb062c
--- /dev/null
+++ b/driver-wrappers/pom.xml
@@ -0,0 +1,20 @@
+
+
+
+ mongock-cli-project
+ io.mongock
+ 5.0.28-SNAPSHOT
+
+ 4.0.0
+
+ driver-wrappers
+ pom
+
+ mongodb-springdata-v3-wrapper
+ mongodb-springdata-v2-wrapper
+
+
+
+
\ No newline at end of file
diff --git a/mongock-cli-core/pom.xml b/mongock-cli-core/pom.xml
index a6c2a8f..5993408 100644
--- a/mongock-cli-core/pom.xml
+++ b/mongock-cli-core/pom.xml
@@ -27,10 +27,12 @@
io.mongock
mongock-runner-core
+ ${mongock.community.version}
io.mongock.professional
mongock-runner-common
+ ${mongock.pro.version}
provided
true
diff --git a/mongock-cli-core/src/main/java/io/mongock/cli/core/CliCoreRunner.java b/mongock-cli-core/src/main/java/io/mongock/cli/core/CliCoreRunner.java
index c17dbf3..bd2a4e1 100644
--- a/mongock-cli-core/src/main/java/io/mongock/cli/core/CliCoreRunner.java
+++ b/mongock-cli-core/src/main/java/io/mongock/cli/core/CliCoreRunner.java
@@ -1,5 +1,6 @@
package io.mongock.cli.core;
+import io.mongock.api.exception.MongockException;
import io.mongock.cli.core.commands.MainCommand;
import io.mongock.cli.core.commands.migrate.MigrateCommand;
import io.mongock.cli.core.commands.undo.UndoCommand;
@@ -10,6 +11,8 @@
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.Callable;
+
+import io.mongock.runner.core.builder.RunnerBuilderProvider;
import picocli.CommandLine;
import static io.mongock.cli.core.commands.CommandName.MIGRATE;
@@ -32,6 +35,7 @@ public static class Builder {
private final Set commands = new HashSet<>();
private IFactory factory;
private RunnerBuilder builder;
+ private RunnerBuilderProvider builderProvider;
private Builder() {
}
@@ -51,7 +55,18 @@ public Builder runnerBuilder(RunnerBuilder builder) {
return this;
}
+ public Builder runnerBuilderProvider(RunnerBuilderProvider builderProvider) {
+ this.builderProvider = builderProvider;
+ return this;
+ }
+
public CommandLine build() {
+ if(builder == null) {
+ if(builderProvider == null) {
+ throw new MongockException("Not injected RunnerBuilder nor RunnerBuilderProvider");
+ }
+ builder = builderProvider.getBuilder();
+ }
addCommand(UNDO , new UndoCommand(builder));
addCommand(MIGRATE, new MigrateCommand(builder));
addCommand(STATE, new StateCommand(builder));
diff --git a/mongock-cli-springboot/pom.xml b/mongock-cli-springboot/pom.xml
index ea0370c..bbfb709 100644
--- a/mongock-cli-springboot/pom.xml
+++ b/mongock-cli-springboot/pom.xml
@@ -32,6 +32,7 @@
io.mongock
mongock-runner-core
+ ${mongock.community.version}
diff --git a/mongock-cli-util/pom.xml b/mongock-cli-util/pom.xml
index 4bafe7c..672159d 100644
--- a/mongock-cli-util/pom.xml
+++ b/mongock-cli-util/pom.xml
@@ -18,6 +18,13 @@
+
+
+ io.mongock
+ mongock-driver-api
+ ${mongock.community.version}
+
+
com.diogonunes
JColor
diff --git a/mongock-cli-util/src/main/java/io/mongock/cli/util/CliConfiguration.java b/mongock-cli-util/src/main/java/io/mongock/cli/util/CliConfiguration.java
new file mode 100644
index 0000000..03a272d
--- /dev/null
+++ b/mongock-cli-util/src/main/java/io/mongock/cli/util/CliConfiguration.java
@@ -0,0 +1,157 @@
+package io.mongock.cli.util;
+
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.util.Optional;
+
+public class CliConfiguration {
+
+ private String driverName;
+
+ private String databaseUrl;
+
+ private String databaseName;
+
+
+ private String jarsLibFolder;
+
+ private String cliVersion;
+
+ private String scanPackage;
+
+ private String licenseKey;
+
+ private String userApplication;
+
+ private String userChangeUnit;
+
+ public static Builder fileBuilder() {
+ return new Builder();
+ }
+
+ public CliConfiguration setScanPackage(String scanPackage) {
+ this.scanPackage = scanPackage;
+ return this;
+ }
+
+ public String getScanPackage() {
+ return scanPackage;
+ }
+
+
+ public CliConfiguration setUserAppIfNotNull(String userApplication) {
+ this.userApplication = userApplication != null ? userApplication : this.userApplication;
+ return this;
+ }
+
+ public Optional getUserApplication() {
+ return Optional.ofNullable(userApplication);
+ }
+
+ public Optional getUserChangeUnit() {
+ return Optional.ofNullable(userChangeUnit);
+ }
+
+ public CliConfiguration setUserChangeUnitIfNotNull(String userChangeUnit) {
+ this.userChangeUnit = userChangeUnit != null ? userChangeUnit : this.userChangeUnit;
+ return this;
+ }
+
+ public CliConfiguration setJarsLibFolder(String jarsLibFolder) {
+ this.jarsLibFolder = jarsLibFolder;
+ return this;
+ }
+
+ public CliConfiguration setCliVersion(String cliVersion) {
+ this.cliVersion = cliVersion;
+ return this;
+ }
+
+
+ public DriverWrapper getDriverWrapper() {
+ return DriverWrapper.getDriver(driverName)
+ .setJarsLibFolder(jarsLibFolder)
+ .setVersion(cliVersion);
+ }
+
+ public CliConfiguration setDriverNameIfNotNull(String driverName) {
+ this.driverName = driverName != null ? driverName : this.driverName;
+ return this;
+ }
+
+ public Optional getLicenseKey() {
+ return Optional.ofNullable(licenseKey);
+ }
+
+ public CliConfiguration setLicenseKeyIfNotNull(String licenseKey) {
+ this.licenseKey = licenseKey != null ? licenseKey : this.licenseKey;
+ return this;
+ }
+
+ public String getDatabaseUrl() {
+ return databaseUrl;
+ }
+
+ public CliConfiguration setDatabaseUrl(String databaseUrl) {
+ this.databaseUrl = databaseUrl != null ? databaseUrl : this.databaseUrl;
+ return this;
+ }
+
+ public String getDatabaseName() {
+ return databaseName;
+ }
+
+ public CliConfiguration setDatabaseName(String databaseName) {
+ this.databaseName = databaseName != null ? databaseName : this.databaseName;
+ return this;
+ }
+
+ public static class Builder {
+
+ private String configFile;
+
+ private Builder() {
+ }
+
+
+ public Builder setConfigFile(String configFile) {
+ this.configFile = configFile;
+ return this;
+ }
+
+
+ public CliConfiguration build() {
+ try {
+ CliConfiguration config = new CliConfiguration();
+ for (String configLine : Files.readAllLines(Paths.get(configFile))) {
+ if (configLine != null && !configLine.isEmpty()) {
+ String[] parts = configLine.split("=");
+ setConfigValue(config, parts[0], parts[1]);
+ }
+ }
+ return config;
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ private CliConfiguration setConfigValue(CliConfiguration config, String propertyName, String propertyValue) {
+ switch (propertyName.toLowerCase()) {
+ case "licensekey":
+ return config.setLicenseKeyIfNotNull(propertyValue);
+ case "scanpackage":
+ return config.setScanPackage(propertyValue);
+ case "driver":
+ return config.setDriverNameIfNotNull(propertyValue);
+ case "databaseurl":
+ return config.setDatabaseUrl(propertyValue);
+ case "databasename":
+ return config.setDatabaseName(propertyValue);
+
+ default:
+ return config;//IGNORED
+ }
+ }
+
+ }
+}
diff --git a/mongock-cli-util/src/main/java/io/mongock/cli/util/ConnectionDriverProvider.java b/mongock-cli-util/src/main/java/io/mongock/cli/util/ConnectionDriverProvider.java
new file mode 100644
index 0000000..e9e22b0
--- /dev/null
+++ b/mongock-cli-util/src/main/java/io/mongock/cli/util/ConnectionDriverProvider.java
@@ -0,0 +1,7 @@
+package io.mongock.cli.util;
+
+import io.mongock.driver.api.driver.ConnectionDriver;
+
+public interface ConnectionDriverProvider {
+ ConnectionDriver getDriver(CliConfiguration configuration);
+}
diff --git a/mongock-cli-util/src/main/java/io/mongock/cli/util/DriverWrapper.java b/mongock-cli-util/src/main/java/io/mongock/cli/util/DriverWrapper.java
new file mode 100644
index 0000000..d46560b
--- /dev/null
+++ b/mongock-cli-util/src/main/java/io/mongock/cli/util/DriverWrapper.java
@@ -0,0 +1,44 @@
+package io.mongock.cli.util;
+
+import java.util.Arrays;
+import java.util.stream.Collectors;
+
+public enum DriverWrapper {
+ MONGODB_SPRING_DATA_V3("%s/mongodb-springdata-v3-wrapper-%s.jar"),
+ MONGODB_SPRING_DATA_V2("%s/mongodb-springdata-v2-wrapper-%s.jar");
+
+ private final String jarTemplate;
+ private String jarsLibFolder;
+ private String version;
+
+ DriverWrapper(String template) {
+ this.jarTemplate = template;
+ }
+
+ public DriverWrapper setJarsLibFolder(String jarsLibFolder) {
+ this.jarsLibFolder = jarsLibFolder;
+ return this;
+ }
+
+ public DriverWrapper setVersion(String version) {
+ this.version = version;
+ return this;
+ }
+
+ public String getJarPath() {
+ return String.format(jarTemplate, jarsLibFolder, version);
+ }
+
+ public static DriverWrapper getDriver(String driverName) {
+ return valueOf(driverName.toUpperCase());
+ }
+
+ public static String getAllDriverNames(String separator) {
+ return Arrays.stream(values())
+ .map(DriverWrapper::name)
+ .collect(Collectors.joining(separator));
+
+ }
+
+
+}
diff --git a/mongock-cli-util/src/main/java/io/mongock/cli/util/MongockDefaultApp.java b/mongock-cli-util/src/main/java/io/mongock/cli/util/MongockDefaultApp.java
new file mode 100644
index 0000000..f853c3a
--- /dev/null
+++ b/mongock-cli-util/src/main/java/io/mongock/cli/util/MongockDefaultApp.java
@@ -0,0 +1,12 @@
+package io.mongock.cli.util;
+
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Target(ElementType.TYPE)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface MongockDefaultApp {
+}
diff --git a/mongock-cli-util/src/main/java/io/mongock/cli/util/RunnerBuilderProviderConfigurable.java b/mongock-cli-util/src/main/java/io/mongock/cli/util/RunnerBuilderProviderConfigurable.java
new file mode 100644
index 0000000..ca71678
--- /dev/null
+++ b/mongock-cli-util/src/main/java/io/mongock/cli/util/RunnerBuilderProviderConfigurable.java
@@ -0,0 +1,5 @@
+package io.mongock.cli.util;
+
+public interface RunnerBuilderProviderConfigurable {
+ void setConfiguration(CliConfiguration configuration);
+}
diff --git a/mongock-cli-util/src/main/java/io/mongock/cli/util/logger/CliLogger.java b/mongock-cli-util/src/main/java/io/mongock/cli/util/logger/CliLogger.java
index 1e761b9..c2962da 100644
--- a/mongock-cli-util/src/main/java/io/mongock/cli/util/logger/CliLogger.java
+++ b/mongock-cli-util/src/main/java/io/mongock/cli/util/logger/CliLogger.java
@@ -37,6 +37,7 @@ default void trace(String format, Object... arguments) {
print(TRACE, format, arguments);
}
+
default void debug(String format, Object... arguments) {
print(DEBUG, format, arguments);
}
@@ -49,14 +50,24 @@ default void warn(String format, Object... arguments) {
print(WARN, format, arguments);
}
-// void warn(String format, Throwable th);
+
+
+ default void warn(Throwable ex) {
+ print(WARN, ex);
+ }
default void error(String format, Object... arguments) {
print(ERROR, format, arguments);
}
+ default void error(Throwable ex) {
+ print(ERROR, ex);
+ }
+
// void error(String format, Throwable th);
void print(Level level, String format, Object... arguments);
+
+ void print(Level level, Throwable ex);
}
diff --git a/mongock-cli-util/src/main/java/io/mongock/cli/util/logger/CliLoggerFactory.java b/mongock-cli-util/src/main/java/io/mongock/cli/util/logger/CliLoggerFactory.java
index 307707a..d4aeb1f 100644
--- a/mongock-cli-util/src/main/java/io/mongock/cli/util/logger/CliLoggerFactory.java
+++ b/mongock-cli-util/src/main/java/io/mongock/cli/util/logger/CliLoggerFactory.java
@@ -78,6 +78,14 @@ public void print(Level level, String format, Object... arguments) {
}
}
+ @Override
+ public void print(Level level, Throwable ex) {
+ if(shouldLog(level)) {
+ ex.printStackTrace(level.isGreaterEqual(ERROR) ? System.err : System.out);
+ }
+
+ }
+
private String getFormattedClassName(String classname) {
String finalClassName = className;
diff --git a/mongock-cli/pom.xml b/mongock-cli/pom.xml
index 24cd445..58d5a90 100644
--- a/mongock-cli/pom.xml
+++ b/mongock-cli/pom.xml
@@ -15,6 +15,7 @@
1.8
1.8
1.8
+
@@ -33,20 +34,66 @@
mongock-cli-util
${project.version}
+
+
+ io.mongock
+ mongock-default-app
+ ${project.version}
+
+
+
+ io.mongock
+ mongock-default-app-professional
+ ${project.version}
+
io.mongock
mongock-api
+ ${mongock.community.version}
+
+
io.mongock
mongock-runner-core
+ ${mongock.community.version}
+
+
+
+
+
+ io.mongock
+ mongock-standalone
+ ${mongock.community.version}
+
+ io.mongock.professional
+ mongock-standalone
+ ${mongock.pro.version}
+
+
+
+
+
+ io.mongock
+ mongodb-springdata-v3-wrapper
+ ${project.version}
+
+
+
+ io.mongock
+ mongodb-springdata-v2-wrapper
+ ${project.version}
+
+
+
+
org.slf4j
slf4j-api
- 1.7.32
+ ${slf4j.version}
org.springframework.boot
@@ -111,6 +158,7 @@
+
org.apache.maven.plugins
maven-shade-plugin
@@ -121,8 +169,12 @@
shade
+
false
+
*:*
diff --git a/mongock-cli/src/main/java/io/mongock/cli/wrapper/MongockCli.java b/mongock-cli/src/main/java/io/mongock/cli/wrapper/MongockCli.java
index 791d198..6efd5ff 100644
--- a/mongock-cli/src/main/java/io/mongock/cli/wrapper/MongockCli.java
+++ b/mongock-cli/src/main/java/io/mongock/cli/wrapper/MongockCli.java
@@ -1,63 +1,80 @@
package io.mongock.cli.wrapper;
+import io.mongock.cli.util.CliConfiguration;
import io.mongock.cli.util.banner.Banner;
import io.mongock.cli.util.logger.CliLogger;
import io.mongock.cli.util.logger.CliLoggerFactory;
+import io.mongock.cli.wrapper.argument.Argument;
+import io.mongock.cli.wrapper.argument.ArgumentsHolder;
+import io.mongock.cli.wrapper.jars.JarFactory;
import io.mongock.cli.wrapper.launcher.LauncherCliJar;
-import io.mongock.cli.wrapper.util.ArgsUtil;
import java.util.stream.Stream;
import static io.mongock.cli.util.logger.CliLogger.Level.INFO;
-import static io.mongock.cli.wrapper.util.ArgsUtil.getCleanArgs;
-import static io.mongock.cli.wrapper.util.Parameters.APP_JAR_ARG_LONG;
-import static io.mongock.cli.wrapper.util.Parameters.APP_JAR_ARG_SHORT;
-import static io.mongock.cli.wrapper.util.Parameters.CLI_CORE_JAR_ARG;
-import static io.mongock.cli.wrapper.util.Parameters.CLI_SPRING_JAR_ARG;
-import static io.mongock.cli.wrapper.util.Parameters.LOG_LEVEL_ARG;
-import static io.mongock.cli.wrapper.util.Parameters.MONGOCK_CORE_JAR_ARG;
+import static io.mongock.cli.wrapper.argument.Argument.CLI_VERSION;
+import static io.mongock.cli.wrapper.argument.Argument.COMMUNITY_VERSION;
+import static io.mongock.cli.wrapper.argument.Argument.DRIVER;
+import static io.mongock.cli.wrapper.argument.Argument.LICENSE_KEY;
+import static io.mongock.cli.wrapper.argument.Argument.LOG_LEVEL;
+import static io.mongock.cli.wrapper.argument.Argument.PROFESSIONAL_VERSION;
+import static io.mongock.cli.wrapper.argument.Argument.USER_APP_JAR;
+import static io.mongock.cli.wrapper.argument.Argument.USER_CHANGE_UNIT_JAR;
+import static io.mongock.cli.wrapper.argument.Argument.USER_CONFIGURATION;
public class MongockCli {
- private static final CliLogger logger = CliLoggerFactory.getLogger(MongockCli.class);
- private static final String[] argumentsToCleanUp = {
- APP_JAR_ARG_LONG,
- APP_JAR_ARG_SHORT,
- CLI_SPRING_JAR_ARG,
- CLI_CORE_JAR_ARG,
- LOG_LEVEL_ARG,
- MONGOCK_CORE_JAR_ARG
- };
+ private static final String JARS_LIB = "lib";
+
+ private static ArgumentsHolder argumentsHolder;
+ private static final CliLogger logger = CliLoggerFactory.getLogger(MongockCli.class);
static {
Banner.print(System.out);
}
public static void main(String... args) {
- setLogger(args);
+ Argument.validateArguments();
+ argumentsHolder = new ArgumentsHolder(args);
+ setLogger();
printArgs(args);
-
try {
- String appJar = ArgsUtil.getOptionalParam(args, APP_JAR_ARG_LONG)
- .orElseGet(() -> ArgsUtil.getParameter(args, APP_JAR_ARG_SHORT, false));
-
- LauncherCliJar.builder()
- .setAppJarFile(appJar)
- .setCliCoreJar(ArgsUtil.getParameter(args, CLI_CORE_JAR_ARG, false))
- .setCliSpringJar(ArgsUtil.getParameter(args, CLI_SPRING_JAR_ARG, false))
- .setMongockCoreJarFile(ArgsUtil.getParameter(args, MONGOCK_CORE_JAR_ARG, false))
+ LauncherCliJar.builder(buildJarFactory())
+ .setConfiguration(getConfiguration())
.build()
- .loadClasses()
- .launch(getCleanArgs(args, argumentsToCleanUp));
+ .launch(argumentsHolder.getCleanArgs());
System.exit(0);
} catch (Exception ex) {
- logger.error(ex.getMessage());
+ logger.error(ex);
System.exit(1);
}
}
+ private static CliConfiguration getConfiguration() {
+ return argumentsHolder.getOptional(USER_CONFIGURATION)
+ .map(file -> CliConfiguration.fileBuilder().setConfigFile(file).build())
+ .orElseGet(CliConfiguration::new)
+ .setJarsLibFolder(JARS_LIB)
+ .setCliVersion(argumentsHolder.getOrException(CLI_VERSION))
+ .setDriverNameIfNotNull(argumentsHolder.getOrNull(DRIVER))
+ .setUserAppIfNotNull(argumentsHolder.getOrNull(USER_APP_JAR))
+ .setUserChangeUnitIfNotNull(argumentsHolder.getOrNull(USER_CHANGE_UNIT_JAR))
+ .setLicenseKeyIfNotNull(argumentsHolder.getOrNull(LICENSE_KEY))
+ ;
+ }
+
+
+ private static JarFactory buildJarFactory() {
+ return new JarFactory(
+ JARS_LIB,
+ argumentsHolder.getOrException(CLI_VERSION),
+ argumentsHolder.getOrException(COMMUNITY_VERSION),
+ argumentsHolder.getOrException(PROFESSIONAL_VERSION));
+ }
+
+
// Unneeded loop when level > DEBUG...but small ;)
private static void printArgs(String[] args) {
StringBuilder sb = new StringBuilder("CLI arguments: ");
@@ -65,8 +82,8 @@ private static void printArgs(String[] args) {
logger.debug(sb.toString());
}
- private static void setLogger(String[] args) {
- CliLoggerFactory.setLevel(ArgsUtil.getOptionalParam(args, LOG_LEVEL_ARG)
+ private static void setLogger() {
+ CliLoggerFactory.setLevel(argumentsHolder.getOptional(LOG_LEVEL)
.map(CliLogger.Level::fromStringDefaultInfo)
.orElse(INFO));
}
diff --git a/mongock-cli/src/main/java/io/mongock/cli/wrapper/argument/Argument.java b/mongock-cli/src/main/java/io/mongock/cli/wrapper/argument/Argument.java
new file mode 100644
index 0000000..9bef6e6
--- /dev/null
+++ b/mongock-cli/src/main/java/io/mongock/cli/wrapper/argument/Argument.java
@@ -0,0 +1,58 @@
+package io.mongock.cli.wrapper.argument;
+
+import java.util.HashSet;
+import java.util.Set;
+
+public enum Argument {
+
+
+ USER_APP_JAR("-aj", "--app-jar"),
+ USER_CHANGE_UNIT_JAR("-cj", "--changes-jar"),
+ USER_CONFIGURATION("-cf", "--config-file"),
+
+ DRIVER("-d", "--driver"),
+ LICENSE_KEY("-lk", "--license-key"),
+
+ CLI_VERSION("-cv", "--cli-version"),
+ COMMUNITY_VERSION("-mcv", "--mongock-community-version"),
+ PROFESSIONAL_VERSION("-mpv", "--mongock-professional-version"),
+ LOG_LEVEL("-ll", "--log-level")
+ ;
+
+ private final String shortName;
+ private final String longName;
+
+ Argument(String shortName, String longName) {
+ this.shortName = shortName;
+ this.longName = longName;
+ }
+
+
+ public String getShortName() {
+ return shortName;
+ }
+
+ public String getLongName() {
+ return longName;
+ }
+
+ public String getDefaultName() {
+ return getLongName();
+ }
+
+ public static void validateArguments() {
+ Set insertedValues = new HashSet<>();
+ for(Argument arg: values()) {
+ checkValueInserted(insertedValues, arg.getLongName());
+ checkValueInserted(insertedValues, arg.getShortName());
+ insertedValues.add(arg.getLongName());
+ insertedValues.add(arg.getShortName());
+ }
+ }
+
+ private static void checkValueInserted(Set values, String value) {
+ if(values.contains(value)) {
+ throw new RuntimeException(String.format("Argument[%s] duplicated", value));
+ }
+ }
+}
diff --git a/mongock-cli/src/main/java/io/mongock/cli/wrapper/argument/ArgumentsHolder.java b/mongock-cli/src/main/java/io/mongock/cli/wrapper/argument/ArgumentsHolder.java
new file mode 100644
index 0000000..de19970
--- /dev/null
+++ b/mongock-cli/src/main/java/io/mongock/cli/wrapper/argument/ArgumentsHolder.java
@@ -0,0 +1,95 @@
+package io.mongock.cli.wrapper.argument;
+
+import io.mongock.cli.util.logger.CliLogger;
+import io.mongock.cli.util.logger.CliLoggerFactory;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+import java.util.Optional;
+import java.util.Set;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+public class ArgumentsHolder {
+
+ private static final CliLogger logger = CliLoggerFactory.getLogger(ArgumentsHolder.class);
+
+ private final String[] args;
+
+ public ArgumentsHolder(String[] args) {
+ this.args = args;
+ }
+
+ public String[] getCleanArgs() {
+
+ StringBuilder sb = new StringBuilder("cleaning arguments: ");
+ Set paramNamesSet = Arrays
+ .stream(Argument.values())
+ .map(arg -> Arrays.asList(arg.getLongName(), arg.getShortName()))
+ .flatMap(Collection::stream)
+ .collect(Collectors.toSet())
+ .stream()
+ .peek(arg -> sb.append(arg).append(" "))
+ .map(String::toLowerCase)
+ .collect(Collectors.toSet());
+ logger.debug(sb.toString());
+
+
+ List tempNewArgs = new ArrayList<>();
+
+ for (int i = 0; i < args.length; i++) {
+ if (!paramNamesSet.contains(args[i].toLowerCase())) {
+ tempNewArgs.add(args[i]);
+ } else {
+ i++;
+ }
+ }
+
+ String[] newArgs = new String[tempNewArgs.size()];
+ tempNewArgs.toArray(newArgs);
+ logger.debug("cleaned args size: " + newArgs.length);
+ StringBuilder sb2 = new StringBuilder("cleaned args: ");
+ Stream.of(newArgs).forEach(arg -> sb2.append(arg).append(" "));
+ logger.debug(sb2.toString());
+ return newArgs;
+ }
+
+ public String getOrNull(Argument argument) {
+ return getByArgument(argument, false);
+ }
+
+ public String getOrException(Argument argument) {
+ return getByArgument(argument, true);
+ }
+
+ public Optional getOptional(Argument argument) {
+ return Optional.ofNullable(getByArgument(argument, false));
+ }
+
+ private String getByArgument(Argument argument, boolean throwException) {
+ String value;
+ if (((value = getValue(argument.getShortName())) == null) && ((value = getValue(argument.getLongName())) == null) && throwException) {
+ String argumentName = argument.getLongName() + " or " + argument.getShortName();
+ throw new RuntimeException(
+ String.format("Found [%s] flag with missing value. Please follow the format \"%s value\"", argumentName, argumentName)
+ );
+ }
+ return value;
+ }
+
+ private String getValue(String paramName) {
+ int i = 0;
+ do {
+ if (paramName.equalsIgnoreCase(args[i])) {
+ if (args.length == i + 1) {
+ return null;
+ }
+ return args[i + 1];
+ }
+ } while ((++i) < args.length);
+ return null;
+ }
+
+}
diff --git a/mongock-cli/src/main/java/io/mongock/cli/wrapper/jars/CliClassLoader.java b/mongock-cli/src/main/java/io/mongock/cli/wrapper/jars/CliClassLoader.java
new file mode 100644
index 0000000..c432b73
--- /dev/null
+++ b/mongock-cli/src/main/java/io/mongock/cli/wrapper/jars/CliClassLoader.java
@@ -0,0 +1,83 @@
+package io.mongock.cli.wrapper.jars;
+
+import io.mongock.cli.util.logger.CliLogger;
+import io.mongock.cli.util.logger.CliLoggerFactory;
+
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.List;
+import java.util.function.Function;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
+
+public class CliClassLoader {
+ private static final CliLogger logger = CliLoggerFactory.getLogger(CliClassLoader.class);
+ private static final String CLASS_EXT = ".class";
+ private static final String SPRINGBOOT_PREFIX = "org/springframework/boot";
+
+ private static final Function springBootEntryFilter = entryName ->
+ entryName.startsWith(SPRINGBOOT_PREFIX) && entryName.endsWith(CLASS_EXT);
+
+ private static final Function nonSpringBootEntryFilter = entryName -> entryName.endsWith(CLASS_EXT);
+
+
+ private final List jars = new ArrayList<>();
+ private URLClassLoader classLoader;
+
+ public CliClassLoader addJar(Jar jar) {
+ jars.add(jar);
+ return this;
+ }
+
+ public CliClassLoader addJars(List jars) {
+ jars.addAll(jars);
+ return this;
+ }
+
+ public void loadClasses() {
+ URLClassLoader classLoader = getClassLoader();
+ jars.forEach(jar -> CliClassLoader.loadJarClasses(jar, classLoader));
+ }
+
+ public static void loadJarClasses(Jar jar, URLClassLoader classLoader) {
+ try {
+ JarFile appJarFile = jar.getJarFile();
+ logger.debug("loading jar: %s, with classLoader %s", appJarFile.getName(), classLoader.getClass().getName());
+ Thread.currentThread().getContextClassLoader();
+ Enumeration jarEntryEnum = appJarFile.entries();
+ Function jarEntryFilter = jar.isSpringApplication()
+ ? springBootEntryFilter
+ : nonSpringBootEntryFilter;
+
+ while (jarEntryEnum.hasMoreElements()) {
+ String entryName = jarEntryEnum.nextElement().getName();
+
+
+ if (jarEntryFilter.apply(entryName)) {
+ String className = entryName.substring(0, entryName.lastIndexOf(CLASS_EXT)).replace('/', '.');
+ try {
+ classLoader.loadClass(className);
+ } catch (Throwable e) {
+ logger.warn(String.format("%s not loaded(%s)", className, e.getMessage()));
+ }
+ logger.trace("Loaded: " + className);
+ }
+ }
+ appJarFile.close();
+ } catch (Exception ex) {
+ throw new RuntimeException(ex);
+ }
+ }
+
+ public URLClassLoader getClassLoader() {
+ if (classLoader == null) {
+ classLoader = URLClassLoader.newInstance(
+ jars.stream().map(Jar::getUrl).toArray(URL[]::new),
+ Thread.currentThread().getContextClassLoader()
+ );
+ }
+ return classLoader;
+ }
+}
diff --git a/mongock-cli/src/main/java/io/mongock/cli/wrapper/jars/Jar.java b/mongock-cli/src/main/java/io/mongock/cli/wrapper/jars/Jar.java
new file mode 100644
index 0000000..bde79d3
--- /dev/null
+++ b/mongock-cli/src/main/java/io/mongock/cli/wrapper/jars/Jar.java
@@ -0,0 +1,82 @@
+package io.mongock.cli.wrapper.jars;
+
+import io.mongock.cli.wrapper.launcher.LauncherSpringboot;
+import org.springframework.boot.loader.archive.JarFileArchive;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.jar.Attributes;
+import java.util.jar.JarFile;
+import java.util.jar.Manifest;
+
+public class Jar {
+
+ public static final String JAR_URL_TEMPLATE = "jar:file:%s!/";
+ private final String jarPath;
+
+ public Jar(String jarPath) {
+ this.jarPath = jarPath;
+ }
+
+ public String getPath() {
+ return jarPath;
+ }
+
+ public URL getUrl() {
+ try {
+ return new URL(String.format(JAR_URL_TEMPLATE, jarPath));
+ } catch (MalformedURLException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public JarFile getJarFile() {
+ try {
+ return new JarFile(jarPath);
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public JarFileArchive getJarFileArchive() {
+ try {
+ return new JarFileArchive(new File(jarPath));
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public Class> getMainClass(ClassLoader classLoader) throws ClassNotFoundException {
+ String className = getMainClassName();
+ return classLoader.loadClass(className);
+ }
+
+ public String getMainClassName() {
+ JarFileArchive archive = getJarFileArchive();
+ String className = getAttributes(archive).getValue(Attributes.Name.MAIN_CLASS);
+ return className;
+ }
+
+ public boolean isSpringApplication() {
+ JarFileArchive archive = getJarFileArchive();
+ return getAttributes(archive).getValue(LauncherSpringboot.BOOT_CLASSPATH_INDEX_ATTRIBUTE) != null;
+ }
+
+ private static Attributes getAttributes(JarFileArchive archive) {
+ try {
+ Manifest manifest = archive.getManifest();
+ if(manifest == null) {
+ throw new RuntimeException("manifest not present in the appJar");
+ }
+ Attributes attributes = manifest.getMainAttributes();
+ if(attributes == null) {
+ throw new RuntimeException("Mongock CLI cannot access to attributes in manifest");
+ }
+ return attributes;
+ } catch (IOException ex) {
+ throw new RuntimeException(ex);
+ }
+ }
+}
diff --git a/mongock-cli/src/main/java/io/mongock/cli/wrapper/jars/JarFactory.java b/mongock-cli/src/main/java/io/mongock/cli/wrapper/jars/JarFactory.java
new file mode 100644
index 0000000..d939c1a
--- /dev/null
+++ b/mongock-cli/src/main/java/io/mongock/cli/wrapper/jars/JarFactory.java
@@ -0,0 +1,50 @@
+package io.mongock.cli.wrapper.jars;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+public class JarFactory {
+ private final String jarsLib;
+ private final String cliVersion;
+ private final String mongockCommunityVersion;
+ private final String mongockProVersion;
+
+
+ public JarFactory(String jarsLib, String cliVersion, String mongockCommunityVersion, String mongockProVersion) {
+ this.jarsLib = jarsLib;
+ this.cliVersion = cliVersion;
+ this.mongockCommunityVersion = mongockCommunityVersion;
+ this.mongockProVersion = mongockProVersion;
+ }
+
+ public Jar defaultApp() {
+ return new Jar(String.format("%s/mongock-default-app-%s.jar", jarsLib, cliVersion));
+ }
+
+ public Jar defaultProfessionalApp() {
+ return new Jar(String.format("%s/mongock-default-app-professional-%s.jar", jarsLib, cliVersion));
+ }
+
+ public Jar cliSpringboot() {
+ return new Jar(String.format("%s/mongock-cli-springboot-%s.jar", jarsLib, cliVersion));
+ }
+
+ public Jar cliCore() {
+ return new Jar(String.format("%s/mongock-cli-core-%s.jar", jarsLib, cliVersion));
+ }
+
+ public List runnerCommunityDependencies() {
+ return Arrays.asList(
+ new Jar(String.format("%s/mongock-standalone-base-%s.jar", jarsLib, mongockCommunityVersion)),
+ new Jar(String.format("%s/mongock-standalone-%s.jar", jarsLib, mongockCommunityVersion))
+ );
+ }
+
+ //TODO generify versions
+ public List runnerProfessionalDependencies() {
+ return Collections.emptyList();
+ }
+
+
+}
diff --git a/mongock-cli/src/main/java/io/mongock/cli/wrapper/launcher/LauncherCliJar.java b/mongock-cli/src/main/java/io/mongock/cli/wrapper/launcher/LauncherCliJar.java
index 9bdd003..208a8e6 100644
--- a/mongock-cli/src/main/java/io/mongock/cli/wrapper/launcher/LauncherCliJar.java
+++ b/mongock-cli/src/main/java/io/mongock/cli/wrapper/launcher/LauncherCliJar.java
@@ -1,103 +1,88 @@
package io.mongock.cli.wrapper.launcher;
-import io.mongock.cli.wrapper.util.JarUtil;
-import org.springframework.boot.loader.archive.JarFileArchive;
+import io.mongock.cli.util.CliConfiguration;
+import io.mongock.cli.util.DriverWrapper;
+import io.mongock.cli.wrapper.jars.CliClassLoader;
+import io.mongock.cli.wrapper.jars.Jar;
+import io.mongock.cli.wrapper.jars.JarFactory;
-import java.io.File;
-import java.io.IOException;
-import java.util.Optional;
+import static io.mongock.cli.wrapper.argument.Argument.DRIVER;
-import static io.mongock.cli.wrapper.util.Parameters.APP_JAR_ARG_LONG;
-import static io.mongock.cli.wrapper.util.Parameters.CLI_CORE_JAR_ARG;
-import static io.mongock.cli.wrapper.util.Parameters.CLI_SPRING_JAR_ARG;
-import static io.mongock.cli.wrapper.util.Parameters.MONGOCK_CORE_JAR_ARG;
public interface LauncherCliJar {
- LauncherCliJar loadClasses();
-
void launch(String[] args);
- static LauncherBuilder builder() {
- return new LauncherBuilder();
+ static LauncherBuilder builder(JarFactory jarFactory) {
+ return new LauncherBuilder(jarFactory);
}
class LauncherBuilder {
- private String cliSpringJar;
- private String cliCoreJar;
-
- private String appJarFile;
-
- private String mongockCoreJarFile;
+ private JarFactory jarFactory;
+ private CliConfiguration configuration;
-
- public LauncherBuilder() {
+ public LauncherBuilder(JarFactory jarFactory) {
+ this.jarFactory = jarFactory;
}
- public LauncherBuilder setAppJarFile(String appJarFile) {
- this.appJarFile = appJarFile;
+ public LauncherBuilder setConfiguration(CliConfiguration configuration) {
+ this.configuration = configuration;
return this;
}
- public LauncherBuilder setCliSpringJar(String cliSpringJar) {
- this.cliSpringJar = cliSpringJar;
- return this;
- }
- public LauncherBuilder setCliCoreJar(String cliCoreJar) {
- this.cliCoreJar = cliCoreJar;
- return this;
- }
-
- public LauncherBuilder setMongockCoreJarFile(String mongockCoreJarFile) {
- this.mongockCoreJarFile = mongockCoreJarFile;
- return this;
- }
-
- public LauncherCliJar build() throws IOException {
- if (getAppJar().isPresent()) {
- JarFileArchive archive = new JarFileArchive(new File(appJarFile));
- if (JarUtil.isSpringApplication(archive)) {
- return buildLauncherSpring(archive);
+ public LauncherCliJar build() {
+ if (configuration.getUserApplication().isPresent()) {
+ Jar userApplicationJar = new Jar(configuration.getUserApplication().get());
+ if (userApplicationJar.isSpringApplication()) {
+ new CliClassLoader().addJar(userApplicationJar).loadClasses();
+ return new LauncherSpringboot(userApplicationJar, jarFactory.cliSpringboot());
} else {
- return buildLauncherStandalone(archive);
+
+ CliClassLoader cliClassLoader = new CliClassLoader()
+ .addJar(userApplicationJar)
+ .addJar(jarFactory.cliCore());
+ cliClassLoader.loadClasses();
+ return new LauncherStandalone(userApplicationJar, cliClassLoader.getClassLoader());
}
+ } else if(configuration.getUserChangeUnit().isPresent()) {
+ DriverWrapper driverWrapper = configuration.getDriverWrapper();
+ CliClassLoader cliClassLoader = new CliClassLoader()
+ .addJar(isProfessional() ? jarFactory.defaultProfessionalApp() : jarFactory.defaultApp())
+ .addJar(jarFactory.cliCore())
+ .addJar(new Jar(driverWrapper.getJarPath()))
+ .addJars(isProfessional() ? jarFactory.runnerProfessionalDependencies() : jarFactory.runnerCommunityDependencies())
+ .addJar(new Jar(configuration.getUserChangeUnit().get()));
+ cliClassLoader.loadClasses();
+ validateDriverIfApply(driverWrapper);
+ return new LauncherDefault(
+ isProfessional() ? jarFactory.defaultProfessionalApp() : jarFactory.defaultApp(),
+ cliClassLoader.getClassLoader(),
+ configuration.getLicenseKey().get(),
+ driverWrapper,
+ configuration
+ );
+
} else {
- return buildLauncherWithoutApp();
+ throw new RuntimeException("Either an application jar or a jar containing the change units must be provided");
}
}
- private LauncherDefault buildLauncherWithoutApp() {
- validateNotNullParameter(mongockCoreJarFile, "parameter " + MONGOCK_CORE_JAR_ARG);
- validateNotNullParameter(cliCoreJar, "parameter " + CLI_CORE_JAR_ARG);
- return new LauncherDefault(mongockCoreJarFile, cliCoreJar);
- }
-
- private LauncherStandalone buildLauncherStandalone(JarFileArchive archive) {
- validateNotNullParameter(appJarFile, "parameter " + APP_JAR_ARG_LONG);
- validateNotNullParameter(cliCoreJar, "parameter " + CLI_CORE_JAR_ARG);
- return new LauncherStandalone(archive, appJarFile, cliCoreJar);
+ private boolean isProfessional() {
+ return configuration.getLicenseKey().isPresent();
}
- private LauncherSpringboot buildLauncherSpring(JarFileArchive archive) {
- validateNotNullParameter(appJarFile, "parameter " + APP_JAR_ARG_LONG);
- validateNotNullParameter(cliSpringJar, "parameter " + CLI_SPRING_JAR_ARG);
- return new LauncherSpringboot(archive, appJarFile, cliSpringJar);
- }
-
-
- private Optional getAppJar() {
- return Optional.ofNullable(appJarFile);
+ private void validateDriverIfApply(DriverWrapper driverWrapper) {
+ if (driverWrapper == null) {
+ throw new RuntimeException(String.format(
+ "When application is missing, Parameter `%s` must be provided : \n%s",
+ DRIVER.getDefaultName(),
+ DriverWrapper.getAllDriverNames("\n")));
+ }
}
-
- private void validateNotNullParameter(Object parameter, String name) {
- if(parameter == null) {
- throw new RuntimeException(name + " must be provided");
- }
- }
}
}
diff --git a/mongock-cli/src/main/java/io/mongock/cli/wrapper/launcher/LauncherDefault.java b/mongock-cli/src/main/java/io/mongock/cli/wrapper/launcher/LauncherDefault.java
index 7033c3b..412a4c3 100644
--- a/mongock-cli/src/main/java/io/mongock/cli/wrapper/launcher/LauncherDefault.java
+++ b/mongock-cli/src/main/java/io/mongock/cli/wrapper/launcher/LauncherDefault.java
@@ -1,101 +1,53 @@
package io.mongock.cli.wrapper.launcher;
-import io.mongock.cli.util.logger.CliLogger;
-import io.mongock.cli.util.logger.CliLoggerFactory;
-import io.mongock.cli.wrapper.util.ClassLoaderUtil;
-import io.mongock.cli.wrapper.util.JarUtil;
+import io.mongock.cli.util.CliConfiguration;
+import io.mongock.cli.util.DriverWrapper;
+import io.mongock.cli.wrapper.jars.Jar;
+import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.net.URLClassLoader;
-import java.util.jar.JarFile;
-import java.util.stream.Stream;
-public class LauncherDefault implements LauncherCliJar {
+public class LauncherDefault extends LauncherStandalone {
- private static final CliLogger logger = CliLoggerFactory.getLogger(LauncherDefault.class);
+ private final DriverWrapper driverWrapper;
- private final String cliJarPath;
+ private final String licenseKey;
+ private final CliConfiguration cliConfiguration;
- private final String mongockCoreJarFile;
- private URLClassLoader classLoader;
+ public LauncherDefault(Jar appJar,
+ ClassLoader classLoader,
+ String licenseKey,
+ DriverWrapper driverWrapper,
+ CliConfiguration cliConfiguration
+ ) {
+ super(appJar, classLoader);
+ this.licenseKey = licenseKey;
+ this.driverWrapper = driverWrapper;
+ this.cliConfiguration = cliConfiguration;
- public LauncherDefault(String mongockCoreJarFile, String cliJarPath) {
- this.mongockCoreJarFile = mongockCoreJarFile;
- this.cliJarPath = cliJarPath;
- }
-
- @Override
- public LauncherCliJar loadClasses() {
-
- try {
- this.classLoader = buildClassLoader();
- ClassLoaderUtil.loadJarClasses(new JarFile(mongockCoreJarFile), classLoader);
- ClassLoaderUtil.loadJarClasses(new JarFile(cliJarPath), classLoader);
- return this;
- } catch (Exception ex) {
- throw new RuntimeException(ex);
- }
}
@Override
- public void launch(String[] args) {
- try {
- logger.info("launching Mongock CLI runner with default launcher");
+ protected Object getRunnerBuilder(Class> builderProviderImplClass) throws NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException, ClassNotFoundException {
- Object commandLine = buildCli(getCliBuilder());
+ Class.forName("io.mongock.runner.core.builder.RunnerBuilderProvider", false, classLoader);
- StringBuilder sb = new StringBuilder();
- Stream.of(args).forEach(s -> sb.append(s).append(" "));
- logger.debug("executing CommandLine with args: " + sb);
- Method executeMethod = commandLine.getClass().getDeclaredMethod("execute", String[].class);
- executeMethod.setAccessible(true);
- executeMethod.invoke(commandLine, new Object[]{args});
- logger.debug("successful call to commandLine.execute()");
+ Constructor> constructor = builderProviderImplClass.getDeclaredConstructor();
+ Object builderProvider = constructor.newInstance();
+ // setting configuration
+ Method setConfigMethod = builderProvider.getClass().getMethod("setConfiguration", CliConfiguration.class);
+ setConfigMethod.invoke(builderProvider, cliConfiguration);
- } catch (Exception ex) {
- throw new RuntimeException(ex);
- }
- }
-
+ Method getBuilderMethod = builderProvider.getClass().getMethod("getBuilder");
+ Object builder = getBuilderMethod.invoke(builderProvider);
- private Object buildCli(Object cliBuilder) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
- logger.debug("building CommandLine");
- Method buildMethod = cliBuilder.getClass().getDeclaredMethod("build");
- buildMethod.setAccessible(true);
- Object commandLine = buildMethod.invoke(cliBuilder);
- logger.debug("successful built commandLine " + commandLine);
- return commandLine;
+ return builder;
}
- private Object getCliBuilder() throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException {
- logger.debug("loading MongockCLI class");
- Class> mongockCliClass = Class.forName("io.mongock.cli.core.CliCoreRunner", false, classLoader);
- logger.debug("successfully loaded MongockCLI class");
-
- logger.debug("obtaining builder setter");
- Method builderMethod = mongockCliClass.getDeclaredMethod("builder");
- builderMethod.setAccessible(true);
- Object cliBuilder = builderMethod.invoke(null);
- logger.debug("obtained cliBuilder");
- return cliBuilder;
- }
-
-
- private URLClassLoader buildClassLoader() throws MalformedURLException {
- return URLClassLoader.newInstance(
- new URL[]{
- new URL(String.format(JarUtil.JAR_URL_TEMPLATE, mongockCoreJarFile)),
- new URL(String.format(JarUtil.JAR_URL_TEMPLATE, cliJarPath))
- },
- Thread.currentThread().getContextClassLoader()
- );
- }
}
diff --git a/mongock-cli/src/main/java/io/mongock/cli/wrapper/launcher/LauncherSpringboot.java b/mongock-cli/src/main/java/io/mongock/cli/wrapper/launcher/LauncherSpringboot.java
index edbd8ed..49089ff 100644
--- a/mongock-cli/src/main/java/io/mongock/cli/wrapper/launcher/LauncherSpringboot.java
+++ b/mongock-cli/src/main/java/io/mongock/cli/wrapper/launcher/LauncherSpringboot.java
@@ -2,18 +2,15 @@
import io.mongock.cli.util.logger.CliLogger;
import io.mongock.cli.util.logger.CliLoggerFactory;
+import io.mongock.cli.wrapper.jars.Jar;
import io.mongock.cli.wrapper.launcher.springboot.CliMainMethodRunner;
-import io.mongock.cli.wrapper.util.ClassLoaderUtil;
-import io.mongock.cli.wrapper.util.JarUtil;
import org.springframework.boot.loader.JarLauncher;
import org.springframework.boot.loader.LaunchedURLClassLoader;
import org.springframework.boot.loader.MainMethodRunner;
import org.springframework.boot.loader.archive.Archive;
import java.net.URL;
-import java.net.URLClassLoader;
import java.util.Iterator;
-import java.util.jar.JarFile;
public class LauncherSpringboot extends JarLauncher implements LauncherCliJar {
@@ -21,17 +18,13 @@ public class LauncherSpringboot extends JarLauncher implements LauncherCliJar {
private static final CliLogger logger = CliLoggerFactory.getLogger(LauncherSpringboot.class);
public static final String BOOT_CLASSPATH_INDEX_ATTRIBUTE = JarLauncher.BOOT_CLASSPATH_INDEX_ATTRIBUTE;
private static final String SPRING_CLI_MAIN_CLASS = "io.mongock.cli.springboot.CliSpringbootRunner";
- private static final String CLASS_EXT = ".class";
- private static final String SPRINGBOOT_PREFIX = "org/springframework/boot";
- private final String cliJarPath;
+ private final Jar cliJar;
private final String cliMainClass;
- private final String appJar;
- public LauncherSpringboot(Archive archive, String appJar, String cliJarPath) {
- super(archive);
- this.appJar = appJar;
- this.cliJarPath = cliJarPath;
+ public LauncherSpringboot(Jar appJar, Jar cliJar) {
+ super(appJar.getJarFileArchive());
+ this.cliJar = cliJar;
this.cliMainClass = SPRING_CLI_MAIN_CLASS;
}
@@ -44,23 +37,6 @@ public String getOriginalMainClass() {
}
}
- public LauncherSpringboot loadClasses() {
- try {
- URLClassLoader classLoader = URLClassLoader.newInstance(
- new URL[]{new URL(String.format(JarUtil.JAR_URL_TEMPLATE, appJar))},
- Thread.currentThread().getContextClassLoader()
- );
-
- ClassLoaderUtil.loadJarClasses(
- new JarFile(appJar),
- classLoader,
- entryName -> entryName.startsWith(SPRINGBOOT_PREFIX) && entryName.endsWith(CLASS_EXT));
- return this;
- } catch (Exception e) {
- throw new RuntimeException(e);
- }
- }
-
@Override
protected String getMainClass() {
return cliMainClass;
@@ -86,7 +62,7 @@ protected ClassLoader createClassLoader(Iterator archives) throws Excep
return new LaunchedURLClassLoader(
this.isExploded(),
this.getArchive(),
- new URL[]{new URL("jar:file:" + cliJarPath + "!/")},
+ new URL[]{cliJar.getUrl()},
super.createClassLoader(archives));
}
}
diff --git a/mongock-cli/src/main/java/io/mongock/cli/wrapper/launcher/LauncherStandalone.java b/mongock-cli/src/main/java/io/mongock/cli/wrapper/launcher/LauncherStandalone.java
index d59583f..b50725a 100644
--- a/mongock-cli/src/main/java/io/mongock/cli/wrapper/launcher/LauncherStandalone.java
+++ b/mongock-cli/src/main/java/io/mongock/cli/wrapper/launcher/LauncherStandalone.java
@@ -3,63 +3,39 @@
import io.mongock.api.annotations.MongockCliConfiguration;
import io.mongock.cli.util.logger.CliLogger;
import io.mongock.cli.util.logger.CliLoggerFactory;
-import io.mongock.cli.wrapper.util.ClassLoaderUtil;
-import io.mongock.cli.wrapper.util.JarUtil;
-import org.springframework.boot.loader.archive.JarFileArchive;
+import io.mongock.cli.wrapper.jars.Jar;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.net.URLClassLoader;
-import java.util.jar.JarFile;
import java.util.stream.Stream;
public class LauncherStandalone implements LauncherCliJar {
private static final CliLogger logger = CliLoggerFactory.getLogger(LauncherStandalone.class);
- private final JarFileArchive appJarArchive;
- private final String appJar;
- private final String cliJarPath;
+ private final Jar appJar;
- private URLClassLoader classLoader;
+ protected final ClassLoader classLoader;
- public LauncherStandalone(JarFileArchive appArchive, String appJar, String cliJarPath) {
- this.appJarArchive = appArchive;
+ public LauncherStandalone(Jar appJar, ClassLoader classLoader) {
this.appJar = appJar;
- this.cliJarPath = cliJarPath;
+ this.classLoader = classLoader;
}
- @Override
- public LauncherCliJar loadClasses() {
-
- try {
- this.classLoader = buildClassLoader();
- ClassLoaderUtil.loadJarClasses(new JarFile(appJar), classLoader);
- ClassLoaderUtil.loadJarClasses(new JarFile(cliJarPath), classLoader);
-
- return this;
- } catch (Exception ex) {
- throw new RuntimeException(ex);
- }
- }
-
-
@Override
public void launch(String[] args) {
try {
logger.info("launching Mongock CLI runner with Standalone launcher");
- String mainClassName = JarUtil.getMainClass(appJarArchive);
- Class> mainClass = getMainClass(mainClassName);
+ Class> mainClass = appJar.getMainClass(classLoader);
if (mainClass.isAnnotationPresent(MongockCliConfiguration.class)) {
MongockCliConfiguration ann = mainClass.getAnnotation(MongockCliConfiguration.class);
Class.forName("io.mongock.runner.core.builder.RunnerBuilderProvider", false, classLoader);
Class> builderProviderImplClass = ann.sources()[0];
+
Object runnerBuilder = getRunnerBuilder(builderProviderImplClass);
Object cliBuilder = getCliBuilder();
@@ -71,19 +47,14 @@ public void launch(String[] args) {
executeCli(args, commandLine);
} else {
- throw new RuntimeException("Main class " + mainClassName + " not annotated with MongockCliConfiguration");
+ throw new RuntimeException("Main class " + mainClass.getName() + " not annotated with MongockCliConfiguration");
}
} catch (Exception ex) {
throw new RuntimeException(ex);
}
}
- private Class> getMainClass(String mainClassName) throws ClassNotFoundException {
- logger.debug("Main class: " + mainClassName);
- Class> mainClass = classLoader.loadClass(mainClassName);
- logger.debug("loaded Main class");
- return mainClass;
- }
+
private void executeCli(String[] args, Object commandLine) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
StringBuilder sb = new StringBuilder();
@@ -116,6 +87,7 @@ private void setRunnerBuilderToCli(Object runnerBuilder, Object cliBuilder) thro
logger.debug("successfully set RunnerBuilder to MongockCli.builder");
}
+
private Object getCliBuilder() throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException {
logger.debug("loading MongockCLI class");
Class> mongockCliClass = Class.forName("io.mongock.cli.core.CliCoreRunner", false, classLoader);
@@ -130,20 +102,13 @@ private Object getCliBuilder() throws ClassNotFoundException, NoSuchMethodExcept
return cliBuilder;
}
- private Object getRunnerBuilder(Class> builderProviderImplClass) throws NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException {
+ protected Object getRunnerBuilder(Class> builderProviderImplClass) throws NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException, ClassNotFoundException {
+ Class.forName("io.mongock.runner.core.builder.RunnerBuilderProvider", false, classLoader);
+
Constructor> constructor = builderProviderImplClass.getDeclaredConstructor();
Object builderProvider = constructor.newInstance();
Method getBuilderMethod = builderProvider.getClass().getMethod("getBuilder");
return getBuilderMethod.invoke(builderProvider);
}
- private URLClassLoader buildClassLoader() throws MalformedURLException {
- return URLClassLoader.newInstance(
- new URL[]{
- new URL(String.format(JarUtil.JAR_URL_TEMPLATE, appJar)),
- new URL(String.format(JarUtil.JAR_URL_TEMPLATE, cliJarPath))
- },
- Thread.currentThread().getContextClassLoader()
- );
- }
}
diff --git a/mongock-cli/src/main/java/io/mongock/cli/wrapper/util/ArgsUtil.java b/mongock-cli/src/main/java/io/mongock/cli/wrapper/util/ArgsUtil.java
deleted file mode 100644
index 3c83367..0000000
--- a/mongock-cli/src/main/java/io/mongock/cli/wrapper/util/ArgsUtil.java
+++ /dev/null
@@ -1,81 +0,0 @@
-package io.mongock.cli.wrapper.util;
-
-import io.mongock.cli.util.logger.CliLogger;
-import io.mongock.cli.util.logger.CliLoggerFactory;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Optional;
-import java.util.Set;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
-
-public final class ArgsUtil {
-
- private static final CliLogger logger = CliLoggerFactory.getLogger(ArgsUtil.class);
-
- private ArgsUtil() {}
-
- public static String[] getCleanArgs(String[] args, String... paramNames) {
-
- StringBuilder sb = new StringBuilder("cleaning arguments: ");
- Set paramNamesSet = Stream.of(paramNames)
- .peek(arg -> sb.append(arg).append(" "))
- .map(String::toLowerCase)
- .collect(Collectors.toSet());
- logger.debug(sb.toString());
-
-
- List tempNewArgs = new ArrayList<>();
-
- for (int i = 0; i < args.length; i++) {
- if (!paramNamesSet.contains(args[i].toLowerCase())) {
- tempNewArgs.add(args[i]);
- } else {
- i++;
- }
- }
-
- String[] newArgs = new String[tempNewArgs.size()];
- tempNewArgs.toArray(newArgs);
- logger.debug("cleaned args size: " + newArgs.length);
- StringBuilder sb2 = new StringBuilder("cleaned args: ");
- Stream.of(newArgs).forEach(arg -> sb2.append(arg).append(" "));
- logger.debug(sb2.toString());
- return newArgs;
- }
-
- public static Optional getOptionalParam(String[] args, String paramName) {
- return Optional.ofNullable(getParameter(args, paramName, false));
- }
-
- public static String getParameter(String[] args, String paramName) {
- return getParameter(args, paramName, true);
- }
-
- public static String getParameter(String[] args, String paramName, boolean throwException) {
- int i = 0;
- do {
- if (paramName.equalsIgnoreCase(args[i])) {
- if (args.length == i + 1) {
- if(throwException) {
- throw new RuntimeException(
- String.format("Found [%s] flag with missing value. Please follow the format \"%s value\"", paramName, paramName)
- );
- } else {
- return null;
- }
-
- }
- return args[i + 1];
- }
- } while ((++i) < args.length);
- if(throwException) {
- throw new RuntimeException(String.format("Missing jar parameter. Please follow the format \"%s jar_path\"", paramName));
-
- } else {
- return null;
- }
-
- }
-}
diff --git a/mongock-cli/src/main/java/io/mongock/cli/wrapper/util/ClassLoaderUtil.java b/mongock-cli/src/main/java/io/mongock/cli/wrapper/util/ClassLoaderUtil.java
deleted file mode 100644
index 5f31052..0000000
--- a/mongock-cli/src/main/java/io/mongock/cli/wrapper/util/ClassLoaderUtil.java
+++ /dev/null
@@ -1,47 +0,0 @@
-package io.mongock.cli.wrapper.util;
-
-import io.mongock.cli.util.logger.CliLogger;
-import io.mongock.cli.util.logger.CliLoggerFactory;
-
-import java.net.URLClassLoader;
-import java.util.Enumeration;
-import java.util.function.Function;
-import java.util.jar.JarEntry;
-import java.util.jar.JarFile;
-
-public final class ClassLoaderUtil {
-
- private static final CliLogger logger = CliLoggerFactory.getLogger(ClassLoaderUtil.class);
-
- private static final String CLASS_EXT = ".class";
-
- public static void loadJarClasses(JarFile appJarFile,
- URLClassLoader classLoader) {
- loadJarClasses(appJarFile, classLoader, e -> e.endsWith(CLASS_EXT));
- }
-
- public static void loadJarClasses(JarFile appJarFile,
- URLClassLoader classLoader,
- Function jarEntryFilter) {
- try {
- logger.debug("lading jar: %s, with classLoader %s", appJarFile.getName(), classLoader.getClass().getName() );
- Thread.currentThread().getContextClassLoader();
- Enumeration jarEntryEnum = appJarFile.entries();
- while (jarEntryEnum.hasMoreElements()) {
- String entryName = jarEntryEnum.nextElement().getName();
- if (jarEntryFilter.apply(entryName)) {
- String className = entryName.substring(0, entryName.lastIndexOf(CLASS_EXT)).replace('/', '.');
- try {
- classLoader.loadClass(className);
- } catch (Throwable e) {
- logger.warn(String.format("%s not loaded(%s)", className, e.getMessage()));
- }
- logger.trace(className + " loaded ");
- }
- }
- appJarFile.close();
- } catch (Exception ex) {
- throw new RuntimeException(ex);
- }
- }
-}
diff --git a/mongock-cli/src/main/java/io/mongock/cli/wrapper/util/JarUtil.java b/mongock-cli/src/main/java/io/mongock/cli/wrapper/util/JarUtil.java
deleted file mode 100644
index 722ed4e..0000000
--- a/mongock-cli/src/main/java/io/mongock/cli/wrapper/util/JarUtil.java
+++ /dev/null
@@ -1,45 +0,0 @@
-package io.mongock.cli.wrapper.util;
-
-import io.mongock.cli.util.logger.CliLogger;
-import io.mongock.cli.util.logger.CliLoggerFactory;
-import io.mongock.cli.wrapper.launcher.LauncherSpringboot;
-import org.springframework.boot.loader.archive.JarFileArchive;
-
-import java.io.IOException;
-import java.util.jar.Attributes;
-import java.util.jar.Manifest;
-
-public final class JarUtil {
-
- private static final CliLogger logger = CliLoggerFactory.getLogger(JarUtil.class);
-
- public static final String JAR_URL_TEMPLATE = "jar:file:%s!/";
- private JarUtil() {}
-
- public static String getMainClass(JarFileArchive archive) throws IOException {
- String mainClass = getAttributes(archive).getValue(Attributes.Name.MAIN_CLASS);
- logger.debug("%s main class: %s", archive.getUrl(), mainClass);
- return mainClass;
- }
-
- public static boolean isSpringApplication(JarFileArchive archive) {
- try {
- return getAttributes(archive).getValue(LauncherSpringboot.BOOT_CLASSPATH_INDEX_ATTRIBUTE) != null;
- } catch (IOException e) {
- throw new RuntimeException(e);
- }
- }
-
- private static Attributes getAttributes(JarFileArchive archive) throws IOException {
- Manifest manifest = archive.getManifest();
- if(manifest == null) {
- throw new RuntimeException("manifest not present in the appJar");
- }
- Attributes attributes = manifest.getMainAttributes();
- if(attributes == null) {
- throw new RuntimeException("Mongock CLI cannot access to attributes in manifest");
- }
- return attributes;
- }
-
-}
diff --git a/mongock-cli/src/main/java/io/mongock/cli/wrapper/util/Parameters.java b/mongock-cli/src/main/java/io/mongock/cli/wrapper/util/Parameters.java
deleted file mode 100644
index ed996ce..0000000
--- a/mongock-cli/src/main/java/io/mongock/cli/wrapper/util/Parameters.java
+++ /dev/null
@@ -1,13 +0,0 @@
-package io.mongock.cli.wrapper.util;
-
-public class Parameters {
-
- public static final String APP_JAR_ARG_SHORT = "-aj";
- public static final String APP_JAR_ARG_LONG = "--app-jar";
-
- public static final String MONGOCK_CORE_JAR_ARG = "--mongock-core-jar";
- public static final String CLI_SPRING_JAR_ARG = "--cli-spring-jar";
- public static final String CLI_CORE_JAR_ARG = "--cli-core-jar";
- public static final String LOG_LEVEL_ARG = "--log-level";
-
-}
diff --git a/mongock-cli/src/main/resources/linux_script_template b/mongock-cli/src/main/resources/linux_script_template
index 17fbe53..8982b11 100755
--- a/mongock-cli/src/main/resources/linux_script_template
+++ b/mongock-cli/src/main/resources/linux_script_template
@@ -1,8 +1,8 @@
#!/bin/sh
#Generated cli script
java -jar ${project.artifactId}-${project.version}.jar \
- --cli-spring-jar lib/mongock-cli-springboot-${project.version}.jar \
- --cli-core-jar lib/mongock-cli-core-${project.version}.jar \
- --mongock-core-jar lib/mongock-runner-core-${mongock.version}.jar \
+ --cli-version ${project.version} \
+ --mongock-community-version ${mongock.community.version} \
+ --mongock-professional-version ${mongock.pro.version} \
"$@" \
\
diff --git a/mongock-default-app-professional/pom.xml b/mongock-default-app-professional/pom.xml
new file mode 100644
index 0000000..66c3301
--- /dev/null
+++ b/mongock-default-app-professional/pom.xml
@@ -0,0 +1,93 @@
+
+
+
+ mongock-cli-project
+ io.mongock
+ 5.0.28-SNAPSHOT
+
+ 4.0.0
+
+ mongock-default-app-professional
+
+
+
+
+ io.mongock
+ mongock-cli-util
+ ${project.version}
+
+
+
+
+ io.mongock.professional
+ mongock-standalone
+ ${mongock.pro.version}
+
+
+
+ org.slf4j
+ slf4j-simple
+ ${slf4j.version}
+
+
+
+
+
+
+
+
+ io.mongock
+ mongodb-springdata-v3-wrapper
+ ${project.version}
+ provided
+ true
+
+
+ io.mongock
+ mongodb-springdata-v2-wrapper
+ ${project.version}
+ provided
+ true
+
+
+
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+
+ ${java.version}
+ ${java.version}
+
+
+
+
+ org.apache.maven.plugins
+ maven-shade-plugin
+
+
+
+ shade
+
+
+ false
+
+
+ io.mongock.cli.app.professional.DefaultProfessionalApp
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/mongock-default-app-professional/src/main/java/io/mongock/cli/app/professional/DefaultProfessionalApp.java b/mongock-default-app-professional/src/main/java/io/mongock/cli/app/professional/DefaultProfessionalApp.java
new file mode 100644
index 0000000..c3d4382
--- /dev/null
+++ b/mongock-default-app-professional/src/main/java/io/mongock/cli/app/professional/DefaultProfessionalApp.java
@@ -0,0 +1,19 @@
+package io.mongock.cli.app.professional;
+
+import io.mongock.api.annotations.MongockCliConfiguration;
+import io.mongock.cli.util.MongockDefaultApp;
+
+
+@MongockDefaultApp
+@MongockCliConfiguration(sources = RunnerBuilderProviderProfessionalImpl.class)
+public class DefaultProfessionalApp {
+
+
+ public static void main(String[] args) {
+ new RunnerBuilderProviderProfessionalImpl()
+ .getBuilder()
+ .buildRunner()
+ .execute();
+ }
+
+}
diff --git a/mongock-default-app-professional/src/main/java/io/mongock/cli/app/professional/DriverFactory.java b/mongock-default-app-professional/src/main/java/io/mongock/cli/app/professional/DriverFactory.java
new file mode 100644
index 0000000..24cad77
--- /dev/null
+++ b/mongock-default-app-professional/src/main/java/io/mongock/cli/app/professional/DriverFactory.java
@@ -0,0 +1,28 @@
+package io.mongock.cli.app.professional;
+
+import io.mongock.cli.util.CliConfiguration;
+import io.mongock.cli.util.ConnectionDriverProvider;
+import io.mongock.cli.util.DriverWrapper;
+import io.mongock.driver.api.driver.ConnectionDriver;
+
+public final class DriverFactory {
+
+ private DriverFactory() {
+ }
+
+ public static ConnectionDriver getDriver(DriverWrapper driverWrapper, CliConfiguration configuration) {
+
+ ConnectionDriverProvider connectionDriverProvider;
+ switch (driverWrapper) {
+ case MONGODB_SPRING_DATA_V3:
+ connectionDriverProvider = new io.mongock.driver.cli.wrapper.mongodb.springdata.v3.SpringDataMongoV3DriverProvider();
+ break;
+ case MONGODB_SPRING_DATA_V2:
+ connectionDriverProvider = new io.mongock.driver.cli.wrapper.mongodb.springdata.v2.SpringDataMongoV2DriverProvider();
+ break;
+ default:
+ throw new RuntimeException(String.format("%s not found", driverWrapper));
+ }
+ return connectionDriverProvider.getDriver(configuration);
+ }
+}
diff --git a/mongock-default-app-professional/src/main/java/io/mongock/cli/app/professional/RunnerBuilderProviderProfessionalImpl.java b/mongock-default-app-professional/src/main/java/io/mongock/cli/app/professional/RunnerBuilderProviderProfessionalImpl.java
new file mode 100644
index 0000000..d6096aa
--- /dev/null
+++ b/mongock-default-app-professional/src/main/java/io/mongock/cli/app/professional/RunnerBuilderProviderProfessionalImpl.java
@@ -0,0 +1,35 @@
+package io.mongock.cli.app.professional;
+
+import io.mongock.cli.app.professional.events.MongockEventListener;
+import io.mongock.cli.util.CliConfiguration;
+import io.mongock.cli.util.DriverWrapper;
+import io.mongock.cli.util.RunnerBuilderProviderConfigurable;
+import io.mongock.runner.core.builder.RunnerBuilder;
+import io.mongock.runner.core.builder.RunnerBuilderProvider;
+import io.mongock.runner.standalone.MongockStandalone;
+
+public class RunnerBuilderProviderProfessionalImpl implements RunnerBuilderProvider, RunnerBuilderProviderConfigurable {
+
+ private DriverWrapper driverWrapper;
+ private CliConfiguration configuration;
+
+ @Override
+ public RunnerBuilder getBuilder() {
+
+ return MongockStandalone.builder()
+ .setDriver(DriverFactory.getDriver(driverWrapper, configuration))
+ .addMigrationScanPackage(configuration.getScanPackage())
+ .setLicenseKey(configuration.getLicenseKey().orElse(null))
+ .setMigrationStartedListener(MongockEventListener::onStart)
+ .setMigrationSuccessListener(MongockEventListener::onSuccess)
+ .setMigrationFailureListener(MongockEventListener::onFail)
+ .setTrackIgnored(true)
+ .setTransactionEnabled(true);
+ }
+
+ @Override
+ public void setConfiguration(CliConfiguration configuration) {
+ this.configuration = configuration;
+ this.driverWrapper = configuration.getDriverWrapper();
+ }
+}
diff --git a/mongock-default-app-professional/src/main/java/io/mongock/cli/app/professional/events/MongockEventListener.java b/mongock-default-app-professional/src/main/java/io/mongock/cli/app/professional/events/MongockEventListener.java
new file mode 100644
index 0000000..5184096
--- /dev/null
+++ b/mongock-default-app-professional/src/main/java/io/mongock/cli/app/professional/events/MongockEventListener.java
@@ -0,0 +1,20 @@
+package io.mongock.cli.app.professional.events;
+
+import io.mongock.runner.core.event.MigrationFailureEvent;
+import io.mongock.runner.core.event.MigrationStartedEvent;
+import io.mongock.runner.core.event.MigrationSuccessEvent;
+
+public class MongockEventListener {
+
+ public static void onStart(MigrationStartedEvent event) {
+ System.out.println("[EVENT LISTENER] - Mongock STARTED successfully");
+ }
+
+ public static void onSuccess(MigrationSuccessEvent event) {
+ System.out.println("[EVENT LISTENER] - Mongock finished successfully");
+ }
+
+ public static void onFail(MigrationFailureEvent event) {
+ System.out.println("[EVENT LISTENER] - Mongock finished with failures");
+ }
+}
diff --git a/mongock-default-app/pom.xml b/mongock-default-app/pom.xml
new file mode 100644
index 0000000..45fd0c9
--- /dev/null
+++ b/mongock-default-app/pom.xml
@@ -0,0 +1,97 @@
+
+
+
+ mongock-cli-project
+ io.mongock
+ 5.0.28-SNAPSHOT
+
+ 4.0.0
+
+ mongock-default-app
+
+
+
+
+
+
+
+ io.mongock
+ mongock-cli-util
+ ${project.version}
+
+
+
+
+ io.mongock
+ mongock-standalone
+ ${mongock.community.version}
+ provided
+ true
+
+
+ org.slf4j
+ slf4j-simple
+ ${slf4j.version}
+
+
+
+
+
+
+
+
+ io.mongock
+ mongodb-springdata-v3-wrapper
+ ${project.version}
+ provided
+ true
+
+
+ io.mongock
+ mongodb-springdata-v2-wrapper
+ ${project.version}
+ provided
+ true
+
+
+
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+
+ ${java.version}
+ ${java.version}
+
+
+
+
+ org.apache.maven.plugins
+ maven-shade-plugin
+
+
+
+ shade
+
+
+ false
+
+
+ io.mongock.cli.app.DefaultApp
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/mongock-default-app/src/main/java/io/mongock/cli/app/DefaultApp.java b/mongock-default-app/src/main/java/io/mongock/cli/app/DefaultApp.java
new file mode 100644
index 0000000..6bd60b9
--- /dev/null
+++ b/mongock-default-app/src/main/java/io/mongock/cli/app/DefaultApp.java
@@ -0,0 +1,18 @@
+package io.mongock.cli.app;
+
+import io.mongock.api.annotations.MongockCliConfiguration;
+import io.mongock.cli.util.MongockDefaultApp;
+
+@MongockDefaultApp
+@MongockCliConfiguration(sources = RunnerBuilderProviderImpl.class)
+public class DefaultApp {
+
+
+ public static void main(String[] args) {
+ new RunnerBuilderProviderImpl()
+ .getBuilder()
+ .buildRunner()
+ .execute();
+ }
+
+}
diff --git a/mongock-default-app/src/main/java/io/mongock/cli/app/DriverFactory.java b/mongock-default-app/src/main/java/io/mongock/cli/app/DriverFactory.java
new file mode 100644
index 0000000..a37d1e0
--- /dev/null
+++ b/mongock-default-app/src/main/java/io/mongock/cli/app/DriverFactory.java
@@ -0,0 +1,28 @@
+package io.mongock.cli.app;
+
+import io.mongock.cli.util.CliConfiguration;
+import io.mongock.cli.util.ConnectionDriverProvider;
+import io.mongock.cli.util.DriverWrapper;
+import io.mongock.driver.api.driver.ConnectionDriver;
+
+public final class DriverFactory {
+
+ private DriverFactory() {
+ }
+
+ public static ConnectionDriver getDriver(DriverWrapper driverWrapper, CliConfiguration configuration) {
+
+ ConnectionDriverProvider connectionDriverProvider;
+ switch (driverWrapper) {
+ case MONGODB_SPRING_DATA_V3:
+ connectionDriverProvider = new io.mongock.driver.cli.wrapper.mongodb.springdata.v3.SpringDataMongoV3DriverProvider();
+ break;
+ case MONGODB_SPRING_DATA_V2:
+ connectionDriverProvider = new io.mongock.driver.cli.wrapper.mongodb.springdata.v2.SpringDataMongoV2DriverProvider();
+ break;
+ default:
+ throw new RuntimeException(String.format("%s not found", driverWrapper));
+ }
+ return connectionDriverProvider.getDriver(configuration);
+ }
+}
diff --git a/mongock-default-app/src/main/java/io/mongock/cli/app/RunnerBuilderProviderImpl.java b/mongock-default-app/src/main/java/io/mongock/cli/app/RunnerBuilderProviderImpl.java
new file mode 100644
index 0000000..05fd7e1
--- /dev/null
+++ b/mongock-default-app/src/main/java/io/mongock/cli/app/RunnerBuilderProviderImpl.java
@@ -0,0 +1,37 @@
+package io.mongock.cli.app;
+
+import io.mongock.cli.app.events.MongockEventListener;
+import io.mongock.cli.util.CliConfiguration;
+import io.mongock.cli.util.DriverWrapper;
+import io.mongock.cli.util.RunnerBuilderProviderConfigurable;
+import io.mongock.runner.core.builder.RunnerBuilder;
+import io.mongock.runner.core.builder.RunnerBuilderProvider;
+import io.mongock.runner.standalone.MongockStandalone;
+
+public class RunnerBuilderProviderImpl implements RunnerBuilderProvider, RunnerBuilderProviderConfigurable {
+
+ private DriverWrapper driverWrapper;
+ private CliConfiguration configuration;
+
+ @Override
+ public RunnerBuilder getBuilder() {
+
+ return MongockStandalone.builder()
+ .setDriver(DriverFactory.getDriver(driverWrapper, configuration))
+ .addMigrationScanPackage(configuration.getScanPackage())
+ .setMigrationStartedListener(MongockEventListener::onStart)
+ .setMigrationSuccessListener(MongockEventListener::onSuccess)
+ .setMigrationFailureListener(MongockEventListener::onFail)
+ .setTrackIgnored(true)
+ .setTransactionEnabled(true);
+ }
+
+
+ @Override
+ public void setConfiguration(CliConfiguration configuration) {
+ this.configuration = configuration;
+ this.driverWrapper = configuration.getDriverWrapper();
+ }
+
+
+}
diff --git a/mongock-default-app/src/main/java/io/mongock/cli/app/events/MongockEventListener.java b/mongock-default-app/src/main/java/io/mongock/cli/app/events/MongockEventListener.java
new file mode 100644
index 0000000..0d3a884
--- /dev/null
+++ b/mongock-default-app/src/main/java/io/mongock/cli/app/events/MongockEventListener.java
@@ -0,0 +1,20 @@
+package io.mongock.cli.app.events;
+
+import io.mongock.runner.core.event.MigrationFailureEvent;
+import io.mongock.runner.core.event.MigrationStartedEvent;
+import io.mongock.runner.core.event.MigrationSuccessEvent;
+
+public class MongockEventListener {
+
+ public static void onStart(MigrationStartedEvent event) {
+ System.out.println("[EVENT LISTENER] - Mongock STARTED successfully");
+ }
+
+ public static void onSuccess(MigrationSuccessEvent event) {
+ System.out.println("[EVENT LISTENER] - Mongock finished successfully");
+ }
+
+ public static void onFail(MigrationFailureEvent event) {
+ System.out.println("[EVENT LISTENER] - Mongock finished with failures");
+ }
+}
diff --git a/pom.xml b/pom.xml
index c557806..2c585e2 100644
--- a/pom.xml
+++ b/pom.xml
@@ -17,6 +17,9 @@
mongock-cli-springboot
mongock-cli
mongock-cli-util
+ mongock-default-app
+ driver-wrappers
+ mongock-default-app-professional
1.8
@@ -27,10 +30,12 @@
false
[2.0.0, 3.0.0)
4.6.1
+ 1.7.32
- 5.1.0
+ 5.1.0-SNAPSHOT
+ 5.0.32-SNAPSHOT
ossrh
@@ -77,17 +82,17 @@
-
-
-
- io.mongock
- mongock-bom
- ${mongock.version}
- pom
- import
-
-
-
+
+
+
+
+
+
+
+
+
+
+