mirror of
https://github.com/corda/corda.git
synced 2025-06-13 12:48:18 +00:00
ENT-11155: Remove internal Kotlin utilities which have since been added after 1.2 (#7585)
This is mostly the `Path` extension functions in `PathUtils.kt`.
This commit is contained in:
@ -13,6 +13,7 @@ import java.nio.file.Files
|
||||
import java.nio.file.Path
|
||||
import java.nio.file.StandardCopyOption
|
||||
import java.util.Collections.singleton
|
||||
import kotlin.io.path.deleteIfExists
|
||||
|
||||
// When scanning of the CorDapp Jar is performed without "corda-core.jar" being in the classpath, there is no way to appreciate
|
||||
// relationships between those interfaces, therefore they have to be listed explicitly.
|
||||
|
@ -4,8 +4,6 @@ import net.corda.core.crypto.CompositeKey
|
||||
import net.corda.core.crypto.generateKeyPair
|
||||
import net.corda.core.identity.CordaX500Name
|
||||
import net.corda.core.identity.Party
|
||||
import net.corda.core.internal.createDirectories
|
||||
import net.corda.core.internal.div
|
||||
import net.corda.core.utilities.trace
|
||||
import net.corda.nodeapi.internal.config.FileBasedCertificateStoreSupplier
|
||||
import net.corda.nodeapi.internal.config.SslConfiguration
|
||||
@ -21,6 +19,8 @@ import java.security.KeyPair
|
||||
import java.security.PublicKey
|
||||
import java.security.cert.X509Certificate
|
||||
import javax.security.auth.x500.X500Principal
|
||||
import kotlin.io.path.createDirectories
|
||||
import kotlin.io.path.div
|
||||
|
||||
/**
|
||||
* Contains utility methods for generating identities for a node.
|
||||
|
@ -1,12 +1,9 @@
|
||||
package net.corda.nodeapi.internal.config
|
||||
|
||||
import net.corda.core.crypto.internal.AliasPrivateKey
|
||||
import net.corda.core.internal.outputStream
|
||||
import net.corda.nodeapi.internal.crypto.X509KeyStore
|
||||
import net.corda.nodeapi.internal.crypto.addOrReplaceCertificate
|
||||
import java.io.InputStream
|
||||
import java.io.OutputStream
|
||||
import java.nio.file.OpenOption
|
||||
import java.nio.file.Path
|
||||
import java.security.PrivateKey
|
||||
import java.security.cert.X509Certificate
|
||||
@ -21,17 +18,18 @@ interface CertificateStore : Iterable<Pair<String, X509Certificate>> {
|
||||
|
||||
fun fromInputStream(stream: InputStream, password: String, entryPassword: String): CertificateStore = DelegatingCertificateStore(X509KeyStore.fromInputStream(stream, password), password, entryPassword)
|
||||
|
||||
fun fromResource(storeResourceName: String, password: String, entryPassword: String, classLoader: ClassLoader = Thread.currentThread().contextClassLoader): CertificateStore = fromInputStream(classLoader.getResourceAsStream(storeResourceName), password, entryPassword)
|
||||
fun fromResource(storeResourceName: String,
|
||||
password: String,
|
||||
entryPassword: String,
|
||||
classLoader: ClassLoader = Thread.currentThread().contextClassLoader): CertificateStore {
|
||||
return fromInputStream(classLoader.getResourceAsStream(storeResourceName)!!, password, entryPassword)
|
||||
}
|
||||
}
|
||||
|
||||
val value: X509KeyStore
|
||||
val password: String
|
||||
val entryPassword: String
|
||||
|
||||
fun writeTo(stream: OutputStream) = value.internal.store(stream, password.toCharArray())
|
||||
|
||||
fun writeTo(path: Path, vararg options: OpenOption) = path.outputStream(*options)
|
||||
|
||||
fun update(action: X509KeyStore.() -> Unit) {
|
||||
val result = action.invoke(value)
|
||||
value.save()
|
||||
|
@ -3,7 +3,13 @@
|
||||
|
||||
package net.corda.nodeapi.internal.config
|
||||
|
||||
import com.typesafe.config.*
|
||||
import com.typesafe.config.Config
|
||||
import com.typesafe.config.ConfigException
|
||||
import com.typesafe.config.ConfigFactory
|
||||
import com.typesafe.config.ConfigUtil
|
||||
import com.typesafe.config.ConfigValue
|
||||
import com.typesafe.config.ConfigValueFactory
|
||||
import com.typesafe.config.ConfigValueType
|
||||
import net.corda.core.identity.CordaX500Name
|
||||
import net.corda.core.internal.isStatic
|
||||
import net.corda.core.internal.noneOrSingle
|
||||
@ -22,7 +28,8 @@ import java.time.Duration
|
||||
import java.time.Instant
|
||||
import java.time.LocalDate
|
||||
import java.time.temporal.Temporal
|
||||
import java.util.*
|
||||
import java.util.Properties
|
||||
import java.util.UUID
|
||||
import javax.security.auth.x500.X500Principal
|
||||
import kotlin.reflect.KClass
|
||||
import kotlin.reflect.KProperty
|
||||
@ -99,7 +106,7 @@ fun <T : Any> Config.parseAs(
|
||||
.toSortedSet()
|
||||
onUnknownKeys.invoke(unknownConfigurationKeys, logger)
|
||||
|
||||
val args = parameters.filterNot { it.isOptional && !hasPath(it.name!!) }.associateBy({ it }) { param ->
|
||||
val args = parameters.filterNot { it.isOptional && !hasPath(it.name!!) }.associateWith { param ->
|
||||
// Get the matching property for this parameter
|
||||
val property = clazz.memberProperties.first { it.name == param.name }
|
||||
val path = defaultToOldPath(property)
|
||||
|
@ -3,13 +3,22 @@
|
||||
package net.corda.nodeapi.internal.crypto
|
||||
|
||||
import net.corda.core.crypto.Crypto
|
||||
import net.corda.core.internal.*
|
||||
import net.corda.core.internal.read
|
||||
import net.corda.core.internal.safeSymbolicRead
|
||||
import net.corda.core.internal.write
|
||||
import java.io.IOException
|
||||
import java.io.InputStream
|
||||
import java.nio.file.Path
|
||||
import java.security.*
|
||||
import java.security.Key
|
||||
import java.security.KeyPair
|
||||
import java.security.KeyStore
|
||||
import java.security.KeyStoreException
|
||||
import java.security.PrivateKey
|
||||
import java.security.Provider
|
||||
import java.security.cert.Certificate
|
||||
import java.security.cert.X509Certificate
|
||||
import kotlin.io.path.createDirectories
|
||||
import kotlin.io.path.exists
|
||||
|
||||
const val KEYSTORE_TYPE = "JKS"
|
||||
|
||||
@ -144,8 +153,8 @@ fun KeyStore.getX509Certificate(alias: String): X509Certificate {
|
||||
* @param keyPassword Password to unlock the private key entries.
|
||||
* @return the requested private key in supported type.
|
||||
* @throws KeyStoreException if the keystore has not been initialized.
|
||||
* @throws NoSuchAlgorithmException if the algorithm for recovering the key cannot be found (not supported from the Keystore provider).
|
||||
* @throws UnrecoverableKeyException if the key cannot be recovered (e.g., the given password is wrong).
|
||||
* @throws java.security.NoSuchAlgorithmException if the algorithm for recovering the key cannot be found (not supported from the Keystore provider).
|
||||
* @throws java.security.UnrecoverableKeyException if the key cannot be recovered (e.g., the given password is wrong).
|
||||
* @throws IllegalArgumentException on not supported scheme or if the given key specification
|
||||
* is inappropriate for a supported key factory to produce a private key.
|
||||
*/
|
||||
|
@ -7,10 +7,8 @@ import net.corda.core.crypto.Crypto
|
||||
import net.corda.core.crypto.newSecureRandom
|
||||
import net.corda.core.internal.CertRole
|
||||
import net.corda.core.internal.SignedDataWithCert
|
||||
import net.corda.core.internal.reader
|
||||
import net.corda.core.internal.signWithCert
|
||||
import net.corda.core.internal.validate
|
||||
import net.corda.core.internal.writer
|
||||
import net.corda.core.utilities.days
|
||||
import net.corda.core.utilities.millis
|
||||
import net.corda.core.utilities.toHex
|
||||
@ -62,11 +60,12 @@ import java.security.cert.X509Certificate
|
||||
import java.time.Duration
|
||||
import java.time.Instant
|
||||
import java.time.temporal.ChronoUnit
|
||||
import java.util.ArrayList
|
||||
import java.util.Date
|
||||
import javax.security.auth.x500.X500Principal
|
||||
import kotlin.experimental.and
|
||||
import kotlin.experimental.or
|
||||
import kotlin.io.path.reader
|
||||
import kotlin.io.path.writer
|
||||
|
||||
object X509Utilities {
|
||||
// Note that this default value only applies to BCCryptoService. Other implementations of CryptoService may have to use different
|
||||
|
@ -6,9 +6,20 @@ import com.typesafe.config.ConfigFactory
|
||||
import net.corda.common.configuration.parsing.internal.Configuration
|
||||
import net.corda.core.identity.CordaX500Name
|
||||
import net.corda.core.identity.Party
|
||||
import net.corda.core.internal.*
|
||||
import net.corda.core.internal.JarSignatureCollector
|
||||
import net.corda.core.internal.NODE_INFO_DIRECTORY
|
||||
import net.corda.core.internal.PLATFORM_VERSION
|
||||
import net.corda.core.internal.VisibleForTesting
|
||||
import net.corda.core.internal.concurrent.fork
|
||||
import net.corda.core.internal.concurrent.transpose
|
||||
import net.corda.core.internal.copyTo
|
||||
import net.corda.core.internal.copyToDirectory
|
||||
import net.corda.core.internal.div
|
||||
import net.corda.core.internal.location
|
||||
import net.corda.core.internal.read
|
||||
import net.corda.core.internal.readObject
|
||||
import net.corda.core.internal.times
|
||||
import net.corda.core.internal.toPath
|
||||
import net.corda.core.node.NetworkParameters
|
||||
import net.corda.core.node.NodeInfo
|
||||
import net.corda.core.node.NotaryInfo
|
||||
@ -21,7 +32,11 @@ import net.corda.core.serialization.internal._contextSerializationEnv
|
||||
import net.corda.core.utilities.days
|
||||
import net.corda.core.utilities.getOrThrow
|
||||
import net.corda.core.utilities.seconds
|
||||
import net.corda.nodeapi.internal.*
|
||||
import net.corda.nodeapi.internal.ContractsJar
|
||||
import net.corda.nodeapi.internal.ContractsJarFile
|
||||
import net.corda.nodeapi.internal.DEV_ROOT_CA
|
||||
import net.corda.nodeapi.internal.DevIdentityGenerator
|
||||
import net.corda.nodeapi.internal.SignedNodeInfo
|
||||
import net.corda.nodeapi.internal.config.getBooleanCaseInsensitive
|
||||
import net.corda.nodeapi.internal.network.NodeInfoFilesCopier.Companion.NODE_INFO_FILE_NAME_PREFIX
|
||||
import net.corda.serialization.internal.AMQP_P2P_CONTEXT
|
||||
@ -29,7 +44,6 @@ import net.corda.serialization.internal.CordaSerializationMagic
|
||||
import net.corda.serialization.internal.SerializationFactoryImpl
|
||||
import net.corda.serialization.internal.amqp.AbstractAMQPSerializationScheme
|
||||
import net.corda.serialization.internal.amqp.amqpMagic
|
||||
import java.io.File
|
||||
import java.net.URL
|
||||
import java.nio.file.FileAlreadyExistsException
|
||||
import java.nio.file.Path
|
||||
@ -38,7 +52,7 @@ import java.nio.file.StandardCopyOption.REPLACE_EXISTING
|
||||
import java.security.PublicKey
|
||||
import java.time.Duration
|
||||
import java.time.Instant
|
||||
import java.util.*
|
||||
import java.util.Timer
|
||||
import java.util.concurrent.Executors
|
||||
import java.util.concurrent.TimeUnit
|
||||
import java.util.jar.JarInputStream
|
||||
@ -46,6 +60,16 @@ import kotlin.collections.component1
|
||||
import kotlin.collections.component2
|
||||
import kotlin.collections.set
|
||||
import kotlin.concurrent.schedule
|
||||
import kotlin.io.path.copyTo
|
||||
import kotlin.io.path.createDirectories
|
||||
import kotlin.io.path.deleteExisting
|
||||
import kotlin.io.path.div
|
||||
import kotlin.io.path.exists
|
||||
import kotlin.io.path.isSameFileAs
|
||||
import kotlin.io.path.listDirectoryEntries
|
||||
import kotlin.io.path.name
|
||||
import kotlin.io.path.readBytes
|
||||
import kotlin.io.path.useDirectoryEntries
|
||||
|
||||
/**
|
||||
* Class to bootstrap a local network of Corda nodes on the same filesystem.
|
||||
@ -88,7 +112,7 @@ constructor(private val initSerEnv: Boolean,
|
||||
private val jarsThatArentCordapps = setOf("corda.jar", "runnodes.jar")
|
||||
|
||||
private fun extractEmbeddedCordaJar(): URL {
|
||||
return Thread.currentThread().contextClassLoader.getResource("corda.jar")
|
||||
return Thread.currentThread().contextClassLoader.getResource("corda.jar")!!
|
||||
}
|
||||
|
||||
private fun generateNodeInfos(nodeDirs: List<Path>): List<Path> {
|
||||
@ -111,9 +135,7 @@ constructor(private val initSerEnv: Boolean,
|
||||
|
||||
private fun generateNodeInfo(nodeDir: Path): Path {
|
||||
runNodeJob(nodeInfoGenCmd, nodeDir, "node-info-gen.log")
|
||||
return nodeDir.list { paths ->
|
||||
paths.filter { it.fileName.toString().startsWith(NODE_INFO_FILE_NAME_PREFIX) }.findFirst().get()
|
||||
}
|
||||
return nodeDir.useDirectoryEntries { paths -> paths.single { it.name.startsWith(NODE_INFO_FILE_NAME_PREFIX) } }
|
||||
}
|
||||
|
||||
private fun createDbSchemas(nodeDir: Path) {
|
||||
@ -122,11 +144,11 @@ constructor(private val initSerEnv: Boolean,
|
||||
|
||||
private fun runNodeJob(command: List<String>, nodeDir: Path, logfileName: String) {
|
||||
val logsDir = (nodeDir / LOGS_DIR_NAME).createDirectories()
|
||||
val nodeRedirectFile = (logsDir / logfileName).toFile()
|
||||
val nodeRedirectFile = logsDir / logfileName
|
||||
val process = ProcessBuilder(command)
|
||||
.directory(nodeDir.toFile())
|
||||
.redirectErrorStream(true)
|
||||
.redirectOutput(nodeRedirectFile)
|
||||
.redirectOutput(nodeRedirectFile.toFile())
|
||||
.apply { environment()["CAPSULE_CACHE_DIR"] = "../.cache" }
|
||||
.start()
|
||||
try {
|
||||
@ -142,7 +164,7 @@ constructor(private val initSerEnv: Boolean,
|
||||
}
|
||||
}
|
||||
|
||||
private fun printNodeOutputToConsoleAndThrow(stdoutFile: File) {
|
||||
private fun printNodeOutputToConsoleAndThrow(stdoutFile: Path) {
|
||||
val nodeDir = stdoutFile.parent
|
||||
val nodeIdentifier = try {
|
||||
ConfigFactory.parseFile((nodeDir / "node.conf").toFile()).getString("myLegalName")
|
||||
@ -150,7 +172,7 @@ constructor(private val initSerEnv: Boolean,
|
||||
nodeDir
|
||||
}
|
||||
System.err.println("#### Error while generating node info file $nodeIdentifier ####")
|
||||
stdoutFile.inputStream().copyTo(System.err)
|
||||
stdoutFile.copyTo(System.err)
|
||||
throw IllegalStateException("Error while generating node info file. Please check the logs in $nodeDir.")
|
||||
}
|
||||
|
||||
@ -238,9 +260,8 @@ constructor(private val initSerEnv: Boolean,
|
||||
require(networkParameterOverrides.minimumPlatformVersion == null || networkParameterOverrides.minimumPlatformVersion <= PLATFORM_VERSION) { "Minimum platform version cannot be greater than $PLATFORM_VERSION" }
|
||||
// Don't accidentally include the bootstrapper jar as a CorDapp!
|
||||
val bootstrapperJar = javaClass.location.toPath()
|
||||
val cordappJars = directory.list { paths ->
|
||||
paths.filter { it.toString().endsWith(".jar") && !it.isSameAs(bootstrapperJar) && !jarsThatArentCordapps.contains(it.fileName.toString().toLowerCase()) }
|
||||
.toList()
|
||||
val cordappJars = directory.useDirectoryEntries("*.jar") { jars ->
|
||||
jars.filter { !it.isSameFileAs(bootstrapperJar) && it.name.lowercase() !in jarsThatArentCordapps }.toList()
|
||||
}
|
||||
bootstrap(directory, cordappJars, copyCordapps, fromCordform = false, networkParametersOverrides = networkParameterOverrides)
|
||||
}
|
||||
@ -262,7 +283,7 @@ constructor(private val initSerEnv: Boolean,
|
||||
println("Nodes found in the following sub-directories: ${nodeDirs.map { it.fileName }}")
|
||||
}
|
||||
|
||||
val configs = nodeDirs.associateBy({ it }, { ConfigFactory.parseFile((it / "node.conf").toFile()) })
|
||||
val configs = nodeDirs.associateWith { ConfigFactory.parseFile((it / "node.conf").toFile()) }
|
||||
checkForDuplicateLegalNames(configs.values)
|
||||
|
||||
copyCordapps.copy(cordappJars, nodeDirs, networkAlreadyExists, fromCordform)
|
||||
@ -300,9 +321,7 @@ constructor(private val initSerEnv: Boolean,
|
||||
}
|
||||
}
|
||||
|
||||
private fun Path.listEndingWith(suffix: String): List<Path> {
|
||||
return list { file -> file.filter { it.toString().endsWith(suffix) }.toList() }
|
||||
}
|
||||
private fun Path.listEndingWith(suffix: String): List<Path> = listDirectoryEntries("*$suffix")
|
||||
|
||||
private fun createNodeDirectoriesIfNeeded(directory: Path, fromCordform: Boolean): Boolean {
|
||||
var networkAlreadyExists = false
|
||||
@ -319,7 +338,7 @@ constructor(private val initSerEnv: Boolean,
|
||||
val webServerConfFiles = directory.listEndingWith("_web-server.conf")
|
||||
|
||||
for (confFile in confFiles) {
|
||||
val nodeName = confFile.fileName.toString().removeSuffix("_node.conf")
|
||||
val nodeName = confFile.name.removeSuffix("_node.conf")
|
||||
println("Generating node directory for $nodeName")
|
||||
if ((directory / nodeName).exists()) {
|
||||
//directory already exists, so assume this network has been bootstrapped before
|
||||
@ -332,25 +351,28 @@ constructor(private val initSerEnv: Boolean,
|
||||
cordaJar.copyToDirectory(nodeDir, REPLACE_EXISTING)
|
||||
}
|
||||
|
||||
val nodeDirs = directory.list { subDir -> subDir.filter { (it / "node.conf").exists() && !(it / "corda.jar").exists() }.toList() }
|
||||
for (nodeDir in nodeDirs) {
|
||||
println("Copying corda.jar into node directory ${nodeDir.fileName}")
|
||||
cordaJar.copyToDirectory(nodeDir)
|
||||
directory.useDirectoryEntries { subDir ->
|
||||
subDir
|
||||
.filter { (it / "node.conf").exists() && !(it / "corda.jar").exists() }
|
||||
.forEach { nodeDir ->
|
||||
println("Copying corda.jar into node directory ${nodeDir.fileName}")
|
||||
cordaJar.copyToDirectory(nodeDir)
|
||||
}
|
||||
}
|
||||
|
||||
if (fromCordform) {
|
||||
confFiles.forEach(Path::delete)
|
||||
webServerConfFiles.forEach(Path::delete)
|
||||
confFiles.forEach(Path::deleteExisting)
|
||||
webServerConfFiles.forEach(Path::deleteExisting)
|
||||
}
|
||||
|
||||
if (fromCordform || usingEmbedded) {
|
||||
cordaJar.delete()
|
||||
cordaJar.deleteExisting()
|
||||
}
|
||||
return networkAlreadyExists
|
||||
}
|
||||
|
||||
private fun gatherNodeDirectories(directory: Path): List<Path> {
|
||||
val nodeDirs = directory.list { subDir -> subDir.filter { (it / "corda.jar").exists() }.toList() }
|
||||
val nodeDirs = directory.useDirectoryEntries { subDir -> subDir.filter { (it / "corda.jar").exists() }.toList() }
|
||||
for (nodeDir in nodeDirs) {
|
||||
require((nodeDir / "node.conf").exists()) { "Missing node.conf in node directory ${nodeDir.fileName}" }
|
||||
}
|
||||
@ -394,7 +416,7 @@ constructor(private val initSerEnv: Boolean,
|
||||
val netParamsFilesGrouped = nodeDirs.mapNotNull {
|
||||
val netParamsFile = it / NETWORK_PARAMS_FILE_NAME
|
||||
if (netParamsFile.exists()) netParamsFile else null
|
||||
}.groupBy { SerializedBytes<SignedNetworkParameters>(it.readAll()) }
|
||||
}.groupBy { SerializedBytes<SignedNetworkParameters>(it.readBytes()) }
|
||||
|
||||
when (netParamsFilesGrouped.size) {
|
||||
0 -> return null
|
||||
@ -492,9 +514,7 @@ constructor(private val initSerEnv: Boolean,
|
||||
}
|
||||
|
||||
private fun isSigned(file: Path): Boolean = file.read {
|
||||
JarInputStream(it).use {
|
||||
JarSignatureCollector.collectSigningParties(it).isNotEmpty()
|
||||
}
|
||||
JarInputStream(it).use(JarSignatureCollector::collectSigningParties).isNotEmpty()
|
||||
}
|
||||
}
|
||||
|
||||
@ -504,8 +524,7 @@ fun NetworkParameters.overrideWith(override: NetworkParametersOverrides): Networ
|
||||
maxMessageSize = override.maxMessageSize ?: this.maxMessageSize,
|
||||
maxTransactionSize = override.maxTransactionSize ?: this.maxTransactionSize,
|
||||
eventHorizon = override.eventHorizon ?: this.eventHorizon,
|
||||
packageOwnership = override.packageOwnership?.map { it.javaPackageName to it.publicKey }?.toMap()
|
||||
?: this.packageOwnership
|
||||
packageOwnership = override.packageOwnership?.associate { it.javaPackageName to it.publicKey } ?: this.packageOwnership
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -3,7 +3,6 @@ package net.corda.nodeapi.internal.network
|
||||
import net.corda.core.internal.SignedDataWithCert
|
||||
import net.corda.core.internal.VisibleForTesting
|
||||
import net.corda.core.internal.copyTo
|
||||
import net.corda.core.internal.div
|
||||
import net.corda.core.node.NetworkParameters
|
||||
import net.corda.core.serialization.SerializedBytes
|
||||
import net.corda.core.serialization.serialize
|
||||
@ -12,6 +11,7 @@ import net.corda.nodeapi.internal.crypto.CertificateAndKeyPair
|
||||
import java.nio.file.FileAlreadyExistsException
|
||||
import java.nio.file.Path
|
||||
import java.nio.file.StandardCopyOption
|
||||
import kotlin.io.path.div
|
||||
|
||||
class NetworkParametersCopier(
|
||||
networkParameters: NetworkParameters,
|
||||
|
@ -1,6 +1,7 @@
|
||||
package net.corda.nodeapi.internal.network
|
||||
|
||||
import net.corda.core.internal.*
|
||||
import net.corda.core.internal.NODE_INFO_DIRECTORY
|
||||
import net.corda.core.internal.ThreadBox
|
||||
import net.corda.core.utilities.contextLogger
|
||||
import net.corda.core.utilities.debug
|
||||
import rx.Observable
|
||||
@ -14,6 +15,14 @@ import java.nio.file.StandardCopyOption.COPY_ATTRIBUTES
|
||||
import java.nio.file.StandardCopyOption.REPLACE_EXISTING
|
||||
import java.nio.file.attribute.FileTime
|
||||
import java.util.concurrent.TimeUnit
|
||||
import kotlin.io.path.copyTo
|
||||
import kotlin.io.path.createDirectories
|
||||
import kotlin.io.path.deleteIfExists
|
||||
import kotlin.io.path.getLastModifiedTime
|
||||
import kotlin.io.path.isRegularFile
|
||||
import kotlin.io.path.moveTo
|
||||
import kotlin.io.path.name
|
||||
import kotlin.io.path.useDirectoryEntries
|
||||
|
||||
/**
|
||||
* Utility class which copies nodeInfo files across a set of running nodes.
|
||||
@ -96,10 +105,10 @@ class NodeInfoFilesCopier(private val scheduler: Scheduler = Schedulers.io()) :
|
||||
private fun poll() {
|
||||
nodeDataMapBox.locked {
|
||||
for (nodeData in values) {
|
||||
nodeData.nodeDir.list { paths ->
|
||||
nodeData.nodeDir.useDirectoryEntries { paths ->
|
||||
paths
|
||||
.filter { it.isRegularFile() }
|
||||
.filter { it.fileName.toString().startsWith(NODE_INFO_FILE_NAME_PREFIX) }
|
||||
.filter { it.name.startsWith(NODE_INFO_FILE_NAME_PREFIX) }
|
||||
.forEach { processPath(nodeData, it) }
|
||||
}
|
||||
}
|
||||
@ -110,7 +119,7 @@ class NodeInfoFilesCopier(private val scheduler: Scheduler = Schedulers.io()) :
|
||||
// be copied.
|
||||
private fun processPath(nodeData: NodeData, path: Path) {
|
||||
nodeDataMapBox.alreadyLocked {
|
||||
val newTimestamp = path.lastModifiedTime()
|
||||
val newTimestamp = path.getLastModifiedTime()
|
||||
val previousTimestamp = nodeData.previouslySeenFiles.put(path, newTimestamp) ?: FileTime.fromMillis(-1)
|
||||
if (newTimestamp > previousTimestamp) {
|
||||
for (destination in this.values.filter { it.nodeDir != nodeData.nodeDir }.map { it.additionalNodeInfoDirectory }) {
|
||||
@ -134,15 +143,15 @@ class NodeInfoFilesCopier(private val scheduler: Scheduler = Schedulers.io()) :
|
||||
source.copyTo(tempDestination, COPY_ATTRIBUTES, REPLACE_EXISTING)
|
||||
} catch (exception: IOException) {
|
||||
log.warn("Couldn't copy $source to $tempDestination.", exception)
|
||||
tempDestination.delete()
|
||||
tempDestination.deleteIfExists()
|
||||
throw exception
|
||||
}
|
||||
try {
|
||||
// Then rename it to the desired name. This way the file 'appears' on the filesystem as an atomic operation.
|
||||
tempDestination.moveTo(destination, REPLACE_EXISTING)
|
||||
tempDestination.moveTo(destination, overwrite = true)
|
||||
} catch (exception: IOException) {
|
||||
log.warn("Couldn't move $tempDestination to $destination.", exception)
|
||||
tempDestination.delete()
|
||||
tempDestination.deleteIfExists()
|
||||
throw exception
|
||||
}
|
||||
}
|
||||
|
@ -1,12 +1,15 @@
|
||||
package net.corda.nodeapi.internal.network
|
||||
|
||||
import net.corda.core.contracts.ContractClassName
|
||||
import net.corda.core.internal.*
|
||||
import net.corda.core.internal.toMultiMap
|
||||
import net.corda.core.node.NetworkParameters
|
||||
import net.corda.core.node.services.AttachmentId
|
||||
import net.corda.nodeapi.internal.ContractsJar
|
||||
import org.slf4j.LoggerFactory
|
||||
import java.nio.file.Path
|
||||
import kotlin.io.path.div
|
||||
import kotlin.io.path.exists
|
||||
import kotlin.io.path.readLines
|
||||
|
||||
private const val EXCLUDE_WHITELIST_FILE_NAME = "exclude_whitelist.txt"
|
||||
private const val INCLUDE_WHITELIST_FILE_NAME = "include_whitelist.txt"
|
||||
@ -37,7 +40,7 @@ fun generateWhitelist(networkParameters: NetworkParameters?,
|
||||
.flatMap { jar -> (jar.scan()).filter { includeContracts.contains(it) }.map { it to jar.hash } }
|
||||
.toMultiMap()
|
||||
|
||||
return (newWhiteList.keys + existingWhitelist.keys + newSignedJarsWhiteList.keys).associateBy({ it }) {
|
||||
return (newWhiteList.keys + existingWhitelist.keys + newSignedJarsWhiteList.keys).associateWith {
|
||||
val existingHashes = existingWhitelist[it] ?: emptyList()
|
||||
val newHashes = newWhiteList[it] ?: emptyList()
|
||||
val newHashesFormSignedJar = newSignedJarsWhiteList[it] ?: emptyList()
|
||||
@ -49,4 +52,4 @@ fun readExcludeWhitelist(directory: Path): List<String> = readAllLines(directory
|
||||
|
||||
fun readIncludeWhitelist(directory: Path): List<String> = readAllLines(directory / INCLUDE_WHITELIST_FILE_NAME)
|
||||
|
||||
private fun readAllLines(path: Path) : List<String> = if (path.exists()) path.readAllLines().map(String::trim) else emptyList()
|
||||
private fun readAllLines(path: Path): List<String> = if (path.exists()) path.readLines().map(String::trim) else emptyList()
|
||||
|
@ -5,7 +5,6 @@ import liquibase.database.Database
|
||||
import liquibase.database.jvm.JdbcConnection
|
||||
import liquibase.exception.ValidationErrors
|
||||
import liquibase.resource.ResourceAccessor
|
||||
import net.corda.core.internal.div
|
||||
import net.corda.core.internal.readObject
|
||||
import net.corda.core.node.NetworkParameters
|
||||
import net.corda.core.serialization.deserialize
|
||||
@ -15,6 +14,7 @@ import net.corda.nodeapi.internal.network.SignedNetworkParameters
|
||||
import net.corda.nodeapi.internal.persistence.SchemaMigration.Companion.NODE_BASE_DIR_KEY
|
||||
import java.nio.file.Path
|
||||
import java.nio.file.Paths
|
||||
import kotlin.io.path.div
|
||||
|
||||
class AttachmentVersionNumberMigration : CustomTaskChange {
|
||||
companion object {
|
||||
@ -27,8 +27,8 @@ class AttachmentVersionNumberMigration : CustomTaskChange {
|
||||
|
||||
try {
|
||||
logger.info("Start executing...")
|
||||
var networkParameters: NetworkParameters?
|
||||
val baseDir = System.getProperty(SchemaMigration.NODE_BASE_DIR_KEY)
|
||||
val networkParameters: NetworkParameters?
|
||||
val baseDir = System.getProperty(NODE_BASE_DIR_KEY)
|
||||
val availableAttachments = getAttachmentsWithDefaultVersion(connection)
|
||||
if (baseDir != null) {
|
||||
val path = Paths.get(baseDir) / NETWORK_PARAMS_FILE_NAME
|
||||
|
@ -13,7 +13,6 @@ import com.esotericsoftware.kryo.util.DefaultClassResolver
|
||||
import com.esotericsoftware.kryo.util.Util
|
||||
import net.corda.core.internal.kotlinObjectInstance
|
||||
import net.corda.core.internal.utilities.PrivateInterner
|
||||
import net.corda.core.internal.writer
|
||||
import net.corda.core.serialization.ClassWhitelist
|
||||
import net.corda.core.serialization.internal.AttachmentsClassLoader
|
||||
import net.corda.core.serialization.internal.CheckpointSerializationContext
|
||||
@ -28,8 +27,8 @@ import java.nio.file.Paths
|
||||
import java.nio.file.StandardOpenOption.APPEND
|
||||
import java.nio.file.StandardOpenOption.CREATE
|
||||
import java.nio.file.StandardOpenOption.WRITE
|
||||
import java.util.ArrayList
|
||||
import java.util.Collections
|
||||
import kotlin.io.path.writer
|
||||
|
||||
/**
|
||||
* Corda specific class resolver which enables extra customisation for the purposes of serialization using Kryo
|
||||
|
@ -6,17 +6,20 @@ import com.typesafe.config.ConfigFactory.empty
|
||||
import com.typesafe.config.ConfigRenderOptions.defaults
|
||||
import com.typesafe.config.ConfigValueFactory
|
||||
import net.corda.core.identity.CordaX500Name
|
||||
import net.corda.core.internal.div
|
||||
import net.corda.core.utilities.NetworkHostAndPort
|
||||
import org.assertj.core.api.Assertions.*
|
||||
import org.assertj.core.api.Assertions.assertThat
|
||||
import org.assertj.core.api.Assertions.assertThatExceptionOfType
|
||||
import org.assertj.core.api.Assertions.assertThatThrownBy
|
||||
import org.junit.Ignore
|
||||
import org.junit.Test
|
||||
import java.net.URL
|
||||
import java.nio.file.Path
|
||||
import java.time.Instant
|
||||
import java.time.LocalDate
|
||||
import java.util.*
|
||||
import java.util.Properties
|
||||
import java.util.UUID
|
||||
import javax.security.auth.x500.X500Principal
|
||||
import kotlin.io.path.div
|
||||
import kotlin.reflect.full.primaryConstructor
|
||||
|
||||
class ConfigParsingTest {
|
||||
@ -86,7 +89,7 @@ class ConfigParsingTest {
|
||||
|
||||
@Test(timeout=300_000)
|
||||
fun Path() {
|
||||
val path = "tmp" / "test"
|
||||
val path = Path.of("tmp", "test")
|
||||
testPropertyType<PathData, PathListData, Path>(path, path / "file", valuesToString = true)
|
||||
}
|
||||
|
||||
|
@ -3,7 +3,6 @@ package net.corda.nodeapi.internal.cryptoservice.bouncycastle
|
||||
import net.corda.core.crypto.Crypto
|
||||
import net.corda.core.crypto.SignatureScheme
|
||||
import net.corda.core.crypto.internal.cordaBouncyCastleProvider
|
||||
import net.corda.core.internal.div
|
||||
import net.corda.core.utilities.days
|
||||
import net.corda.nodeapi.internal.config.CertificateStoreSupplier
|
||||
import net.corda.nodeapi.internal.crypto.CertificateType
|
||||
@ -31,6 +30,7 @@ import java.time.Duration
|
||||
import java.util.*
|
||||
import javax.crypto.Cipher
|
||||
import javax.security.auth.x500.X500Principal
|
||||
import kotlin.io.path.div
|
||||
import kotlin.test.assertFailsWith
|
||||
import kotlin.test.assertFalse
|
||||
import kotlin.test.assertTrue
|
||||
@ -49,8 +49,8 @@ class BCCryptoServiceTests {
|
||||
@JvmField
|
||||
val temporaryKeystoreFolder = TemporaryFolder()
|
||||
|
||||
lateinit var certificatesDirectory: Path
|
||||
lateinit var wrappingKeyStorePath: Path
|
||||
private lateinit var certificatesDirectory: Path
|
||||
private lateinit var wrappingKeyStorePath: Path
|
||||
|
||||
@Before
|
||||
fun setUp() {
|
||||
|
@ -1,8 +1,5 @@
|
||||
package net.corda.nodeapi.internal.network
|
||||
|
||||
import net.corda.core.internal.div
|
||||
import net.corda.core.internal.list
|
||||
import net.corda.core.internal.write
|
||||
import net.corda.core.internal.NODE_INFO_DIRECTORY
|
||||
import net.corda.testing.common.internal.eventually
|
||||
import org.assertj.core.api.Assertions.assertThat
|
||||
@ -14,6 +11,10 @@ import rx.schedulers.TestScheduler
|
||||
import java.nio.file.Path
|
||||
import java.time.Duration
|
||||
import java.util.concurrent.TimeUnit
|
||||
import kotlin.io.path.div
|
||||
import kotlin.io.path.listDirectoryEntries
|
||||
import kotlin.io.path.name
|
||||
import kotlin.io.path.writeBytes
|
||||
|
||||
class NodeInfoFilesCopierTest {
|
||||
companion object {
|
||||
@ -34,7 +35,7 @@ class NodeInfoFilesCopierTest {
|
||||
private val rootPath get() = folder.root.toPath()
|
||||
private val scheduler = TestScheduler()
|
||||
|
||||
private fun nodeDir(nodeBaseDir: String) = rootPath.resolve(nodeBaseDir).resolve(ORGANIZATION.toLowerCase())
|
||||
private fun nodeDir(nodeBaseDir: String): Path = rootPath / nodeBaseDir / ORGANIZATION.lowercase()
|
||||
|
||||
private val node1RootPath by lazy { nodeDir(NODE_1_PATH) }
|
||||
private val node2RootPath by lazy { nodeDir(NODE_2_PATH) }
|
||||
@ -56,8 +57,8 @@ class NodeInfoFilesCopierTest {
|
||||
advanceTime()
|
||||
|
||||
// Create 2 files, a nodeInfo and another file in node1 folder.
|
||||
(node1RootPath / GOOD_NODE_INFO_NAME).write(content)
|
||||
(node1RootPath / BAD_NODE_INFO_NAME).write(content)
|
||||
(node1RootPath / GOOD_NODE_INFO_NAME).writeBytes(content)
|
||||
(node1RootPath / BAD_NODE_INFO_NAME).writeBytes(content)
|
||||
|
||||
// Configure the second node.
|
||||
nodeInfoFilesCopier.addConfig(node2RootPath)
|
||||
@ -77,8 +78,8 @@ class NodeInfoFilesCopierTest {
|
||||
advanceTime()
|
||||
|
||||
// Create 2 files, one of which to be copied, in a node root path.
|
||||
(node2RootPath / GOOD_NODE_INFO_NAME).write(content)
|
||||
(node2RootPath / BAD_NODE_INFO_NAME).write(content)
|
||||
(node2RootPath / GOOD_NODE_INFO_NAME).writeBytes(content)
|
||||
(node2RootPath / BAD_NODE_INFO_NAME).writeBytes(content)
|
||||
advanceTime()
|
||||
|
||||
eventually(Duration.ofMinutes(1)) {
|
||||
@ -95,14 +96,14 @@ class NodeInfoFilesCopierTest {
|
||||
advanceTime()
|
||||
|
||||
// Create a file, in node 2 root path.
|
||||
(node2RootPath / GOOD_NODE_INFO_NAME).write(content)
|
||||
(node2RootPath / GOOD_NODE_INFO_NAME).writeBytes(content)
|
||||
advanceTime()
|
||||
|
||||
// Remove node 2
|
||||
nodeInfoFilesCopier.removeConfig(node2RootPath)
|
||||
|
||||
// Create another file in node 2 directory.
|
||||
(node2RootPath / GOOD_NODE_INFO_NAME).write(content)
|
||||
(node2RootPath / GOOD_NODE_INFO_NAME).writeBytes(content)
|
||||
advanceTime()
|
||||
|
||||
eventually(Duration.ofMinutes(1)) {
|
||||
@ -121,11 +122,11 @@ class NodeInfoFilesCopierTest {
|
||||
nodeInfoFilesCopier.reset()
|
||||
|
||||
advanceTime()
|
||||
(node2RootPath / GOOD_NODE_INFO_NAME_2).write(content)
|
||||
(node2RootPath / GOOD_NODE_INFO_NAME_2).writeBytes(content)
|
||||
|
||||
// Give some time to the filesystem to report the change.
|
||||
eventually {
|
||||
assertThat(node1AdditionalNodeInfoPath.list()).isEmpty()
|
||||
assertThat(node1AdditionalNodeInfoPath.listDirectoryEntries()).isEmpty()
|
||||
}
|
||||
}
|
||||
|
||||
@ -134,8 +135,8 @@ class NodeInfoFilesCopierTest {
|
||||
}
|
||||
|
||||
private fun checkDirectoryContainsSingleFile(path: Path, filename: String) {
|
||||
val files = path.list()
|
||||
val files = path.listDirectoryEntries()
|
||||
assertThat(files).hasSize(1)
|
||||
assertThat(files[0].fileName.toString()).isEqualTo(filename)
|
||||
assertThat(files[0].name).isEqualTo(filename)
|
||||
}
|
||||
}
|
@ -35,7 +35,7 @@ class SSLHelperTest {
|
||||
trustManagerFactory,
|
||||
ImmediateExecutor.INSTANCE
|
||||
)
|
||||
val legalNameHash = SecureHash.sha256(legalName.toString()).toString().take(32).toLowerCase()
|
||||
val legalNameHash = SecureHash.sha256(legalName.toString()).toString().take(32).lowercase()
|
||||
|
||||
// These hardcoded values must not be changed, something is broken if you have to change these hardcoded values.
|
||||
assertEquals("O=Test, L=London, C=GB", legalName.toString())
|
||||
|
Reference in New Issue
Block a user