Launch DB viewer for node.

This commit is contained in:
Chris Rankin 2017-01-30 13:57:43 +00:00
parent 5ee7930a16
commit 02323e8207
9 changed files with 116 additions and 8 deletions

View File

@ -1,15 +1,15 @@
group 'net.corda' group 'net.corda'
version '0.8-SNAPSHOT' version "$corda_version"
buildscript { buildscript {
ext.kotlin_version = '1.0.6' ext.kotlin_version = '1.0.6'
ext.tornadofx_version = '1.6.0' ext.tornadofx_version = '1.6.0'
ext.h2_version = '1.4.193'
ext.jna_version = '4.1.0' ext.jna_version = '4.1.0'
ext.purejavacomm_version = '0.0.17' ext.purejavacomm_version = '0.0.17'
ext.guava_version = '14.0.1' ext.guava_version = '14.0.1'
ext.slf4j_version = '1.7.22' ext.slf4j_version = '1.7.22'
ext.logback_version = '1.1.3' ext.logback_version = '1.1.3'
ext.typesafeconfig_version = '1.3.1'
repositories { repositories {
mavenCentral() mavenCentral()
@ -44,6 +44,7 @@ dependencies {
compile "no.tornado:tornadofx:$tornadofx_version" compile "no.tornado:tornadofx:$tornadofx_version"
compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
compile "com.h2database:h2:$h2_version"
compile "net.java.dev.jna:jna:$jna_version" compile "net.java.dev.jna:jna:$jna_version"
compile "net.java.dev.jna:jna-platform:$jna_version" compile "net.java.dev.jna:jna-platform:$jna_version"
compile "com.google.guava:guava:$guava_version" compile "com.google.guava:guava:$guava_version"
@ -51,11 +52,11 @@ dependencies {
compile "org.slf4j:log4j-over-slf4j:$slf4j_version" compile "org.slf4j:log4j-over-slf4j:$slf4j_version"
compile "org.slf4j:jul-to-slf4j:$slf4j_version" compile "org.slf4j:jul-to-slf4j:$slf4j_version"
compile "ch.qos.logback:logback-classic:$logback_version" compile "ch.qos.logback:logback-classic:$logback_version"
compile "com.typesafe:config:$typesafeconfig_version" compile "com.typesafe:config:$typesafe_config_version"
compile ":jediterm-terminal-2.5" compile ":jediterm-terminal-2.5"
compile ':pty4j-0.7.2' compile ':pty4j-0.7.2'
testCompile group: 'junit', name: 'junit', version: '4.11' testCompile group: 'junit', name: 'junit', version: "$junit_version"
} }
jar { jar {

View File

@ -0,0 +1,53 @@
package net.corda.demobench.model
import org.h2.server.web.LocalWebServer
import org.h2.tools.Server
import org.h2.util.JdbcUtils
import org.slf4j.LoggerFactory
import java.util.concurrent.Executors
class DBViewer : AutoCloseable {
private val log = LoggerFactory.getLogger(DBViewer::class.java)
private val webServer: Server
private val pool = Executors.newCachedThreadPool()
private val t = Thread("DBViewer")
override fun close() {
webServer.shutdown()
pool.shutdown()
t.join()
}
fun openBrowser(h2Port: Int) {
val conn = JdbcUtils.getConnection(
"org.h2.Driver",
"jdbc:h2:tcp://localhost:%d/node".format(h2Port),
"sa",
""
)
val url = (webServer.service as LocalWebServer).addSession(conn)
log.info("URL: {}", url)
pool.execute {
Server.openBrowser(url)
}
}
init {
val ws = LocalWebServer()
webServer = Server(ws, "-webPort", "0")
ws.setShutdownHandler(webServer)
webServer.setShutdownHandler {
webServer.stop()
}
t.run {
webServer.start()
}
}
}

View File

@ -11,6 +11,7 @@ class NodeConfig(
artemisPort: Int, artemisPort: Int,
nearestCity: String, nearestCity: String,
webPort: Int, webPort: Int,
h2Port: Int,
extraServices: List<String> extraServices: List<String>
) : NetworkMapConfig(legalName, artemisPort) { ) : NetworkMapConfig(legalName, artemisPort) {
@ -22,6 +23,10 @@ class NodeConfig(
val webPort : Int val webPort : Int
get() { return webPortValue } get() { return webPortValue }
private var h2PortValue: Int = h2Port
val h2Port : Int
get() { return h2PortValue }
private var extraServicesValue: List<String> = extraServices private var extraServicesValue: List<String> = extraServices
val extraServices : List<String> val extraServices : List<String>
get() { return extraServicesValue } get() { return extraServicesValue }
@ -43,6 +48,7 @@ class NodeConfig(
} )) } ))
.withValue("webAddress", addressValueFor(webPort)) .withValue("webAddress", addressValueFor(webPort))
.withValue("rpcUsers", valueFor(listOf<String>())) .withValue("rpcUsers", valueFor(listOf<String>()))
.withValue("h2port", valueFor(h2Port))
.withValue("useTestClock", valueFor(true)) .withValue("useTestClock", valueFor(true))
} }

View File

@ -34,6 +34,7 @@ class NodeController : Controller() {
nodeData.artemisPort.value, nodeData.artemisPort.value,
nodeData.nearestCity.value.trim(), nodeData.nearestCity.value.trim(),
nodeData.webPort.value, nodeData.webPort.value,
nodeData.h2Port.value,
nodeData.extraServices.value nodeData.extraServices.value
) )

