mirror of
https://github.com/corda/corda.git
synced 2024-12-29 09:18:58 +00:00
Create a capsule for Node Explorer, and allow login via command line parameters to bypass login screen.
This commit is contained in:
parent
30f9cc8fcd
commit
f9ac03287c
@ -13,6 +13,7 @@ include 'experimental:sandbox'
|
|||||||
include 'test-utils'
|
include 'test-utils'
|
||||||
include 'tools:demobench'
|
include 'tools:demobench'
|
||||||
include 'tools:explorer'
|
include 'tools:explorer'
|
||||||
|
include 'tools:explorer:capsule'
|
||||||
include 'tools:loadtest'
|
include 'tools:loadtest'
|
||||||
include 'docs/source/example-code' // Note that we are deliberately choosing to use '/' here. With ':' gradle would treat the directories as actual projects.
|
include 'docs/source/example-code' // Note that we are deliberately choosing to use '/' here. With ':' gradle would treat the directories as actual projects.
|
||||||
include 'samples:attachment-demo'
|
include 'samples:attachment-demo'
|
||||||
|
54
tools/explorer/capsule/build.gradle
Normal file
54
tools/explorer/capsule/build.gradle
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
/**
|
||||||
|
* This build.gradle exists to package Node Explorer as an executable fat jar.
|
||||||
|
*/
|
||||||
|
apply plugin: 'us.kirchmeier.capsule'
|
||||||
|
|
||||||
|
description 'Node Explorer'
|
||||||
|
|
||||||
|
repositories {
|
||||||
|
mavenLocal()
|
||||||
|
mavenCentral()
|
||||||
|
maven {
|
||||||
|
url 'http://oss.sonatype.org/content/repositories/snapshots'
|
||||||
|
}
|
||||||
|
jcenter()
|
||||||
|
maven {
|
||||||
|
url 'https://dl.bintray.com/kotlin/exposed'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Force the Caplet to target Java 6. This ensures that running 'java -jar explorer.jar' on any Java 6 VM upwards
|
||||||
|
// will get as far as the Capsule version checks, meaning that if your JVM is too old, you will at least get
|
||||||
|
// a sensible error message telling you what to do rather than a bytecode version exception that doesn't.
|
||||||
|
// If we introduce .java files into this module that need Java 8+ then we will have to push the caplet into
|
||||||
|
// its own module so its target can be controlled individually, but for now this suffices.
|
||||||
|
sourceCompatibility = 1.6
|
||||||
|
targetCompatibility = 1.6
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
compile project(':tools:explorer')
|
||||||
|
}
|
||||||
|
|
||||||
|
task buildExplorerJAR(type: FatCapsule) {
|
||||||
|
applicationClass 'net.corda.explorer.Main'
|
||||||
|
archiveName "node-explorer-${corda_version}.jar"
|
||||||
|
applicationSource = files(project.tasks.findByName('jar'), '../build/classes/main/ExplorerCaplet.class')
|
||||||
|
classifier 'fat'
|
||||||
|
|
||||||
|
capsuleManifest {
|
||||||
|
systemProperties['visualvm.display.name'] = 'Node Explorer'
|
||||||
|
minJavaVersion = '1.8.0'
|
||||||
|
// This version is known to work and avoids earlier 8u versions that have bugs.
|
||||||
|
minUpdateVersion['1.8'] = '102'
|
||||||
|
caplets = ['ExplorerCaplet']
|
||||||
|
|
||||||
|
// JVM configuration:
|
||||||
|
// - Constrain to small heap sizes to ease development on low end devices.
|
||||||
|
// - Switch to the G1 GC which is going to be the default in Java 9 and gives low pause times/string dedup.
|
||||||
|
//
|
||||||
|
// If you change these flags, please also update Driver.kt
|
||||||
|
jvmArgs = ['-Xmx200m', '-XX:+UseG1GC']
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
build.dependsOn buildExplorerJAR
|
49
tools/explorer/src/main/java/ExplorerCaplet.java
Normal file
49
tools/explorer/src/main/java/ExplorerCaplet.java
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
import java.io.File;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class ExplorerCaplet extends Capsule {
|
||||||
|
|
||||||
|
protected ExplorerCaplet(Capsule pred) {
|
||||||
|
super(pred);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Overriding the Caplet classpath generation via the intended interface in Capsule.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
protected <T> T attribute(Map.Entry<String, T> attr) {
|
||||||
|
// Equality is used here because Capsule never instantiates these attributes but instead reuses the ones
|
||||||
|
// defined as public static final fields on the Capsule class, therefore referential equality is safe.
|
||||||
|
if (ATTR_APP_CLASS_PATH == attr) {
|
||||||
|
T cp = super.attribute(attr);
|
||||||
|
List<Path> classpath = augmentClasspath((List<Path>) cp, "plugins");
|
||||||
|
return (T) augmentClasspath(classpath, "dependencies");
|
||||||
|
}
|
||||||
|
return super.attribute(attr);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Make directory configurable via the capsule manifest.
|
||||||
|
// TODO: Add working directory variable to capsules string replacement variables.
|
||||||
|
private List<Path> augmentClasspath(List<Path> classpath, String dirName) {
|
||||||
|
File dir = new File(dirName);
|
||||||
|
if (!dir.exists()) {
|
||||||
|
dir.mkdir();
|
||||||
|
}
|
||||||
|
|
||||||
|
File[] files = dir.listFiles();
|
||||||
|
for (File file : files) {
|
||||||
|
if (file.isFile() && isJAR(file)) {
|
||||||
|
classpath.add(file.toPath().toAbsolutePath());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return classpath;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Boolean isJAR(File file) {
|
||||||
|
return file.getName().toLowerCase().endsWith(".jar");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -55,10 +55,40 @@ class Main : App(MainView::class) {
|
|||||||
}.showAndWait().get()
|
}.showAndWait().get()
|
||||||
if (button != ButtonType.OK) it.consume()
|
if (button != ButtonType.OK) it.consume()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val hostname = parameters.named["host"]
|
||||||
|
val port = asInteger(parameters.named["port"])
|
||||||
|
val username = parameters.named["username"]
|
||||||
|
val password = parameters.named["password"]
|
||||||
|
var isLoggedIn = false
|
||||||
|
|
||||||
|
if ((hostname != null) && (port != null) && (username != null) && (password != null)) {
|
||||||
|
try {
|
||||||
|
loginView.login(hostname, port, username, password)
|
||||||
|
isLoggedIn = true
|
||||||
|
} catch (e: Exception) {
|
||||||
|
ExceptionDialog(e).apply { initOwner(stage.scene.window) }.showAndWait()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isLoggedIn) {
|
||||||
stage.hide()
|
stage.hide()
|
||||||
loginView.login()
|
loginView.login()
|
||||||
stage.show()
|
stage.show()
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun asInteger(s: String?): Int? {
|
||||||
|
if (s == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
return s.toInt();
|
||||||
|
} catch (e: NumberFormatException) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
init {
|
init {
|
||||||
// Shows any uncaught exception in exception dialog.
|
// Shows any uncaught exception in exception dialog.
|
||||||
|
@ -38,6 +38,10 @@ class LoginView : View() {
|
|||||||
private val keyStorePasswordProperty by objectProperty(SettingsModel::keyStorePasswordProperty)
|
private val keyStorePasswordProperty by objectProperty(SettingsModel::keyStorePasswordProperty)
|
||||||
private val trustStorePasswordProperty by objectProperty(SettingsModel::trustStorePasswordProperty)
|
private val trustStorePasswordProperty by objectProperty(SettingsModel::trustStorePasswordProperty)
|
||||||
|
|
||||||
|
fun login(host: String?, port: Int, username: String, password: String) {
|
||||||
|
getModel<NodeMonitorModel>().register(HostAndPort.fromParts(host, port), configureSSL(), username, password)
|
||||||
|
}
|
||||||
|
|
||||||
fun login() {
|
fun login() {
|
||||||
val status = Dialog<LoginStatus>().apply {
|
val status = Dialog<LoginStatus>().apply {
|
||||||
dialogPane = root
|
dialogPane = root
|
||||||
@ -46,7 +50,7 @@ class LoginView : View() {
|
|||||||
ButtonBar.ButtonData.OK_DONE -> try {
|
ButtonBar.ButtonData.OK_DONE -> try {
|
||||||
root.isDisable = true
|
root.isDisable = true
|
||||||
// TODO : Run this async to avoid UI lockup.
|
// TODO : Run this async to avoid UI lockup.
|
||||||
getModel<NodeMonitorModel>().register(HostAndPort.fromParts(hostTextField.text, portProperty.value), configureSSL(), usernameTextField.text, passwordTextField.text)
|
login(hostTextField.text, portProperty.value, usernameTextField.text, passwordTextField.text)
|
||||||
if (!rememberMe.value) {
|
if (!rememberMe.value) {
|
||||||
username.value = ""
|
username.value = ""
|
||||||
host.value = ""
|
host.value = ""
|
||||||
|
Loading…
Reference in New Issue
Block a user