Skip to content

Commit

Permalink
Merge pull request #270 from corda/chrisr3-backport
Browse files Browse the repository at this point in the history
NOTICK: Backport changes from master 5.x branch.
  • Loading branch information
chrisr3 authored Nov 24, 2019
2 parents 84308a7 + 1b30fe5 commit bcf9128
Show file tree
Hide file tree
Showing 19 changed files with 132 additions and 115 deletions.
1 change: 1 addition & 0 deletions CONTRIBUTORS.md
Original file line number Diff line number Diff line change
Expand Up @@ -138,4 +138,5 @@ changes to this list.
* Viktor Kolomeyko (R3)
* Wawrzek Niewodniczanski (R3)
* Wei Wu Zhang (Commonwealth Bank of Australia)
* William Yang
* Zabrina Smith (Northern Trust)
1 change: 0 additions & 1 deletion api-scanner/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ description "Generates a summary of the artifact's public API"

repositories {
mavenCentral()
jcenter()
}

gradlePlugin {
Expand Down
8 changes: 4 additions & 4 deletions api-scanner/src/main/java/net/corda/plugins/ScanApi.java
Original file line number Diff line number Diff line change
Expand Up @@ -318,7 +318,7 @@ private void writeMethods(ApiPrintWriter writer, List<MethodInfo> methods) {
sort(methods);
for (MethodInfo method : methods) {
if (isVisible(method.getModifiers()) // Only public and protected methods
&& !isExcluded(filterAnnotationsFor(method)) // Filter out methods explicitly excluded
&& !isExcluded(method) // Filter out methods explicitly excluded
&& isValid(method.getModifiers(), METHOD_MASK) // Excludes bridge methods
&& !hasInternalAnnotation(method.getAnnotationNames()) // Excludes methods annotated as @CordaInternal
&& !isKotlinInternalScope(method)) {
Expand Down Expand Up @@ -452,9 +452,9 @@ private static boolean isValid(int modifiers, int mask) {
return (modifiers & mask) == modifiers;
}

private boolean isExcluded(MethodInfo methodWithoutAnnotations) {
final String methodSignature = methodWithoutAnnotations.getMethodName() + methodWithoutAnnotations.getTypeDescriptorStr();
final String className = methodWithoutAnnotations.getClassName();
private boolean isExcluded(MethodInfo method) {
final String methodSignature = method.getMethodName() + method.getTypeDescriptorStr();
final String className = method.getClassName();

return this.excludeMethods.containsKey(className) &&
this.excludeMethods.get(className).contains(methodSignature);
Expand Down
3 changes: 1 addition & 2 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,13 @@ buildscript {
snake_yaml_version = '1.19'
commons_io_version = '2.6'
assertj_version = '3.12.1'
junit_jupiter_version = '5.4.2'
junit_jupiter_version = '5.5.2'
hamcrest_version = '2.1'
asm_version = '6.2.1'
}

repositories {
mavenCentral()
jcenter()
}

dependencies {
Expand Down
4 changes: 4 additions & 0 deletions changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@

### Version 4.0.47

* `cordformation`: Add `--base-debug-port=` and `--base-monitoring-port=` options to the `runnodes` script to change the port numbers that the script will begin incrementing from.

* `publish-utils`: Fix NPE for dependencies without group, name or version when generating POMs from custom Gradle configurations.

### Version 4.0.46

* `publish-utils`: Generate appropriate `compile` and `runtime` dependencies when publishing from a given Gradle configuration.
Expand Down
1 change: 0 additions & 1 deletion cordapp/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ description 'Turns a project into a cordapp project that produces cordapp fat JA

repositories {
mavenCentral()
jcenter()
}

gradlePlugin {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ class CordappGradleConfigurationsTest {
|
|dependencies {
| compile "org.slf4j:slf4j-api:1.7.26"
| runtime "commons-io:commons-io:2.4"
| runtime "commons-io:commons-io:2.6"
| cordaCompile "com.google.guava:guava:20.0"
| cordaRuntime "javax.servlet:javax.servlet-api:3.1.0"
| implementation "javax.persistence:javax.persistence-api:2.2"
Expand Down Expand Up @@ -77,7 +77,7 @@ class CordappGradleConfigurationsTest {
@Test
fun testRuntimeIncluded() {
assertThat(testProject.output)
.contains("CorDapp dependency: commons-io-2.4.jar")
.contains("CorDapp dependency: commons-io-2.6.jar")
assertThat(poms)
.anyMatch { it.name == "META-INF/maven/commons-io/commons-io/pom.xml" }
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ class CordappLibraryGradleConfigurationsTest {
|
|dependencies {
| compile "org.slf4j:slf4j-api:1.7.26"
| runtime "commons-io:commons-io:2.4"
| runtime "commons-io:commons-io:2.6"
| cordaCompile "com.google.guava:guava:20.0"
| cordaRuntime "javax.servlet:javax.servlet-api:3.1.0"
| api "javax.annotation:javax.annotation-api:1.3.2"
Expand Down Expand Up @@ -87,7 +87,7 @@ class CordappLibraryGradleConfigurationsTest {
@Test
fun testRuntimeIncluded() {
assertThat(testProject.output)
.contains("CorDapp dependency: commons-io-2.4.jar")
.contains("CorDapp dependency: commons-io-2.6.jar")
assertThat(poms)
.anyMatch { it.name == "META-INF/maven/commons-io/commons-io/pom.xml" }
}
Expand Down
201 changes: 111 additions & 90 deletions cordformation/src/noderunner/kotlin/net/corda/plugins/NodeRunner.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,17 @@ import java.util.*

private const val HEADLESS_FLAG = "--headless"
private const val CAPSULE_DEBUG_FLAG = "--capsule-debug"
private const val BASE_DEBUG_PORT_FLAG = "--base-debug-port="
private const val BASE_MONITORING_PORT_FLAG = "--base-monitoring-port="
private const val CORDA_JAR_NAME = "corda.jar"
private const val CORDA_WEBSERVER_JAR_NAME = "corda-webserver.jar"
private const val CORDA_CONFIG_NAME = "node.conf"
private const val CORDA_WEBSERVER_CONFIG_NAME = "web-server.conf"
private val CORDA_HEADLESS_ARGS = listOf("--no-local-shell")

private const val DEFAULT_BASE_DEBUG_PORT = 5005
private const val DEFAULT_BASE_MONITORING_PORT = 7005

private val os by lazy {
val osName = System.getProperty("os.name", "generic").toLowerCase(Locale.ENGLISH)
if ("mac" in osName || "darwin" in osName) OS.MACOS
Expand All @@ -21,124 +26,140 @@ private val os by lazy {

private enum class OS { MACOS, WINDOWS, LINUX }

private object DebugPortAlloc {
private var basePort = 5005
internal fun next() = basePort++
}

private object MonitoringPortAlloc {
private var basePort = 7005
private class PortAlloc(private var basePort: Int) {
internal fun next() = basePort++
}

fun main(args: Array<String>) {
val startedProcesses = mutableListOf<Process>()
val headless = ((!isTmux() && GraphicsEnvironment.isHeadless()) || args.contains(HEADLESS_FLAG))
val isHeadless = ((!isTmux() && GraphicsEnvironment.isHeadless()) || args.contains(HEADLESS_FLAG))
val capsuleDebugMode = args.contains(CAPSULE_DEBUG_FLAG)
val workingDir = File(System.getProperty("user.dir"))
val javaArgs = args.filter { it != HEADLESS_FLAG && it != CAPSULE_DEBUG_FLAG }
val baseDebugPort = parseArg(args, BASE_DEBUG_PORT_FLAG, DEFAULT_BASE_DEBUG_PORT)
println("base debug port set to: $baseDebugPort")
val baseMonitoringPort = parseArg(args, BASE_MONITORING_PORT_FLAG, DEFAULT_BASE_MONITORING_PORT)
println("base monitoring port set to: $baseMonitoringPort")
val javaArgs = args.filter { it != HEADLESS_FLAG && it != CAPSULE_DEBUG_FLAG && !it.startsWith(BASE_DEBUG_PORT_FLAG) && !it.startsWith(BASE_MONITORING_PORT_FLAG) }
val jvmArgs = if (capsuleDebugMode) listOf("-Dcapsule.log=verbose") else emptyList()
println("Starting nodes in $workingDir")
workingDir.listFiles { file -> file.isDirectory }.forEach { dir ->
startNode(dir, headless, jvmArgs, javaArgs)?.let { startedProcesses += it }
startWebserver(dir, headless, jvmArgs, javaArgs)?.let { startedProcesses += it }
}
println("Started ${startedProcesses.size} processes")
NodeRunner(baseDebugPort, baseMonitoringPort).run(isHeadless, javaArgs, jvmArgs)
println("Finished starting nodes")
}

private fun startNode(nodeDir: File, headless: Boolean, jvmArgs: List<String>, javaArgs: List<String>): Process? {
val jarFile = nodeDir.resolve(CORDA_JAR_NAME)
return if(!jarFile.isFile) {
println("No file $CORDA_JAR_NAME found in $nodeDir")
null
} else if(!nodeDir.resolve(CORDA_CONFIG_NAME).isFile) {
println("Node conf file $CORDA_CONFIG_NAME not found in $nodeDir")
null
} else {
val debugPort = DebugPortAlloc.next()
println("Starting $CORDA_JAR_NAME in $nodeDir on debug port $debugPort")
startJar(jarFile, headless, jvmArgs + getDebugArgs(debugPort) + getJolokiaArgs(nodeDir), javaArgs, CORDA_HEADLESS_ARGS)
private class NodeRunner(baseDebugPort: Int, baseMonitoringPort: Int) {
private val debugPortAlloc = PortAlloc(baseDebugPort)
private val monitoringPortAlloc = PortAlloc(baseMonitoringPort)

fun run(isHeadless: Boolean, javaArgs: List<String>, jvmArgs: List<String>) {
val startedProcesses = mutableListOf<Process>()
val workingDir = File(System.getProperty("user.dir"))
println("Starting nodes in $workingDir")
workingDir.listFiles { file -> file.isDirectory }.forEach { dir ->
startNode(dir, isHeadless, jvmArgs, javaArgs)?.let { startedProcesses += it }
startWebserver(dir, isHeadless, jvmArgs, javaArgs)?.let { startedProcesses += it }
}
println("Started ${startedProcesses.size} processes")
}
}

private fun startWebserver(nodeDir: File, headless: Boolean, jvmArgs: List<String>, javaArgs: List<String>): Process? {
val jarFile = nodeDir.resolve(CORDA_WEBSERVER_JAR_NAME)
return if(!jarFile.isFile) {
null
} else if(!nodeDir.resolve(CORDA_WEBSERVER_CONFIG_NAME).isFile) {
println("Webserver conf file $CORDA_WEBSERVER_CONFIG_NAME not found in $nodeDir")
null
} else {
println("Starting $CORDA_WEBSERVER_JAR_NAME in $nodeDir")
startJar(jarFile, headless, jvmArgs, javaArgs)
private fun startNode(nodeDir: File, headless: Boolean, jvmArgs: List<String>, javaArgs: List<String>): Process? {
val jarFile = nodeDir.resolve(CORDA_JAR_NAME)
return if (!jarFile.isFile) {
println("No file $CORDA_JAR_NAME found in $nodeDir")
null
} else if (!nodeDir.resolve(CORDA_CONFIG_NAME).isFile) {
println("Node conf file $CORDA_CONFIG_NAME not found in $nodeDir")
null
} else {
val debugPort = debugPortAlloc.next()
println("Starting $CORDA_JAR_NAME in $nodeDir on debug port $debugPort")
startJar(jarFile, headless, jvmArgs + getDebugArgs(debugPort) + getJolokiaArgs(nodeDir), javaArgs, CORDA_HEADLESS_ARGS)
}
}
}

fun startJar(jar: File, headless: Boolean, jvmArgs: List<String>, javaArgs: List<String>, headlessArgs: List<String> = emptyList()): Process {
val workingDir = jar.parentFile
val nodeName = workingDir.name
val command = getBaseCommand(jvmArgs, nodeName) + listOf("-jar", jar.absolutePath) + javaArgs
val process = if (headless) startHeadless(command, workingDir, nodeName, headlessArgs) else startWindowed(command, workingDir, nodeName)
if (os == OS.MACOS) Thread.sleep(1000)
return process
}
private fun startWebserver(nodeDir: File, headless: Boolean, jvmArgs: List<String>, javaArgs: List<String>): Process? {
val jarFile = nodeDir.resolve(CORDA_WEBSERVER_JAR_NAME)
return if (!jarFile.isFile) {
null
} else if (!nodeDir.resolve(CORDA_WEBSERVER_CONFIG_NAME).isFile) {
println("Webserver conf file $CORDA_WEBSERVER_CONFIG_NAME not found in $nodeDir")
null
} else {
println("Starting $CORDA_WEBSERVER_JAR_NAME in $nodeDir")
startJar(jarFile, headless, jvmArgs, javaArgs)
}
}

private fun startHeadless(command: List<String>, workingDir: File, nodeName: String, headlessArgs: List<String> = emptyList()): Process {
println("Running command: ${command.joinToString(" ")}")
return ProcessBuilder(command + headlessArgs).redirectError(File("error.$nodeName.log")).inheritIO().directory(workingDir).start()
}
private fun startJar(jar: File, headless: Boolean, jvmArgs: List<String>, javaArgs: List<String>, headlessArgs: List<String> = emptyList()): Process {
val workingDir = jar.parentFile
val nodeName = workingDir.name
val command = getBaseCommand(jvmArgs, nodeName) + listOf("-jar", jar.absolutePath) + javaArgs
val process = if (headless) startHeadless(command, workingDir, nodeName, headlessArgs) else startWindowed(command, workingDir, nodeName)
if (os == OS.MACOS) Thread.sleep(1000)
return process
}

private fun startWindowed(command: List<String>, workingDir: File, nodeName: String): Process {
val params = when (os) {
OS.MACOS -> {
listOf("osascript", "-e", """tell app "Terminal"
private fun startHeadless(command: List<String>, workingDir: File, nodeName: String, headlessArgs: List<String> = emptyList()): Process {
println("Running command: ${command.joinToString(" ")}")
return ProcessBuilder(command + headlessArgs).redirectError(File("error.$nodeName.log")).inheritIO().directory(workingDir).start()
}

private fun startWindowed(command: List<String>, workingDir: File, nodeName: String): Process {
val params = when (os) {
OS.MACOS -> {
listOf("osascript", "-e", """tell app "Terminal"
activate
delay 0.5
tell app "System Events" to tell process "Terminal" to keystroke "t" using command down
delay 0.5
do script "bash -c 'cd \"$workingDir\" ; \"${command.joinToString("""\" \"""")}\" && exit'" in selected tab of the front window
end tell""")
}
OS.WINDOWS -> {
listOf("cmd", "/C", "start ${command.joinToString(" ") { windowsSpaceEscape(it) }}")
}
OS.LINUX -> {
// Start shell to keep window open unless java terminated normally or due to SIGTERM:
val unixCommand = "${unixCommand(command)}; [ $? -eq 0 -o $? -eq 143 ] || sh"
if (isTmux()) {
listOf("tmux", "new-window", "-n", nodeName, unixCommand)
} else {
listOf("xterm", "-T", nodeName, "-e", unixCommand)
}
OS.WINDOWS -> {
listOf("cmd", "/C", "start ${command.joinToString(" ") { windowsSpaceEscape(it) }}")
}
OS.LINUX -> {
// Start shell to keep window open unless java terminated normally or due to SIGTERM:
val unixCommand = "${unixCommand(command)}; [ $? -eq 0 -o $? -eq 143 ] || sh"
if (isTmux()) {
listOf("tmux", "new-window", "-n", nodeName, unixCommand)
} else {
listOf("xterm", "-T", nodeName, "-e", unixCommand)
}
}
}
println("Running command: ${params.joinToString(" ")}")
return ProcessBuilder(params).directory(workingDir).start()
}
println("Running command: ${params.joinToString(" ")}")
return ProcessBuilder(params).directory(workingDir).start()
}

private fun getBaseCommand(baseJvmArgs: List<String>, nodeName: String): List<String> {
val jvmArgs = if (baseJvmArgs.isNotEmpty()) {
listOf("-Dcapsule.jvm.args=${baseJvmArgs.joinToString(separator = " ")}")
} else {
emptyList()
private fun getBaseCommand(baseJvmArgs: List<String>, nodeName: String): List<String> {
val jvmArgs = if (baseJvmArgs.isNotEmpty()) {
listOf("-Dcapsule.jvm.args=${baseJvmArgs.joinToString(separator = " ")}")
} else {
emptyList()
}
return listOf(getJavaPath()) + jvmArgs + listOf("-Dname=$nodeName")
}
return listOf(getJavaPath()) + jvmArgs + listOf("-Dname=$nodeName")
}

private fun getDebugArgs(debugPort: Int) = listOf("-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=$debugPort")
private fun getJolokiaArgs(dir: File): List<String> {
val jolokiaJar = File("$dir/drivers").listFiles { _, filename ->
filename.matches("jolokia-jvm-.*-agent\\.jar$".toRegex())
}.firstOrNull()?.name
private fun getDebugArgs(debugPort: Int) = listOf("-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=$debugPort")
private fun getJolokiaArgs(dir: File): List<String> {
val jolokiaJar = File("$dir/drivers").listFiles { _, filename ->
filename.matches("jolokia-jvm-.*-agent\\.jar$".toRegex())
}.firstOrNull()?.name

return if (jolokiaJar != null) {
val monitoringPort = monitoringPortAlloc.next()
println("Node will expose jolokia monitoring port on $monitoringPort")

return if(jolokiaJar != null) {
val monitoringPort = MonitoringPortAlloc.next()
println("Node will expose jolokia monitoring port on $monitoringPort")
listOf("-javaagent:drivers/$jolokiaJar=port=$monitoringPort,logHandlerClass=net.corda.node.JolokiaSlf4jAdapter")
} else {
emptyList()
}
}
}

listOf("-javaagent:drivers/$jolokiaJar=port=$monitoringPort,logHandlerClass=net.corda.node.JolokiaSlf4jAdapter")
} else {
emptyList()
private fun parseArg(args: Array<String>, flagPrefix: String, defaultValue: Int): Int {
return try {
args.firstOrNull { it.startsWith(flagPrefix) }?.removePrefix(flagPrefix)?.run(Integer::valueOf) ?: defaultValue
} catch (_: NumberFormatException) {
println("Invalid option - using default: $flagPrefix$defaultValue")
defaultValue
}
}

Expand All @@ -148,4 +169,4 @@ private fun isTmux() = System.getenv("TMUX")?.isNotEmpty() ?: false
// Quoting the entire path does not work, only the space or directory within the path.
private fun windowsSpaceEscape(s:String) = s.replace(" ", "\" \"")
private fun unixCommand(command: List<String>) = command.map(::quotedFormOf).joinToString(" ")
private fun getJavaPath(): String = File(File(System.getProperty("java.home"), "bin"), "java").path
private fun getJavaPath(): String = File(File(System.getProperty("java.home"), "bin"), "java").path
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ repositories {
mavenCentral()
maven { url 'https://ci-artifactory.corda.r3cev.com/artifactory/corda-dev' }
maven { url 'https://ci-artifactory.corda.r3cev.com/artifactory/corda-releases' }
maven { url 'https://jitpack.io' }
}

dependencies {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ repositories {
mavenCentral()
maven { url 'https://ci-artifactory.corda.r3cev.com/artifactory/corda-dev' }
maven { url 'https://ci-artifactory.corda.r3cev.com/artifactory/corda-releases' }
maven { url 'https://jitpack.io' }
}

dependencies {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ repositories {
mavenCentral()
maven { url 'https://ci-artifactory.corda.r3cev.com/artifactory/corda-dev' }
maven { url 'https://ci-artifactory.corda.r3cev.com/artifactory/corda-releases' }
maven { url 'https://jitpack.io' }
}

dependencies {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ repositories {
mavenCentral()
maven { url 'https://ci-artifactory.corda.r3cev.com/artifactory/corda-dev' }
maven { url 'https://ci-artifactory.corda.r3cev.com/artifactory/corda-releases' }
maven { url 'https://jitpack.io' }
}

dependencies {
Expand Down
Loading

0 comments on commit bcf9128

Please sign in to comment.