View File

@ -9,8 +9,9 @@ class NodeData {
val legalName = SimpleStringProperty("") val legalName = SimpleStringProperty("")
val nearestCity = SimpleStringProperty("London") val nearestCity = SimpleStringProperty("London")
val artemisPort = SimpleIntegerProperty(0) val artemisPort = SimpleIntegerProperty()
val webPort = SimpleIntegerProperty(0) val webPort = SimpleIntegerProperty()
val h2Port = SimpleIntegerProperty()
val extraServices = SimpleListProperty(mutableListOf<String>().observable()) val extraServices = SimpleListProperty(mutableListOf<String>().observable())
} }

View File

@ -8,5 +8,6 @@ class NodeDataModel : ItemViewModel<NodeData>(NodeData()) {
val nearestCity = bind { item?.nearestCity } val nearestCity = bind { item?.nearestCity }
val artemisPort = bind { item?.artemisPort } val artemisPort = bind { item?.artemisPort }
val webPort = bind { item?.webPort } val webPort = bind { item?.webPort }
val h2Port = bind { item?.h2Port }
} }

View File

@ -92,6 +92,21 @@ class NodeTabView : Fragment() {
} }
} }
} }
field("Database Port") {
textfield(model.h2Port, NumberStringConverter(INTEGER_FORMAT)) {
minWidth = 100.0
maxWidth = 100.0
validator {
if ((it == null) || it.isEmpty()) {
error("Port number required")
} else if (it.contains(NOT_NUMBER)) {
error("Invalid port number")
} else {
null
}
}
}
}
} }
fieldset("Services") { fieldset("Services") {
@ -144,5 +159,6 @@ class NodeTabView : Fragment() {
model.artemisPort.value = nodeController.nextPort model.artemisPort.value = nodeController.nextPort
model.webPort.value = nodeController.nextPort model.webPort.value = nodeController.nextPort
model.h2Port.value = nodeController.nextPort
} }
} }

View File

@ -10,6 +10,7 @@ import javafx.scene.control.Label
import javafx.scene.layout.Priority import javafx.scene.layout.Priority
import javafx.scene.layout.VBox import javafx.scene.layout.VBox
import javax.swing.SwingUtilities import javax.swing.SwingUtilities
import net.corda.demobench.model.DBViewer
import net.corda.demobench.model.NodeConfig import net.corda.demobench.model.NodeConfig
import net.corda.demobench.model.NodeController import net.corda.demobench.model.NodeController
import net.corda.demobench.pty.R3Pty import net.corda.demobench.pty.R3Pty
@ -20,7 +21,7 @@ import tornadofx.vgrow
class NodeTerminalView : Fragment() { class NodeTerminalView : Fragment() {
override val root by fxml<VBox>() override val root by fxml<VBox>()
private val controller by inject<NodeController>() private val nodeController by inject<NodeController>()
private val nodeName by fxid<Label>() private val nodeName by fxid<Label>()
private val p2pPort by fxid<PropertyLabel>() private val p2pPort by fxid<PropertyLabel>()
@ -31,6 +32,7 @@ class NodeTerminalView : Fragment() {
private val viewDatabaseButton by fxid<Button>() private val viewDatabaseButton by fxid<Button>()
private val launchExplorerButton by fxid<Button>() private val launchExplorerButton by fxid<Button>()
var viewer : DBViewer = DBViewer()
var pty : R3Pty? = null var pty : R3Pty? = null
fun open(config: NodeConfig) { fun open(config: NodeConfig) {
@ -50,11 +52,16 @@ class NodeTerminalView : Fragment() {
pty = r3pty pty = r3pty
swingTerminal.content = r3pty.terminal swingTerminal.content = r3pty.terminal
controller.runCorda(r3pty, config) nodeController.runCorda(r3pty, config)
viewDatabaseButton.setOnAction {
viewer.openBrowser(config.h2Port)
}
}) })
} }
fun close() { fun close() {
viewer.close()
pty?.close() pty?.close()
} }

View File

@ -0,0 +1,22 @@
package org.h2.server.web
import java.sql.Connection
/**
*
*/
class LocalWebServer : WebServer() {
/**
* Create a new session that will not kill the entire
* web server if/when we disconnect it.
*/
override fun addSession(conn: Connection): String {
val session = createNewSession("local")
session.setConnection(conn)
session.put("url", conn.metaData.url)
val s = session.get("sessionId") as String
return url + "/frame.jsp?jsessionid=" + s
}
}