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:
Tudor Malene 2018-03-22 10:35:55 +00:00 committed by GitHub
commit 72b97be42c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 41 additions and 14 deletions

View File

@ -14,10 +14,14 @@ import com.zaxxer.hikari.HikariConfig
import com.zaxxer.hikari.HikariDataSource
import com.zaxxer.hikari.util.PropertyElf
import net.corda.core.internal.declaredField
import net.corda.core.internal.div
import org.h2.engine.Database
import org.h2.engine.Engine
import org.slf4j.LoggerFactory
import java.lang.reflect.Modifier
import java.net.URLClassLoader
import java.nio.file.Files
import java.nio.file.Path
import java.util.*
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)
}
}

View File

@ -37,6 +37,7 @@ dependencies{
shadowJar {
transform(de.sebastianboegl.gradle.plugins.shadow.transformers.Log4j2PluginsFileTransformer)
archiveName = "migration-tool-${version}.jar"
}
task buildMigrationTool(dependsOn: shadowJar)

View File

@ -13,8 +13,7 @@
package com.r3.corda.dbmigration
import com.typesafe.config.ConfigFactory
import com.zaxxer.hikari.HikariConfig
import com.zaxxer.hikari.HikariDataSource
import com.zaxxer.hikari.util.PropertyElf
import joptsimple.OptionException
import joptsimple.OptionParser
import joptsimple.OptionSet
@ -23,6 +22,7 @@ import net.corda.core.internal.MigrationHelpers
import net.corda.core.internal.copyTo
import net.corda.core.internal.div
import net.corda.core.schemas.MappedSchema
import net.corda.node.internal.DataSourceFactory.createDatasourceFromDriverJars
import net.corda.node.internal.cordapp.CordappLoader
import net.corda.node.services.config.ConfigHelper
import net.corda.node.services.config.parseAsNodeConfiguration
@ -37,6 +37,7 @@ import java.io.FileWriter
import java.io.PrintWriter
import java.io.Writer
import java.net.URLClassLoader
import java.nio.file.Files
import java.nio.file.Path
import java.nio.file.Paths
import java.text.SimpleDateFormat
@ -71,7 +72,7 @@ private fun initOptionParser(): OptionParser = OptionParser().apply {
.defaultsTo(Mode.NODE)
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.")
.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>) {
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))
}
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()
}
options.has(DRY_RUN) -> {
@ -165,7 +166,7 @@ private fun handleCommand(options: OptionSet, baseDirectory: Path, configFile: P
fun generateMigrationFileForSchema(schemaClass: String) {
logger.info("Creating database migration files for schema: $schemaClass into ${baseDirectory / "migration"}")
try {
runWithDataSource(config) {
runWithDataSource(config, baseDirectory, classLoader) {
MigrationExporter(baseDirectory, config.dataSourceProperties, classLoader, it).generateMigrationForCorDapp(schemaClass)
}
} catch (e: Exception) {
@ -211,12 +212,9 @@ private fun getMigrationOutput(baseDirectory: Path, options: OptionSet): Writer
}
}
private fun runWithDataSource(config: Configuration, withDatasource: (DataSource) -> Unit) {
val cfg = HikariConfig(config.dataSourceProperties)
cfg.maximumPoolSize = 1
return HikariDataSource(cfg).use { dataSource ->
withDatasource(dataSource)
}
private fun runWithDataSource(config: Configuration, baseDirectory: Path, classLoader: ClassLoader, withDatasource: (DataSource) -> Unit) {
val driversFolder = baseDirectory / "drivers"
return withDatasource(createDatasourceFromDriverJars(config.dataSourceProperties, classLoader, driversFolder))
}
private fun errorAndExit(message: String?) {