mirror of
https://github.com/corda/corda.git
synced 2024-12-29 09:18:58 +00:00
Merge pull request #587 from corda/feature/ENT-1637/migration-tool-changes
ENT-1673 Update migration tool to use the drivers folder and created reusable "createDatasourceFromDriverJars" function
This commit is contained in:
commit
72b97be42c
@ -14,10 +14,14 @@ import com.zaxxer.hikari.HikariConfig
|
|||||||
import com.zaxxer.hikari.HikariDataSource
|
import com.zaxxer.hikari.HikariDataSource
|
||||||
import com.zaxxer.hikari.util.PropertyElf
|
import com.zaxxer.hikari.util.PropertyElf
|
||||||
import net.corda.core.internal.declaredField
|
import net.corda.core.internal.declaredField
|
||||||
|
import net.corda.core.internal.div
|
||||||
import org.h2.engine.Database
|
import org.h2.engine.Database
|
||||||
import org.h2.engine.Engine
|
import org.h2.engine.Engine
|
||||||
import org.slf4j.LoggerFactory
|
import org.slf4j.LoggerFactory
|
||||||
import java.lang.reflect.Modifier
|
import java.lang.reflect.Modifier
|
||||||
|
import java.net.URLClassLoader
|
||||||
|
import java.nio.file.Files
|
||||||
|
import java.nio.file.Path
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import javax.sql.DataSource
|
import javax.sql.DataSource
|
||||||
|
|
||||||
@ -53,4 +57,28 @@ object DataSourceFactory {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun createDatasourceFromDriverJars(dataSourceProperties: Properties, baseClassLoader: ClassLoader, driverJarsPath: Path): DataSource {
|
||||||
|
return URLClassLoader(Files.newDirectoryStream(driverJarsPath, "*.jar").map { it.toUri().toURL() }.toTypedArray(), baseClassLoader).use { driversClassLoader ->
|
||||||
|
val dataSourceClassName = dataSourceProperties["dataSourceClassName"] as String?
|
||||||
|
val dataSourceClass = driversClassLoader.loadClass(dataSourceClassName)
|
||||||
|
val dataSourceInstance = dataSourceClass.newInstance() as DataSource
|
||||||
|
|
||||||
|
val props = Properties().also {
|
||||||
|
it.putAll(dataSourceProperties.propertyNames().toList()
|
||||||
|
.filter { name -> (name as String).startsWith("dataSource.") }
|
||||||
|
.map { name -> (name as String).substring("dataSource.".length) to (dataSourceProperties[name]) }.toMap())
|
||||||
|
}
|
||||||
|
PropertyElf.setTargetFromProperties(dataSourceInstance, props)
|
||||||
|
|
||||||
|
dataSourceInstance
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun createHikariDatasourceFromDriverJars(dataSourceProperties: Properties, baseClassLoader: ClassLoader, driverJarsPath: Path): DataSource {
|
||||||
|
val dataSource = createDatasourceFromDriverJars(dataSourceProperties, baseClassLoader, driverJarsPath)
|
||||||
|
val cfg = HikariConfig(dataSourceProperties)
|
||||||
|
cfg.dataSource = dataSource
|
||||||
|
return HikariDataSource(cfg)
|
||||||
|
}
|
||||||
}
|
}
|
@ -37,6 +37,7 @@ dependencies{
|
|||||||
|
|
||||||
shadowJar {
|
shadowJar {
|
||||||
transform(de.sebastianboegl.gradle.plugins.shadow.transformers.Log4j2PluginsFileTransformer)
|
transform(de.sebastianboegl.gradle.plugins.shadow.transformers.Log4j2PluginsFileTransformer)
|
||||||
|
archiveName = "migration-tool-${version}.jar"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
task buildMigrationTool(dependsOn: shadowJar)
|
@ -13,8 +13,7 @@
|
|||||||
package com.r3.corda.dbmigration
|
package com.r3.corda.dbmigration
|
||||||
|
|
||||||
import com.typesafe.config.ConfigFactory
|
import com.typesafe.config.ConfigFactory
|
||||||
import com.zaxxer.hikari.HikariConfig
|
import com.zaxxer.hikari.util.PropertyElf
|
||||||
import com.zaxxer.hikari.HikariDataSource
|
|
||||||
import joptsimple.OptionException
|
import joptsimple.OptionException
|
||||||
import joptsimple.OptionParser
|
import joptsimple.OptionParser
|
||||||
import joptsimple.OptionSet
|
import joptsimple.OptionSet
|
||||||
@ -23,6 +22,7 @@ import net.corda.core.internal.MigrationHelpers
|
|||||||
import net.corda.core.internal.copyTo
|
import net.corda.core.internal.copyTo
|
||||||
import net.corda.core.internal.div
|
import net.corda.core.internal.div
|
||||||
import net.corda.core.schemas.MappedSchema
|
import net.corda.core.schemas.MappedSchema
|
||||||
|
import net.corda.node.internal.DataSourceFactory.createDatasourceFromDriverJars
|
||||||
import net.corda.node.internal.cordapp.CordappLoader
|
import net.corda.node.internal.cordapp.CordappLoader
|
||||||
import net.corda.node.services.config.ConfigHelper
|
import net.corda.node.services.config.ConfigHelper
|
||||||
import net.corda.node.services.config.parseAsNodeConfiguration
|
import net.corda.node.services.config.parseAsNodeConfiguration
|
||||||
@ -37,6 +37,7 @@ import java.io.FileWriter
|
|||||||
import java.io.PrintWriter
|
import java.io.PrintWriter
|
||||||
import java.io.Writer
|
import java.io.Writer
|
||||||
import java.net.URLClassLoader
|
import java.net.URLClassLoader
|
||||||
|
import java.nio.file.Files
|
||||||
import java.nio.file.Path
|
import java.nio.file.Path
|
||||||
import java.nio.file.Paths
|
import java.nio.file.Paths
|
||||||
import java.text.SimpleDateFormat
|
import java.text.SimpleDateFormat
|
||||||
@ -71,7 +72,7 @@ private fun initOptionParser(): OptionParser = OptionParser().apply {
|
|||||||
.defaultsTo(Mode.NODE)
|
.defaultsTo(Mode.NODE)
|
||||||
|
|
||||||
accepts(BASE_DIRECTORY, "The node or doorman directory")
|
accepts(BASE_DIRECTORY, "The node or doorman directory")
|
||||||
.withRequiredArg()
|
.withRequiredArg().required()
|
||||||
|
|
||||||
accepts(CONFIG, "The name of the config file. By default 'node.conf' for a simple node and 'network-management.conf' for a doorman.")
|
accepts(CONFIG, "The name of the config file. By default 'node.conf' for a simple node and 'network-management.conf' for a doorman.")
|
||||||
.withOptionalArg()
|
.withOptionalArg()
|
||||||
@ -141,12 +142,12 @@ private fun runCommand(options: OptionSet, parser: OptionParser) {
|
|||||||
private fun handleCommand(options: OptionSet, baseDirectory: Path, configFile: Path, mode: Mode, classLoader: ClassLoader, schemas: Set<MappedSchema>) {
|
private fun handleCommand(options: OptionSet, baseDirectory: Path, configFile: Path, mode: Mode, classLoader: ClassLoader, schemas: Set<MappedSchema>) {
|
||||||
val config = ConfigFactory.parseFile(configFile.toFile()).resolve().parseAs(Configuration::class, false)
|
val config = ConfigFactory.parseFile(configFile.toFile()).resolve().parseAs(Configuration::class, false)
|
||||||
|
|
||||||
fun runMigrationCommand(withMigration: (SchemaMigration) -> Unit): Unit = runWithDataSource(config) { dataSource ->
|
fun runMigrationCommand(withMigration: (SchemaMigration) -> Unit): Unit = runWithDataSource(config, baseDirectory, classLoader) { dataSource ->
|
||||||
withMigration(SchemaMigration(schemas, dataSource, true, config.database, classLoader))
|
withMigration(SchemaMigration(schemas, dataSource, true, config.database, classLoader))
|
||||||
}
|
}
|
||||||
|
|
||||||
when {
|
when {
|
||||||
options.has(RELEASE_LOCK) -> runWithDataSource(ConfigFactory.parseFile(configFile.toFile()).resolve().parseAs(Configuration::class)) {
|
options.has(RELEASE_LOCK) -> runWithDataSource(ConfigFactory.parseFile(configFile.toFile()).resolve().parseAs(Configuration::class), baseDirectory, classLoader) {
|
||||||
SchemaMigration(emptySet(), it, true, config.database, Thread.currentThread().contextClassLoader).forceReleaseMigrationLock()
|
SchemaMigration(emptySet(), it, true, config.database, Thread.currentThread().contextClassLoader).forceReleaseMigrationLock()
|
||||||
}
|
}
|
||||||
options.has(DRY_RUN) -> {
|
options.has(DRY_RUN) -> {
|
||||||
@ -165,7 +166,7 @@ private fun handleCommand(options: OptionSet, baseDirectory: Path, configFile: P
|
|||||||
fun generateMigrationFileForSchema(schemaClass: String) {
|
fun generateMigrationFileForSchema(schemaClass: String) {
|
||||||
logger.info("Creating database migration files for schema: $schemaClass into ${baseDirectory / "migration"}")
|
logger.info("Creating database migration files for schema: $schemaClass into ${baseDirectory / "migration"}")
|
||||||
try {
|
try {
|
||||||
runWithDataSource(config) {
|
runWithDataSource(config, baseDirectory, classLoader) {
|
||||||
MigrationExporter(baseDirectory, config.dataSourceProperties, classLoader, it).generateMigrationForCorDapp(schemaClass)
|
MigrationExporter(baseDirectory, config.dataSourceProperties, classLoader, it).generateMigrationForCorDapp(schemaClass)
|
||||||
}
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
@ -211,12 +212,9 @@ private fun getMigrationOutput(baseDirectory: Path, options: OptionSet): Writer
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun runWithDataSource(config: Configuration, withDatasource: (DataSource) -> Unit) {
|
private fun runWithDataSource(config: Configuration, baseDirectory: Path, classLoader: ClassLoader, withDatasource: (DataSource) -> Unit) {
|
||||||
val cfg = HikariConfig(config.dataSourceProperties)
|
val driversFolder = baseDirectory / "drivers"
|
||||||
cfg.maximumPoolSize = 1
|
return withDatasource(createDatasourceFromDriverJars(config.dataSourceProperties, classLoader, driversFolder))
|
||||||
return HikariDataSource(cfg).use { dataSource ->
|
|
||||||
withDatasource(dataSource)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun errorAndExit(message: String?) {
|
private fun errorAndExit(message: String?) {
|
||||||
|
Loading…
Reference in New Issue
Block a user