mirror of
https://github.com/corda/corda.git
synced 2025-02-20 17:33:15 +00:00
ENT-6547 Remove url classloader in shell loading (#7034)
The `corda-shell` jar will already be installed if it exists in the the node's `/drivers` directory. There is no need to include a `URLClassLoader` to load its classes. Rely on the process's main classloader.
This commit is contained in:
parent
bb55d93915
commit
c05c1934cf
@ -100,7 +100,6 @@ import net.corda.node.services.api.WritableTransactionStorage
|
||||
import net.corda.node.services.attachments.NodeAttachmentTrustCalculator
|
||||
import net.corda.node.services.config.NodeConfiguration
|
||||
import net.corda.node.services.config.rpc.NodeRpcOptions
|
||||
import net.corda.node.services.config.shell.toShellConfigMap
|
||||
import net.corda.node.services.config.shouldInitCrashShell
|
||||
import net.corda.node.services.diagnostics.NodeDiagnosticsService
|
||||
import net.corda.node.services.events.NodeSchedulerService
|
||||
@ -688,11 +687,10 @@ abstract class AbstractNode<S>(val configuration: NodeConfiguration,
|
||||
|
||||
open fun startShell() {
|
||||
if (configuration.shouldInitCrashShell()) {
|
||||
val shellConfiguration = configuration.toShellConfigMap()
|
||||
shellConfiguration["sshdPort"]?.let {
|
||||
configuration.sshd?.port?.let {
|
||||
log.info("Binding Shell SSHD server on port $it.")
|
||||
}
|
||||
InteractiveShell.startShellIfInstalled(configuration, shellConfiguration, cordappLoader)
|
||||
InteractiveShell.startShellIfInstalled(configuration, cordappLoader)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -263,9 +263,8 @@ open class NodeStartup : NodeStartupLogging {
|
||||
Node.printBasicNodeInfo("Node for \"$name\" started up and registered in $elapsed sec")
|
||||
|
||||
// Don't start the shell if there's no console attached.
|
||||
// Look for shell here??
|
||||
if (node.configuration.shouldStartLocalShell()) {
|
||||
InteractiveShell.runLocalShellIfInstalled(node.configuration.baseDirectory, node::stop)
|
||||
InteractiveShell.runLocalShellIfInstalled(node::stop)
|
||||
}
|
||||
if (node.configuration.shouldStartSSHDaemon()) {
|
||||
Node.printBasicNodeInfo("SSH server listening on port", node.configuration.sshd!!.port.toString())
|
||||
|
@ -2,12 +2,9 @@ package net.corda.node.internal.shell
|
||||
|
||||
import net.corda.node.services.config.NodeConfiguration
|
||||
import net.corda.node.services.config.shell.determineUnsafeUsers
|
||||
import net.corda.node.services.config.shell.toShellConfigMap
|
||||
import net.corda.nodeapi.internal.cordapp.CordappLoader
|
||||
import org.slf4j.LoggerFactory
|
||||
import java.io.File
|
||||
import java.net.URLClassLoader
|
||||
import java.nio.file.Path
|
||||
import java.nio.file.Paths
|
||||
|
||||
object InteractiveShell {
|
||||
|
||||
@ -20,13 +17,12 @@ object InteractiveShell {
|
||||
private const val RUN_LOCAL_SHELL_METHOD = "runLocalShell"
|
||||
private const val SET_USER_INFO_METHOD = "setUserInfo"
|
||||
|
||||
fun startShellIfInstalled(configuration: NodeConfiguration, shellConfiguration: Map<String, Any?>, cordappLoader: CordappLoader) {
|
||||
val shellJar = getSingleShellJarInDriversDirectory(configuration.baseDirectory)
|
||||
if (shellJar != null) {
|
||||
fun startShellIfInstalled(configuration: NodeConfiguration, cordappLoader: CordappLoader) {
|
||||
if (isShellInstalled()) {
|
||||
try {
|
||||
val classLoader = URLClassLoader(arrayOf(shellJar.toPath().toUri().toURL()), javaClass.classLoader)
|
||||
setUnsafeUsers(classLoader, configuration)
|
||||
startShell(classLoader, shellConfiguration, cordappLoader)
|
||||
val shellConfiguration = configuration.toShellConfigMap()
|
||||
setUnsafeUsers(configuration)
|
||||
startShell(shellConfiguration, cordappLoader)
|
||||
} catch (e: Exception) {
|
||||
log.error("Shell failed to start", e)
|
||||
}
|
||||
@ -36,63 +32,48 @@ object InteractiveShell {
|
||||
/**
|
||||
* Only call this after [startShellIfInstalled] has been called or the required classes will not be loaded into the current classloader.
|
||||
*/
|
||||
fun runLocalShellIfInstalled(baseDirectory: Path, onExit: () -> Unit = {}) {
|
||||
val shellJar = getSingleShellJarInDriversDirectory(baseDirectory)
|
||||
if (shellJar != null) {
|
||||
fun runLocalShellIfInstalled(onExit: () -> Unit = {}) {
|
||||
if (isShellInstalled()) {
|
||||
try {
|
||||
runLocalShell(javaClass.classLoader, onExit)
|
||||
runLocalShell(onExit)
|
||||
} catch (e: Exception) {
|
||||
log.error("Shell failed to start", e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun getSingleShellJarInDriversDirectory(baseDirectory: Path): File? {
|
||||
val uriToDriversDirectory = Paths.get("${baseDirectory}/drivers").toUri()
|
||||
val files = File(uriToDriversDirectory)
|
||||
.listFiles()
|
||||
?.filter { "corda-shell" in it.name }
|
||||
?.filter { "jar" == it.extension }
|
||||
?: emptyList()
|
||||
|
||||
return if (files.isNotEmpty()) {
|
||||
check(files.size == 1) {
|
||||
("More than one corda-shell jar installed in /drivers directory. " +
|
||||
"Remove all corda-shell jars except for the one that should be used").also {
|
||||
log.error(it)
|
||||
}
|
||||
}
|
||||
files.single()
|
||||
} else {
|
||||
null
|
||||
private fun isShellInstalled(): Boolean {
|
||||
return try {
|
||||
javaClass.classLoader.loadClass(INTERACTIVE_SHELL_CLASS)
|
||||
true
|
||||
} catch (e: ClassNotFoundException) {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
private fun setUnsafeUsers(classLoader: ClassLoader, configuration: NodeConfiguration) {
|
||||
private fun setUnsafeUsers(configuration: NodeConfiguration) {
|
||||
val unsafeUsers = determineUnsafeUsers(configuration)
|
||||
val clazz = classLoader.loadClass(CRASH_COMMAND_CLASS)
|
||||
val clazz = javaClass.classLoader.loadClass(CRASH_COMMAND_CLASS)
|
||||
clazz.getDeclaredMethod(SET_USER_INFO_METHOD, Set::class.java, Boolean::class.java, Boolean::class.java)
|
||||
.invoke(null, unsafeUsers, true, false)
|
||||
log.info("Setting unsafe users as: $unsafeUsers")
|
||||
}
|
||||
|
||||
private fun startShell(classLoader: ClassLoader, shellConfiguration: Map<String, Any?>, cordappLoader: CordappLoader) {
|
||||
val clazz = classLoader.loadClass(INTERACTIVE_SHELL_CLASS)
|
||||
private fun startShell(shellConfiguration: Map<String, Any?>, cordappLoader: CordappLoader) {
|
||||
val clazz = javaClass.classLoader.loadClass(INTERACTIVE_SHELL_CLASS)
|
||||
val instance = clazz.getDeclaredConstructor()
|
||||
.apply { this.isAccessible = true }
|
||||
.newInstance()
|
||||
clazz.getDeclaredMethod(START_SHELL_METHOD, Map::class.java, ClassLoader::class.java, Boolean::class.java)
|
||||
.invoke(instance, shellConfiguration, cordappLoader.appClassLoader, false)
|
||||
log.info("INTERACTIVE SHELL STARTED ABSTRACT NODE")
|
||||
}
|
||||
|
||||
private fun runLocalShell(classLoader: ClassLoader, onExit: () -> Unit = {}) {
|
||||
val clazz = classLoader.loadClass(INTERACTIVE_SHELL_CLASS)
|
||||
private fun runLocalShell(onExit: () -> Unit = {}) {
|
||||
val clazz = javaClass.classLoader.loadClass(INTERACTIVE_SHELL_CLASS)
|
||||
// Gets the existing instance created by [startShell] as [InteractiveShell] is a static instance
|
||||
val instance = clazz.getDeclaredConstructor()
|
||||
.apply { this.isAccessible = true }
|
||||
.newInstance()
|
||||
clazz.getDeclaredMethod(RUN_LOCAL_SHELL_METHOD, Function0::class.java).invoke(instance, onExit)
|
||||
log.info("INTERACTIVE SHELL STARTED")
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user